eve
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 and evlog versions in production agents.Add evlog wide events to my eve agent
When to use what
| Need | Use |
|---|---|
| Debug a session in Vercel | eve Agent Runs (automatic) |
| Span-level traces in Datadog / Honeycomb | eve agent/instrumentation.ts + OTel exporter |
| Wide events to Axiom / Better Stack / FS, billing, audit, tail sampling | evlog/eve |
Quick Start
1. Install
pnpm add evlog eve
bun add evlog eve
yarn add evlog eve
npm install evlog eve
2. Add the hook
Create 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:
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:
{
"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
| Option | Description |
|---|---|
init | Passed to initLogger() on first hook invocation |
drain / enrich / keep / plugins | Same as HTTP integrations (plugins) |
redactMessage | Default true — omits user message text from the wide event |
include / exclude | Route-style filters on turn paths (/sessions/*/turns/*) |
Tail sampling
Use keep to force-keep turns with failed tools or high token usage:
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.
What to read next
- eve hooks guide — stream event vocabulary
- eve instrumentation — OTel spans (complementary)
- AI SDK use case — when you own the model loop directly
- Adapters overview — drain destinations
Enrichers
Add derived context to every wide event automatically — user agent, geo, request size, and trace context. Built-in enrichers from evlog/enrichers, plus how to compose them with your own.
Overview
Observe what flows through the pipeline (stream, fs reader, consumer recipes), plug into the pipeline (plugins, enrichers, tail sampling, identity headers), or build your own bricks (custom drains, drain pipeline, custom framework integration).