Skip to main content
Bitfab records chat completions your code sends to OpenRouter through the official openai client: the prompt, the model OpenRouter routed to, token counts, latency, and the cost OpenRouter reports for that call. Canonical signatures: TypeScript wrapOpenRouter · Python wrap_openrouter

Language Support

Under a trace root

Beneath a trace root, every non-streaming chat.completions.create call on an openai client whose base URL is openrouter.ai is recorded with no wrapper, as its own llm span named Completions.create (Python’s async client: AsyncCompletions.create). The span attaches under the function that made the call.
The trace shows detect, then classify, then an llm span named Completions.create carrying the prompt and cost. In TypeScript, the build transform rewrites each .chat.completions.create(...) call site in your code, so it works in bundled apps and the SDK never loads or patches openai. The client’s own APIPromise is handed back, so .withResponse() keeps working. In Python, the SDK patches the openai completions classes when a trace() root is set up. exclude: ["create"] on the root skips these calls, and withNode() / node() on a wrapper (below) configures the one span.

Wrapping a call

Use wrapOpenRouter() / wrap_openrouter() when you trace with withSpan() / span() instead of a trace root, or when your client reaches OpenRouter through a proxy whose host is not openrouter.ai. It wraps the function that sends the request and writes the prompt, usage, and cost into the span that is current when the call starts. It opens no span of its own.
Beneath a trace root, a wrapper around a call that is already recorded as Completions.create records nothing more. onResponse / on_response receives each completion after it is recorded.

No duplicate spans

Each model call is recorded once:
  • A wrapper around a call the trace root already recorded adds nothing.
  • In TypeScript, calls made inside framework libraries (LangChain, the OpenAI Agents SDK) live in node_modules, which the build transform never rewrites, so only the framework’s own integration records them.
  • In Python, a call the OpenAI Agents SDK integration is recording as a generation or response span, or the LangChain callback handler is recording as an LLM run, is not recorded a second time.

What gets captured

The context fields go in one context entry on the span. A key the response does not carry is left out.

Limitations

  • Streaming calls are not recorded. A call with stream: true / stream=True runs normally and records nothing.
  • Calls outside any trace are not recorded. A wrapper used outside a span or trace records nothing and never starts a trace of its own.
  • TypeScript automatic capture needs the build transform. Code the transform does not compile (for example a call made from a dependency) is not rewritten; wrap it instead.
  • Python automatic capture needs Python 3.12+, the same as trace() subtree capture.
  • Only chat completions. The Responses API and structured-output parse helpers are not recorded.