Skip to main content
Claude Platform emits OpenTelemetry spans for your Claude usage on its own. You don’t need a Raindrop package. Point those spans at Raindrop and you get one Raindrop event per user turn, with the input, the output, tool calls, token usage, and cost. The full span tree appears in the trace view. The spans come from two sources. Set up one or both, depending on how you call Claude: If you send both, Raindrop deduplicates them: each model call is counted once.
Claude Platform’s OpenTelemetry support is in beta, and Anthropic may change span names and attributes. For a wrapper-based integration with more control over users and properties, see Claude Managed Agents and Claude Agent SDK.

Prerequisites

  • A Raindrop write key from app.raindrop.ai.
  • The admin role in your Claude Console organization, to add a destination.

1. Add Raindrop as a destination

  1. In the Claude Console, open Settings → OpenTelemetry (platform.claude.com/settings/telemetry-destinations) and click Add destination.
    Claude Console OpenTelemetry settings page with the Add destination button
  2. Fill in the destination:
    Add destination form filled in for Raindrop
  3. Click Add destination.
  4. In the destination’s More actions menu, click Test. The Console should report that the test span was delivered. A 401 means the write key or the Bearer prefix is wrong.
    Test delivery result for the Raindrop destination
The destination now forwards spans for all Claude API traffic in the selected workspaces. No code changes are needed for the Messages API. Add only one Raindrop destination per workspace: a second one sends every span twice.

Content mode

  • Full content: spans carry prompts, responses, system prompts, and tool inputs and outputs. Raindrop needs this mode to create events.
  • Metadata only: spans carry models, token counts, timing, and stop reasons, with no text. Raindrop stores the spans in the trace view, but doesn’t create events from them, so they get no signals and aren’t included in event usage or cost.
Raindrop accepts spans of any size Claude sends. Raindrop stores the full span and caps event inputs and outputs for display.

Messages API

With the destination in place, every Messages API request appears in Raindrop. This works from any client, including raw HTTP. Each request produces:
  • anthropic.messages.create: the request, with input and output messages, model, stop reason, and usage.
  • anthropic.model_request: each model run inside the request.
  • anthropic.tool_use <name>: each server tool the API ran, such as web search.
Tool loops. When your code runs a tool and calls Claude again, Raindrop reads the tool call and its result from the conversation history. They appear on the event and in the trace view. The API can’t see how long your tool took, so there’s no duration or status. Use the Claude SDK for that. Keep a tool loop in one trace. Send a W3C traceparent header with each request from a span you own, so all the requests of one user turn share a trace. Without it, each request starts its own trace.

Claude SDK

The Claude SDK emits its own spans: one per request, one per tool the tool runner runs (with real duration and status), and one for the whole tool runner loop. It also sends traceparent, so the API destination’s spans nest under the SDK’s in the same trace. Register a tracer provider that exports to Raindrop before you create the client:
  • contentMode: the SDK defaults to metadata only. Set content to send prompts and responses (the env var ANTHROPIC_OPEN_TELEMETRY_TRACES_CONTENT_MODE=content does the same). Without the destination, metadata-only SDK spans create no events.
  • Conversations: pass a conversation ID per call in the request options ({ openTelemetry: { conversationId } }). Raindrop uses it as the event’s conversation.
  • Without the destination, Raindrop builds events from the SDK spans alone. You lose the per-model-run spans and server tool spans, which only the API emits.
In TypeScript, if you use @opentelemetry/auto-instrumentations-node (which includes the undici instrumentation), set openTelemetry: { propagation: false } on the client. Otherwise each request carries two traceparent headers and the API’s spans don’t join your trace.

Claude Managed Agents

The destination covers Managed Agents sessions with no code changes:
  • anthropic.session.turn: each agent turn, with its input, output, system prompt, and stop reason.
  • anthropic.model_request: each model run in the turn, with token usage.
  • anthropic.tool_use <name> / anthropic.mcp_tool_use <name>: tools the agent ran in Anthropic’s cloud sandbox (bash, file tools, web fetch, MCP).
A user message that needs a custom tool takes several turns: the first ends requires_action, and your tool result starts the next. Raindrop records the whole chain as one event, with the user’s message as input, the final answer as output, the custom tool calls, and the usage of every turn. Add SDK tracing (as above) to also get a span for each custom tool your app runs with the session tool runner (client.beta.sessions.events.toolRunner), with duration and status. Keep each user message in one trace. Raindrop chains the turns of one user message within a single trace. Send the user message and the tool results from inside one span of yours:
If the user message and the tool results are sent from separate requests (for example, from webhook handlers), the turns land in different traces. The event then covers only the final turn. See Known limitations.

Self-hosted sandboxes

In a self-hosted sandbox, Claude runs on Anthropic’s side, but an environment worker on your infrastructure runs every tool. This applies wherever the worker runs: AWS (for example Lambda MicroVMs), a VPS, Kubernetes, or a provider such as Modal or E2B. The API destination never sees those tool runs, so:
  1. Set up SDK tracing in the worker process, exporting to Raindrop as above. The EnvironmentWorker in the Python, TypeScript, and Go SDKs (and ant beta:worker poll) then emits:
    • anthropic.environment.work: one span per work item, with anthropic.environment.id, anthropic.environment.work.id, and anthropic.session.id.
    • A tool span for each tool it runs (bash, read, your custom tools), with duration and status.
    • Spans for its own requests, including the tool results it sends back.
  2. Allow outbound HTTPS from the sandbox to api.raindrop.ai.
  3. Keep the API destination on for the turns and model requests.
The worker starts a new trace per work item, and the turns after each tool result nest under the worker’s request. So for a message that used tools, the Raindrop event comes from the worker’s trace. It includes the tool calls with durations, the final answer, and the final turn’s usage, but not the turn that carried the user’s prompt. See Known limitations.

How spans become events

Identifying users

Claude’s spans don’t carry your application’s user ID yet. Until they do, Raindrop uses a fallback: the request ID for Messages API events and the session ID for Managed Agents events. These fallback users are marked with the event property user_id_source, so you can filter them out of user analytics.

Limits

  • Raindrop accepts OTLP/HTTP protobuf exports up to 10 MB compressed and 32 MiB decompressed. Claude’s per-span content limit is well below this.
  • Raindrop counts each Claude span toward your OTLP rate limit. An always-on self-hosted worker also emits a small span per poll; these never become events.

Known limitations

  • Managed Agents turns in separate traces aren’t grouped. When one user message’s turns land in different traces (self-hosted sandboxes, or tool results sent from separate requests), the event covers the final turn’s trace only. The user’s prompt and the earlier turns’ usage are missing from that event.
  • Metadata-only mode creates no events. Spans appear in the trace view only.
  • Late spans. Spans that arrive after Raindrop finalizes an event (by default, about 30 seconds after the trace goes quiet) are stored in the trace view but not added to the event.

Troubleshooting

The Test button fails. Check that the endpoint is https://api.raindrop.ai with no /v1/traces suffix, and that the header value is Bearer followed by your write key. No Messages API events. Make sure the destination covers the workspace your API key belongs to. If your key isn’t scoped to a workspace, requests go to the workspace you name in the anthropic-workspace-id header, or to the default workspace. SDK spans are missing. Register the tracer provider before you create the client, and call provider.shutdown() (or forceFlush()) before a short-lived process exits. A tool shows no duration. Only spans from code that runs the tool (the SDK tool runner or a self-hosted worker) carry timing. Calls read from messages have none. Spans appear twice in the trace view. You have two destinations pointing at Raindrop for the same workspace. Raindrop still creates one event, but remove the extra destination.