How do I trace the Anthropic API in TypeScript?
Rius traces the Anthropic API in TypeScript when you install its Anthropic instrumentation package next to the SDK and call init(). Your existing call sites stay as they are. Each messages.create call then appears as a span with the model, token counts, messages and a cost. The steps below cover the install, the init call, a minimal traced call and what shows in the trace.
How it works
The TypeScript SDK, @glassflow-ai/rius, has no extras. Its integrations are optional peer dependencies that you install yourself, and a plain npm install @glassflow-ai/rius patches nothing. For Anthropic, the peer is @arizeai/openinference-instrumentation-anthropic, version 0.2.7 or newer. Older versions report Anthropic’s cache-exclusive input count and drop both cache counts, so cost undercounts any call that uses prompt caching.
When you call init(), it enables the Anthropic integration if that package is installed. It instruments the client library for the whole process, so you use your @anthropic-ai/sdk client exactly as before. init() is synchronous and attaches auto-instrumentation asynchronously. Awaiting ready gives you the names of the integrations that attached, so you can check that anthropic is among them. It never rejects.
Rius computes cost from the model and the token counts. You never send a cost value. For the full list of integrations and how they attach, see Integrations.
Set it up
- Install the SDK, its peer dependency and the Anthropic instrumentation. Your project already has
@anthropic-ai/sdkif it calls Anthropic.
npm install @glassflow-ai/rius @opentelemetry/api
npm install @arizeai/openinference-instrumentation-anthropic-
Create an API key in the Rius console. Keys start with
ri_. SetANTHROPIC_API_KEYin your environment, because the Anthropic client reads it. -
Call init() once, as early as possible, then make a call. This example wraps the call in observe so the model call nests inside a named run. It awaits
readyso the instrumentation is attached before the first call, and awaitsshutdown()so queued spans are exported before the process exits.
import Anthropic from '@anthropic-ai/sdk'
import { init, observe } from '@glassflow-ai/rius'
const rius = init({ apiKey: 'ri_...', serviceName: 'my-agent' })
await rius.ready // auto-instrumentation is attached before the first call
const claude = new Anthropic() // reads ANTHROPIC_API_KEY
const handle = observe(async function handle(query: string) {
const message = await claude.messages.create({
model: 'claude-haiku-4-5-20251001',
max_tokens: 200,
messages: [{ role: 'user', content: query }],
})
const [block] = message.content
return block.type === 'text' ? block.text : ''
})
await handle('What should I check when a collector drops spans?')
await rius.shutdown() // export queued spans before the process exits-
Name the wrapped function, as
handleis named above, because an anonymous one traces as anonymous. The TypeScript SDK does not flush spans on process exit, so a short script must awaitrius.shutdown(). -
Check the order of your imports if you use CommonJS. Require
@anthropic-ai/sdkbefore init(). A require that happens only after init() stays untraced, even thoughreadylistsanthropic. Pure-ESM applications have no such rule. -
Run the script and open the trace in the console. The setup options are in Installation and configuration, and the Anthropic details are on the Anthropic integration page.
What you get
Each messages.create call becomes a span for the model call. It carries:
- The model, for example
claude-haiku-4-5-20251001. - Input and output token usage from the response, including cache reads and writes.
- The request and response messages. Text blocks become text parts and tool calls become tool_call parts. Any other block, such as an image or a reasoning block, is kept as a text part holding the serialized block.
- The system prompt, which Anthropic takes as a separate parameter. It appears as the leading system message of the input messages.
- A cost computed by Rius from the model and tokens, as a list-price estimate in US dollars.
- On a failed call,
error.typeset to the error class, such asanthropic.NotFoundError.
Streamed calls also capture token usage, because Anthropic reports it in the message lifecycle events. With observe, the model call nests inside your agent’s run. Prompt and response content follows your privacy controls, and RIUS_CAPTURE_CONTENT set to false strips content at export while metadata still flows.
When something else fits
- If you deploy a pnpm app to a file-tracing host such as a Vercel function, the SDK may not find the instrumentation package and
readyleaves outanthropic. Pass your own imported modules withinstrumentModules, as shown in Integrations. - Auto-instrumented Anthropic streams carry no time to first token. If it matters for a call, trace that call as a manual generation instead. To avoid counting it twice, leave
anthropicout ofinit({ instruments: [...] }). The integration is then off for the whole process, so every other Anthropic call needs a manual generation too. - If you work in Python, install the
anthropicextra instead. The Anthropic integration page has both languages.