Skip to main content
The @raindrop-ai/eve package instruments Vercel’s Eve agent framework using its native instrumentation entry point: agent/instrumentation/raindrop.ts on Eve >= 0.62, agent/instrumentation.ts on older Eve. No wrapping, no per-call setup — Eve auto-discovers the integration at server startup and every agent turn flows to Raindrop. What gets tracked:
  • Every agent turn as a single Raindrop event, grouped by the Eve session, with the user’s message as its input
  • Multi-step streamText / generateText / generateObject calls with full attribute capture
  • Eve’s own agent spans (agent run, steps, model calls, tool executions), filed under the same event on Eve >= 0.62
  • Tool calls (inputs, outputs, durations, errors)
  • Token usage per step and per turn
  • Sub-agents nested inside the turn that dispatched them, even across Eve’s V8 sandbox boundary
  • Model name, finish reason, errors, and full AI SDK telemetry attributes
  • Automatic mirroring to the local Workshop daemon during development

Installation

eve is expected to already be in your agent project. The integration declares eve: "*" as an optional peer dependency and is verified against Eve 1.0.0-rc.6 and 0.91.0; a single defineRaindropInstrumentation() call works on both layouts without any per-version configuration.
  • Eve >= 0.62 discovers one instrumentation provider per file under agent/instrumentation/ and owns the process-wide OpenTelemetry pipeline. The object returned by defineRaindropInstrumentation() is an Eve otelIntegration() destination (Raindrop exporter + span processors + runtimeContext resolver). Do not pass registerOTel: Eve refuses to start when another runtime owns the global tracer provider.
  • Eve <= 0.61 reads the legacy agent/instrumentation.ts default export. Pass registerOTel from @vercel/otel so Eve’s own spans are exported.
  • Cross-sandbox sub-agent linkage is sourced from the session.parent lineage Eve forwards on every dispatch (via otelIntegration({ runtimeContext }) on >= 0.62, events["step.started"] before).
  • Per-turn dynamic metadata is authored once via the events["step.started"] option (see Identifying Users) and forwarded to Eve on both layouts; it runs once per model call.

Quick Start

Drop a single file into your Eve project. On Eve >= 0.62:
Passing otelIntegration explicitly is required for bundled deploys: eve build output runs without node_modules, where the runtime fallback lookup cannot resolve eve/instrumentation/otel. Keep the export default un-annotated. The declared return type does not carry Eve’s provider/integration symbol markers, so annotating it as Eve’s InstrumentationProvider fails to type-check even though the object is one. Process-wide OpenTelemetry settings (functionId, tracePolicy, sampler, propagators) live in Eve’s own otel() declaration, one per project, next to the Raindrop file:
On Eve <= 0.61:
That’s it. Eve runs the file at server startup before any agent code. Every turn from every session in your agent will land in Raindrop.
Upgrading an agent from Eve <= 0.61 to >= 0.62: move the file to agent/instrumentation/raindrop.ts, replace registerOTel with otelIntegration from eve/instrumentation/otel, and move functionId into otel({ functionId }) if you set it. See Configuration for content capture and redaction behavior.

How It Works

The package does two things:
  1. Implements a SpanExporter (RaindropEveSpanExporter) that serializes OTel spans to OTLP/HTTP JSON and ships them to https://api.raindrop.ai/v1/traces. On Eve >= 0.62 Eve wires it into its own OpenTelemetry pipeline as an otelIntegration() destination; on older Eve the integration registers it through registerOTel. On Eve >= 0.62 it also files Eve’s agent spans under the turn’s Raindrop event (see Captured Trace Hierarchy). It mirrors every export to a local Workshop daemon when one is reachable (http://localhost:5899/), so the same agent run shows up in raindrop workshop AND hosted Raindrop without changing code.
  2. Registers a Raindrop TelemetryIntegration with Vercel AI SDK v7’s global registry so every streamText / generateText / tool call in your agent becomes a proper Raindrop LLM / tool span — and a track_partial semantic event — instead of opaque AI SDK spans. This is what hydrates the Workshop Overview tab and the hosted Raindrop event feed. All AI SDK calls within one Eve turn are grouped under a single eventId built from Eve’s session and turn ids (eve:<sessionId>:<turnId>), so a single agent turn shows up as a single Raindrop event in both UIs. The event’s input is the user’s message, not the task or state messages Eve adds to the model’s history.
For users who’d rather wire OpenTelemetry themselves, RaindropEveSpanExporter is exported separately for use as the traceExporter of an Eve otelIntegration() destination or any registerOTel({ traceExporter }) call (see Application Git identity).

Sub-Agents

Eve runs each sub-agent in its own V8 sandbox. The integration reads the session.parent lineage Eve forwards on dispatch (the otelIntegration({ runtimeContext }) input on Eve >= 0.62, the events["step.started"] input before that), and records the sub-agent inside the parent turn that dispatched it:
  • Eve >= 0.62: Eve records the sub-agent as an invoke_agent span nested under the parent’s tool call, with the sub-agent’s own steps, model calls and tool executions. The integration files that run under the parent turn’s Raindrop event, so the sub-agent appears inside the parent’s conversation as one sub-agent, with its own steps and tool calls. The integration does not ship a separate AI SDK copy of a sub-agent’s calls; its content follows recordInputs / recordOutputs like every other Eve span.
  • Eve <= 0.61: the sub-agent’s AI SDK calls are wrapped in a synthetic agent.subagent tool call and reported under the parent turn’s event.
The lineage is attached to the sub-agent’s spans: When Eve exposes no session.parent (a root session), spans carry raindrop.agent.role = "root".

Configuration

On Eve >= 0.62, omitted recordInputs / recordOutputs declare a redacting exportPolicy for Eve’s OTel spans sent to this destination (Raindrop and Workshop). Setting a flag to true removes that direction’s redaction; Eve’s tracePolicy still controls what content is captured. On Eve <= 0.61, the flags are forwarded to Eve’s telemetry settings. These options are not a content-redaction guarantee for the separate Raindrop AI SDK shippers: their traces follow the AI SDK call’s telemetry settings, and event input/output text is not gated by these flags. On Eve >= 0.62 a sub-agent’s prompts and replies are recorded only on Eve’s spans, so these flags decide whether that content reaches Raindrop. Other OTel destinations follow their own policies. Per-chunk spans named exactly workflow.stream.flush are dropped from Raindrop and Workshop by default (includeStreamFlushSpans: false). Set includeStreamFlushSpans: true to retain them; other workflow and step spans are unchanged. Two ways to attach metadata: Both feed the same event fields — the events callback just lets you compute them per turn.

Projects

If your org has multiple projects, route this agent’s events to a specific one by passing its slug as projectId (or via RAINDROP_PROJECT_ID):
This sets the X-Raindrop-Project-Id header on every cloud export. Omit it (or pass "default") to use your org’s default Production project, which is the existing behavior. Single-project orgs need nothing new.
Eve is one instrumentation per process by design — run one project per process. defineRaindropInstrumentation() installs its OpenTelemetry exporter behind a process-global symbol gate (the first call wins) and registers its AI SDK telemetry integration on globalThis (the last call wins). Two defineRaindropInstrumentation() calls with different writeKeys or projectIds in the same process therefore split-brain — the exporter belongs to the first call, the AI SDK capture to the last — and spans land in the wrong project. To report several agents to different projects, run one instrumented Eve process per project rather than calling defineRaindropInstrumentation() more than once.

Identifying Users

Raindrop sets each event’s user and conversation from two reserved keys: raindrop.userId and raindrop.convoId. Put them on staticMetadata if they never change, or return them from the events["step.started"] callback to compute them per turn. Same user every time — put the keys on staticMetadata:
Different user per turn — return the keys from the events["step.started"] callback. Eve runs it once per model call with the live input, so you can derive identity from the request that triggered the turn — e.g. map the Slack user onto the Raindrop event userId:
How the keys map onto the event:
  • raindrop.userId → the event’s userId; raindrop.convoId → the event’s convoId.
  • Every other key → the event’s properties, except keys starting with raindrop. or eve., which are reserved for the integration and are not copied onto the event.
The same values are also attached to the AI SDK spans (as ai.settings.context.*).
When the same key is set in more than one place, the most specific value wins: per-call AI SDK metadata > the events["step.started"] callback > staticMetadata. If no raindrop.userId is set anywhere, Raindrop falls back to the Eve session.id.

Using the Slack user’s name / email / channel name

Whatever string you return as raindrop.userId becomes the event’s userId — so to make Raindrop track e.g. the Slack email instead of the user id, just return that string. What’s reachable from step.started:
  • User id (Uxxxx) — directly on input.channel.metadata.triggeringUserId.
  • User’s name — already resolved, no API call: read input.session.auth.current?.attributes and use full_name / user_name (Eve’s default Slack auth puts them there).
  • Email / channel name — not in any Slack mention payload, so resolve them once on the async inbound side (onAppMention) via the Slack Web API (users.info → user.profile.email, needs the users:read.email scope; conversations.info → channel.name), stash them on the session auth attributes, then read them back in step.started (which is synchronous and can’t call Slack itself):

Workshop / Production Mirroring

localWorkshopUrl controls Workshop mirroring: Run raindrop workshop locally to get a daemon at http://localhost:5899 — the integration starts mirroring as soon as the daemon is reachable.

Production-Only Mode

Workshop-Only Mode (no Raindrop account)

Leave writeKey undefined. Spans still flow to Workshop:

Captured Trace Hierarchy

Eve >= 0.62 owns the agent spans and emits OpenTelemetry GenAI semantic-convention attributes (gen_ai.*). A turn that dispatches a sub-agent looks like:
The integration files these agent spans (invoke_agent, agent.step, chat, execute_tool) under the turn’s Raindrop event by setting ai.telemetry.metadata.raindrop.eventId, so they land on the same event as the AI SDK spans and the event itself. Eve’s internal workflow spans are exported as before but are not attached to the event. Older Eve relies on the AI SDK’s spans:
On every Eve version the AI SDK telemetry integration this package registers also ships each root-agent model / tool call as a Raindrop event (track_partial).

Captured Event Fields

Each turn’s Raindrop event carries: Model, token usage and cost come from the turn’s model-call spans. Sub-agent lineage (raindrop.agent.role, raindrop.parent.*) is recorded on spans, not as event properties.

Flush & Shutdown

Eve’s BatchSpanProcessor flushes spans automatically at process exit, and the integration registers a shutdown() hook that drains the internal Raindrop client buffer before the process exits. Most users don’t need to call anything manually. If you’re embedding RaindropEveSpanExporter directly, call await exporter.shutdown() before exit.

Known Limitations

  • Streaming: The integration captures aggregate token usage and the final outputs of each step. Individual token-by-token deltas are not traced separately.
  • functionId on Eve >= 0.62: the functionId option only affects the integration’s own sub-agent detection; Eve reads the span functionId from otel({ functionId }).
  • OTel provider access (Eve <= 0.61): The integration calls addSpanProcessor on the NodeTracerProvider returned by @vercel/otel. Custom OTel setups that hide the underlying provider behind a non-standard proxy will gracefully skip the ai.eve.turn session-id enrichment path and fall back to the events["step.started"] session input only.

Application Git identity

Set appGit on defineRaindropInstrumentation (or RaindropEveSpanExporter) to provide commitSha, commitDirty, and optional branch, or pass false to opt out. Local Git is not read unless sourceDirectory explicitly identifies the AUT; both Eve telemetry feeds use that same identity. See the TypeScript Git reference. defineRaindropInstrumentation installs span-start capture automatically. If you wire RaindropEveSpanExporter directly, add its public start processor to freeze automatic Git metadata. On Eve >= 0.62 declare it as a destination in agent/instrumentation/raindrop.ts:
On older Eve, keep "auto" to preserve Vercel’s default processors:
This keeps the normal batch exporter and Vercel processors. Without start capture, a direct exporter reports only explicit client, environment, operation, or span values; it never adds an inferred revision discovered after an unobserved span started.