@raindrop-ai/eve package instruments Vercel’s Eve agent framework using its native agent/instrumentation.ts entry point. 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
- Multi-step
streamText/generateText/generateObjectcalls with full attribute capture - Tool calls (inputs, outputs, durations, errors)
- Token usage per step and per turn
- Sub-agent dispatches as nested
agent.subagentspans — even across Eve’s V8 sandbox boundary - Cross-sandbox parent linkage (
raindrop.parent.eventId/sessionId/turnId/turnSequence) - 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 >= 0.11.0 as an optional peer dependency and reads only Eve’s documented runtime surface, so a single defineRaindropInstrumentation() call works without any per-version configuration.- Cross-sandbox sub-agent linkage is sourced from the
events["step.started"]session.parentlineage Eve forwards on every dispatch. - Per-turn dynamic metadata (the
step.startedcallback — see Identifying Users) is wired through Eve’seventsconfig and runs once per model call.
Quick Start
Drop a single file into your Eve project atagent/instrumentation.ts:
agent/instrumentation.ts and runs it at server startup before any agent code. Every turn from every session in your agent will land in Raindrop.
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. It also 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 singleeventIdderived from Eve’s active OTel trace, so a single agent turn shows up as a single Raindrop event in both UIs.
@vercel/otel themselves, RaindropEveSpanExporter is exported separately for use with any registerOTel({ traceExporter }) call.
Sub-Agents
Eve runs each sub-agent in its own V8 sandbox. The integration detects when the current sandbox was dispatched as a sub-agent and lifts the parent’s turn identity onto every sub-agent event, sourcing the lineage from theevents["step.started"] session.parent Eve forwards on dispatch:
These attributes power the AGENT block in Workshop’s Overview tab and let the Raindrop dashboard stitch sub-agent events under the parent turn that dispatched them (matching on
raindrop.parent.eventId).
Configuration
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.
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
A typical Eve turn produces this trace shape:raindrop.parent.eventId (plus sessionId / turnId / turnSequence) so the Raindrop dashboard renders them nested under the parent’s turn — matching on raindrop.parent.eventId — even though they are on a different OTel trace.
Captured Properties
The following properties land on every event:
Any keys you set on
staticMetadata (or return from the events["step.started"] callback) are also forwarded to event.properties, except the reserved raindrop.* identity keys.
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.
- OTel provider access: 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.