record()

Signature and every parameter of capsera.record(), for logging spend from an LLM client the SDK does not patch.

record() writes a usage event for a call the SDK did not intercept: a proprietary wrapper, a raw HTTP request, or a provider with no patch yet.

See Manual record for when this is the right tool and what it cannot know.

record()

capsera.record(
    *,
    input_tokens: int,
    output_tokens: int,
    model: str,
    provider: str,
    cost_usd: float | None = None,
    agent_id: str | None = None,
    task_type: str | None = None,
    session_id: str | None = None,
    customer_id: str | None = None,
    cost_center: str | None = None,
    cache_read_tokens: int = 0,
    cache_write_tokens: int = 0,
    latency_ms: int = 0,
    gateway: str | None = None,
) -> None

Every argument is keyword-only. Returns None.

Required

ParameterNotes
input_tokensPrompt tokens consumed.
output_tokensCompletion tokens generated.
modelThe provider's own model identifier, such as claude-sonnet-4-6. Pricing lookup depends on it.
provider"anthropic", "openai", "google", and so on.

Cost

ParameterDefaultNotes
cost_usdNonePass the exact figure if you have it. Left unset, cost is computed from the built-in pricing catalogue in decimal arithmetic.

A model the catalogue does not recognise does not fail the call: lookup falls back to a generic estimate and logs a warning, so a typo in model becomes a plausible-looking but wrong cost rather than a crash. Watch the log the first time you record a new model. See Cost and pricing.

Attribution

ParameterNotes
agent_idOverrides the enclosing scope. Falls back to the scope, then init(agent_name=…), then "unknown".
task_typeOverrides the enclosing scope.
customer_idOverrides the enclosing scope.
cost_centerOverrides the enclosing scope.
session_idOverrides the scope, which overrides the ambient set_session() value.

There is deliberately no team_id or env parameter. team_id comes from the enclosing scope, env from init().

Optional metadata

ParameterDefaultNotes
cache_read_tokens0Prompt-cache reads, priced at the cache rate.
cache_write_tokens0Prompt-cache writes.
latency_ms0End-to-end latency.
gatewayNoneThe gateway the call rode through. Falls back to init(gateway=…). Added in 0.4.0.
capsera.record(
    input_tokens=1_200,
    output_tokens=340,
    model="claude-sonnet-4-6",
    provider="anthropic",
    agent_id="legacy_pipeline",
    latency_ms=880,
)

Before init()

record() called before init() logs a warning and drops the event. There is no queue to hold it and no configuration to attribute it with, so it cannot be buffered — call init() at startup, not lazily on first use.

What it does not do

record() is a write. It does not consult budgets, so a blocking budget cannot stop a call you record yourself, and it does not route, since the call has already happened. Enforcement only exists on the intercepted path.