assets/calculators/flex_calculator.py
#!/usr/bin/env python3
"""Flex Credit calculator for Agentforce and Data Cloud."""
from __future__ import annotations
import argparse
import json
from dataclasses import asdict, dataclass, field
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple
FC_COST = 0.004
PRIVATE_CONNECT_MULTIPLIER = 0.20
PROMPT_RATES: Dict[str, float] = {
"starter": 2,
"basic": 2,
"standard": 4,
"advanced": 16,
}
ACTION_RATES: Dict[str, float] = {
"standard": 20,
"custom": 20,
"voice": 30,
"sandbox": 16,
}
DC_RATES: Dict[str, float] = {
"data_360_prep": 40,
"data_360_unification": 75_000,
"data_360_segmentation": 50,
"data_360_activation": 60,
"data_360_zero_copy_sharing": 60,
"data_360_queries": 3,
"data_360_unstructured_processing": 150,
"data_360_intelligent_processing": 600,
"data_360_streaming_pipeline": 3_500,
"data_360_real_time_pipeline": 250_000,
"data_360_code_extension": 40,
}
DC_ALIASES: Dict[str, str] = {
"batch_internal": "data_360_prep",
"batch_external": "data_360_prep",
"prep": "data_360_prep",
"profile_unification": "data_360_unification",
"unification": "data_360_unification",
"segmentation": "data_360_segmentation",
"activation_batch": "data_360_activation",
"activation_streaming": "data_360_activation",
"queries": "data_360_queries",
"unstructured": "data_360_unstructured_processing",
"intelligent_processing": "data_360_intelligent_processing",
"streaming": "data_360_streaming_pipeline",
"real_time_pipeline": "data_360_real_time_pipeline",
"zero_copy_sharing": "data_360_zero_copy_sharing",
"code_extension": "data_360_code_extension",
}
TIER_THRESHOLDS: List[Tuple[float, float, float, str]] = [
(0, 300_000, 1.0, "Tier 1"),
(300_000, 1_500_000, 0.8, "Tier 2"),
(1_500_000, 12_500_000, 0.4, "Tier 3"),
(12_500_000, float("inf"), 0.2, "Tier 4"),
]
@dataclass
class AgentStructure:
prompts: Dict[str, int] = field(default_factory=dict)
actions: Dict[str, int] = field(default_factory=dict)
token_overages: Dict[str, Any] = field(default_factory=lambda: {"prompts": 0, "actions": 0})
def normalized(self) -> "AgentStructure":
prompts = {k.lower(): int(v) for k, v in self.prompts.items() if int(v) != 0}
actions = {k.lower(): int(v) for k, v in self.actions.items() if int(v) != 0}
token_overages = self.token_overages or {"prompts": 0, "actions": 0}
return AgentStructure(prompts=prompts, actions=actions, token_overages=token_overages)
@dataclass
class DataCloudOperations:
operations: Dict[str, float] = field(default_factory=dict)
private_connect: bool = False
def normalized(self) -> "DataCloudOperations":
normalized_ops: Dict[str, float] = {}
for meter, volume in self.operations.items():
canonical = normalize_meter_name(meter)
normalized_ops[canonical] = normalized_ops.get(canonical, 0.0) + float(volume)
return DataCloudOperations(operations=normalized_ops, private_connect=bool(self.private_connect))
@dataclass
class ScenarioVolumes:
name: str
agent_invocations: int
dc_operations: Optional[Dict[str, float]] = None
@dataclass
class CostBreakdown:
scenario_name: str
agent_invocations: int
af_prompt_fc: float
af_action_fc: float
af_token_overage_fc: float
af_total_fc: float
dc_base_fc: float
dc_tiered_fc: float
dc_discount_percent: float
dc_private_connect_fc: float
dc_total_fc: float
total_monthly_fc: float
total_monthly_cost: float
total_annual_cost: float
def normalize_meter_name(meter: str) -> str:
key = meter.strip().lower()
return DC_ALIASES.get(key, key)
def empty_agent_structure() -> AgentStructure:
return AgentStructure(
prompts={"basic": 0, "standard": 0, "advanced": 0},
actions={"standard": 0, "voice": 0, "sandbox": 0},
token_overages={"prompts": 0, "actions": 0},
)
def load_json(path: str | Path) -> Dict[str, Any]:
with open(path, "r", encoding="utf-8") as handle:
return json.load(handle)
def extract_agent_structure(data: Dict[str, Any]) -> AgentStructure:
if not data:
return empty_agent_structure()
if "prompts" in data or "actions" in data:
return AgentStructure(**data).normalized()
nested = data.get("agent_structure")
if isinstance(nested, dict):
return AgentStructure(**nested).normalized()
return empty_agent_structure()
def extract_dc_operations(data: Dict[str, Any]) -> Optional[DataCloudOperations]:
if not data:
return None
if "operations" in data:
return DataCloudOperations(**data).normalized()
nested = data.get("data_cloud_operations")
if isinstance(nested, dict):
return DataCloudOperations(**nested).normalized()
return None
def _weighted_extra_charge(base_breakdown: Dict[str, float], count: Any, total_components: int) -> float:
if not count:
return 0.0
if isinstance(count, dict):
raise TypeError("Dict-based overage handling is not supported by this helper")
if total_components <= 0:
return 0.0
average_charge = base_breakdown["total_fc"] / total_components
return float(count) * average_charge
def _explicit_prompt_overage_fc(prompt_overages: Dict[str, Any]) -> float:
total = 0.0
for tier, count in prompt_overages.items():
total += PROMPT_RATES[tier.lower()] * float(count)
return total
def _explicit_action_overage_fc(action_overages: Dict[str, Any]) -> float:
total = 0.0
for action_type, count in action_overages.items():
total += ACTION_RATES[action_type.lower()] * float(count)
return total
def calculate_per_invocation_cost(agent: AgentStructure) -> Tuple[float, Dict[str, float]]:
agent = agent.normalized()
prompt_fc = sum(PROMPT_RATES[tier] * count for tier, count in agent.prompts.items())
action_fc = sum(ACTION_RATES[action_type] * count for action_type, count in agent.actions.items())
prompt_count = sum(agent.prompts.values())
action_count = sum(agent.actions.values())
overage_fc = 0.0
prompt_overages = (agent.token_overages or {}).get("prompts", 0)
action_overages = (agent.token_overages or {}).get("actions", 0)
if isinstance(prompt_overages, dict):
overage_fc += _explicit_prompt_overage_fc(prompt_overages)
else:
overage_fc += _weighted_extra_charge(
{"total_fc": prompt_fc}, prompt_overages, prompt_count
)
if isinstance(action_overages, dict):
overage_fc += _explicit_action_overage_fc(action_overages)
else:
overage_fc += _weighted_extra_charge(
{"total_fc": action_fc}, action_overages, action_count
)
total_fc = prompt_fc + action_fc + overage_fc
breakdown = {
"prompt_fc": round(prompt_fc, 2),
"action_fc": round(action_fc, 2),
"token_overage_fc": round(overage_fc, 2),
"total_fc": round(total_fc, 2),
"cost": round(total_fc * FC_COST, 4),
}
return round(total_fc, 2), breakdown
def calculate_dc_base_cost(dc_ops: DataCloudOperations) -> Tuple[float, Dict[str, Dict[str, float]]]:
if not dc_ops:
return 0.0, {}
dc_ops = dc_ops.normalized()
breakdown: Dict[str, Dict[str, float]] = {}
total_fc = 0.0
for meter, volume in dc_ops.operations.items():
if meter not in DC_RATES:
continue
fc = float(volume) * DC_RATES[meter]
breakdown[meter] = {
"volume": round(float(volume), 4),
"rate": DC_RATES[meter],
"fc": round(fc, 2),
}
total_fc += fc
return round(total_fc, 2), breakdown
def apply_tiered_multiplier(base_fc: float) -> Tuple[float, float, List[Dict[str, float]]]:
if base_fc <= 0:
return 0.0, 0.0, []
remaining = float(base_fc)
tiered_fc = 0.0
tier_breakdown: List[Dict[str, float]] = []
for start, end, multiplier, name in TIER_THRESHOLDS:
if remaining <= 0:
break
tier_capacity = end - start
fc_in_tier = min(remaining, tier_capacity)
tier_value = fc_in_tier * multiplier
tiered_fc += tier_value
tier_breakdown.append(
{
"tier": name,
"range_start": start,
"range_end": end,
"multiplier": multiplier,
"base_fc": round(fc_in_tier, 2),
"tiered_fc": round(tier_value, 2),
}
)
remaining -= fc_in_tier
discount_percent = ((base_fc - tiered_fc) / base_fc * 100) if base_fc > 0 else 0.0
return round(tiered_fc, 2), round(discount_percent, 2), tier_breakdown
def calculate_scenario_cost(
agent: AgentStructure,
dc_ops: Optional[DataCloudOperations],
scenario: ScenarioVolumes,
) -> CostBreakdown:
per_invocation_fc, af_breakdown = calculate_per_invocation_cost(agent)
af_total_fc = per_invocation_fc * scenario.agent_invocations
dc_base_fc = 0.0
dc_tiered_fc = 0.0
dc_discount_percent = 0.0
dc_private_connect_fc = 0.0
if dc_ops and dc_ops.operations:
effective_dc_ops = dc_ops
if scenario.dc_operations is not None:
effective_dc_ops = DataCloudOperations(
operations=scenario.dc_operations,
private_connect=dc_ops.private_connect,
).normalized()
dc_base_fc, _ = calculate_dc_base_cost(effective_dc_ops)
dc_tiered_fc, dc_discount_percent, _ = apply_tiered_multiplier(dc_base_fc)
if effective_dc_ops.private_connect:
dc_private_connect_fc = round(dc_tiered_fc * PRIVATE_CONNECT_MULTIPLIER, 2)
dc_total_fc = round(dc_tiered_fc + dc_private_connect_fc, 2)
total_monthly_fc = round(af_total_fc + dc_total_fc, 2)
total_monthly_cost = round(total_monthly_fc * FC_COST, 2)
total_annual_cost = round(total_monthly_cost * 12, 2)
return CostBreakdown(
scenario_name=scenario.name,
agent_invocations=scenario.agent_invocations,
af_prompt_fc=round(af_breakdown["prompt_fc"] * scenario.agent_invocations, 2),
af_action_fc=round(af_breakdown["action_fc"] * scenario.agent_invocations, 2),
af_token_overage_fc=round(af_breakdown["token_overage_fc"] * scenario.agent_invocations, 2),
af_total_fc=round(af_total_fc, 2),
dc_base_fc=round(dc_base_fc, 2),
dc_tiered_fc=round(dc_tiered_fc, 2),
dc_discount_percent=round(dc_discount_percent, 2),
dc_private_connect_fc=round(dc_private_connect_fc, 2),
dc_total_fc=round(dc_total_fc, 2),
total_monthly_fc=round(total_monthly_fc, 2),
total_monthly_cost=round(total_monthly_cost, 2),
total_annual_cost=round(total_annual_cost, 2),
)
def generate_standard_scenarios(
agent: AgentStructure,
dc_ops: Optional[DataCloudOperations] = None,
scale_dc_volumes: bool = True,
) -> List[CostBreakdown]:
scenarios = [
ScenarioVolumes("Low (1K/month)", 1_000),
ScenarioVolumes("Medium (10K/month)", 10_000),
ScenarioVolumes("High (100K/month)", 100_000),
ScenarioVolumes("Enterprise (500K/month)", 500_000),
]
if dc_ops and dc_ops.operations and scale_dc_volumes:
baseline_invocations = 1_000
for scenario in scenarios:
factor = scenario.agent_invocations / baseline_invocations
scenario.dc_operations = {
meter: round(volume * factor, 6)
for meter, volume in dc_ops.normalized().operations.items()
}
return [calculate_scenario_cost(agent, dc_ops, scenario) for scenario in scenarios]
def _resolve_agent_and_dc(
agent_path: Optional[str], dc_path: Optional[str]
) -> Tuple[AgentStructure, Optional[DataCloudOperations], Dict[str, Any], Dict[str, Any]]:
agent_doc = load_json(agent_path) if agent_path else {}
dc_doc = load_json(dc_path) if dc_path else agent_doc
agent = extract_agent_structure(agent_doc)
dc_ops = extract_dc_operations(dc_doc)
if dc_ops is None:
dc_ops = extract_dc_operations(agent_doc)
return agent, dc_ops, agent_doc, dc_doc
def main() -> None:
parser = argparse.ArgumentParser(description="Calculate Flex Credit estimates")
parser.add_argument("--mode", required=True, choices=["structure", "scenarios", "tier-only"])
parser.add_argument("--agent-def", help="Path to an agent or combined estimate JSON document")
parser.add_argument("--dc-ops", help="Path to a Data Cloud or combined estimate JSON document")
parser.add_argument("--base-fc", type=float, help="Base Data Cloud FC for tier-only mode")
parser.add_argument("--output", help="Optional output JSON path")
args = parser.parse_args()
if args.mode == "tier-only":
if args.base_fc is None:
raise SystemExit("--base-fc is required for tier-only mode")
tiered_fc, discount_percent, tier_breakdown = apply_tiered_multiplier(args.base_fc)
result: Dict[str, Any] = {
"base_fc": round(args.base_fc, 2),
"tiered_fc": tiered_fc,
"discount_percent": discount_percent,
"tier_breakdown": tier_breakdown,
}
else:
if not args.agent_def:
raise SystemExit("--agent-def is required for structure and scenarios mode")
agent, dc_ops, _, _ = _resolve_agent_and_dc(args.agent_def, args.dc_ops)
if args.mode == "structure":
per_invocation_fc, breakdown = calculate_per_invocation_cost(agent)
result = {
"per_invocation_fc": per_invocation_fc,
"per_invocation_cost": round(per_invocation_fc * FC_COST, 4),
"breakdown": breakdown,
}
else:
scenarios = generate_standard_scenarios(agent, dc_ops)
per_invocation_fc, breakdown = calculate_per_invocation_cost(agent)
result = {
"per_invocation_fc": per_invocation_fc,
"per_invocation_cost": round(per_invocation_fc * FC_COST, 4),
"breakdown": breakdown,
"scenarios": [asdict(s) for s in scenarios],
}
if args.output:
Path(args.output).write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8")
else:
print(json.dumps(result, indent=2))
if __name__ == "__main__":
main()
assets/calculators/tier_multiplier.py
#!/usr/bin/env python3
"""Standalone Data Cloud tier multiplier calculator."""
from __future__ import annotations
import argparse
import json
from pathlib import Path
from typing import Dict, List, Tuple
TIERS: List[Tuple[float, float, float, str]] = [
(0, 300_000, 1.0, "Tier 1"),
(300_000, 1_500_000, 0.8, "Tier 2"),
(1_500_000, 12_500_000, 0.4, "Tier 3"),
(12_500_000, float("inf"), 0.2, "Tier 4"),
]
def calculate_tiered_fc(base_fc: float, verbose: bool = False) -> Dict[str, object]:
if base_fc <= 0:
return {
"base_fc": round(base_fc, 2),
"tiered_fc": 0.0,
"discount_percent": 0.0,
"savings_fc": 0.0,
"savings_dollars": 0.0,
"tier_breakdown": [],
}
remaining = float(base_fc)
tiered_fc = 0.0
tier_breakdown = []
for start, end, multiplier, label in TIERS:
if remaining <= 0:
break
tier_capacity = end - start
fc_in_tier = min(remaining, tier_capacity)
fc_after_multiplier = fc_in_tier * multiplier
savings = fc_in_tier - fc_after_multiplier
tiered_fc += fc_after_multiplier
if verbose or fc_in_tier > 0:
discount_pct = round((1 - multiplier) * 100)
tier_breakdown.append(
{
"tier": label,
"range": f"{start:,.0f} - {end:,.0f} FC" if end != float('inf') else f"{start:,.0f}+ FC",
"multiplier": f"{multiplier:.1f}x",
"discount": f"{discount_pct}%",
"base_fc_in_tier": round(fc_in_tier, 2),
"tiered_fc_in_tier": round(fc_after_multiplier, 2),
"savings_in_tier": round(savings, 2),
}
)
remaining -= fc_in_tier
savings_fc = base_fc - tiered_fc
discount_percent = (savings_fc / base_fc * 100) if base_fc > 0 else 0.0
return {
"base_fc": round(base_fc, 2),
"tiered_fc": round(tiered_fc, 2),
"discount_percent": round(discount_percent, 2),
"savings_fc": round(savings_fc, 2),
"savings_dollars": round(savings_fc * 0.004, 2),
"tier_breakdown": tier_breakdown,
}
def main() -> None:
parser = argparse.ArgumentParser(description="Calculate cumulative Data Cloud tiering")
parser.add_argument("--base-fc", type=float, required=True, help="Base monthly Data Cloud FC before tiering")
parser.add_argument("--verbose", action="store_true", help="Include detailed tier breakdown")
parser.add_argument("--pretty", action="store_true", help="Pretty-print results")
parser.add_argument("--output", help="Optional JSON output path")
args = parser.parse_args()
result = calculate_tiered_fc(args.base_fc, verbose=args.verbose or args.pretty)
if args.output:
Path(args.output).write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8")
if args.pretty:
print("\n" + "=" * 60)
print("Data Cloud Tiered Multiplier Calculation")
print("=" * 60)
print(f"\nBase FC: {result['base_fc']:>15,.0f} FC")
print(f"Tiered FC: {result['tiered_fc']:>15,.0f} FC")
print(f"Savings: {result['savings_fc']:>15,.0f} FC (${result['savings_dollars']:,.2f})")
print(f"Discount: {result['discount_percent']:>15.2f}%")
if result["tier_breakdown"]:
print("\nTier Breakdown:")
print("-" * 60)
for tier in result["tier_breakdown"]:
if tier["base_fc_in_tier"] > 0:
print(f"\n{tier['tier']} ({tier['range']})")
print(f" Multiplier: {tier['multiplier']:>8} ({tier['discount']} discount)")
print(f" Base FC: {tier['base_fc_in_tier']:>15,.0f} FC")
print(f" After discount: {tier['tiered_fc_in_tier']:>15,.0f} FC")
print(f" Savings: {tier['savings_in_tier']:>15,.0f} FC")
print("\n" + "=" * 60 + "\n")
elif not args.output:
print(json.dumps(result, indent=2))
if __name__ == "__main__":
main()
assets/templates/basic-agent-template.json
{
"agent_structure": {
"prompts": {
"basic": 1,
"standard": 2,
"advanced": 0
},
"actions": {
"standard": 3,
"voice": 0,
"sandbox": 0
},
"token_overages": {
"prompts": 0,
"actions": 0
}
},
"assumptions": [
"Agentforce only",
"No Data Cloud usage",
"No token overages",
"Single-org rollout"
]
}
assets/templates/data-cloud-template.json
{
"data_cloud_operations": {
"operations": {
"data_360_prep": 500.0,
"data_360_streaming_pipeline": 50.0,
"data_360_queries": 100.0,
"data_360_segmentation": 50.0,
"data_360_activation": 100.0
},
"private_connect": false
},
"assumptions": [
"Data Cloud only",
"Baseline meter volumes are scaled across standard scenarios",
"No Private Connect"
]
}
assets/templates/hybrid-agent-template.json
{
"agent_structure": {
"prompts": {
"basic": 1,
"standard": 3,
"advanced": 0
},
"actions": {
"standard": 5,
"voice": 0,
"sandbox": 0
},
"token_overages": {
"prompts": 0,
"actions": 0
}
},
"data_cloud_operations": {
"operations": {
"data_360_prep": 10.0,
"data_360_streaming_pipeline": 2.0,
"data_360_queries": 5.0,
"data_360_segmentation": 1.0
},
"private_connect": false
},
"assumptions": [
"Data Cloud volumes represent a 1K-invocation baseline for scenario scaling",
"No token overages",
"No Private Connect",
"Single-org rollout"
]
}
CREDITS.md
# Credits and Sources
## Primary contributor
### [August Krys](https://github.com/not2technical)
This skill is credited primarily to August Krys.
Related repo:
- [not2technical/sf-skills](https://github.com/not2technical/sf-skills)
Primary contribution areas reflected in this skill:
- Flex Credit estimation workflow design
- Agentforce and Data Cloud cost-model framing
- scenario-based estimation structure
- pricing-oriented documentation and planning guidance
## Public sources used for this skill
- Salesforce Flex Credits public rate card
- Salesforce public Agentforce pricing guidance
- Salesforce public Data Cloud documentation and meter terminology
- General cloud cost-estimation best practices for scenario modeling and validation
## Repository adaptation
This skill was normalized for this repository by:
- converting the skill entry point to repository-style `SKILL.md` frontmatter
- aligning templates, calculator inputs, and validation expectations
- updating tiering and Data Cloud meter references to a consistent public model
- removing non-essential local authoring artifacts before adding the skill to the repository
## Scope of this skill
This skill is intended to provide:
- public list-price estimation
- scenario planning
- architecture tradeoff discussions
- cost optimization guidance
It is **not** a substitute for contract-specific pricing, legal approval, or commercial quoting.
hooks/scripts/validate_estimate.py
#!/usr/bin/env python3
"""Manual validation helper for Flex Credit estimate inputs and outputs."""
from __future__ import annotations
import argparse
import json
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple
VALID_PROMPT_TIERS = {"starter", "basic", "standard", "advanced"}
VALID_ACTION_TYPES = {"standard", "custom", "voice", "sandbox"}
METER_ALIASES = {
"batch_internal": "data_360_prep",
"batch_external": "data_360_prep",
"queries": "data_360_queries",
"segmentation": "data_360_segmentation",
"streaming": "data_360_streaming_pipeline",
"activation_batch": "data_360_activation",
"activation_streaming": "data_360_activation",
"profile_unification": "data_360_unification",
"unstructured": "data_360_unstructured_processing",
"intelligent_processing": "data_360_intelligent_processing",
"real_time_pipeline": "data_360_real_time_pipeline",
"code_extension": "data_360_code_extension",
}
DC_REASONABLE_RANGES: Dict[str, Tuple[float, float]] = {
"data_360_prep": (0.1, 50_000),
"data_360_unification": (0.01, 1_000),
"data_360_segmentation": (0.1, 10_000),
"data_360_activation": (0.1, 10_000),
"data_360_zero_copy_sharing": (0.1, 10_000),
"data_360_queries": (0.001, 100_000),
"data_360_unstructured_processing": (1, 100_000),
"data_360_intelligent_processing": (1, 100_000),
"data_360_streaming_pipeline": (0.01, 1_000),
"data_360_real_time_pipeline": (0.001, 1_000),
"data_360_code_extension": (0.1, 100_000),
}
REASONABLE_PROMPTS = (0, 20)
REASONABLE_ACTIONS = (0, 50)
REASONABLE_INVOCATIONS = (100, 10_000_000)
TYPICAL_PER_INVOCATION_RANGE = (4, 500)
@dataclass
class ValidationResult:
passed: bool
score: int
max_score: int
errors: List[str]
warnings: List[str]
recommendations: List[str]
def normalize_meter(meter: str) -> str:
key = meter.strip().lower()
return METER_ALIASES.get(key, key)
def extract_agent_structure(data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
if "agent_structure" in data and isinstance(data["agent_structure"], dict):
return data["agent_structure"]
if "prompts" in data or "actions" in data:
return data
return None
def extract_dc_operations(data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
if "data_cloud_operations" in data and isinstance(data["data_cloud_operations"], dict):
return data["data_cloud_operations"]
if "operations" in data:
return data
return None
def validate_agent_structure(agent_data: Optional[Dict[str, Any]]) -> Tuple[List[str], List[str]]:
errors: List[str] = []
warnings: List[str] = []
if not agent_data:
return errors, warnings
prompts = agent_data.get("prompts", {})
actions = agent_data.get("actions", {})
total_prompts = sum(int(v) for v in prompts.values())
total_actions = sum(int(v) for v in actions.values())
if total_prompts < REASONABLE_PROMPTS[0]:
warnings.append("Prompt count is below the normal range.")
if total_prompts > REASONABLE_PROMPTS[1]:
warnings.append(f"Many prompts configured ({total_prompts}). Consider consolidation.")
if total_actions > REASONABLE_ACTIONS[1]:
warnings.append(f"Many actions configured ({total_actions}). Consider consolidation or batching.")
for tier in prompts:
if tier.lower() not in VALID_PROMPT_TIERS:
errors.append(f"Unknown prompt tier: {tier}")
for action_type in actions:
if action_type.lower() not in VALID_ACTION_TYPES:
errors.append(f"Unknown action type: {action_type}")
token_overages = agent_data.get("token_overages", {}) or {}
prompt_overages = token_overages.get("prompts", 0)
if isinstance(prompt_overages, (int, float)) and total_prompts > 0:
overage_percent = float(prompt_overages) / total_prompts
if overage_percent > 0.30:
warnings.append(f"High prompt overage rate ({overage_percent:.1%}).")
return errors, warnings
def validate_dc_operations(dc_data: Optional[Dict[str, Any]]) -> Tuple[List[str], List[str]]:
errors: List[str] = []
warnings: List[str] = []
if not dc_data:
return errors, warnings
operations = dc_data.get("operations", {})
if not operations:
warnings.append("Data Cloud operations document is present but contains no operations.")
return errors, warnings
normalized_ops: Dict[str, float] = {}
for meter, volume in operations.items():
canonical = normalize_meter(meter)
normalized_ops[canonical] = normalized_ops.get(canonical, 0.0) + float(volume)
for meter, volume in normalized_ops.items():
if meter not in DC_REASONABLE_RANGES:
warnings.append(f"Unknown Data Cloud meter: {meter}")
continue
min_volume, max_volume = DC_REASONABLE_RANGES[meter]
if volume < min_volume:
warnings.append(f"{meter}: very low volume ({volume}).")
elif volume > max_volume:
warnings.append(f"{meter}: very high volume ({volume}). Please confirm.")
if normalized_ops.get("data_360_streaming_pipeline", 0) > 0:
warnings.append("Streaming usage detected. Confirm that real-time latency is actually required.")
if normalized_ops.get("data_360_unification", 0) > 10:
warnings.append("Unification volume is high. Recheck cadence and identity-resolution scope.")
return errors, warnings
def validate_scenarios(scenarios: Optional[List[Dict[str, Any]]]) -> Tuple[List[str], List[str]]:
errors: List[str] = []
warnings: List[str] = []
if not scenarios:
warnings.append("No scenarios found in estimate.")
return errors, warnings
for scenario in scenarios:
name = scenario.get("scenario_name", "Unknown")
for required in ["agent_invocations", "total_monthly_fc", "total_monthly_cost"]:
if required not in scenario:
errors.append(f"{name}: scenario missing required field {required}")
invocations = int(scenario.get("agent_invocations", 0) or 0)
if invocations < REASONABLE_INVOCATIONS[0]:
warnings.append(f"{name}: very low invocation count ({invocations}).")
elif invocations > REASONABLE_INVOCATIONS[1]:
warnings.append(f"{name}: very high invocation count ({invocations:,}).")
af_total = float(scenario.get("af_total_fc", 0) or 0)
if invocations > 0 and af_total > 0:
per_invocation = af_total / invocations
if per_invocation < TYPICAL_PER_INVOCATION_RANGE[0]:
warnings.append(f"{name}: low per-invocation cost ({per_invocation:.1f} FC).")
elif per_invocation > TYPICAL_PER_INVOCATION_RANGE[1]:
warnings.append(f"{name}: high per-invocation cost ({per_invocation:.1f} FC).")
dc_base = float(scenario.get("dc_base_fc", 0) or 0)
dc_tiered = float(scenario.get("dc_tiered_fc", 0) or 0)
if dc_base > 300_000 and dc_tiered >= dc_base:
errors.append(f"{name}: Data Cloud tiering does not appear to have been applied.")
pc = float(scenario.get("dc_private_connect_fc", 0) or 0)
if pc > 0 and dc_tiered > 0:
expected_pc = round(dc_tiered * 0.20, 2)
if abs(pc - expected_pc) / expected_pc > 0.01:
errors.append(f"{name}: Private Connect appears inconsistent with tiered Data Cloud FC.")
return errors, warnings
def calculate_score(errors: List[str], warnings: List[str]) -> int:
score = 130
score -= len(errors) * 10
score -= len(warnings) * 2
return max(0, score)
def validate_estimate(data: Dict[str, Any]) -> ValidationResult:
errors: List[str] = []
warnings: List[str] = []
recommendations: List[str] = []
agent_data = extract_agent_structure(data)
dc_data = extract_dc_operations(data)
scenarios = data.get("scenarios")
if not agent_data and not dc_data:
errors.append("Estimate must contain agent_structure, data_cloud_operations, or both.")
agent_errors, agent_warnings = validate_agent_structure(agent_data)
dc_errors, dc_warnings = validate_dc_operations(dc_data)
scenario_errors, scenario_warnings = validate_scenarios(scenarios)
errors.extend(agent_errors + dc_errors + scenario_errors)
warnings.extend(agent_warnings + dc_warnings + scenario_warnings)
if dc_data and dc_data.get("private_connect"):
recommendations.append("Double-check that Private Connect is truly required, since it adds 20% to tiered Data Cloud FC.")
if dc_data and normalize_meter("streaming") in {normalize_meter(m) for m in dc_data.get("operations", {})}:
recommendations.append("Compare a lower-streaming alternative if latency requirements allow it.")
if agent_data:
prompts = sum(int(v) for v in agent_data.get("prompts", {}).values())
actions = sum(int(v) for v in agent_data.get("actions", {}).values())
if actions > prompts and actions >= 5:
recommendations.append("Action count may be the dominant cost driver. Look for consolidation opportunities.")
score = calculate_score(errors, warnings)
passed = len(errors) == 0 and score >= 78
return ValidationResult(
passed=passed,
score=score,
max_score=130,
errors=errors,
warnings=warnings,
recommendations=recommendations,
)
def main() -> None:
parser = argparse.ArgumentParser(description="Validate a Flex Credit estimate JSON document")
parser.add_argument("--input", required=True, help="Path to estimate JSON")
parser.add_argument("--verbose", action="store_true", help="Pretty-print output")
args = parser.parse_args()
try:
data = json.loads(Path(args.input).read_text(encoding="utf-8"))
except Exception as exc: # pragma: no cover - CLI path
print(f"Error loading estimate: {exc}", file=sys.stderr)
raise SystemExit(1)
result = validate_estimate(data)
if args.verbose:
print("\n" + "=" * 60)
print("Flex Credit Estimate Validation")
print("=" * 60)
print(f"\nStatus: {'✅ PASSED' if result.passed else '❌ FAILED'}")
print(f"Score: {result.score}/{result.max_score} ({result.score / result.max_score * 100:.1f}%)")
if result.errors:
print(f"\n❌ Errors ({len(result.errors)}):")
for error in result.errors:
print(f" - {error}")
if result.warnings:
print(f"\n⚠️ Warnings ({len(result.warnings)}):")
for warning in result.warnings:
print(f" - {warning}")
if result.recommendations:
print("\n💡 Recommendations:")
for recommendation in result.recommendations:
print(f" - {recommendation}")
print("\n" + "=" * 60 + "\n")
else:
print(
json.dumps(
{
"passed": result.passed,
"score": result.score,
"max_score": result.max_score,
"errors": result.errors,
"warnings": result.warnings,
"recommendations": result.recommendations,
},
indent=2,
)
)
raise SystemExit(0 if result.passed else 1)
if __name__ == "__main__":
main()
LICENSE
MIT License
Copyright (c) 2024-2025 Jag Valaiyapathy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
README.md
# sf-flex-estimator
Flex Credit estimation for **Agentforce** and **Data Cloud** workloads in sf-skills.
This skill helps you estimate:
- Agentforce per-invocation Flex Credits from prompt and action structure
- Data Cloud monthly Flex Credits from usage meters
- cumulative Data Cloud tier discounts
- Private Connect uplift
- low / medium / high / enterprise scenarios
## What this skill is for
Use `sf-flex-estimator` when you need **planning guidance before implementation**:
- pricing a new agent design
- sizing a pilot vs production rollout
- comparing architecture options
- identifying the main cost drivers in a proposed design
## What this skill is not for
- It does **not** create Agentforce metadata or `.agent` files.
- It does **not** provision or mutate Data Cloud assets.
- It does **not** replace contract-specific pricing from Salesforce commercial teams.
## Quick start
### Basic agent estimate
```bash
python3 assets/calculators/flex_calculator.py \
--mode structure \
--agent-def assets/templates/basic-agent-template.json
```
### Agentforce + Data Cloud scenario estimate
```bash
python3 assets/calculators/flex_calculator.py \
--mode scenarios \
--agent-def assets/templates/hybrid-agent-template.json
```
### Data Cloud tiering only
```bash
python3 assets/calculators/tier_multiplier.py \
--base-fc 5000000 \
--pretty
```
### Validate an estimate input
```bash
python3 hooks/scripts/validate_estimate.py \
--input assets/templates/hybrid-agent-template.json \
--verbose
```
## Included templates
| Template | Best for |
|---|---|
| `assets/templates/basic-agent-template.json` | Agentforce-only estimates |
| `assets/templates/hybrid-agent-template.json` | Agentforce + Data Cloud grounding |
| `assets/templates/data-cloud-template.json` | Data Cloud-only workloads |
## Included references
| Path | Purpose |
|---|---|
| `SKILL.md` | main skill instructions and handoff rules |
| `references/agentforce-pricing.md` | Agentforce prompt/action pricing |
| `references/data-cloud-pricing.md` | Data Cloud meter pricing and tiering |
| `references/calculation-methodology.md` | formulas, assumptions, and scenario logic |
| `references/common-use-cases.md` | sample estimation patterns |
| `references/edge-cases.md` | token overages, Private Connect, multi-org notes |
| `references/scoring-rubric.md` | 130-point validation rubric |
## Key pricing assumptions in this skill
- Agentforce uses **linear** pricing in this model.
- Data Cloud uses **monthly cumulative tiering**:
- Tier 1: `0 - 300K` at `1.0x`
- Tier 2: `300K - 1.5M` at `0.8x`
- Tier 3: `1.5M - 12.5M` at `0.4x`
- Tier 4: `12.5M+` at `0.2x`
- Flex Credits are modeled at **$0.004 per FC**.
- Private Connect adds **20% of Data Cloud spend after tiering**.
- Estimates use **public list-price guidance** only.
## Notes on validation
`hooks/scripts/validate_estimate.py` is a **manual validation helper**. It is not connected to the shared repo-wide auto-validation dispatcher because generic estimate files do not map cleanly to a single file extension or path convention.
## Credit
Primary contributor: [August Krys](https://github.com/not2technical)
Related repo:
- [not2technical/sf-skills](https://github.com/not2technical/sf-skills)
## License
MIT — see [LICENSE](LICENSE)
references/agentforce-pricing.md
# Agentforce Flex Credit Pricing Reference
## Overview
Agentforce pricing is based on per-invocation charges for prompts and actions. Unlike Data Cloud, Agentforce does **not** use tiered multipliers - pricing is linear.
**Key Concepts:**
- **Per-Invocation Billing**: Each agent execution incurs prompt + action charges
- **Prompt Tiers**: Four tiers based on model capability (2-16 FC)
- **Action Types**: Three types with different rates (16-30 FC)
- **Token Overages**: Additional charges when exceeding token limits
- **No Volume Discounts**: Linear pricing regardless of volume
---
## Prompt/Topic Pricing
### Prompt Tier Table
| Tier | FC per Call | Cost | Model Examples | Use Case |
|------|-------------|------|----------------|----------|
| **Starter (BYOLLM)** | 2 FC | $0.008 | Bring Your Own LLM | Custom model integration |
| **Basic** | 2 FC | $0.008 | Gemini Flash, GPT-4o mini | Simple classification, routing |
| **Standard** | 4 FC | $0.016 | GPT-4o, Claude Sonnet 4 | General-purpose agents |
| **Advanced** | 16 FC | $0.064 | Future deep research models | Complex reasoning, research |
### How to Choose a Tier
**Use Basic (2 FC) when:**
- Simple intent classification
- Yes/no questions
- Basic routing logic
- FAQ responses
- Low-complexity reasoning
**Use Standard (4 FC) when:**
- Multi-step reasoning required
- Context-aware responses
- Integration with multiple data sources
- Moderate complexity workflows
- **Most production agents** (80% of use cases)
**Use Advanced (16 FC) when:**
- Deep research required
- Complex multi-step planning
- Advanced reasoning tasks
- Specialized domain expertise
- High-stakes decision making
**Cost Comparison:**
| Scenario | Basic (2 FC) | Standard (4 FC) | Advanced (16 FC) |
|----------|--------------|-----------------|------------------|
| 1,000 calls | $8 | $16 | $64 |
| 10,000 calls | $80 | $160 | $640 |
| 100,000 calls | $800 | $1,600 | $6,400 |
**Recommendation:** Start with Standard tier for production agents. Downgrade to Basic only for simple classification topics. Reserve Advanced for specialized deep-research topics.
---
## Action Pricing
### Action Type Table
| Action Type | FC per Invocation | Cost | Use Case |
|-------------|-------------------|------|----------|
| **Standard/Custom Action** | 20 FC | $0.08 | API calls, data operations, integrations |
| **Voice Action** | 30 FC | $0.12 | Voice-enabled agent actions |
| **Sandbox Action** | 16 FC | $0.064 | Testing/development actions |
### Action Details
**Standard/Custom Actions (20 FC):**
- Most common action type
- Includes:
- Apex action invocations
- Flow invocations
- External API calls (via Named Credentials)
- Data operations (SOQL queries, DML)
- Custom integrations
- Used in 95% of production agents
**Voice Actions (30 FC):**
- Voice-enabled action execution
- 50% premium over standard actions
- Includes:
- Speech-to-text processing
- Voice-optimized responses
- Telephony integrations
- Use when: Voice channel required, accessibility needs
**Sandbox Actions (16 FC):**
- Development/testing environment
- 20% discount vs standard actions
- Use when: Testing new actions, staging environments
- **Not for production use**
---
## Token Overage Pricing
### Token Limits
**Prompt Token Limit:** 2,000 tokens
- Average prompt: 500-1,000 tokens
- ~1,500 words or ~10KB of text
- Includes: System instructions + user input + context
**Action Token Limit:** 10,000 tokens
- Average action: 2,000-5,000 tokens
- ~7,500 words or ~50KB of text
- Includes: Action input + output + metadata
### Overage Charges
**When overage occurs:**
- Additional prompt charge: 1 × prompt tier rate
- Additional action charge: 1 × action rate
**Example: Standard Prompt Overage**
```
Normal prompt (1,500 tokens): 4 FC
Oversized prompt (2,500 tokens): 4 FC + 4 FC = 8 FC
Cost: $0.016 → $0.032 (2x)
```
**Example: Standard Action Overage**
```
Normal action (5,000 tokens): 20 FC
Oversized action (12,000 tokens): 20 FC + 20 FC = 40 FC
Cost: $0.08 → $0.16 (2x)
```
### Overage Frequency
**Typical overage rates:**
- Prompts: <1% in well-designed agents
- Actions: <1% in normal operations
**High overage risk scenarios:**
- Large document grounding (>5 pages)
- Complex multi-step reasoning
- Extensive context injection
- Large API response processing
**How to estimate:**
- Simple agents: 0% overage
- Moderate complexity: 5% prompt overage, 0% action overage
- Complex agents: 20% prompt overage, 1% action overage
### Avoiding Overages
**Prompt optimization:**
- Keep system instructions concise (<500 tokens)
- Limit context injection (<1,000 tokens)
- Use retrieval for large documents (don't embed full text)
- Paginate long responses
**Action optimization:**
- Limit API response sizes
- Use field filtering in SOQL (SELECT only needed fields)
- Paginate large result sets
- Compress action outputs
---
## Per-Invocation Cost Calculation
### Formula
```
per_invocation_fc = Σ(prompt_fc) + Σ(action_fc) + overage_fc
per_invocation_cost = per_invocation_fc × $0.004
```
### Example 1: Simple Customer Service Agent
**Structure:**
- 3 prompts (Basic tier): Classification, Response Generation, Escalation Check
- 2 actions (Standard): Fetch Case Data, Update Case
- No token overages
**Calculation:**
```
Prompts: 3 × 2 FC = 6 FC
Actions: 2 × 20 FC = 40 FC
Total: 46 FC per invocation = $0.184
Monthly costs:
- 1K invocations: 46K FC = $184
- 10K invocations: 460K FC = $1,840
- 100K invocations: 4.6M FC = $18,400
```
### Example 2: Complex Sales Agent
**Structure:**
- 5 prompts (Standard tier): Intent, Lead Qualification, Recommendation, Objection Handling, Summary
- 10 actions (Standard): CRM lookups, opportunity updates, email sends
- 20% prompt overage (complex reasoning)
**Calculation:**
```
Prompts: 5 × 4 FC = 20 FC
Actions: 10 × 20 FC = 200 FC
Overages: 20% × 1 prompt × 4 FC = 0.8 FC (per invocation average)
Total: 220.8 FC per invocation ≈ 221 FC = $0.884
Monthly costs:
- 1K invocations: 221K FC = $884
- 10K invocations: 2.21M FC = $8,840
- 100K invocations: 22.1M FC = $88,400
```
### Example 3: Voice-Enabled Agent
**Structure:**
- 4 prompts (Standard tier): Voice transcription processing, Intent, Response, Confirmation
- 6 actions (Voice): Phone system integration, CRM updates, scheduling
- No overages
**Calculation:**
```
Prompts: 4 × 4 FC = 16 FC
Actions: 6 × 30 FC = 180 FC
Total: 196 FC per invocation = $0.784
Monthly costs:
- 1K invocations: 196K FC = $784
- 10K invocations: 1.96M FC = $7,840
- 100K invocations: 19.6M FC = $78,400
```
---
## Optimization Strategies
### 1. Prompt Tier Optimization
**Before: All Standard Prompts**
```
Agent: 5 prompts (Standard)
Per-invocation: 5 × 4 FC = 20 FC
Cost per 100K: $8,000
```
**After: Mixed Tier Strategy**
```
Agent:
- 2 prompts (Basic): Classification, routing
- 3 prompts (Standard): Main reasoning
Per-invocation: (2 × 2) + (3 × 4) = 16 FC
Cost per 100K: $6,400
Savings: $1,600 (20%)
```
### 2. Action Consolidation
**Before: Many Small Actions**
```
Agent: 10 actions (each a separate API call)
Per-invocation: 10 × 20 FC = 200 FC
Cost per 100K: $80,000
```
**After: Batch Operations**
```
Agent: 4 actions (batch API calls, combined operations)
Per-invocation: 4 × 20 FC = 80 FC
Cost per 100K: $32,000
Savings: $48,000 (60%)
```
**Consolidation techniques:**
- Batch API calls where possible
- Combine related data fetches
- Use composite APIs (e.g., Salesforce Composite API)
- Cache frequently accessed data
### 3. Token Overage Prevention
**Before: 20% Prompt Overages**
```
Base: 5 × 4 FC = 20 FC
Overages: 20% × 5 × 4 FC = 4 FC
Total: 24 FC per invocation
Cost per 100K: $9,600
```
**After: Optimized Context**
```
Base: 5 × 4 FC = 20 FC
Overages: 0% (optimized)
Total: 20 FC per invocation
Cost per 100K: $8,000
Savings: $1,600 (16.7%)
```
### 4. Agent Structure Review
**High-cost patterns to avoid:**
- ❌ Using Advanced tier prompts unnecessarily
- ❌ Calling actions that return unused data
- ❌ Redundant prompts (duplicate reasoning steps)
- ❌ Overly complex system instructions
- ❌ Not batching related operations
**Cost-efficient patterns:**
- ✅ Use Basic tier for classification/routing
- ✅ Batch related API calls
- ✅ Keep system instructions concise
- ✅ Use retrieval instead of full-text embedding
- ✅ Cache frequently accessed data
---
## Agent Structure Templates
### Minimal Agent (Low Cost)
```
Prompts:
- 1 Basic: Intent classification (2 FC)
- 1 Standard: Response generation (4 FC)
Actions:
- 1 Standard: Data fetch (20 FC)
Total: 26 FC per invocation = $0.104
```
**Use case:** Simple FAQ bot, basic routing
### Standard Agent (Balanced)
```
Prompts:
- 1 Basic: Classification (2 FC)
- 3 Standard: Reasoning, response, validation (12 FC)
Actions:
- 5 Standard: Data operations, integrations (100 FC)
Total: 114 FC per invocation = $0.456
```
**Use case:** Customer service, sales agent, most production use cases
### Complex Agent (High Cost)
```
Prompts:
- 2 Basic: Classification, routing (4 FC)
- 5 Standard: Main reasoning (20 FC)
- 1 Advanced: Deep research (16 FC)
Actions:
- 10 Standard: Extensive integrations (200 FC)
Total: 240 FC per invocation = $0.96
```
**Use case:** Complex reasoning, multi-system integration, research agents
---
## Real-World Cost Examples
### Example 1: E-commerce Customer Service (10K invocations/month)
**Agent Structure:**
- 3 Standard prompts: Intent, Product Lookup, Response
- 4 Standard actions: Order lookup, inventory check, update CRM, send email
**Costs:**
```
Prompts: 3 × 4 = 12 FC
Actions: 4 × 20 = 80 FC
Total: 92 FC × 10,000 = 920K FC
Monthly: $3,680
Annual: $44,160
```
### Example 2: Financial Services Advisor (100K invocations/month)
**Agent Structure:**
- 5 Standard prompts: Classification, risk assessment, recommendation, compliance check, summary
- 8 Standard actions: Account lookups, transaction queries, portfolio analysis, reporting
- 10% prompt overage (complex calculations)
**Costs:**
```
Prompts: 5 × 4 = 20 FC
Actions: 8 × 20 = 160 FC
Overages: 0.5 × 4 = 2 FC (average per invocation)
Total: 182 FC × 100,000 = 18.2M FC
Monthly: $72,800
Annual: $873,600
```
### Example 3: Healthcare Appointment Scheduler (Voice, 5K invocations/month)
**Agent Structure:**
- 4 Standard prompts: Transcription processing, intent, scheduling, confirmation
- 6 Voice actions: Phone system, calendar lookups, booking, SMS notifications
**Costs:**
```
Prompts: 4 × 4 = 16 FC
Actions: 6 × 30 = 180 FC
Total: 196 FC × 5,000 = 980K FC
Monthly: $3,920
Annual: $47,040
```
---
## Calculation Checklist
When estimating Agentforce costs:
1. ✅ **Count prompts/topics** by tier (Basic/Standard/Advanced)
2. ✅ **Count actions** by type (Standard/Voice/Sandbox)
3. ✅ **Estimate token overages** (0-20% of prompts, 0-1% of actions)
4. ✅ **Calculate per-invocation FC** (sum of all components)
5. ✅ **Apply to usage scenarios** (1K, 10K, 100K, 500K invocations)
6. ✅ **Document agent structure** (for future re-estimation)
7. ✅ **Identify optimization opportunities** (tier changes, action consolidation)
---
## Common Mistakes
### ❌ Mistake 1: Applying Tiered Multipliers to Agentforce
```python
# WRONG: Agentforce does not use tiered multipliers
af_fc = per_invocation_fc × invocations × 0.8 # No discount!
# CORRECT: Linear pricing
af_fc = per_invocation_fc × invocations
```
### ❌ Mistake 2: Not Counting All Prompts
```python
# WRONG: Only counting "main" prompts
prompts = 2 # Missing classification, validation, etc.
# CORRECT: Count every prompt/topic in agent definition
prompts = 5 # All topics that execute per invocation
```
### ❌ Mistake 3: Overage on Total Instead of Per-Component
```python
# WRONG: Applying overage to total
total_fc = prompt_fc + action_fc
overage_fc = total_fc × 0.20
# CORRECT: Overage on prompts only (usually)
prompt_overage_fc = prompt_fc × 0.20
action_overage_fc = action_fc × 0.01 # Rare
```
---
## Python Calculation Tools
### Using flex_calculator.py
```bash
# Calculate per-invocation cost
python3 flex_calculator.py --mode structure --agent-def agent.json
# Generate full scenarios
python3 flex_calculator.py --mode scenarios \
--agent-def agent.json \
--output scenarios.json
```
### Agent Definition JSON Format
```json
{
"prompts": {
"basic": 2,
"standard": 3,
"advanced": 0
},
"actions": {
"standard": 5,
"voice": 0,
"sandbox": 0
},
"token_overages": {
"prompts": 0,
"actions": 0
}
}
```
---
## Version History
- **v1.0.0** (2026-03-10): Initial Agentforce pricing reference with per-invocation calculation
references/calculation-methodology.md
# Calculation Methodology
This document defines how `sf-flex-estimator` turns an Agentforce + Data Cloud design into a public list-price Flex Credit estimate.
## 1. Scope the workload
Start by separating the estimate into two buckets:
1. **Agentforce**
- prompt tiers
- action types
- token overages
2. **Data Cloud**
- monthly usage meters
- Private Connect requirement
These buckets are priced differently and should be modeled independently before combining the result.
---
## 2. Agentforce per-invocation formula
Agentforce is modeled per invocation.
```text
per-invocation FC = prompt FC + action FC + token overage FC
per-invocation cost = per-invocation FC × 0.004
```
### Prompt rates
| Tier | FC |
|---|---:|
| starter | 2 |
| basic | 2 |
| standard | 4 |
| advanced | 16 |
### Action rates
| Type | FC |
|---|---:|
| standard | 20 |
| custom | 20 |
| voice | 30 |
| sandbox | 16 |
### Example
```text
Prompts:
- 1 basic = 2 FC
- 3 standard = 12 FC
Actions:
- 5 standard = 100 FC
Per invocation = 114 FC
Per invocation cost = 114 × 0.004 = $0.456
```
---
## 3. Token overage handling
This skill models token overages as **additional prompt or action charges**.
### Preferred input
Use explicit counts when you know them:
```json
{
"token_overages": {
"prompts": 1,
"actions": 0
}
}
```
That means one extra prompt-sized charge is added per invocation.
### If exact distribution is unknown
The calculator uses a **weighted average prompt or action rate** based on the configured structure.
Example:
```text
Prompts:
- 1 basic (2 FC)
- 3 standard (4 FC)
Average prompt rate = 14 / 4 = 3.5 FC
If prompt overages = 1:
extra prompt FC = 3.5
```
This keeps the estimate usable when the user only knows that overages occur, not which exact prompt/action causes them.
---
## 4. Data Cloud base FC formula
Data Cloud is modeled from **monthly meter volumes**.
```text
base meter FC = monthly volume × public rate
base Data Cloud FC = sum(all meter FC)
```
### Current public meter set used by this skill
| Meter | FC per 1M units |
|---|---:|
| data_360_prep | 40 |
| data_360_unification | 75,000 |
| data_360_segmentation | 50 |
| data_360_activation | 60 |
| data_360_zero_copy_sharing | 60 |
| data_360_queries | 3 |
| data_360_streaming_pipeline | 3,500 |
| data_360_real_time_pipeline | 250,000 |
| data_360_code_extension | 40 |
### Meter units that are not per 1M rows
| Meter | Unit |
|---|---|
| data_360_unstructured_processing | MB |
| data_360_intelligent_processing | MB |
| data_360_code_extension | compute unit |
The calculator accepts both current names and a limited set of legacy aliases, but the recommendation is to use the current `data_360_*` names in new estimate inputs.
---
## 5. Data Cloud tiering
After the base monthly Data Cloud FC is calculated, apply cumulative monthly tiering.
| Tier | Range | Multiplier |
|---|---:|---:|
| 1 | 0 - 300K | 1.0x |
| 2 | 300K - 1.5M | 0.8x |
| 3 | 1.5M - 12.5M | 0.4x |
| 4 | 12.5M+ | 0.2x |
### Cumulative example: 5M FC base
```text
Tier 1: 300,000 × 1.0 = 300,000
Tier 2: 1,200,000 × 0.8 = 960,000
Tier 3: 3,500,000 × 0.4 = 1,400,000
Total tiered FC = 2,660,000
```
```text
Effective discount = (5,000,000 - 2,660,000) / 5,000,000 = 46.8%
```
---
## 6. Private Connect
If Private Connect is enabled, apply it **after** Data Cloud tiering.
```text
private connect FC = tiered Data Cloud FC × 0.20
```
Example:
```text
tiered Data Cloud FC = 2,660,000
Private Connect FC = 532,000
Data Cloud total = 3,192,000
```
---
## 7. Combined monthly total
```text
total monthly FC = Agentforce FC + tiered Data Cloud FC + Private Connect FC
total monthly cost = total monthly FC × 0.004
total annual cost = total monthly cost × 12
```
---
## 8. Standard scenario generation
The default scenario set in this skill is:
| Scenario | Invocations / month |
|---|---:|
| Low | 1,000 |
| Medium | 10,000 |
| High | 100,000 |
| Enterprise | 500,000 |
### Default scaling behavior
If Data Cloud operations are present, the calculator scales the monthly meter volumes in proportion to the scenario multiplier using **1K invocations as the baseline**.
Example baseline:
```json
{
"data_cloud_operations": {
"operations": {
"data_360_prep": 10.0,
"data_360_streaming_pipeline": 2.0,
"data_360_queries": 5.0,
"data_360_segmentation": 1.0
}
}
}
```
Then the generated scenarios use:
| Scenario | Scale factor |
|---|---:|
| Low | 1x |
| Medium | 10x |
| High | 100x |
| Enterprise | 500x |
This is useful when the user only has a baseline design and wants a rough scenario ladder.
---
## 9. Validation philosophy
The 130-point rubric is intended to check:
- completeness of the structure model
- correctness of the pricing model used
- realism of usage assumptions
- clarity of scenario output
- handling of edge cases like overages and Private Connect
Use the manual validator when you want a fast sanity check:
```bash
python3 hooks/scripts/validate_estimate.py --input assets/templates/hybrid-agent-template.json --verbose
```
---
## 10. What this skill does not model
This skill intentionally does **not** model:
- custom contract discounts
- promotional pricing
- regional commercial exceptions
- non-public enterprise agreement terms
- operational costs outside Flex Credits (implementation effort, support, monitoring, data quality work)
When the user needs commercial certainty, treat this skill as a **public baseline estimate**, not a substitute for actual pricing approval.
references/common-use-cases.md
# Common Use Cases
This file shows a few representative estimation patterns supported by `sf-flex-estimator`.
## 1. Basic Agentforce-only estimate
Template:
- `assets/templates/basic-agent-template.json`
Structure:
- 1 basic prompt
- 2 standard prompts
- 3 standard actions
- no Data Cloud
### Result
```text
Per invocation: 70 FC ($0.28)
```
### Typical scenarios
| Scenario | Monthly FC | Monthly cost | Annual cost |
|---|---:|---:|---:|
| Low (1K) | 70,000 | $280.00 | $3,360.00 |
| Medium (10K) | 700,000 | $2,800.00 | $33,600.00 |
| High (100K) | 7,000,000 | $28,000.00 | $336,000.00 |
Best fit:
- FAQ agents
- lightweight service triage
- pilot implementations without Data Cloud grounding
---
## 2. Hybrid Agentforce + Data Cloud estimate
Template:
- `assets/templates/hybrid-agent-template.json`
Structure:
- 1 basic prompt
- 3 standard prompts
- 5 standard actions
- Data Cloud baseline:
- `data_360_prep`: 10.0
- `data_360_streaming_pipeline`: 2.0
- `data_360_queries`: 5.0
- `data_360_segmentation`: 1.0
### Per invocation
```text
114 FC ($0.456)
```
### Standard generated scenarios
| Scenario | Total monthly FC | Monthly cost | Annual cost | Data Cloud discount |
|---|---:|---:|---:|---:|
| Low (1K) | 121,465 | $485.86 | $5,830.32 | 0.00% |
| Medium (10K) | 1,214,650 | $4,858.60 | $58,303.20 | 0.00% |
| High (100K) | 12,057,200 | $48,228.80 | $578,745.60 | 11.96% |
| Enterprise (500K) | 59,153,000 | $236,612.00 | $2,839,344.00 | 42.32% |
Best fit:
- service agents grounded with unified customer context
- order history or profile lookup use cases
- architecture tradeoff conversations where the user wants to compare action count versus Data Cloud scaling
---
## 3. Data Cloud-only estimate
Template:
- `assets/templates/data-cloud-template.json`
Baseline meters:
- `data_360_prep`: 500.0
- `data_360_streaming_pipeline`: 50.0
- `data_360_queries`: 100.0
- `data_360_segmentation`: 50.0
- `data_360_activation`: 100.0
### Standard generated scenarios
| Scenario | Base Data Cloud FC | Tiered FC | Monthly cost | Annual cost |
|---|---:|---:|---:|---:|
| Low (1K) | 203,800 | 203,800 | $815.20 | $9,782.40 |
| Medium (10K) | 2,038,000 | 1,475,200 | $5,900.80 | $70,809.60 |
| High (100K) | 20,380,000 | 7,236,000 | $28,944.00 | $347,328.00 |
| Enterprise (500K) | 101,900,000 | 23,540,000 | $94,160.00 | $1,129,920.00 |
Best fit:
- Data Cloud planning before an agent exists
- ingestion/segment/activation scenario modeling
- conversations focused on meter mix and tier savings
---
## Command patterns
```bash
# Agentforce only
python3 assets/calculators/flex_calculator.py --mode structure --agent-def assets/templates/basic-agent-template.json
# Hybrid scenario ladder
python3 assets/calculators/flex_calculator.py --mode scenarios --agent-def assets/templates/hybrid-agent-template.json
# Data Cloud tiering sanity check
python3 assets/calculators/tier_multiplier.py --base-fc 5000000 --pretty
```
references/data-cloud-pricing.md
# Data Cloud Flex Credit Pricing Reference
This reference captures the **public Data Cloud pricing model** used by `sf-flex-estimator`.
## Core concepts
- Data Cloud is modeled from **monthly usage meters**.
- The base monthly FC total is then reduced using **cumulative monthly tiering**.
- Private Connect is modeled as **20% of tiered Data Cloud FC**.
- This document reflects the **public list-price assumptions** used by the skill, not contract-specific pricing.
---
## Current meter table used by the skill
| Meter | FC per 1M units | Typical use |
|---|---:|---|
| `data_360_prep` | 40 | preparation and transformation |
| `data_360_unification` | 75,000 | identity resolution / unification |
| `data_360_segmentation` | 50 | segment creation and refresh |
| `data_360_activation` | 60 | outbound activation/export |
| `data_360_zero_copy_sharing` | 60 | sharing without copying |
| `data_360_queries` | 3 | query execution |
| `data_360_streaming_pipeline` | 3,500 | streaming/event ingestion |
| `data_360_real_time_pipeline` | 250,000 | high-cost real-time pipeline workloads |
| `data_360_code_extension` | 40 | code extension compute |
### Meter units that are not per 1M rows
| Meter | Unit |
|---|---|
| `data_360_unstructured_processing` | MB |
| `data_360_intelligent_processing` | MB |
| `data_360_code_extension` | compute unit |
---
## Legacy alias handling
The calculator accepts a compatibility layer for common legacy names, including:
- `batch_internal` → `data_360_prep`
- `queries` → `data_360_queries`
- `segmentation` → `data_360_segmentation`
- `streaming` → `data_360_streaming_pipeline`
- `profile_unification` → `data_360_unification`
- `activation_batch` / `activation_streaming` → `data_360_activation`
For new estimate inputs, prefer the current `data_360_*` meter names.
---
## Tier structure
Data Cloud tiering is applied **monthly** and **cumulatively**.
| Tier | Monthly FC range | Multiplier | Discount |
|---|---:|---:|---:|
| Tier 1 | `0 - 300,000` | `1.0x` | 0% |
| Tier 2 | `300,000 - 1,500,000` | `0.8x` | 20% |
| Tier 3 | `1,500,000 - 12,500,000` | `0.4x` | 60% |
| Tier 4 | `12,500,000+` | `0.2x` | 80% |
### Cumulative example: 5M base FC
```text
Tier 1: 300,000 × 1.0 = 300,000
Tier 2: 1,200,000 × 0.8 = 960,000
Tier 3: 3,500,000 × 0.4 = 1,400,000
Total tiered FC = 2,660,000
```
```text
Savings = 5,000,000 - 2,660,000 = 2,340,000 FC
Effective discount = 46.8%
```
---
## Private Connect
Private Connect is modeled as:
```text
Private Connect FC = tiered Data Cloud FC × 0.20
```
### Example
```text
Tiered Data Cloud FC: 2,660,000
Private Connect FC: 532,000
Data Cloud total FC: 3,192,000
```
Private Connect applies only to the Data Cloud portion of the estimate in this skill.
---
## Practical interpretation of the meters
### `data_360_prep`
Use for transformation-heavy preparation workloads and baseline ingestion prep.
### `data_360_streaming_pipeline`
Use for true streaming/event-style ingestion. This is often one of the largest cost drivers in mixed workloads.
### `data_360_queries`
Usually a relatively small meter unless the workload is heavily query-driven.
### `data_360_unification`
This is a high-cost meter and deserves explicit discussion whenever identity resolution volume is large.
### `data_360_activation`
Model outbound audience or data activation here.
---
## Optimization heuristics
### 1. Challenge streaming assumptions
Streaming can dominate monthly FC faster than prep/query/segment meters. If hourly or scheduled latency is acceptable, estimate a batch-oriented alternative and compare.
### 2. Separate high-cost meters from background meters
Call out `data_360_unification`, `data_360_streaming_pipeline`, and `data_360_real_time_pipeline` explicitly so the user sees what is really driving cost.
### 3. Show the impact of tiering at scale
The effective discount can change materially as Data Cloud FC crosses 300K, 1.5M, and 12.5M monthly thresholds.
### 4. Price Private Connect separately
Keep Private Connect visible as its own line item. It should not disappear into the base meter total.
---
## Example base calculation
```json
{
"data_cloud_operations": {
"operations": {
"data_360_prep": 10.0,
"data_360_streaming_pipeline": 2.0,
"data_360_queries": 5.0,
"data_360_segmentation": 1.0
},
"private_connect": false
}
}
```
```text
data_360_prep: 10 × 40 = 400 FC
data_360_streaming_pipeline: 2 × 3,500 = 7,000 FC
data_360_queries: 5 × 3 = 15 FC
data_360_segmentation: 1 × 50 = 50 FC
Base Data Cloud FC = 7,465 FC
```
Since 7,465 FC is below Tier 2, tiering does not change the result.
---
## Command reference
```bash
python3 assets/calculators/tier_multiplier.py --base-fc 5000000 --pretty
python3 assets/calculators/flex_calculator.py --mode scenarios --agent-def assets/templates/hybrid-agent-template.json
```
---
## Pricing caution
This skill intentionally stays within public list-price guidance. If a user needs exact commercial numbers for a live deal, call out that contract-specific terms may differ from the estimate produced here.
references/edge-cases.md
# Edge Cases
This document highlights the most common scenarios where a fast estimate can become misleading if assumptions are not called out explicitly.
## 1. Token overages
If prompts or actions exceed their normal token thresholds, add extra prompt/action charges per invocation.
### Guidance
- use explicit overage counts when known
- if the user only knows that overages happen, document that the estimate is using a weighted average overage charge
- high-context grounding, large payload actions, and document-heavy prompts deserve extra scrutiny
---
## 2. Private Connect
Private Connect is a separate uplift on top of tiered Data Cloud FC.
```text
Private Connect FC = tiered Data Cloud FC × 0.20
```
### Guidance
- show it as its own line item
- do not bury it inside the base Data Cloud number
- confirm whether it is actually required for the target deployment
---
## 3. Unification-heavy workloads
`data_360_unification` is one of the highest-cost meters in the public model.
### Guidance
- challenge the proposed cadence
- check whether the volume is full-refresh or incremental
- show unification separately from lower-cost prep/query/segment meters
---
## 4. Streaming overuse
`data_360_streaming_pipeline` can dominate monthly cost faster than prep/query/segment meters.
### Guidance
- estimate an alternative with lower streaming volume whenever the business process tolerates latency
- present both the real-time and batch-oriented option if the user is undecided
---
## 5. Multi-org architectures
This skill can still guide multi-org planning, but the estimate should be broken into buckets instead of pretending everything is one homogeneous workload.
Recommended split:
- home org Agentforce spend
- home org Data Cloud spend
- companion org Data Cloud spend
- Private Connect by org, if required
### Guidance
- keep each org or region as its own line item
- do not assume the same Data Cloud volumes across every org unless the user confirms that assumption
- note that this skill is still a public-price planning model, not a substitute for commercial review
---
## 6. Contract-specific pricing
This skill intentionally uses public list-price assumptions.
### Guidance
If the user asks for exact commercial numbers:
- provide the public baseline estimate
- explicitly say commercial terms may differ
- avoid claiming contract accuracy that the public model cannot guarantee
---
## 7. Unknown or legacy meter names
Older notes may use legacy names such as `batch_internal`, `streaming`, `queries`, or `profile_unification`.
### Guidance
- normalize them to current `data_360_*` meters when possible
- call out that the estimate is using the current public meter model
- avoid mixing current and legacy labels in the final report
references/scoring-rubric.md
# Scoring Rubric
## Overview
SF-Flex-Estimator uses a 130-point scoring system across 7 categories to evaluate estimate quality. This document provides detailed scoring criteria for each category.
---
## Scoring Categories
### 1. Use Case Analysis (25 points)
**Purpose:** Measure completeness of workload decomposition and component identification.
| Score | Criteria |
|-------|----------|
| **23-25 (Excellent)** | • All agent components identified (prompts, actions, DC ops)<br>• Prompt tiers correctly determined<br>• Action types properly categorized<br>• Data Cloud operations fully mapped<br>• Requirements gathering complete with no gaps |
| **18-22 (Good)** | • Most components identified<br>• Minor gaps in prompt tier determination<br>• Action types mostly correct<br>• DC operations partially mapped<br>• Requirements mostly complete |
| **13-17 (Fair)** | • Basic components identified<br>• Some uncertainty in prompt tiers<br>• Action types partially correct<br>• DC operations incomplete<br>• Requirements have significant gaps |
| **<13 (Poor)** | • Incomplete component identification<br>• Prompt tiers unknown or incorrect<br>• Action types not categorized<br>• DC operations missing or wrong<br>• Requirements gathering inadequate |
**Common Deductions:**
- Missing prompt count: -5 points
- Unknown prompt tiers: -3 points per tier
- Actions not categorized: -4 points
- DC operations not mapped: -5 points
- No edge case consideration: -3 points
---
### 2. Estimation Accuracy (25 points)
**Purpose:** Measure correctness of Flex Credit calculations.
| Score | Criteria |
|-------|----------|
| **23-25 (Excellent)** | • Per-invocation cost calculated correctly<br>• All rates applied accurately<br>• Token overages handled properly<br>• DC rates correct for all meters<br>• Math verified and correct |
| **18-22 (Good)** | • Per-invocation cost mostly correct<br>• Minor rate application errors<br>• Token overages estimated reasonably<br>• DC rates mostly correct<br>• Math has minor errors (<5%) |
| **13-17 (Fair)** | • Per-invocation cost has errors<br>• Some rates applied incorrectly<br>• Token overages not estimated<br>• DC rates partially incorrect<br>• Math errors (5-15%) |
| **<13 (Poor)** | • Per-invocation cost wrong<br>• Rates applied incorrectly<br>• Token overages ignored<br>• DC rates wrong<br>• Significant math errors (>15%) |
**Common Deductions:**
- Wrong prompt rate: -3 points per prompt
- Wrong action rate: -4 points per action
- Token overage not calculated: -3 points
- DC rate incorrect: -3 points per meter
- Calculation error >10%: -5 points
---
### 3. Data Cloud Tiering (20 points)
**Purpose:** Measure correctness of tiered multiplier application.
| Score | Criteria |
|-------|----------|
| **18-20 (Excellent)** | • Correct 4-tier cumulative calculation<br>• All tier boundaries identified<br>• Volume-based discounting accurate<br>• Private Connect calculated correctly<br>• Tier savings documented |
| **14-17 (Good)** | • Tiered multiplier applied (minor errors)<br>• Most tier boundaries correct<br>• Volume discounting mostly accurate<br>• Private Connect handled<br>• Tier savings estimated |
| **10-13 (Fair)** | • Tiered multiplier attempted but errors<br>• Some tier boundaries wrong<br>• Volume discounting partially correct<br>• Private Connect may be wrong<br>• Tier savings missing |
| **<10 (Poor)** | • No tiered multiplier applied<br>• Flat discount used instead<br>• Tier boundaries ignored<br>• Private Connect calculation wrong<br>• Tier savings not calculated |
**Common Deductions:**
- Flat discount instead of cumulative: -8 points
- Wrong tier boundary: -3 points each
- Private Connect on wrong base (AF+DC instead of DC only): -5 points
- Private Connect not applied when required: -4 points
- Tier savings not documented: -2 points
**Critical Errors (immediate score <10):**
- Using flat multiplier across all volume (e.g., base_fc × 0.6 for entire amount)
- Applying Private Connect to Agentforce FC
- Not applying any tiering when DC FC > 300K
---
### 4. Cost Breakdown (20 points)
**Purpose:** Measure clarity and completeness of cost presentation.
| Score | Criteria |
|-------|----------|
| **18-20 (Excellent)** | • Clear categorization (AF, DC, PC)<br>• All scenarios generated (Low/Medium/High/Enterprise)<br>• Monthly and annual projections<br>• Per-component visibility<br>• Formatted for readability |
| **14-17 (Good)** | • Good categorization<br>• Most scenarios generated<br>• Monthly projections present<br>• Component breakdown mostly clear<br>• Reasonable formatting |
| **10-13 (Fair)** | • Basic categorization<br>• Limited scenarios<br>• Only monthly OR annual<br>• Component breakdown incomplete<br>• Poor formatting |
| **<10 (Poor)** | • No clear categorization<br>• Single scenario only<br>• Missing projections<br>• No component breakdown<br>• Unreadable format |
**Common Deductions:**
- Missing scenario: -3 points each (max 4 scenarios)
- No annual projection: -2 points
- No component breakdown: -4 points
- Poor formatting: -2 points
- Missing cost summary: -3 points
---
### 5. Edge Case Handling (15 points)
**Purpose:** Measure handling of special scenarios and complexity.
| Score | Criteria |
|-------|----------|
| **14-15 (Excellent)** | • Token overages estimated and applied<br>• Private Connect handled correctly<br>• Multi-org scenarios addressed<br>• Sandbox vs production considered<br>• All edge cases documented |
| **11-13 (Good)** | • Token overages considered<br>• Private Connect mentioned<br>• Multi-org partially addressed<br>• Most edge cases handled |
| **8-10 (Fair)** | • Token overages mentioned<br>• Private Connect may be missed<br>• Multi-org not considered<br>• Some edge cases handled |
| **<8 (Poor)** | • Token overages ignored<br>• Private Connect not handled<br>• Multi-org not addressed<br>• Edge cases missing |
**Common Deductions:**
- Token overages not estimated: -3 points
- Private Connect not considered when >1M DC FC: -4 points
- Multi-org not addressed when applicable: -3 points
- Sandbox costs not differentiated: -2 points
- Voice actions not priced correctly: -3 points
**Edge Cases Checklist:**
- ✅ Token overages (prompts >2K, actions >10K)
- ✅ Private Connect (20% of DC, not AF)
- ✅ Multi-org deployments (Home + Companion)
- ✅ Sandbox vs production action rates
- ✅ Voice action premium (30 FC vs 20 FC)
- ✅ Mixed workloads (AF + DC)
---
### 6. Documentation Quality (15 points)
**Purpose:** Measure clarity of assumptions, methodology, and recommendations.
| Score | Criteria |
|-------|----------|
| **14-15 (Excellent)** | • Clear assumptions documented<br>• Methodology explained<br>• Actionable recommendations (3+)<br>• Optimization opportunities identified<br>• Well-structured and readable |
| **11-13 (Good)** | • Assumptions documented<br>• Methodology described<br>• Some recommendations (1-2)<br>• Optimization mentioned<br>• Readable structure |
| **8-10 (Fair)** | • Basic assumptions<br>• Methodology unclear<br>• Limited recommendations<br>• No optimization guidance<br>• Poor structure |
| **<8 (Poor)** | • No assumptions documented<br>• Methodology missing<br>• No recommendations<br>• No optimization guidance<br>• Disorganized |
**Common Deductions:**
- Assumptions not documented: -4 points
- Methodology not explained: -3 points
- No optimization recommendations: -4 points
- Poor structure/readability: -2 points
- Missing next steps: -2 points
**Documentation Checklist:**
- ✅ Assumptions clearly stated
- ✅ Calculation methodology explained
- ✅ At least 3 optimization recommendations
- ✅ Savings projections for recommendations
- ✅ Next steps provided
- ✅ Confidence level stated (High/Medium/Low)
---
### 7. Validation & Sanity Checks (10 points)
**Purpose:** Measure reasonableness and validation of estimates.
| Score | Criteria |
|-------|----------|
| **9-10 (Excellent)** | • All validation checks pass<br>• Realistic volume estimates<br>• Sanity checks documented<br>• Warnings flagged appropriately<br>• Confidence level assessed |
| **7-8 (Good)** | • Most validation passes<br>• Volumes reasonable<br>• Basic sanity checks<br>• Major warnings noted<br>• Confidence mentioned |
| **5-6 (Fair)** | • Some validation issues<br>• Volumes questionable<br>• Limited sanity checks<br>• Warnings may be missed<br>• Confidence unclear |
| **<5 (Poor)** | • Validation fails<br>• Unrealistic volumes<br>• No sanity checks<br>• Warnings ignored<br>• No confidence assessment |
**Common Deductions:**
- Unrealistic agent invocations (e.g., 50M/month for pilot): -2 points
- Unrealistic DC volumes (e.g., 1B rows streaming): -3 points
- Per-invocation cost out of range (4-500 FC): -2 points
- No validation performed: -5 points
- Confidence level not stated: -1 point
**Validation Checks:**
- ✅ Agent invocations: 100 - 10M/month
- ✅ Prompt count: 1-20 per agent
- ✅ Action count: 0-50 per agent
- ✅ Per-invocation: 4-500 FC
- ✅ DC volumes: Within reasonable ranges per meter
- ✅ Token overage: 0-30% of prompts
- ✅ Cost scaling: Linear for AF, tiered for DC
---
## Overall Scoring
### Score Calculation
```
Total Score = Use Case (25) + Accuracy (25) + DC Tiering (20) +
Cost Breakdown (20) + Edge Cases (15) +
Documentation (15) + Validation (10)
Max Score = 130 points
```
### Quality Thresholds
| Score Range | Grade | Description | Action |
|-------------|-------|-------------|--------|
| **117-130 (90%+)** | ✅ Excellent | High confidence, production ready | Proceed with confidence |
| **104-116 (80-89%)** | ⭐ Very Good | Production ready with minor review | Minor adjustments recommended |
| **91-103 (70-79%)** | ⚠️ Good | Review assumptions before proceeding | Review and validate |
| **78-90 (60-69%)** | ⚠️ Needs Work | Address gaps in analysis | Significant revision needed |
| **<78 (<60%)** | ❌ BLOCKED | Critical issues must be resolved | Must re-estimate |
### Common Score Ranges
**117-130 (Excellent):**
- All components identified and mapped correctly
- Tiered multipliers applied accurately
- All scenarios generated with proper breakdowns
- Edge cases handled comprehensively
- Clear documentation with actionable recommendations
- All validation checks pass
**104-116 (Very Good):**
- Most components correct, minor gaps
- Tiered multipliers mostly correct
- All scenarios present, minor formatting issues
- Most edge cases handled
- Good documentation, some recommendations
- Validation mostly passes
**91-103 (Good):**
- Core components identified, some uncertainties
- Tiered multipliers applied with some errors
- Limited scenarios or missing projections
- Some edge cases missed
- Basic documentation, limited recommendations
- Some validation warnings
**78-90 (Needs Work):**
- Missing components or incorrect mapping
- Tiered multipliers wrong or not applied
- Incomplete scenarios
- Edge cases largely ignored
- Poor documentation
- Multiple validation failures
**<78 (Blocked):**
- Critical calculation errors
- Flat discount instead of tiered
- No scenarios or breakdowns
- Edge cases completely missed
- No documentation
- Unrealistic estimates
---
## Scoring Examples
### Example 1: Excellent Score (125/130)
**Breakdown:**
- Use Case Analysis: 25/25 - All components identified, prompt tiers correct
- Estimation Accuracy: 24/25 - Per-invocation correct, minor rounding
- Data Cloud Tiering: 20/20 - Cumulative tiers applied perfectly
- Cost Breakdown: 19/20 - All scenarios, minor formatting improvement
- Edge Case Handling: 15/15 - Token overages, Private Connect, multi-org
- Documentation: 14/15 - Clear assumptions, 3 recommendations
- Validation: 8/10 - All checks pass, one minor warning
**Grade:** ✅ Excellent - Production ready
### Example 2: Good Score (95/130)
**Breakdown:**
- Use Case Analysis: 20/25 - Some prompt tier uncertainty
- Estimation Accuracy: 22/25 - Minor rate application errors
- Data Cloud Tiering: 14/20 - Tiered multiplier applied, boundary issues
- Cost Breakdown: 16/20 - Missing one scenario
- Edge Case Handling: 9/15 - Token overages missed, Private Connect handled
- Documentation: 10/15 - Basic assumptions, limited recommendations
- Validation: 4/10 - Some unrealistic volumes
**Grade:** ⚠️ Good - Review assumptions before proceeding
### Example 3: Blocked Score (65/130)
**Breakdown:**
- Use Case Analysis: 15/25 - Missing action types
- Estimation Accuracy: 10/25 - Wrong rates applied
- Data Cloud Tiering: 5/20 - Flat discount used instead of cumulative
- Cost Breakdown: 12/20 - Only one scenario
- Edge Case Handling: 6/15 - Most edge cases ignored
- Documentation: 7/15 - No assumptions, no recommendations
- Validation: 10/10 - Unrealistic volumes, no validation
**Grade:** ❌ BLOCKED - Must re-estimate
---
## Self-Assessment Checklist
Before finalizing an estimate, verify:
### Use Case Analysis (25 points)
- [ ] All prompts counted and tiers assigned
- [ ] All actions counted and types categorized
- [ ] Token overages estimated
- [ ] Data Cloud operations identified and mapped
- [ ] Special requirements noted (Private Connect, multi-org)
### Estimation Accuracy (25 points)
- [ ] Per-invocation cost calculated
- [ ] Correct rates applied to all components
- [ ] Token overages factored in
- [ ] DC rates correct for all meters
- [ ] Math verified
### Data Cloud Tiering (20 points)
- [ ] Cumulative 4-tier logic applied (not flat discount)
- [ ] Tier boundaries correct (300K, 1.5M, 12.5M)
- [ ] Private Connect calculated correctly (20% of DC tiered FC)
- [ ] Tier savings documented
### Cost Breakdown (20 points)
- [ ] 4 scenarios generated (Low/Medium/High/Enterprise)
- [ ] Monthly and annual projections
- [ ] AF, DC, PC broken out separately
- [ ] Clear formatting
### Edge Case Handling (15 points)
- [ ] Token overages estimated
- [ ] Private Connect considered if DC >1M FC
- [ ] Multi-org addressed if applicable
- [ ] Voice/sandbox rates correct
### Documentation (15 points)
- [ ] Assumptions documented
- [ ] Methodology explained
- [ ] 3+ optimization recommendations with savings
- [ ] Next steps provided
### Validation (10 points)
- [ ] Volumes realistic
- [ ] Per-invocation in range (4-500 FC)
- [ ] Sanity checks performed
- [ ] Confidence level stated
---
## Version History
- **v1.0.0** (2026-03-10): Initial scoring rubric with 130-point system