Skip to main content
Eve is Vercel’s filesystem-first framework for durable backend AI agents: you define an agent as files under an agent/ directory and Eve runs it on Vercel Functions. In this guide you’ll scaffold Eve’s hello-world weather agent, wire it to Arize AX with a single instrumentation file, run a session, and explore the resulting trace — the per-turn breakdown of model calls and tool executions. Eve emits Vercel AI SDK OpenTelemetry spans, and Arize AX ingests them through the @arizeai/openinference-vercel span processor — the same processor used by the Vercel AI SDK integration.

Prerequisites

  • Node.js 24+ (Eve’s CLI requires it)
  • An Arize AX account (sign up) — copy your Space ID and API Key from Space Settings
  • An AI_GATEWAY_API_KEY for Eve’s model routing (or run vercel link to use a VERCEL_OIDC_TOKEN)

Step 1: Scaffold the agent

Create a new Eve agent. The CLI scaffolds the project, installs dependencies, initializes Git, and starts a dev server:
This generates an agent/ directory — instructions.md (the system prompt), agent.ts (runtime config), tools/ (one file per tool), and channels/eve.ts (the built-in HTTP channel). The minimal agent is just two files. agent/instructions.md:
agent/agent.ts — the scaffold writes a default model (currently anthropic/claude-sonnet-4.6):
Eve resolves the model string through AI Gateway, so you authenticate once with your gateway credential instead of managing provider keys. Any AI Gateway model works — swap in openai/gpt-5.4-mini or another provider/model if you prefer. Add a tool so the agent has something to call. Each file in agent/tools/ is one tool, and the runtime tool name comes from the filename — agent/tools/get_weather.ts:

Step 2: Add Arize AX observability

Tracing in Eve is configured in a single file: agent/instrumentation.ts. Eve looks for that exact path and, if it exists, runs it once when the server starts, before any agent or tool code executes. That ordering is the whole reason the file exists separately: OpenTelemetry has to be registered before the AI SDK that Eve runs on is imported, otherwise its spans are never captured. Because Eve owns this startup hook, there’s no per-call telemetry flag to set — unlike the raw Vercel AI SDK where you pass experimental_telemetry on every call. The file’s presence is what turns tracing on. You write the file with defineInstrumentation from eve/instrumentation. Its setup callback runs at startup and receives the resolved agent name; inside it you register an OpenTelemetry provider. This guide uses @vercel/otel’s registerOTel to wire an OTLP exporter that ships Eve’s spans to Arize AX through an OpenInference span processor. Install the OpenInference processor and the OpenTelemetry packages:
Eve nests each turn’s spans under its own ai.eve.turn workflow span, which in turn hangs off Vercel Workflow spans that aren’t OpenInference spans. Filtering with isOpenInferenceSpan drops those non-AI spans — which would orphan every surviving span on the Traces tab, since their parent is gone. Set reparentOrphanedSpans: true on the processor to fix this: it re-roots any AI span whose dropped parent was a non-AI span, and recognizes Eve’s ai.eve.turn wrapper as an AI-like root, tagging it openinference.span.kind = AGENT so it survives the filter as a clean per-turn agent root. Create agent/instrumentation.ts — the file Eve auto-discovers and runs at startup. Inside the setup callback, registerOTel builds the OpenTelemetry provider: it sets the model_id resource attribute (Arize routes spans to a project by it — without it the OTLP endpoint rejects spans), points the OTLP exporter at Arize with your space and API key, and registers the OpenInference span processor with spanFilter and reparentOrphanedSpans set:
OpenInferenceSimpleSpanProcessor exports each span as it ends — so there’s no forceFlush to call on exit, even on the short-lived serverless functions Eve runs on. reparentOrphanedSpans runs statelessly at span start, so it adds no buffering.

Step 3: Run a session

Set your credentials and start the dev server:
The dev server listens on http://127.0.0.1:2000 by default (pass --port to change it). Open a session against the built-in HTTP channel. The agent should call your get_weather tool and answer (for example, “The weather in Brooklyn is sunny and 72°F.”):
The POST is asynchronous — it returns 202 with the session id (sessionId in the body, also the x-eve-session-id response header) and a continuationToken, but not the model’s reply; Eve runs the turn in the background. Stream the session to watch it run and see the answer:
This emits NDJSON lifecycle events — session.started, the get_weather actions.requested and action.result, streaming message.appended deltas, and finally a message.completed event with the full reply:
Send a follow-up on the same session to produce a second turn (stream it the same way to see its reply):

Step 4: Explore the trace in Arize AX

Open your Arize AX space and select the project named after your agent (weather-agent). Eve runs on the AI SDK’s GenAI-convention spans, so every span arrives named gen_ai (or gen_ai.client for the model request) rather than ai.streamText/ai.toolCall — the OpenInference processor classifies them by span kind (agent, llm, tool), which is what you read in the UI. Each turn is one trace, parented by Eve’s ai.eve.turn workflow span — which reparentOrphanedSpans re-roots and tags as an agent span so the per-turn root reads cleanly in the UI; per step, an agent span wraps an llm span, which parents the gen_ai.client model request and any gen_ai tool spans:
Arize AX trace view of a Vercel Eve agent turn, showing the ai.eve.turn agent root span with nested agent, llm, and tool spans for each step

The full Vercel Eve turn trace in Arize AX, with the ai.eve.turn agent span as the root over the per-step agent, llm, and tool spans

Because you set reparentOrphanedSpans: true in Step 2, ai.eve.turn is re-rooted and tagged as an agent span — so each turn is a single clean tree with no orphaned spans. The integration guide’s Span filter section explains the option in more detail.
From the trace you can inspect:
  • The llm span (gen_ai.client) with the prompt, the model’s response, and input/output token counts.
  • Each tool span (gen_ai, carrying tool.name) with its arguments and returned result.
  • Session grouping — Eve attaches ai.settings.context.eve.session.id, ai.settings.context.eve.turn.id, ai.settings.context.eve.step.index, and ai.settings.context.eve.channel.kind to the spans, so the two turns from your follow-up message group under the same session.

Next steps