@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/generateObjectcalls 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 bydefineRaindropInstrumentation()is an EveotelIntegration()destination (Raindrop exporter + span processors +runtimeContextresolver). Do not passregisterOTel: Eve refuses to start when another runtime owns the global tracer provider. - Eve <= 0.61 reads the legacy
agent/instrumentation.tsdefault export. PassregisterOTelfrom@vercel/otelso Eve’s own spans are exported. - Cross-sandbox sub-agent linkage is sourced from the
session.parentlineage Eve forwards on every dispatch (viaotelIntegration({ 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: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:
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:-
Implements a
SpanExporter(RaindropEveSpanExporter) that serializes OTel spans to OTLP/HTTP JSON and ships them tohttps://api.raindrop.ai/v1/traces. On Eve >= 0.62 Eve wires it into its own OpenTelemetry pipeline as anotelIntegration()destination; on older Eve the integration registers it throughregisterOTel. 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 inraindrop workshopAND hosted Raindrop without changing code. -
Registers a Raindrop
TelemetryIntegrationwith Vercel AI SDK v7’s global registry so everystreamText/generateText/ tool call in your agent becomes a proper Raindrop LLM / tool span — and atrack_partialsemantic 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 singleeventIdbuilt 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.
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 thesession.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_agentspan 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 followsrecordInputs/recordOutputslike every other Eve span. - Eve <= 0.61: the sub-agent’s AI SDK calls are wrapped in a synthetic
agent.subagenttool call and reported under the parent turn’s event.
When Eve exposes no
session.parent (a root session), spans carry raindrop.agent.role = "root".
Configuration
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 asprojectId (or via RAINDROP_PROJECT_ID):
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.
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:
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:
raindrop.userId→ the event’suserId;raindrop.convoId→ the event’sconvoId.- Every other key → the event’s
properties, except keys starting withraindrop.oreve., which are reserved for the integration and are not copied onto the event.
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 asraindrop.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 oninput.channel.metadata.triggeringUserId. - User’s name — already resolved, no API call: read
input.session.auth.current?.attributesand usefull_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 theusers:read.emailscope;conversations.info→channel.name), stash them on the session authattributes, then read them back instep.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)
LeavewriteKey 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:
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:
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’sBatchSpanProcessor 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.
functionIdon Eve >= 0.62: thefunctionIdoption only affects the integration’s own sub-agent detection; Eve reads the spanfunctionIdfromotel({ functionId }).- OTel provider access (Eve <= 0.61): The integration calls
addSpanProcessoron theNodeTracerProviderreturned by@vercel/otel. Custom OTel setups that hide the underlying provider behind a non-standard proxy will gracefully skip theai.eve.turnsession-id enrichment path and fall back to theevents["step.started"]sessioninput only.
Application Git identity
SetappGit 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:
"auto" to preserve Vercel’s default processors: