@telemetry-dev/eve
v0.1.0
Published
Eve (Vercel agent framework) telemetry integration for telemetry.dev.
Downloads
70
Readme
@telemetry-dev/eve
Eve telemetry integration for telemetry.dev. It wires Vercel's Eve agent framework to telemetry.dev through Eve's native OpenTelemetry, lifecycle-hook, and HTTP-client surfaces.
Install
npm install @telemetry-dev/eve eveRequires eve >=0.19.0 <1 and Node.js 24 or newer.
Environment
| Variable | Required | Default | Notes |
| --------------------------- | -------- | ------------------------------ | ----------------------------------------------------------------------- |
| TELEMETRY_DEV_API_KEY | yes | — | Ingest key (td_live_…). No key ⇒ the integration is a complete no-op. |
| TELEMETRY_DEV_BASE_URL | no | https://ingest.telemetry.dev | Trailing slashes are stripped. |
| TELEMETRY_DEV_ENVIRONMENT | no | production | Environment label on every trace/log. |
| OTEL_SERVICE_NAME | no | SDK default | Server instrumentation falls back to the Eve agent name after this env. |
All four are also settable through SDK options. Pass SDK options to exactly one entry point in a
process; whichever initializes first wins. If you only use telemetryDevHook() or
wrapEveClient(), pass serviceName explicitly or set OTEL_SERVICE_NAME.
Server instrumentation
Create agent/instrumentation.ts:
import { telemetryDevInstrumentation } from "@telemetry-dev/eve";
export default telemetryDevInstrumentation();This registers telemetry.dev as the global OpenTelemetry provider during Eve startup, so Eve's tracer
scope ("eve") and the AI SDK GenAI tracer scope ("gen_ai") export to telemetry.dev.
Useful options:
export default telemetryDevInstrumentation({
functionId: "support-agent",
recordInputs: false,
recordOutputs: true,
runtimeContext: { "team.id": "support" },
stepStarted(input) {
return { runtimeContext: { "channel.kind": input.channel.kind } };
},
});recordInputs defaults to captureInput ?? true; recordOutputs defaults to
captureOutput ?? true. Runtime context is attached by Eve to model-call spans under the
ai.settings.context. prefix. The integration also adds user.id when Eve auth exposes a principal.
Lifecycle logs
Create agent/hooks/telemetry-dev.ts:
import { telemetryDevHook } from "@telemetry-dev/eve";
export default telemetryDevHook();The hook emits bounded lifecycle logs for:
- session start/completion/failure;
- turn start/completion/failure;
- user message receipt without message content;
- step completion/failure with usage where available;
- non-completed tool results;
- HITL input requests and authorization outcomes;
- subagent calls/completions;
- compaction requests/completions.
Every log includes gen_ai.conversation.id, gen_ai.agent.name, Eve turn/step ids when present, and
eventName equal to the Eve stream-event type. Hook handlers are fail-open; instrumentation errors are
routed to onError and never thrown back into Eve.
Client wrapper
For apps that call an Eve agent over HTTP:
import { wrapEveClient } from "@telemetry-dev/eve";
import { Client } from "eve/client";
const client = wrapEveClient(new Client({ host: "http://127.0.0.1:3000" }), {
agentName: "support-agent",
});
const session = client.session();
const response = await session.send("Summarize this incident.");
const result = await response.result();wrapEveClient() creates one caller-side invoke_agent span per ClientSession.send() turn. It
records the outgoing message or HITL input responses as span input, sets gen_ai.conversation.id from
Eve's response session id, streams TTFT from the first message/reasoning delta, accumulates usage from
step.completed, records final message/result output, and marks failures/cancellations as errors.
ClientSession.stream(), Client.info(), and Client.health() are intentionally not spanned.
Attach-streams are unbounded and the probe routes are not agent turns.
Trace shape
A typical turn contains:
- Eve server root span
ai.eve.turn, normalized by telemetry.dev asinvoke_agent. - Nested AI SDK GenAI spans:
chat {modelId},step N, providerchat {modelId}client spans, andexecute_tool {toolName}spans. - Usage attributes such as
gen_ai.usage.input_tokens,gen_ai.usage.output_tokens, cache token counts, finish reasons, response ids, TTFT, and time-per-output-chunk when Eve's AI SDK integration emits them. - Runtime context attributes under
ai.settings.context.*, including Eve session/turn/step/channel context and any custom runtime context you return fromstep.started. - Lifecycle logs joined to the same session via
gen_ai.conversation.id.
Eve's internal workflow-engine spans (workflow.execute, step.execute, world.*, hook.resume,
etc., tracer scope workflow) are excluded by default so traces stay AI-centric. Pass
spanFilter: () => true to export them too.
Content capture
Server-side model content follows Eve's recordInputs / recordOutputs settings. Caller-side wrapper
content follows the telemetry.dev SDK captureInput / captureOutput settings. The SDK mask and
truncation options apply to captured client-wrapper inputs, outputs, and logs.
Limitations
- Pass options to exactly one entry point in a process. Initialization is one-shot so duplicate entry points do not replace the first configuration.
ClientSession.stream()is not spanned.- Cost is computed server-side by telemetry.dev from usage and pricing data; Eve stream events carry no cost fields, so the client wrapper records usage only.
- The client wrapper's
invoke_agentspan ends when the response stream is consumed (iteration orresult()); an unconsumed response leaves the span unexported. - Inline subagent child streams (
subagent.event) are not fanned out in full; the hook logssubagent.started,subagent.called,subagent.completed, and child failure events. - Eve workflow
$eve.*run tags are a Vercel-dashboard surface and are not visible to OpenTelemetry, so this package does not capture them.
