Skip to Content
Rius

How do I add tracing to my AI agent in TypeScript?

Rius traces a TypeScript agent once you install @glassflow-ai/rius, call init once at startup, and wrap each step of your agent with observe. Model calls from a supported client library such as Anthropic become spans with model, token counts and cost, with no code at the call site. Run the agent once and the trace appears in the Traces view in the console.

How it works

  • init() starts the SDK. It is synchronous, and auto-instrumentation attaches a moment later, so you await ready before your first call.
  • observe() wraps a function so each call becomes a span with its input and output. Errors are recorded on the span with the error type and re-thrown.
  • Calls through an installed client library, such as the Anthropic client, get a span for each model call automatically. Rius computes cost from the model and token counts, so you never send a cost value.
  • For steps that are not one function, startAsCurrentSpan opens a span around a callback, and startAsCurrentGeneration records a model call by hand.
  • The TypeScript SDK does not flush spans when the process exits. A short script ends with await rius.shutdown().

The full list of init options is in Installation and configuration.

Set it up

  1. Install the SDK. It needs Node 18 or newer. @opentelemetry/api is a peer dependency. The last package is the Anthropic instrumentation, not the Anthropic client. Swap it for the instrumentation of the library you use. Create an account and an API key in the console first, as described in the Quickstart.
npm install @glassflow-ai/rius @opentelemetry/api @anthropic-ai/sdk \ @arizeai/openinference-instrumentation-anthropic
  1. Initialize once and wrap your entry point. Save this as agent.ts and run it with your usual TypeScript runner. Name the wrapped function. observe takes the span name from the function, and an anonymous arrow function traces as anonymous.
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. Wrap each step of your agent. Apply observe to the planner, each tool function and each helper. A wrapped function always returns a promise, so every call site awaits it. Pass kind, such as SpanKind.TOOL or SpanKind.RETRIEVER, to label the step. Set serviceName explicitly, because it is how you find the agent later.

  2. Add a span for a step that is not one function. startAsCurrentSpan takes a callback. Children nest under the span and errors are recorded for you. Here search and query are your own.

import { startAsCurrentSpan, SpanKind } from '@glassflow-ai/rius' await startAsCurrentSpan( { kind: SpanKind.RETRIEVER, dataSourceId: 'product-kb', topK: 5, input: query }, async (obs) => { const docs = await search(query) obs.setRetrievedDocuments(docs.map((d) => ({ id: d.id, score: d.score }))) }, )
  1. Trace a model call that has no integration. Use startAsCurrentGeneration with the model and provider options, then call setUsage with input and output token counts. Send tokens, never cost. Pass provider: 'anthropic' for every Claude call. For a streamed answer, call recordFirstToken() on each chunk to get time to first token. Anthropic streams and TypeScript OpenAI streams do not record it on their own.

  2. Group turns and users. Wrap each conversation in withSession and each request in withUser. Every span inside carries the id, including spans from auto-instrumentation. Prefer an opaque user id to an email. Details are in Tracing your code.

  3. Check the first trace. Open the Traces view in the console and run the agent once. The list checks for new traces on its own, so you do not reload. Open the trace to see the waterfall of steps, with token counts, cost and any errors.

What you get

  • A trace for each run, with a span for every wrapped function, manual span and model call.
  • Model, token counts and a cost estimate on each model call. Cost is a list-price estimate in US dollars, not a billed amount.
  • Errors on the span where they happened, grouped by error type.
  • Sessions and users, when you scope them, so you can follow one conversation or one person across traces.
  • An agent that reports a heartbeat from init(), so the Agents view shows whether it is alive between runs.

From here, add alerts and queries by following Monitor AI agents in production.

When something else fits

  • If your agent runs on a framework or router that has its own Rius integration, install that integration’s package and init() enables it automatically, so you write fewer manual spans.
  • If you already use OpenTelemetry SDKs or a collector, you can send OTLP traces to Rius over HTTP without the Rius SDK.
  • If your agent is Python, the same steps apply with the glassflow-rius package and the @rius.observe decorator.

Still stuck? Get help

Last updated on