Skip to Content
Rius

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

  1. Install the SDK, its peer dependency and the Anthropic instrumentation. Your project already has @anthropic-ai/sdk if it calls Anthropic.
npm install @glassflow-ai/rius @opentelemetry/api npm install @arizeai/openinference-instrumentation-anthropic
  1. Create an API key in the Rius console. Keys start with ri_. Set ANTHROPIC_API_KEY in your environment, because the Anthropic client reads it.

  2. 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 ready so the instrumentation is attached before the first call, and awaits shutdown() 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
  1. Name the wrapped function, as handle is named above, because an anonymous one traces as anonymous. The TypeScript SDK does not flush spans on process exit, so a short script must await rius.shutdown().

  2. Check the order of your imports if you use CommonJS. Require @anthropic-ai/sdk before init(). A require that happens only after init() stays untraced, even though ready lists anthropic. Pure-ESM applications have no such rule.

  3. 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.type set to the error class, such as anthropic.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 ready leaves out anthropic. Pass your own imported modules with instrumentModules, 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 anthropic out of init({ 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 anthropic extra instead. The Anthropic integration page has both languages.

Still stuck? Get help

Last updated on