Skip to main content
Auto-instrumentation captures calls to common LLM and agent frameworks as spans with no span code on your part. Call tracing.init(), then call an instrumented library, and Surface Area records the call.

How it works

tracing.init() instruments installed AI libraries by default (instrument_default=True). Each library is instrumented when both the library and its instrumentor package are installed. Install the common instrumentor packages with the tracing extra. It bundles the instrumentors for OpenAI, the OpenAI Agents SDK, Anthropic, and LiteLLM. It installs the instrumentors, not the libraries: LiteLLM is traced only when your app installs litellm itself, and the extra places no upper bound on openai.
The Claude Agent SDK instrumentor ships inside gatewaysdk and needs no extra package. LangChain, LlamaIndex, and the additional frameworks below each need their own OpenInference package (for example, pip install openinference-instrumentation-langchain).
If you have an AI library installed but not its instrumentor, init() logs a warning naming the library and pointing at the tracing extra.
In TypeScript, wrap clients explicitly with observeOpenAI, observeAnthropic, and observeClaude. See the TypeScript SDK page.
The instrumentors are built on OpenInference, plus a native instrumentor for the Claude Agent SDK. They produce standard OpenTelemetry spans, so they flow to Surface Area alongside the spans you create yourself.

The core set instrumented by default

With instrument_default=True, init() enables the core set below, each one only if it is installed.
The OpenAI call in the Quickstart is captured this way. After init(), the call nests under whatever trace is active, and Surface Area records its model, messages, token counts, and cost automatically.

Additional instrumentors you can enable by name

These instrumentors are registered but not enabled by default. Enable them with tracing.instrument(names=[...]). Each still requires its target library and OpenInference instrumentor package to be installed.

Older client versions

An instrumentor package can declare that it supports only newer releases of its library. When yours is older, init() still instruments it and logs one warning naming the version range. For anthropic releases before 0.84 (for example 0.76, which browser-use pins), Surface Area switches to its own built-in Anthropic instrumentor and logs a warning that says so. It traces messages.create and beta.messages.create, sync and async, on anthropic 0.41 and later: one generation span per call with the model, messages, response and token counts, including cached prompt tokens. Base64 images and documents are replaced by a short marker, and MCP server authorization_token values are never recorded. Upgrade anthropic to 0.84 or later to get the full instrumentor.

Credentials are never exported

A request can carry a credential the model provider needs, such as an MCP server’s authorization_token. tracing.init() removes it from every span before export, whichever instrumentor recorded it, and wherever it sits as a JSON key in a recorded request. When a recorded value names the key any other way (an attribute cut short by OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, a Python repr, a query string, key/value pairs, or text that mentions authorization_token), the whole value is replaced by [redacted: holds a credential] rather than risk exporting the token. That can also hide a value that only mentions the name, such as a tool output quoting SDK source. The request itself still goes to the provider unchanged.
This covers every exporter passed to or created by init(). If you attach an exporter to your own TracerProvider (or init() reuses one that already has exporters, which it warns about), wrap its processor: SecretRedactingSpanProcessor(BatchSpanProcessor(exporter)) from gatewaysdk.tracing.processors.

Control which libraries get instrumented

Turn off the default core set and enable specific instrumentors by name.
Skip a single instrumentor while keeping the rest of the core set.
tracing.instrument(skip=[...]) skips names from the core set only. To enable an additional instrumentor such as crewai or mistral, pass it explicitly with names=[...], since it is not part of the default set.
Do not set OPENAI_AGENTS_DISABLE_TRACING=1. The openai_agents instrumentor rides on the Agents SDK’s own tracing pipeline: that variable turns the pipeline off entirely, and with it all Surface Area telemetry for the agent, silently. It’s often set to silence the OpenAI trace-upload 401s that appear when pointing the client at a non-OpenAI base URL; those 401s are harmless noise. tracing.init() prints a warning if it detects the variable.

Tag auto-instrumented calls

Auto-instrumented spans are created where no tracing.trace block is in scope. Wrap the call in tracing.tracing_context() to attach a session id, tags, or a call type to those spans.

Where to go next