Repository navigation
Conversation
JeremyFunk
added a commit
that referenced
this pull request
Sep 28, 2026
…ey are valid UTF-8 Review fix for #16. Binary that happens to be valid UTF-8 was stored as control-character text: all-zero bytes became NULs instead of "", and [0x01, 0x02, 0x7f] became "\u0001\u0002\u007f" instead of "01027f". The text path now also requires no control characters other than tab, LF and CR, on both the Rust encoder and its apps/cli port. The port's TextDecoder also keeps a leading BOM (`ignoreBOM`), as Rust's from_utf8 does.
JeremyFunk
added a commit
that referenced
this pull request
Sep 29, 2026
* fix(agent-sessions): fingerprint the OpenInference, .NET and TypeScript scopes of known frameworks
Symptom: sessions from OpenInference's LangChain and LlamaIndex
instrumentors, the .NET Agent Framework, Strands TypeScript under a custom
service.name and OpenInference's TypeScript OpenAI Agents instrumentor were
listed as "Unidentified" (unknown:genai / unknown:openinference per span).
Cause: scope_facts matched none of these scopes. OpenInference's langchain
and llama_index scopes only set the generic foreign-OpenInference flag;
`Experimental.Microsoft.Agents.AI` and
`@arizeai/openinference-instrumentation-openai-agents` matched nothing; the
Strands TS SDK names both its tracer and `gen_ai.provider.name` (or
`gen_ai.system`) after the service, so a custom service.name hid its
"strands-agents" marker.
Fix: map the scopes to langchain, llamaindex, microsoft_agent_framework and
openai_agents_sdk; detect Strands when the scope and the provider both equal
service.name. langchain and llamaindex also read OpenInference's `session.id`
and the `gen_ai.conversation.id` dual-write as session keys.
Seen in: docs_langchain_a, docs_llamaindex_a,
docs_microsoft-agent-framework_net, docs_strands_ts, docs_openai-agents_ts.
* fix(agent-sessions): detect Vercel AI SDK v7 spans without ai.* keys and read runtimeContext session ids
Symptom: with the AI SDK v7 OpenTelemetry integration, chat, invoke_agent
and execute_tool spans fell to unknown:genai unless the app enabled the
`usage` supplemental attributes, and an id passed as
`runtimeContext: { sessionId }` did not group the session, so the guide had
to require `usage: true`, `runtimeContext: true` and an `enrichSpan` hook.
Cause: detect_vercel_ai_sdk required an `ai.*` key even inside the SDK's own
scope; v7 writes those keys only for opted-in supplemental attributes. The
session keys did not include `ai.settings.context.*`, where the SDK writes
runtime context.
Fix: inside the `ai`/`gen_ai` scopes a `gen_ai.operation.name` is enough.
`ai.settings.context.sessionId` and `ai.settings.context.conversationId` are
read after `gen_ai.conversation.id`.
Seen in: docs_vercel-ai-sdk_a / _b (ai 7.0.54, @ai-sdk/otel tracer "gen_ai").
* fix(agent-sessions): detect Spring AI chat spans from any model starter
Symptom: Spring AI chat calls through a non-OpenAI starter (Anthropic,
Ollama, Bedrock, ...) fell to unknown:genai whenever the call had no tools,
so the session lost its framework.
Cause: detect_spring_ai only accepted a bare chat span in the
org.springframework.boot scope when `gen_ai.system=openai`. A model
starter's chat observation carries only `gen_ai.*`, with its own provider as
`gen_ai.system`; `spring.ai.*` keys appear only when tools are attached.
Fix: any `gen_ai.operation.name` in the Boot scope is Spring AI. The scope's
other spans (HTTP server/client) carry no operation name.
Seen in: docs_spring-ai_a / _b / _agent (chat spans without tools carry no
spring.ai.* key).
* fix(agent-sessions): stop reading an agent_step operation as Vercel AI SDK evidence
Symptom: any span with `gen_ai.operation.name=agent_step` was stamped
vercel_ai_sdk, whatever emitted it. The LangChain and LlamaIndex guides
tried `agent_step` for their step spans and had to switch to
`invoke_workflow` because the spans turned into Vercel AI SDK spans.
Cause: detect_vercel_ai_sdk accepted `agent_step` on its own
(ai_session.rs:1210). The op is the AI SDK's name for its step span, not a
value only the SDK can write.
Fix: drop the clause. The SDK's own step spans are still detected through
its `gen_ai` scope (previous commit), and a step op from any other emitter
takes the generic path.
Seen in: docs_langchain_a / docs_llamaindex_a guide processors (step spans).
* fix(agent-sessions): store OTLP bytes attributes as text when they are valid UTF-8
Symptom: LangChain traced through LangSmith's OTel export showed hex blobs
as its transcript: `gen_ai.prompt` / `gen_ai.completion` arrived as hex
strings on every span, so the transcript was unreadable, turns had no label
and tool results read "not captured".
Cause: any_value_string (apps/ingest/src/telemetry.rs:4019) hex-encoded
every OTLP bytesValue. LangSmith 0.14 sends those two keys as bytes holding
UTF-8 JSON.
Fix: a bytes value that is valid UTF-8 is stored as that text; anything else
keeps the hex form. The local-mode encoder in apps/cli (a port of the Rust
encoder) does the same.
Seen in: docs_langchain_ls (50 spans, both keys bytesValue).
* fix(agent-sessions): keep nested OTLP arrays and maps as JSON instead of escaped strings
Symptom: a structured attribute value, such as `gen_ai.input.messages` sent
as an OTLP array of maps (the form the GenAI semconv describes), was stored
as an array of escaped JSON strings, so no reader could decode the messages.
Guides had to tell emitters to send JSON strings.
Cause: any_value_string (apps/ingest/src/telemetry.rs:4020-4027) turned
every array element and map value into a string first, so each nesting level
was re-encoded as a string inside the outer JSON.
Fix: arrays and maps render through any_value_json, which keeps nested
arrays and maps as JSON. Scalars keep their string form, so every flat array
or map (the only shapes in the captures: `gen_ai.response.finish_reasons`,
`agno.tools`, ...) is stored byte for byte as before. The local-mode encoder
in apps/cli does the same.
Seen in: none of the 113 captures sends a nested value on a span (checked
every array, map and bytes attribute); the fix is for SDKs that emit the
structured form.
* fix(agent-sessions): leave OpenRouter's connection-test span unstamped
Symptom: every "Test Connection" click in OpenRouter's Broadcast settings
created a junk agent session (trace:e6d594d2..., vendor openrouter, 3 spans,
0 LLM calls).
Cause: detect_openrouter matched on the scope alone, and the scope forces
predicate evaluation, so the dashboard's attribute-less
`openrouter-connection-test` span was stamped like a generation.
Fix: an OpenRouter span needs a `gen_ai.operation.name`. Every generation,
provider attempt and moderation span in the capture carries one; the
connection-test span carries no attributes at all.
Seen in: capture `openrouter` (3 connection-test spans on trace id 0...01).
* fix(agent-sessions): type the local-mode any_value_json port as JSON, not unknown
Review fix for #18: effect-lint rejects a function returning `unknown`.
anyValueJson now returns the named AttrJson type (string, array or map of
the same).
* fix(agent-sessions): keep binary bytes attributes as hex even when they are valid UTF-8
Review fix for #16. Binary that happens to be valid UTF-8 was stored as
control-character text: all-zero bytes became NULs instead of "", and
[0x01, 0x02, 0x7f] became "\u0001\u0002\u007f" instead of "01027f".
The text path now also requires no control characters other than tab, LF
and CR, on both the Rust encoder and its apps/cli port. The port's
TextDecoder also keeps a leading BOM (`ignoreBOM`), as Rust's from_utf8 does.
* fix(agent-sessions): require the Strands event-time key for the custom-service Strands TS rule
Review fix for #1. The custom-service fallback accepted any span whose
scope and gen_ai provider (or system) both equal service.name, so an app
that names its own tracer and provider after its service would be read as
Strands.
The rule now also requires `gen_ai.event.start_time`, a non-semconv key the
Strands TS tracer writes on every span (docs_strands_ts: invoke_agent, chat,
execute_tool).
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.
No description provided.