Eve

Eve Integration

Source Code
Export one evlog wide event per Eve agent turn — token usage, tool executions, business context, drains, enrichers, and tail sampling alongside Agent Runs and OpenTelemetry.

Eve ships built-in observability: Agent Runs on Vercel and optional OpenTelemetry spans via agent/instrumentation.ts. evlog/eve adds a third layer — exportable wide events per turn with your full evlog pipeline (drains, enrichers, tail sampling, audit).

Eve is currently in beta; hook and stream event shapes may change before GA. Pin eve and evlog versions in production agents.

Add evlog wide events to my Eve agent

When to use what

NeedUse
Debug a session in VercelEve Agent Runs (automatic)
Span-level traces in Datadog / HoneycombEve agent/instrumentation.ts + OTel exporter
Wide events to Axiom / Better Stack / FS, billing, audit, tail samplingevlog/eve

Quick Start

1. Install

pnpm add evlog eve

2. Add the hook

Create agent/hooks/evlog.ts:

agent/hooks/evlog.ts
import { defineEvlogHook } from 'evlog/eve'
import { createAxiomDrain } from 'evlog/axiom'

export default defineEvlogHook({
  init: { env: { service: 'my-agent' } },
  drain: createAxiomDrain(),
  enrich: (ctx) => {
    ctx.event.region = process.env.VERCEL_REGION
  },
})

Eve auto-discovers hook files under agent/hooks/. No HTTP middleware — the unit of work is an agent turn, not a request.

3. Log business context from tools

In the example agent, support tools attach customer and order context as the agent works a refund:

agent/tools/lookup_order.ts
import { defineTool } from 'eve/tools'
import { useTurnLogger } from 'evlog/eve'
import { z } from 'zod'

export default defineTool({
  description: 'Look up an order by id.',
  inputSchema: z.object({ orderId: z.string() }),
  async execute({ orderId }, ctx) {
    const order = await fetchOrder(orderId)
    const log = useTurnLogger(ctx)
    log.set({ order: { id: order.id, amount: order.amount, status: order.status } })
    return order
  },
})

4. Next.js web chat (optional)

Wrap next.config.ts with withEve() from eve/next and use useEveAgent() from eve/react in your app. Eve starts alongside next dev and proxies /eve/v1/* on the same origin — tool calls, approvals, and ask_question work out of the box. See the example agent.

Wide event shape

Each completed turn emits one event:

Wide Event — support refund turn
{
  "method": "EVE",
  "path": "/sessions/sess_abc/turns/turn_0",
  "status": 200,
  "duration": "4.2s",
  "service": "clearbill-support-agent",
  "eve": {
    "sessionId": "sess_abc",
    "turnId": "turn_0",
    "turnSequence": 0
  },
  "customer": { "slug": "acme-corp", "plan": "enterprise", "mrr": 2400 },
  "order": { "id": "4821", "amount": 890, "currency": "USD" },
  "refund": { "orderId": "4821", "amount": 890, "requiresApproval": true },
  "audit": { "action": "refund.issued", "actor": { "type": "agent", "id": "" }, "target": { "type": "order", "id": "4821" } },
  "ai": {
    "calls": 3,
    "steps": 3,
    "inputTokens": 3312,
    "outputTokens": 814,
    "tools": [
      { "name": "lookup_customer", "success": true },
      { "name": "lookup_order", "success": true },
      { "name": "issue_refund", "success": true }
    ]
  }
}

Token usage and tool executions are accumulated from Eve stream events (step.completed, action.result). Eve owns the model loop — you do not wrap the model with evlog/ai.

Options

OptionDescription
initPassed to initLogger() on first hook invocation
drain / enrich / keep / pluginsSame as HTTP integrations (plugins)
redactMessageDefault true — omits user message text from the wide event
include / excludeRoute-style filters on turn paths (/sessions/*/turns/*)

Tail sampling

Use keep to force-keep turns with failed tools or high token usage:

agent/hooks/evlog.ts
export default defineEvlogHook({
  drain: createAxiomDrain(),
  keep: (ctx) => {
    const ai = ctx.context.ai as { totalTokens?: number, tools?: Array<{ success: boolean }> } | undefined
    if ((ai?.totalTokens ?? 0) > 10_000) ctx.shouldKeep = true
    if (ai?.tools?.some(t => !t.success)) ctx.shouldKeep = true
  },
})

Audit logs

Combine with Audit Logs: register auditEnricher() via init.plugins or a global plugin, and call log.audit() inside tools when a human approval gate fires. Tool rejections surface on action.result with status: "rejected".

Run locally

git clone https://github.com/HugoRCD/evlog
cd evlog
pnpm install
pnpm run example:eve

The examples/eve project is a support refund copilot (Clearbill SaaS): lookup customer → lookup order → issue refund, with Eve approvals when amount > $100. Run pnpm run example:eve, open http://localhost:3000, and click a starter prompt.