Cost Tracking & Retry Policies#
OpenIntent provides built-in cost tracking for budgeting multi-agent workflows and configurable retry policies for handling transient failures. Defined in RFC-0009 and RFC-0010.
Cost Tracking#
Recording Costs#
Every billable action — LLM calls, API requests, tool invocations — can be recorded against an intent:
# Record a cost event
client.record_cost(
intent_id=intent.id,
amount_cents=15,
currency="USD",
category="llm",
metadata={
"model": "gpt-4",
"input_tokens": 500,
"output_tokens": 200,
"provider": "openai"
}
)
Cost Categories#
| Category | Description |
|---|---|
llm |
Language model API calls |
tool |
External tool invocations |
compute |
Processing and compute time |
storage |
Data storage and retrieval |
api |
Third-party API calls |
custom |
User-defined categories |
Querying Costs#
# Get total costs for an intent
costs = client.get_costs(intent.id)
print(f"Total: ${costs.total_cents / 100:.2f}")
print(f"By category:")
for category, amount in costs.by_category.items():
print(f" {category}: ${amount / 100:.2f}")
Budget Enforcement#
Set budgets at the intent or portfolio level:
# Intent-level budget
intent = client.create_intent(
title="Research competitors",
constraints={"max_budget_cents": 1000} # $10 budget
)
# Portfolio-level budget
portfolio = client.create_portfolio(
name="Q1 Analysis",
governance={"budget_limit_cents": 50000} # $500 budget
)
Automatic LLM Cost Tracking#
LLM Adapters record costs automatically:
from openintent.adapters import OpenAIAdapter
adapter = OpenAIAdapter(openai_client, oi_client, intent.id)
# Costs are tracked automatically for every call
response = adapter.chat_complete(
model="gpt-4",
messages=[{"role": "user", "content": "Analyze this data"}]
)
# → Cost event recorded: model, tokens, provider
Cost Tracking in YAML Workflows#
workflow:
research:
title: "Research Phase"
assign: researcher
cost_tracking:
enabled: true
budget_usd: 5.00
alert_threshold_pct: 80
governance:
max_cost_usd: 50.00
Retry Policies#
Configuring Retries#
Retry policies define how the protocol handles transient failures:
# Set a retry policy for an intent
client.set_retry_policy(
intent_id=intent.id,
max_attempts=3,
backoff="exponential",
initial_delay_seconds=1,
max_delay_seconds=60
)
Backoff Strategies#
| Strategy | Behavior |
|---|---|
none |
No delay between retries |
fixed |
Same delay every time |
linear |
Delay increases linearly (1s, 2s, 3s, ...) |
exponential |
Delay doubles each attempt (1s, 2s, 4s, 8s, ...) |
Recording Failures#
When an agent encounters a transient error, record the failure so the protocol can schedule a retry:
from openintent.agents import Agent, on_assignment
from openintent.exceptions import TransientError
@Agent("resilient-worker")
class ResilientWorker:
@on_assignment
async def handle(self, intent):
try:
result = await call_external_api(intent.state)
return {"result": result}
except TransientError as e:
# Record the failure — protocol handles retry scheduling
await self.client.record_failure(
intent_id=intent.id,
attempt_number=intent.state.get("attempt", 1),
error_code="API_TIMEOUT",
error_message=str(e),
retry_scheduled_at=None # Let the policy decide
)
Querying Failure History#
# Get failure history
failures = client.get_failures(intent.id)
for f in failures:
print(f"Attempt {f.attempt_number}: {f.error_code} — {f.error_message}")
if f.retry_scheduled_at:
print(f" Retry at: {f.retry_scheduled_at}")
Retry Policies in YAML Workflows#
workflow:
fetch_data:
title: "Fetch External Data"
assign: data-fetcher
retry:
max_attempts: 5
backoff: exponential
initial_delay_seconds: 2
max_delay_seconds: 120
Idempotency
When using retry policies, ensure your agent handlers are idempotent — safe to call multiple times with the same input without side effects.
Next Steps#
- LLM Adapters — Automatic cost tracking for LLM calls
- Governance & Arbitration — Budget enforcement and escalation
- YAML Workflows — Declarative retry and cost configuration