Manual record

record() reports spend from a client the SDK does not patch, such as a self-hosted model, an internal gateway, or an unsupported provider.

capsera.record() puts an event on the same queue an intercepted call would use. It takes the same attribution from the surrounding scope and appears in the same reports.

capsera.record(
    input_tokens=1_240,
    output_tokens=310,
    model="llama-3.3-70b",
    provider="self-hosted",
)

When to use it

A provider the SDK does not patch. See Providers for what is covered.

A self-hosted or fine-tuned model behind your own serving stack, where there is no vendor client to patch.

An internal gateway using a private protocol. If your gateway is OpenAI-compatible, you do not need this. Point the OpenAI client at it and calls are recorded automatically. See OpenAI-compatible providers.

A call style that is not covered, such as an unsupported streaming shape. Check Troubleshooting first.

Parameters

input_tokens, output_tokens, model, and provider are required. All arguments are keyword-only.

ParameterNotes
input_tokens, output_tokensRequired. Use real counts where available.
model, providerRequired. model is looked up in the pricing catalog.
cost_usdOptional. Overrides the catalog.
agent_id, task_type, session_id, customer_id, cost_centerOptional. Omit to inherit from the enclosing scope.
cache_read_tokens, cache_write_tokensOptional, if your stack reports them.
latency_msOptional. Worth passing, since it cannot be inferred here.

Attribution is inherited

Called inside a decorated function or a tag() block, record() picks up that scope:

@capsera.agent("local-summarizer", team="research")
def summarize(text):
    result = my_local_model.generate(text)
    capsera.record(
        input_tokens=result.prompt_tokens,
        output_tokens=result.completion_tokens,
        model="llama-3.3-70b",
        provider="self-hosted",
        latency_ms=result.elapsed_ms,
    )
    return result.text

No agent_id is needed, because it comes from the decorator. Pass one only to override.

Costing a model that is not in the catalog

An unlisted model is priced with a generic fallback and logs a warning. For a self-hosted model that estimate is usually wrong, because your cost is GPU time rather than per-token vendor pricing. Two options:

Supply the cost directly:

capsera.record(..., cost_usd=gpu_seconds * COST_PER_GPU_SECOND)

Or record zero, which is accurate for a model with no marginal cost, and keeps token-volume reporting intact:

capsera.record(..., cost_usd=0.0)

Leaving the fallback estimate in place produces a dollar figure that will not reconcile against any invoice.

Limits

record() only records. It does not participate in routing or budget enforcement, because both act before a call and this runs after yours has completed. A blocking budget cannot stop a call the SDK never saw, so enforce it yourself if it matters:

if projected_cost > remaining_budget:
    raise RuntimeError("over budget")

Fields you do not pass are absent from the event rather than inferred.