Skip to content

feat(eve): add agent-semantic OTel provider#1192

Draft
chadhietala wants to merge 2 commits into
chad/trace-lifecycle-wiringfrom
chad/trace-agent-otel-provider
Draft

feat(eve): add agent-semantic OTel provider#1192
chadhietala wants to merge 2 commits into
chad/trace-lifecycle-wiringfrom
chad/trace-agent-otel-provider

Conversation

@chadhietala

Copy link
Copy Markdown
Contributor

Summary

Phase 3 of local observability, stacked on #1191.

This PR adds the first lifecycle provider and defines eve’s agent-first OpenTelemetry semantics:

  • Injected Tracer; no global OTel registration
  • Provider-owned session trace context store
  • Zero-duration session root marker
  • agent.turn -> agent.step -> agent.action hierarchy
  • Session lifecycle events carried by turn spans
  • Stable agent.* identity, framework, lineage, model, usage, and action attributes
  • Tool/action failures remain localized to the action span
  • Content is not captured

The same provider can later run with a private local tracer or the global tracer configured by @vercel/otel.

Scope

This PR does not register the provider, wire harness-native lifecycle events, persist traces, call registerOTel(), or change production behavior. The provider is exercised only through real in-memory OTel tests.

Testing

  • Session root ignores ambient parent context
  • Multiple turns share one trace ID
  • Turn, step, and action parentage
  • Session event placement
  • Structural attributes and no content capture
  • Action failure does not fail the turn
  • Provider-neutral bridge tests
  • Tool-loop regression tests
  • Package typecheck, build, lint, formatting, and invariants

Signed-off-by: Chad Hietala <chadhietala@gmail.com>
@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
eve-docs Ready Ready Preview, Comment, Open in v0 Jul 24, 2026 8:53pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
eve-docs-1644 Skipped Skipped Open in v0 Jul 24, 2026 8:53pm
eve-docs-4759 Skipped Skipped Open in v0 Jul 24, 2026 8:53pm

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Bundle + Package Summary: apps/fixtures/weather-agent

Key takeaways

  • No notable deltas vs chad/trace-lifecycle-wiring (20d53bc).

Delta vs chad/trace-lifecycle-wiring (20d53bc)

Area Metric Baseline Current Delta
Package Packed tarball 4.05 MB 4.05 MB +2.8 kB ⚠️
Package Unpacked publish size 14.73 MB 14.74 MB +8.6 kB ⚠️
Package Installed footprint 53.89 MB 53.90 MB +8.6 kB ⚠️
Package Published files 2751 2753 +2
Package Installed files 5991 5993 +2
Runtime Unique function payloads 2 2 0
Runtime Total function bytes 11.67 MB 11.67 MB -40 B ✅
Runtime Public routes 11 11 0
Changed function payloads vs chad/trace-lifecycle-wiring (20d53bc) (2)
Function Status Baseline Current Delta Route changes
functions/__server.func changed 4.41 MB 4.41 MB -20 B ✅ none
functions/.well-known/workflow/v1/flow.func changed 7.27 MB 7.27 MB -20 B ✅ none

eve init install

Metric Baseline Current Delta
Installed footprint 92.29 MB 92.30 MB +8.6 kB ⚠️
Installed packages 122 122 0
dependencies 4 4 0
devDependencies 2 2 0
Dependency package bytes 29.01 MB 29.02 MB +8.6 kB ⚠️
devDependency package bytes 5.04 MB 5.04 MB 0 B ➖
Build Metadata
  • Preset: vercel
  • Nitro: nitro@3.0.260610-beta
  • Output directory: apps/fixtures/weather-agent/.vercel/output
  • Build metadata timestamp: 2026-07-24T20:53:37.794Z
  • Route aliases: 11 public, 1 internal (12 total aliases)
  • Vercel routes in config: 12
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.27.3
  • Package directory: packages/eve
  • Tarball: 4.05 MB (eve-0.27.3.tgz)
  • Unpacked payload: 14.74 MB across 2753 published files
  • Installed footprint: 53.90 MB across 5993 installed files
  • Installed root package: 13.46 MB
  • Installed dependencies: 40.44 MB
  • Runtime dependencies: 1
  • Peer dependencies: 5 (4 optional)

Installed footprint is measured from an isolated temporary npm install of the packed tarball.

Heavy installed dependencies

  • @rolldown/binding-linux-x64-gnu: 18.96 MB (35.2%)
  • eve: 13.46 MB (25.0%)
  • ai: 6.43 MB (11.9%)
  • zod: 5.04 MB (9.4%)
  • nitro: 2.41 MB (4.5%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/experimental-ai-sdk-code-mo... [###.....................] 1.51 MB 10.2%
🟡 dist/src/compiled/@vercel/sandbox/index.js       [#.......................] 632.4 kB 4.3%
🟡 dist/src/compiled/_chunks/workflow/undici-C2Z... [#.......................] 502.4 kB 3.4%
🟡 dist/src/compiled/@chat-adapter/slack/index.js   [#.......................] 440.5 kB 3.0%
🟡 dist/src/compiled/@vercel/oidc/index.js          [#.......................] 379.5 kB 2.6%
🔴 Other published files                            [########################] 11.28 MB 76.5%
Installed footprint breakdown
Installed package size
🔴 @rolldown/binding-linux-x64-gnu [########################] 18.96 MB 35.2%
🔴 eve                             [#################.......] 13.46 MB 25.0%
🔴 ai                              [########................] 6.43 MB 11.9%
🔴 zod                             [######..................] 5.04 MB 9.4%
🟠 nitro                           [###.....................] 2.41 MB 4.5%
🟡 @ai-sdk/provider-utils          [#.......................] 852.0 kB 1.6%
🔴 Other installed packages        [#########...............] 6.75 MB 12.5%
Runtime dependencies (1)
Package Range Notes
nitro 3.0.260610-beta
Peer dependencies (5)
Package Range Notes
@opentelemetry/api ^1.0.0 optional peer
ai catalog:
braintrust ^3.0.0 optional peer
just-bash ^3.0.0 optional peer
microsandbox ^0.5.0 optional peer
eve init install drill-down

eve init install details

  • Command: eve init my-agent
  • Package manager: npm
  • Installed footprint: 92.30 MB across 7861 installed files
  • Installed packages: 122 total (116 transitive-only)
  • dependencies: 4 direct packages totaling 29.02 MB
  • devDependencies: 2 direct packages totaling 5.04 MB
  • Other transitive package files: 58.24 MB

Installed footprint is measured from an isolated temporary eve init my-agent using the current packed eve tarball.

Heavy installed dependencies

  • @typescript/typescript-linux-x64: 27.95 MB (30.3%)
  • @rolldown/binding-linux-x64-gnu: 18.96 MB (20.5%)
  • eve: 13.46 MB (14.6%)
  • zod: 9.00 MB (9.7%)
  • ai: 6.43 MB (7.0%)
Installed footprint breakdown
Installed package size
🔴 @typescript/typescript-linux-x64 [########################] 27.95 MB 30.3%
🔴 @rolldown/binding-linux-x64-gnu  [################........] 18.96 MB 20.5%
🔴 eve                              [############............] 13.46 MB 14.6%
🔴 zod                              [########................] 9.00 MB 9.7%
🔴 ai                               [######..................] 6.43 MB 7.0%
🟠 @types/node                      [##......................] 2.54 MB 2.8%
🔴 Other installed packages         [############............] 13.97 MB 15.1%
dependencies (4)
Package Range Installed size Share
@vercel/connect 0.4.2 135.8 kB 0.1%
ai ^7.0.34 6.43 MB 7.0%
eve file:eve-0.27.3.tgz 13.46 MB 14.6%
zod 4.4.3 9.00 MB 9.7%
devDependencies (2)
Package Range Installed size Share
@types/node 24.x 2.54 MB 2.8%
typescript 7.0.2 2.50 MB 2.7%
Function Drill-Down

Payload Size Graph

Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func     [########################] 7.27 MB 62.3%
🟠 functions/__server.func                         [###############.........] 4.41 MB 37.7%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 7.27 MB
Metric Value
Public routes /.well-known/workflow/v1/flow
Runtime nodejs24.x
Handler index.mjs
Payload 7.27 MB
Function files 7.27 MB across 39 files
Traced dependencies 0 B
Signal 🟠 Bundled file __eve_nitro_handler__.mjs is 2.71 MB (37.3%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 __eve_nitro_handler__.mjs       [########################] 2.71 MB 37.3%
🟡 _chunks/world-vercel.mjs        [########................] 903.2 kB 12.4%
🟡 _chunks/sandbox.mjs             [#######.................] 767.6 kB 10.6%
🟡 _libs/@ai-sdk/gateway+[...].mjs [####....................] 432.5 kB 6.0%
🟡 _chunks/token-util-B6qBs3-0.mjs [###.....................] 379.1 kB 5.2%
🟠 Other bundled files             [##################......] 2.08 MB 28.6%

🧾 Vercel Config

{
  "handler": "index.mjs",
  "launcherType": "Nodejs",
  "shouldAddHelpers": false,
  "supportsResponseStreaming": true,
  "runtime": "nodejs24.x",
  "environment": {
    "WORKFLOW_PRECONDITION_GUARD": "1",
    "NODE_OPTIONS": "--experimental-require-module"
  },
  "maxDuration": "max",
  "experimentalTriggers": [
    {
      "type": "queue/v2beta",
      "topic": "__eve776561746865722d6167656e74_wkf_workflow_*",
      "consumer": "default",
      "retryAfterSeconds": 5,
      "initialDelaySeconds": 0
    }
  ]
}

🟠 functions/__server.func • 10 public routes, 1 internal alias • 4.41 MB
Metric Value
Public routes /
/eve/v1/callback/[token]
/eve/v1/connections/[name]/callback/[token]
/eve/v1/health
/eve/v1/info
/eve/v1/session
/eve/v1/session/[sessionId]
/eve/v1/session/[sessionId]/cancel
/eve/v1/session/[sessionId]/stream
/eve/v1/session/reset
Internal aliases /__server
Runtime nodejs24.x
Handler index.mjs
Payload 4.41 MB
Function files 4.41 MB across 30 files
Traced dependencies 0 B
Signal 🟠 Bundled file _chunks/runtime-artifacts.mjs is 1.41 MB (32.0%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 _chunks/runtime-artifacts.mjs   [########################] 1.41 MB 32.0%
🟠 _chunks/world-vercel.mjs        [###############.........] 900.3 kB 20.4%
🟠 _chunks/sandbox.mjs             [#############...........] 767.6 kB 17.4%
🟡 _chunks/token-util-B6qBs3-0.mjs [######..................] 379.1 kB 8.6%
🟡 _chunks/dist-BX517Nmz.mjs       [######..................] 348.7 kB 7.9%
🟡 Other bundled files             [##########..............] 599.1 kB 13.6%

🧾 Vercel Config

{
  "handler": "index.mjs",
  "launcherType": "Nodejs",
  "shouldAddHelpers": false,
  "supportsResponseStreaming": true,
  "runtime": "nodejs24.x"
}

Build Timing: e2e/fixtures/agent-tools-sandbox

This is an informational timing measurement inside eve build, from preflight through publication. Output-size measurement and profile writing are excluded.

Build mode: deployable Vercel build with sandbox template prewarm included.

  • Build pipeline: 2.59 s -> 2.60 s (+6.7 ms) vs chad/trace-lifecycle-wiring (20d53bc).
  • Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `chad/trace-lifecycle-wiring (20d53bc)`
Phase Baseline Current Delta
extension.check 1.1 ms 1.2 ms +0.1 ms
project.resolve 0.6 ms 0.7 ms +0.1 ms
workspace.create 0.8 ms 0.8 ms 0.0 ms
host.prepare 178.5 ms 144.1 ms -34.4 ms
vercel.service-prefix.resolve 2.0 ms 2.5 ms +0.5 ms
nitro.app.create 26.8 ms 25.1 ms -1.7 ms
nitro.app.cache.prepare 0.2 ms 0.3 ms +0.1 ms
nitro.app.prepare 1.0 ms 1.0 ms 0.0 ms
nitro.app.public-assets 0.8 ms 0.7 ms -0.1 ms
nitro.app.prerender 0.5 ms 0.6 ms +0.1 ms
nitro.app.bundle 705.2 ms 700.4 ms -4.8 ms
nitro.app.cache.write 0.4 ms 0.4 ms 0.0 ms
sandbox.prewarm 242.1 ms 285.4 ms +43.3 ms
nitro.flow.create 189.4 ms 171.5 ms -17.9 ms
nitro.flow.cache.prepare 0.2 ms 0.2 ms 0.0 ms
nitro.flow.prepare 0.9 ms 0.9 ms 0.0 ms
nitro.flow.public-assets 0.1 ms 0.2 ms +0.1 ms
nitro.flow.prerender 0.0 ms 0.0 ms 0.0 ms
nitro.flow.bundle 1.06 s 1.09 s +27.2 ms
nitro.flow.cache.write 0.4 ms 0.4 ms 0.0 ms
nitro.flow.close 0.2 ms 0.2 ms 0.0 ms
workflow.emit 171.6 ms 165.3 ms -6.3 ms
agent-summary.emit 0.6 ms 0.6 ms 0.0 ms
nitro.app.close 0.0 ms 0.1 ms +0.1 ms
output.publish 3.7 ms 4.1 ms +0.4 ms
workspace.remove 5.9 ms 6.0 ms +0.1 ms

Comment thread packages/eve/src/harness/agent-otel-provider.ts Outdated
…removed, causing an unbounded memory leak in long-lived durable-agent processes.

This commit fixes the issue reported at packages/eve/src/harness/agent-otel-provider.ts:74

## Bug

In `createAgentOtelProvider` (`packages/eve/src/harness/agent-otel-provider.ts`), most per-scope maps are released as spans complete:

*   `modelContexts` — deleted in `afterModelCall`
*   `actions` — deleted in `afterToolCall`
*   `steps` — deleted in `onStepTerminal`
*   `turns` — deleted in `onSessionTransition`

But the session-scoped state was never released:

*   `sessionMetadata.set(event.sessionId, event)` happens on `session.started` and is only ever *read* in `onTurnStarted`; there was no `delete`.
*   `pendingSessionStarted.add(...)` happens on `session.started` and is only removed inside `onTurnStarted` (via `pendingSessionStarted.delete(...)`). A session that emits `session.started` but never a `turn.started` (e.g. created then abandoned) leaks its entry.

The old `onSessionTransition`:

```ts
const onSessionTransition = (event) => {
  if (event.turnId === undefined) return;
  const key = turnKey(event.sessionId, event.turnId);
  const turn = turns.get(key);
  if (turn === undefined) return;
  turn.span.addEvent(event.type);
  turn.span.end();
  turns.delete(key);
};
```

handles the terminal session events (`session.completed`, `session.failed`) and `session.waiting`, but it only ended/removed the turn span. It never touched `sessionMetadata` / `pendingSessionStarted`.

### Failure mode

A durable runtime process that serves many sessions over its lifetime accumulates one `SessionMetadata` entry per session in `sessionMetadata` (and potentially a `pendingSessionStarted` entry for abandoned sessions) that is **never freed**, even after the session completes or fails. Over a long-lived process this grows without bound and eventually exhausts memory — directly undermining the observability-for-long-lived-agents purpose of the feature.

## Fix

Reworked `onSessionTransition` so that:

1.  The turn-span teardown logic still runs only when `turnId` is defined and a matching turn exists (unchanged behavior), but it no longer early-returns and skips session cleanup.
2.  Session-scoped state (`sessionMetadata`, `pendingSessionStarted`) is deleted **only on terminal transitions** (`session.completed` / `session.failed`).

`session.waiting` is intentionally excluded because it is not terminal — the session may resume with a new turn that still needs the metadata/channel info.

```ts
const onSessionTransition = (event) => {
  if (event.turnId !== undefined) {
    const key = turnKey(event.sessionId, event.turnId);
    const turn = turns.get(key);
    if (turn !== undefined) {
      turn.span.addEvent(event.type);
      turn.span.end();
      turns.delete(key);
    }
  }
  if (event.type === "session.completed" || event.type === "session.failed") {
    sessionMetadata.delete(event.sessionId);
    pendingSessionStarted.delete(event.sessionId);
  }
};
```

The `event.type` literal-union narrowing is type-safe against `InstrumentationSessionTransitionEvent` (`"session.completed" | "session.failed" | "session.waiting"`). No installed toolchain was available in the sandbox to run `tsc`, but the change introduces no new symbols and relies only on existing literal narrowing.


Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Co-authored-by: chietala <chad.hietala@vercel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant