Agent Skills › MapleTechLabs/maple › maple-agent-tracing-eve

maple-agent-tracing-eve

GitHub

为 Vercel eve 框架集成 Maple 可观测性,通过添加 OpenTelemetry 配置实现 Agent 会话追踪、工具调用及 Token 统计。

skills/maple-agent-tracing-eve/SKILL.md MapleTechLabs/maple

触发场景

trace my eve agent add Maple to eve agent sessions for eve OpenTelemetry for eve

安装

npx skills add MapleTechLabs/maple --skill maple-agent-tracing-eve -g -y
更多选项

不安装直接使用

npx skills use MapleTechLabs/maple@maple-agent-tracing-eve

指定 Agent (Claude Code)

npx skills add MapleTechLabs/maple --skill maple-agent-tracing-eve -a claude-code -g -y

安装 repo 全部 skill

npx skills add MapleTechLabs/maple --all -g -y

预览 repo 内 skill

npx skills add MapleTechLabs/maple --list

SKILL.md

Frontmatter
{
    "name": "maple-agent-tracing-eve",
    "description": "Trace eve agents (Vercel's eve framework, npm `eve`) with Maple: add one OpenTelemetry destination file under agent\/instrumentation\/ so each eve session is one Maple Agent Session with transcript, tool calls, subagent lanes, approvals and tokens. Covers eve dev, eve start, the channel audience that gates message content, and dropping the workflow engine's spans. Triggers on 'trace my eve agent', 'add Maple to eve', 'agent sessions for eve', 'OpenTelemetry for eve'."
}

Maple agent tracing: eve

Goal

One eve session (wrun_...) = one Maple Agent Session. One user message = one turn = one trace rooted at invoke_agent <agent>, with agent.step spans holding a chat <model> span (model, provider, tokens, messages) and execute_tool <tool> spans (arguments, result, failures). Subagents nest inside the caller's trace and show as their own lanes.

eve owns the tracer provider and writes gen_ai.conversation.id (the root session id) on every agent span. You add a destination; you never start an SDK and never pass a conversation id.

Known gaps (tell the user, don't try to fix):

  • Outside eve dev, message content is exported only for public conversations (Step 4).
  • Cost shows as unpriced with a model called directly at its provider. With Vercel AI Gateway, eve writes gen_ai.usage.cost on the agent.step span; Maple counts it in the session total (the per-model table has tokens, not cost).
  • eve does not log failed exports (Step 6).

Step 0: Detect

  • eve version in package.json / lockfile.
    • >= 0.62: this skill. Exercised on 0.62.0, 0.70.3, 0.72.1, 0.77.0 and 0.78.0 with the Step 2/3 files unchanged; every version produced complete sessions in Maple.
    • 0.62 to 0.71: each tool call is an agent.action span wrapping execute_tool. Maple shows the wrapper as a structure row and counts one tool call. Expected.
    • < 0.62: telemetry lives in agent/instrumentation.ts (defineInstrumentation({ setup }) calling registerOTel), and eve ignores agent/instrumentation/ without an error: the Step 2 files export nothing (tested on 0.61.1). With experimental: { instrumentationProviders: true } in agent.ts they export, but the exportPolicy is ignored and every workflow span goes out. Don't use the flag: upgrade (npm install eve@latest), delete agent/instrumentation.ts (until then eve build fails with Found removed instrumentation file), remove the flag, then do Steps 2-3. Move every other exporter from the old setup into its own otelIntegration({ traceExporter }) file; serviceName becomes otel({ resource }), functionId becomes otel({ functionId }), events["step.started"] runtime context becomes otelIntegration({ runtimeContext }). See https://eve.dev/docs/observability/instrumentation-migration.
    • Tell the user: from 0.35 to 0.61 the old file recorded no content unless recordInputs/recordOutputs were set (before 0.35 it recorded content by default); after the upgrade, content is recorded during eve dev and for public conversations (Step 4). The first eve dev after the upgrade deletes the local .eve/.workflow-data (incompatible storage layout), so open local dev sessions are lost.
  • Node.js >= 24 at runtime; eve enforces it. bun or pnpm as the package manager is fine.
  • Layout: one agent in agent/, or a workspace with agents/<name>/agent/. In a workspace add the files to each member's agent/instrumentation/ (not exercised; run Step 7 per member).
  • Existing files in agent/instrumentation/:
    • An otel() file: add the resource attributes from Step 3 to it. Two otel() files are a boot error.
    • Other otelIntegration() files (Honeycomb, Braintrust, Datadog...): keep them. Maple is one more file; each destination has its own exportPolicy.
    • agent-runs.ts, local.ts: leave them.
  • Search for NodeSDK, registerOTel(, registerTelemetry(, @ai-sdk/otel, NodeTracerProvider. eve replaces all of them with otelIntegration(); don't add one, and tell the user if one exists.
  • eve depends on ai. Use this skill, not maple-agent-tracing-vercel-ai-sdk.
  • agent/skills/maple-agent-tracing-eve/ exists (an npx skills add run in an eve project installs into the eve agent's own skills, and skills-lock.json records it): it would ship with the agent as a runtime skill. Tell the user and remove both the directory and its skills-lock.json entry once setup is done, unless they want it there.
  • Models: a string id in agent.ts (model: "openai/gpt-…") runs through Vercel AI Gateway; a provider object (openai() from eve/models/openai, createOpenRouter(...), anthropic()) calls the provider directly. This decides the cost line in Step 7.

Step 1: Key and region

  • US https://ingest.maple.dev/v1/traces, EU https://ingest.eu.maple.dev/v1/traces. The exporter takes the full URL. Header authorization: Bearer <key>.
  • Key in the user's prompt: use it. No key: use the literal MAPLE_TEST (ingest accepts and discards it) and tell the user to replace it with their key from Settings → Ingestion.
  • Private maple_sk_ keys never go in browser code. Ingest keys are write-only.
  • eve loads .env.local for eve dev and eve start: put MAPLE_INGEST_KEY=<key> there (check it is gitignored). Deployments read the host's environment variables.
  • Instrumentation files run at server start, not at build: eve build works without the key.
  • Never let an unset variable become Bearer undefined. When the key is missing, log one warning and export disableInstrumentation() so the agent runs normally (Step 2 does this).
  • A 401 ingest_unauthorized with a key you trust usually means the key belongs to the other region: try the other endpoint.

Step 2: Install and add the destination

npm install @vercel/otel

Use the repo's package manager. Create agent/instrumentation/maple.ts:

import { OTLPHttpProtoTraceExporter } from "@vercel/otel"
import { disableInstrumentation } from "eve/instrumentation"
import { otelIntegration } from "eve/instrumentation/otel"

// A missing key disables export; it never stops the agent.
const mapleKey = process.env.MAPLE_INGEST_KEY
if (!mapleKey) console.warn("MAPLE_INGEST_KEY is not set; Maple telemetry export is disabled")

export default mapleKey
	? otelIntegration({
			traceExporter: new OTLPHttpProtoTraceExporter({
				url: "https://ingest.maple.dev/v1/traces",
				headers: { authorization: `Bearer ${mapleKey}` },
			}),
			// Keep the spans of a conversation; drop the workflow engine's own
			exportPolicy: { span: ({ attributes }) => ({ emit: "gen_ai.conversation.id" in attributes }) },
		})
	: disableInstrumentation()
  • The file name is free; it must default-export the integration.
  • eve wraps traceExporter in its own batch processor (5 s delay, flushes on shutdown). Don't wrap it in a BatchSpanProcessor yourself.
  • The exportPolicy is required in practice. eve's second scope, workflow, is the durable-execution engine: workflow.*, world.*, step.*, hook.resume, queue.publish, including one workflow.stream.flush span per streamed chunk. In two test runs it was 1,031 of 1,060 and 1,794 of 1,829 spans, all in traces of their own with no gen_ai.conversation.id.
  • The policy decides at span start. Every eve agent span has gen_ai.conversation.id at start. Per eve's docs the id is also on third-party instrumentation spans created during model, tool and memory execution; spans outside those (for example agent.channel.request with traceChannelRequests: true) are dropped by this policy.
  • The user wants the workflow spans too: remove exportPolicy and tell them the volume.

Step 3: Service name and environment

Without settings, service.name is the package.json name. Create agent/instrumentation/otel.ts, or extend the existing otel() file:

import { otel } from "eve/instrumentation/otel"

export default otel({
	resource: {
		"service.name": "support-agent",
		"deployment.environment.name": process.env.VERCEL_ENV ?? "development",
	},
})
  • Use the app's own environment variable for the environment (VERCEL_ENV on Vercel).
  • gen_ai.agent.name is the package.json name for the root agent and the directory name for a declared subagent (agent/subagents/<name>/). They are the lane names in Maple.

Step 4: Content and audience

eve attaches content to spans only when the conversation's audience allows it. The channel assigns the audience once, when the session starts:

Runs as Audience Content exported
eve dev any yes
preview / production (eve start, Vercel) public yes
preview / production private / unknown no
  • Without content the session still has turns, model calls, tools, tokens and failures. Missing: gen_ai.input.messages, gen_ai.output.messages, gen_ai.system_instructions, gen_ai.tool.definitions, gen_ai.tool.call.arguments, gen_ai.tool.call.result, the session title and the turn labels.
  • Defaults: HTTP channel (eveChannel): authenticated user/service/runtime principals are private, anonymous callers unknown. Slack: public channels public; DMs, group DMs and private channels private.
  • otel({ tracePolicy }) cannot widen this. Tested on eve start with a private caller and a policy returning { emit: true, recordInputs: true, recordOutputs: true }: the spans say agent.trace.content.input=true and still carry no content. The policy only narrows.
  • The lever is the channel. HTTP channel: eveChannel({ auth: [...], audience: "public" }) in agent/channels/eve.ts. The file replaces the whole default channel, so keep the auth list the project already uses. audience also takes a function; a custom channel has an audience() hook. See https://eve.dev/docs/channels/overview#audience.
  • Ask the user before setting audience: "public". It is a data decision: it applies to every trace destination, including Vercel Agent Runs, not only Maple. Don't set it on your own.
  • To keep content out of Maple while other destinations keep it, add a second policy to the Maple destination:
exportPolicy: [
	{ span: ({ attributes }) => ({ emit: "gen_ai.conversation.id" in attributes }) },
	{ span: () => ({ redact: true, inputs: true, outputs: true }) },
],
  • Each content attribute is capped at 32,768 characters by eve.

Step 5: Tools, subagents, approvals

  • A tool's span name and gen_ai.tool.name are its file name under agent/tools/.
  • Failures must throw. Thrown: span status ERROR with the message, error.type=ACTION_RESULT_FAILED, an exception event; Maple counts the tool call as failed. A returned { error } counts as success.
  • Declared subagents: the call is execute_tool <subagent> and returns a task receipt within ~0.1 s; the child's invoke_agent <subagent> nests under it in the same trace. In Maple the lane's result is the receipt text ("Started task ..."), and the real result arrives through the framework tool eve__task_wait. Expected.
  • Framework tools (eve__task_wait, bash, read_file...) are tool calls like any other.
  • Approvals (approval: always() and friends): eve adds an agent.approval span under the tool call. The turn stays open while it waits, so the wait counts toward the turn's and the tool call's duration. A denied call is a failed tool call with error.type=TOOL_EXECUTION_DENIED, which raises Maple's "Tool errors" check. Expected.
  • Tokens: invoke_agent spans repeat the turn total and agent.step repeats the call's usage under agent.usage.*. Maple counts the chat spans only; totals are not doubled.

Step 6: Flush and silent failures

  • Add no flush code. On eve start, a SIGTERM right after a turn still delivered every span. Vercel deployments were not exercised.
  • eve does not report a failed export, also not with EVE_LOG_LEVEL=warn. A wrong key or region looks exactly like no traffic. Test the key directly:
curl -s -w "%{http_code}\n" -X POST https://ingest.maple.dev/v1/traces \
  -H "Authorization: Bearer <key>" \
  -H "Content-Type: application/json" -d '{"resourceSpans":[]}'

200 = valid. 401 prints the reason, including the right endpoint when the key is from the other region.

Step 7: Verify

Run one real conversation: eve dev (or eve dev --no-ui plus a script on eve/client), 2+ messages in one session, one of them calling a tool; plus a second session. If the project has subagents or an approval-gated tool, exercise each once. Then check (Maple MCP list_agent_sessions filtered by service, get_agent_session_transcript, or the Agent Sessions page, ~30 s after the run):

  • The startup log has no MAPLE_INGEST_KEY is not set.
  • One session per eve session, id wrun_...; the second session is separate; no trace:<id> sessions.
  • One turn per user message, labeled with the message. A turn paused for an approval is still one turn.
  • Transcript shows user messages, the system instructions, assistant replies and tool calls with arguments and results.
  • Every chat <model> span has model, provider, input and output tokens. LLM calls = number of chat spans.
  • A throwing tool is failed with its message; successful tools are not.
  • Subagents show as lanes named after their directory, inside the calling turn.
  • No span named workflow.*, world.*, step.*, hook.* or queue.* for the service (Maple MCP search_traces, or the Traces page).
  • Framework shows eve, not Unidentified.
  • Cost: present for AI Gateway models, unpriced for direct provider models (see Known gaps).
  • Then start the production build once (eve build && eve start) and send one message. Expect the session without content unless the audience is public; tell the user which it is.

Without Maple access: the curl check in Step 6 returns 200, the startup log is clean, and a conversation ran. That shows delivery is possible, not that spans arrived; say so.

Do not

  • Do not start NodeSDK, registerOTel or registerTelemetry, and do not add @ai-sdk/otel, OpenLLMetry or OpenInference: eve already traces every model call.
  • Do not stamp gen_ai.conversation.id or maple_ai.session.id yourself.
  • Do not add a second otel() file.
  • Do not set audience: "public" without the user's decision.

版本历史

  • 27a645c 当前 2026-10-18 23:11

同 Skill 集合

.agents/skills/clickhouse-architecture-advisor/SKILL.md
.agents/skills/clickhouse-best-practices/SKILL.md
.agents/skills/clickhousectl-cloud-deploy/SKILL.md
.agents/skills/clickhousectl-local-dev/SKILL.md
.agents/skills/coss-particles/SKILL.md
.agents/skills/coss/SKILL.md
.agents/skills/react-doctor/SKILL.md
.agents/skills/tinybird-cli-guidelines/SKILL.md
.agents/skills/tinybird-python-sdk-guidelines/SKILL.md
.agents/skills/tinybird-typescript-sdk-guidelines/SKILL.md
.agents/skills/tinybird/SKILL.md
.context/effect/.agents/skills/grill-me/SKILL.md
.context/effect/.agents/skills/jsdocs/SKILL.md
.context/effect/.agents/skills/scratchpad/SKILL.md
.factory/skills/react-doctor/SKILL.md
apps/slack-agent/agent/skills/dashboard-builder/SKILL.md
apps/slack-agent/agent/skills/incident-investigation/SKILL.md
skills/maple-agent-tracing-agno/SKILL.md
skills/maple-agent-tracing-claude-agent-sdk/SKILL.md
skills/maple-agent-tracing-crewai/SKILL.md
skills/maple-agent-tracing-dspy/SKILL.md
skills/maple-agent-tracing-genkit/SKILL.md
skills/maple-agent-tracing-google-adk/SKILL.md
skills/maple-agent-tracing-haystack/SKILL.md
skills/maple-agent-tracing-litellm/SKILL.md
skills/maple-agent-tracing-llamaindex/SKILL.md
skills/maple-agent-tracing-mastra/SKILL.md
skills/maple-agent-tracing-microsoft-agent-framework/SKILL.md
skills/maple-agent-tracing-openrouter/SKILL.md
skills/maple-agent-tracing-opentelemetry/SKILL.md
skills/maple-agent-tracing-pydantic-ai/SKILL.md
skills/maple-agent-tracing-smolagents/SKILL.md
skills/maple-agent-tracing-spring-ai/SKILL.md
skills/maple-agent-tracing-strands/SKILL.md
skills/maple-agent-tracing-vercel-ai-sdk/SKILL.md
skills/maple-audit/SKILL.md
skills/maple-csharp-style/SKILL.md
skills/maple-effect-style/SKILL.md
skills/maple-go-style/SKILL.md
skills/maple-java-style/SKILL.md
skills/maple-kotlin-style/SKILL.md
skills/maple-nextjs-style/SKILL.md
skills/maple-nodejs-style/SKILL.md
skills/maple-onboard/SKILL.md
skills/maple-onboarding-style/SKILL.md
skills/maple-python-style/SKILL.md
skills/maple-rust-style/SKILL.md
.agents/skills/chdb-datastore/SKILL.md
.agents/skills/chdb-sql/SKILL.md

元信息

文件数
0
版本
27a645c
Hash
273e30b1
收录时间
2026-10-18 23:11

首页 - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-10-20 00:09
浙ICP备14020137号-1