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 a weather agent, wire it to Arize AX with two instrumentation files, run a session, and explore the resulting traces: the per-turn breakdown of model steps, model calls, and tool executions. Eve emits OpenTelemetry GenAI spans, and Arize AX ingests them through the @arizeai/openinference-vercel span processor. This is the same processor the Vercel AI SDK integration uses.

Prerequisites

  • Node.js 24+ (Eve’s CLI requires it)
  • Eve 0.62 or later (this guide scaffolds the latest)
  • 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, and initializes Git:
This generates an agent/ directory with instructions.md (the system prompt), agent.ts (runtime config), and channels/eve.ts (the built-in HTTP channel). Replace the scaffolded instructions in agent/instructions.md:
Set the model in agent/agent.ts:
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, so 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. Create agent/tools/get_weather.ts:

Step 2: Add Arize AX observability

Tracing in Eve is configured with files in the agent/instrumentation/ directory. Eve discovers every file there and loads them once when the server starts, before any agent or tool code runs. That ordering is why tracing lives in its own directory: OpenTelemetry has to be registered before the agent code runs, otherwise its spans are never captured. Because Eve owns the startup and registers the OpenTelemetry pipeline itself, there’s no per-call telemetry flag to set, unlike the raw Vercel AI SDK, where you pass experimental_telemetry on every call. Each file exports one piece of the setup:
  • otel() declares the process-wide OpenTelemetry settings: the resource attributes and what content spans capture. Declare it once.
  • otelIntegration() declares one trace destination. Add one file per destination; Eve combines them into one pipeline.
Install the OpenInference processor, the OpenTelemetry trace SDK it builds on, and the OTLP exporter:
Create agent/instrumentation/otel.ts. It sets the model_id resource attribute, which Arize uses to route spans to a project; without it the OTLP endpoint rejects spans:
agent/instrumentation/otel.ts
Eve’s Vercel Workflow runtime emits many spans that aren’t OpenInference spans (workflow.*, step.*, and queue and HTTP spans), well over a hundred per turn. Filtering with isOpenInferenceSpan drops them and keeps only the agent, model, and tool spans. Setting reparentOrphanedSpans: true re-roots any AI span whose dropped parent was a non-AI span. Eve already roots each turn at its own invoke_agent span, so this is a safeguard rather than a fix. Create agent/instrumentation/arize.ts to declare Arize AX as a destination. It registers the OpenInference span processor with an OTLP exporter pointed at Arize:
agent/instrumentation/arize.ts
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.
In development, Eve records model and tool inputs and outputs on spans, so you’ll see prompts, responses, and tool arguments in Arize AX. In production, Eve records them only for public conversations unless you set tracePolicy in otel(). See Control what content is captured.

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 in the x-eve-session-id response header, 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 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 weather-agent project. Each turn is one trace, rooted at Eve’s invoke_agent agent span. Eve runs the turn as a series of model steps. Each step is an agent.step chain span holding the chat LLM span for the model call. When the model calls a tool, the step also holds an agent.action chain span over the execute_tool tool span:
From the trace you can inspect:
  • The chat LLM span, with the prompt, the model’s response, and input and output token counts.
  • The execute_tool tool span, carrying tool.name, with its arguments and returned result.
  • Session grouping. Every span carries a session.id taken from Eve’s session id (gen_ai.conversation.id), so the two turns from your follow-up message group under one session on the Sessions tab.

Next steps