No data appearing
Every reason a call is not recorded, including the streaming shapes and provider call styles that are known gaps.
Verify it works covers the first checks. This page is the complete list, including known gaps.
Start by confirming interception is happening:
capsera.init(api_key=..., debug=True)
print(capsera.get_interception_report())
If a call produces no capsera: intercepted line, the problem is capture. If it
produces one but nothing reaches the dashboard, the problem is delivery. See
Reliability.
Streaming shapes that are not recorded
Token counts only exist once a stream ends, so how you consume the response determines whether the call is recorded.
Anthropic: iterating without a context manager. This is a known gap, tracked as a failing test in the SDK.
# Not recorded. The proxy records on context exit, which never happens.
for event in client.messages.stream(model=..., messages=[...]):
...
# Recorded
with client.messages.stream(model=..., messages=[...]) as stream:
for chunk in stream.text_stream:
...
Use the context manager, which is also the form Anthropic's documentation uses.
OpenAI: a stream that is not finished. Usage arrives on the final chunk, so a stream abandoned early has no counts and is not recorded.
stream = client.chat.completions.create(..., stream=True)
for chunk in stream:
if done_early:
break # Not recorded. The usage chunk never arrived.
OpenAI: a context manager with no iteration. Entering the context without consuming chunks records nothing.
Cache tokens on streamed OpenAI calls are recorded as zero. The non-streaming path reports them correctly.
Provider call styles that are not covered
| Provider | Covered | Not covered |
|---|---|---|
| Anthropic | sync, async, streaming, errors | raw SSE form, Batches |
| OpenAI chat | sync, async, streaming, errors | responses.create, legacy Completions |
| OpenAI embeddings | sync, async, errors | none |
google-genai | sync generate_content, errors | async, streaming |
google-generativeai | sync and async, errors | streaming, embed_content |
| Mistral | sync chat.complete, errors | async, streaming, embeddings |
| Cohere | sync chat, errors | async, chat_stream, embed |
| Vertex AI | sync generate_content, errors | async, chat sessions |
| Bedrock | Converse, errors | InvokeModel, async |
For anything in the right-hand column, use
record().
Embeddings bypass routing and budgets
Embedding calls are recorded and costed, but they skip routing, pre-call budget enforcement, and prompt analysis. A blocking budget will not stop an embedding call and a routing rule will not redirect one.
This matters most for indexing jobs, where embeddings are often the dominant cost.
Attribution problems
If spend appears under unknown, the call was recorded and only attribution was
missing. See Agents.
If caller_file points into a library rather than your code, the call passed through a
wrapper that is not on the frame-skip list. Capture is still correct. Report the library
and it will be added.
Throttle budgets do not delay calls
A budget with the throttle action records the decision but does not delay the call.
block and margin downgrade both work as documented.
To slow calls rather than stop them, use a gateway rate limit or a semaphore in your own code.
If everything looks correct
Check the version and interpreter:
import capsera, sys
print(capsera.__version__, sys.executable)
A stale version or an unexpected interpreter explains many cases, such as a virtualenv that is not the one running your service, or a container image built before the dependency was added.
Then test delivery independently of interception:
capsera.record(input_tokens=1, output_tokens=1, model="gpt-4o-mini",
provider="openai", agent_id="wiring-check")
capsera.shutdown()
If wiring-check arrives, the account, key, and network are correct and the problem is
capture. If it does not, the problem is delivery, and on_error will report why.