Repository navigation
fix(vercel): keep eve 0.76 agent.step and agent.approval spans as CHAIN - #4007
Open
jimbobbennett wants to merge 3 commits into
Open
jimbobbennett wants to merge 3 commits into
jimbobbennett wants to merge 3 commits into
Conversation
@arizeai/openinference-core
@arizeai/openinference-genai
@arizeai/openinference-instrumentation-anthropic
@arizeai/openinference-instrumentation-bedrock
@arizeai/openinference-instrumentation-bedrock-agent-runtime
@arizeai/openinference-instrumentation-beeai
@arizeai/openinference-instrumentation-claude-agent-sdk
@arizeai/openinference-instrumentation-langchain
@arizeai/openinference-instrumentation-langchain-v0
@arizeai/openinference-instrumentation-mcp
@arizeai/openinference-instrumentation-openai
@arizeai/openinference-instrumentation-openai-agents
@arizeai/openinference-instrumentation-typesafe
@arizeai/openinference-semantic-conventions
@arizeai/openinference-tanstack-ai
@arizeai/openinference-vercel
commit: |
eve 0.76 sets operation.name and gen_ai.operation.name to "workflow" on its agent.step and agent.approval spans and moves the span name to resource.name. Neither matched the eve span-kind map, so both fell through to the GenAI converter's LLM default and a turn reported twice as many LLM spans as model calls. Match resource.name against the map as well. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L6w89c59Ev5pKTN2eqZ9WA
Apply the resource.name lookup only when gen_ai.operation.name is missing or "workflow", so a span with a recognized gen_ai operation keeps its kind. Add tests for the agent-identity guard, gen_ai precedence, an AI SDK span whose functionId is agent.step, and the eve 0.75 shape with resource.name set, and set operation.name explicitly on the eve 0.76 cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L6w89c59Ev5pKTN2eqZ9WA
jimbobbennett
force-pushed
the
fix/vercel-eve-workflow-span-kind
branch
from
October 9, 2026 23:25
c3eed7a to
3b945c2
Compare
…orkflow Drop the missing-operation case so only eve 0.76 spans classify differently from before. Add a test for a span with resource.name agent.step and no gen_ai operation, and a parity test that an eve 0.76 agent.step gets the same OpenInference attributes as an eve 0.75 one. Update the changeset and the eve map comment to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L6w89c59Ev5pKTN2eqZ9WA
jimbobbennett
marked this pull request as ready for review
October 10, 2026 00:06
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #4008
Summary
Eve 0.76.0 (published 2026-10-09 17:28 UTC) changed the attributes on its
agent.stepandagent.approvalcontrol-flow spans, and@arizeai/openinference-vercel3.2.4 classifies them as LLM again. A turn now reports twice as many LLM spans as model calls. The fix that 3.2.3 shipped in #3877 no longer applies to these spans.Cause
getOISpanKindFromAttributeslooks up Eve control-flow spans inEveOperationNameToSpanKindMapbyoperation.name. Eve 0.76.0 no longer setsoperation.nameto the span name:agent.stepoperation.nameagent.stepworkflowgen_ai.operation.nameworkflowresource.nameagent.stepagent.stepopeninference.span.kindCHAINLLMIn Eve's published
dist/src/tracing/agent-otel-runtime-context.js(0.76.0), the step span is built with"gen_ai.operation.name": "workflow", ...agentSpanNamingAttributes("agent.step", "workflow"), whereagentSpanNamingAttributes(name, op)returns{ "operation.name": op, "resource.name": name }.agent-approval-instrumentation.jsdoes the same foragent.approval. Sinceworkflowisn't a key in the Eve map or inGenAIOperationNameToSpanKindMap, the span falls through to the GenAI converter, whosemapSpanKinddefaults to LLM for an unrecognized operation.Fix
When the existing lookups miss and
gen_ai.operation.nameisworkflow, also matchresource.nameagainstEveOperationNameToSpanKindMap. See Backward compatibility for the exact conditions.I also considered mapping
gen_ai.operation.name: "workflow"to CHAIN. I didn't, becauseworkflowisn't a GenAI semconv operation value (the spec value isinvoke_workflow), and keying on Eve's span identity matches the map's existing purpose.Backward compatibility
Only Eve 0.76 spans change: those with
gen_ai.operation.name=workflowand aresource.namein the Eve map. Every other span classifies exactly as it does onmain.getOISpanKindFromAttributesnow checks, in order:openinference.span.kind(unchanged).operation.nameagainst the AI SDK map, then the Eve map when the span has nogen_ai.agent.*identity (unchanged).resource.nameagainst the Eve map. This applies only when all of these hold:gen_ai.agent.*identity (the same guard as step 2);gen_ai.operation.nameis exactlyworkflow, which is the Eve 0.76 shape. A span with nogen_ai.operation.namenever reaches this check.gen_ai.operation.nameagainst the GenAI map (unchanged), then the GenAI converter's default.Unchanged:
operation.nameresolves them at step 2, beforeresource.name(their functionId) is read.gen_ai.operation.name(chat,execute_tool,invoke_agent,decide, and so on): step 3 doesn't apply, so it keeps its GenAI kind.gen_ai.operation.name, even ifresource.nameisagent.step: step 3 doesn't apply, so they keepmain's kind.Tests: new cases in
OpenInferenceSpanProcessor.test.ts:agent.step(workflow+resource.name=agent.step)agent.approvalagent.stepgets exactly the same OpenInference attributes as Eve 0.75 (parity)agent.stepwithresource.namealso setgen_ai.agent.name(guard)resource.name=agent.step,gen_ai.operation.name=chat, unmappedoperation.name(precedence)resource.name=agent.step, nogen_ai.operation.name, unmappedoperation.nameai.generateTextwhose functionId andresource.nameareagent.stepTo show that nothing else changed, I ran the full test file against
main'ssrc/utils.tsandsrc/constants.ts. Only the three Eve 0.76 tests fail there (the two cases and the parity test). Every other new and existing test gives the same result onmainand on this branch.Verification
openinference-vercel: 183 tests pass, andtype:check,oxlintandoxfmt --checkare clean. The branch is rebased onto the latestmain(including feat: support AI SDK decision model telemetry #4005).anthropic/claude-sonnet-4.6turn with aget_weathertool gated byapproval: always()and approved through the session API, and spans exported back from Arize AX. Every run used a fresh scaffold and its own project.This branch, final version (packed 3.3.0 tarball,
workflow-only check):agent.stepagent.approvalchatspansVersion matrix, run on the previous commit (3b945c2). Versions before 0.76 resolve at the
operation.namelookup, which no later commit touches:agent.stepagent.approvalagent.actionoperation.nameonagent.*workflowIn every run,
chatspans are LLM,execute_toolis TOOL andinvoke_agentis AGENT. The LLM count always equals thechatcount (2). Eve 0.62–0.66 start a secondinvoke_agenttrace when the turn resumes after approval; that's Eve behavior and unrelated to this change.Before the fix (published 3.2.4, no approval tool): Eve 0.75.1 had
agent.stepas CHAIN in 2/2 runs. Eve 0.76.0 had bothagent.stepspans as LLM in 7/7 runs (4 LLM spans for 2chatspans), so the failure is deterministic. The first version of this branch then gave CHAIN in 8/8 runs on 0.76.0.Review
openinference has no TypeScript reviewer skill, so I applied
.agents/skills/python-code-reviewerand.agents/skills/java-code-reviewerto this TypeScript change, adapting the language-specific parts. I also checked.agents/skills/js-docs-sync.dist/src/tracing/*.jsin 0.62.0, 0.66.3, 0.71.3, 0.75.1 and 0.76.0) and against raw span attributes captured from real turns. The only shape that setsoperation.name/gen_ai.operation.nametoworkflowis 0.76.0.session.id, so they wouldn't catch extra or missing attributes on the reclassified spans. Resolved: added a parity test that asserts an Eve 0.76agent.stepgets exactly the same attributes as the matching Eve 0.75 span, apart from the two raw operation-name attributes. Real exports agree: on both versions, the only non-Eve attributes onagent.stepandagent.approvalareopeninference.span.kind,session.idand (approvals)tool_call.id.EveOperationNameToSpanKindMapcomment still described matchingresource.nameunconditionally. Resolved: both now say it applies only whengen_ai.operation.nameisworkflow."resource.name"and"workflow"are string literals. Kept as is: the surrounding lookups ("operation.name","gen_ai.operation.name") use literals too, and Eve exports no constants for these.TraceConfigmasking, context propagation and span lifecycle. This change only affects how an already-ended span's kind is derived; it doesn't create spans, wrap calls or add attributes.openinference-vercelhas nodocs/folder (onlyopeninference-coredoes), and the change adds no exports or public API. The README doesn't describe Eve span kinds, so it needs no update.A second pass over the final diff found nothing further.
🤖 Generated with Claude Code
https://claude.ai/code/session_01L6w89c59Ev5pKTN2eqZ9WA