The SDK needs no configuration, and each option changes one default.
The quickstart sets no option of the client. This page gives these options, the keys of the agents, the rules of the HTTP capture, the packages that send the model calls, and what the SDK does not see.
The client reads the key of its agent from the environment.
new Paidwen() in TypeScript and Paidwen() in Python read the key from the PAIDWEN_API_KEY environment variable. They throw PaidwenError when the variable is missing or empty. The apiKey option in TypeScript, or the first argument api_key in Python, takes the key from another source, such as a secret manager.
An agent on Kubernetes, AWS or GitHub Actions needs no key. The workload identity page shows how its platform proves its identity.
Each agent has its own key.
- A production agent gets a key that starts with
pw_live_, and a test agent a key that starts withpw_test_. - Two agents never share a key, so each action belongs to one agent.
- An agent keeps at most two active keys, so you can change its key without downtime.
The SDK applies your choice when Paidwen does not answer.
When Paidwen does not answer within 3 seconds, or answers with a server error, the SDK applies onUnavailable in TypeScript or on_unavailable in Python: "block" by default, or "allow". It writes a warning with the cause. The timeoutMs option in TypeScript, or timeout in seconds in Python, changes the delay.
const paidwen = new Paidwen({ onUnavailable: "allow", timeoutMs: 2000 });paidwen = Paidwen(on_unavailable="allow", timeout=2.0)When the organization has used all the events that its plan allows for the month, Paidwen answers 503 until the first day of the next month, in UTC, and the SDK applies the same choice. An error 4xx, such as a refused key, throws RequestError instead: it comes from the request, not from an outage.
The HTTP capture follows fixed rules.
paidwen.http() asks Paidwen before each outgoing HTTP call of the process, as the quickstart shows.
- The tool name is the method and the path, such as
POST /v1/refunds, andtool.serveris the host. An identifier in the path, such as an order number, enters the name. - The parameters carry
method,url,query, andbodywhen theContent-Typeheader says JSON or a form, and the body holds at most 64 KiB. - The SDK never sends the headers, and replaces the value of each sensitive key, such as
password,tokenorapi_key, withREDACTED. - The SDK asks nothing for its own calls, for the calls made inside an action already decided, and for the hosts that match
ignore.
In TypeScript, the capture covers fetch, http.request, http.get, https.request and https.get, the paths that Axios, got and the SDKs of the providers take. In Python, it covers httpx, requests, urllib3 and aiohttp.
Paidwen reads the model calls that follow the OpenTelemetry conventions.
The span processor of the SDK sends a span to the journal when its gen_ai.operation.name is chat, text_completion, generate_content or embeddings, the names of the OpenTelemetry conventions for generative AI. Paidwen reads the model in gen_ai.response.model, then in gen_ai.request.model, and the provider in gen_ai.provider.name.
Paidwen prices the call from gen_ai.usage.input_tokens, gen_ai.usage.output_tokens, gen_ai.usage.cache_read.input_tokens and gen_ai.usage.cache_creation.input_tokens. As the conventions ask, it counts the cached tokens inside the input tokens. The budgets page explains the price.
A process that already has a tracer provider adds the span processor of the SDK to it, and keeps one provider.
These packages send the model calls.
The packages below were tested on October 10, 2026, with the SDK 0.9.0. A test agent called each client against a local server, and the export of the SDK carried the attributes that Paidwen reads.
@traceloop/instrumentation-openai0.27.0, from OpenLLMetry, sends the chat completions and the Responses API ofopenai6.49.0 and 7.32.0, throughmanuallyInstrument(OpenAI), as the quickstart shows.opentelemetry-instrumentation-openai0.62.4, from OpenLLMetry, sends the chat completions, the Responses API and the embeddings ofopenai3.28.0, with the cached tokens.@traceloop/instrumentation-anthropic0.27.0 andopentelemetry-instrumentation-anthropic0.62.4, from OpenLLMetry, send the calls of@anthropic-ai/sdk0.133.0 andanthropic1.13.0, streamed or not.@ai-sdk/otel1.0.137 sends the calls of the Vercel AI SDK 7.0.137, for OpenAI and Anthropic, streamed or not, with the cached tokens.- The OpenAI Agents SDK, 0.20.0 in TypeScript and 0.23.1 in Python, calls the OpenAI SDK, so the OpenAI instrumentation sends its model calls.
The packages of OpenLLMetry and the Vercel AI SDK are open source under the Apache 2.0 license. These packages also send the messages of each call. The journal keeps them only while Record content is on, in the Settings tab of the agent.
For Anthropic, add these lines after the lines of the quickstart, and drop the OpenAI lines when the agent does not call OpenAI:
import * as AnthropicSDK from "@anthropic-ai/sdk";
import { AnthropicInstrumentation } from "@traceloop/instrumentation-anthropic";
const anthropic = new AnthropicInstrumentation();
registerInstrumentations({ instrumentations: [anthropic] });
anthropic.manuallyInstrument(AnthropicSDK);from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
AnthropicInstrumentor().instrument()For the Vercel AI SDK, install @opentelemetry/sdk-trace-node and @ai-sdk/otel, and write these lines instead of the lines of the quickstart:
import { OpenTelemetry } from "@ai-sdk/otel";
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import { registerTelemetry } from "ai";
new NodeTracerProvider({ spanProcessors: [paidwen.spanProcessor()] }).register();
registerTelemetry(new OpenTelemetry());The tested packages have five limits.
@traceloop/instrumentation-openaisends no cached tokens, so Paidwen prices them at the input price. In the test, a call of gpt-4.1-mini with 1,000 cached tokens out of 1,200 input tokens cost $0.000608 instead of $0.000308.- A streamed OpenAI call reaches the journal without tokens in TypeScript, so it counts nothing in the budget. In Python, it carries its tokens only when the call sets
stream_options={"include_usage": True}. @traceloop/instrumentation-openaidoes not send the embeddings.@traceloop/instrumentation-anthropicwrites the input tokens without the cached tokens, unlike the conventions. Paidwen then undercounts the input of a call that reads or writes the cache. In the test, a call of claude-sonnet-4-5 that read 1,000 cached tokens cost $0.0015 instead of $0.0021.- With the NodeNext module resolution of TypeScript, the types of
@traceloop/instrumentation-anthropicreject the module of@anthropic-ai/sdk, though the code runs. The castAnthropicSDK as neversatisfies the compiler.
Other packages fall short in the tested versions.
@opentelemetry/instrumentation-openai0.21.0, from the OpenTelemetry project, sends nothing withopenai7, because it supports the versions from 4.19 to 6. Withopenai6.49.0, it sends the calls without the cached tokens.opentelemetry-instrumentation-openai-v22.4b0, from the OpenTelemetry project, fails at import withopentelemetry-util-genai1.2b0, the version that pip installs with it. With version 0.4b0, it sends the chat completions without the cached tokens, and not the Responses API.- The OpenInference instrumentations, such as
@arizeai/openinference-instrumentation-openai4.4.1 andopeninference-instrumentation-openai0.1.65, write their own attributes, such asllm.token_count.prompt. Paidwen does not read them. - The Vercel AI SDK 6 writes its own attributes through
experimental_telemetry, such asai.operationId. Paidwen does not read them. - The OpenAI Agents SDK sends no span of its own. Without the OpenAI instrumentation, its model calls do not reach the journal.
- A model call that goes through no instrumented client, such as a direct HTTP request to the provider, does not reach the journal.
The journal can be turned off.
Each tool call that goes through the SDK reaches the journal as an OpenTelemetry span, with its decision. await paidwen.flush() in TypeScript, or paidwen.flush() in Python, sends the waiting spans without closing the client.
The option journal: false in TypeScript, or journal=False in Python, turns off every journal export of the SDK: the tool calls and the model calls. The decisions still reach the journal, since Paidwen records them when it answers.
The SDK sees only what passes through it.
- An action that is neither an HTTP call, nor an MCP call, nor a wrapped function escapes Paidwen, such as a database driver called directly. The function that calls the driver can be wrapped.
- A tool that runs at the model provider, such as a hosted web search, escapes the check before the action. Paidwen sees it only in the journal.
- In Python, the HTTP capture does not see
urllib.request,http.client, pycurl or gRPC. In TypeScript, it does not see undici called directly,node:http2, gRPC, or a library that kept its own copy ofhttp.requestbefore the capture. - A key sent under a name outside the lists of sensitive keys reaches Paidwen in clear, in the parameters.
- A process has one HTTP capture. A process that runs several agents with their own keys uses wrapped functions or one MCP client per agent.