See also (wiki): wiki/agent-telemetry-format-standardization.md · wiki/agent-operations-observability.md · wiki/semantic-observability.md
Executive Summary
This appendix answers the format question left open by the first agent-log mining playbook: do not collapse Claude, Codex, Bedrock, Strands, AG-UI, A2A, OpenInference, ATIF, Phoenix, and LangSmith into one lossy JSON object. Keep native raw records, normalize trace causality to OpenTelemetry, normalize AI semantics to OpenInference or the OTel-community GenAI semantic conventions, and expose LangSmith-compatible run/dataset views where they add value. The OpenInference-vs-OTel framing is not clean in practice: both are OTel-compatible ways to describe AI work, but they use different attributes and backend display contracts.
OTel GenAI is also not a fixed target. Current OpenTelemetry docs still mark
the GenAI conventions as development and document a v1.36 transition path using
OTEL_SEMCONV_STABILITY_OPT_IN, including gen_ai_latest_experimental.
Therefore every OTel/OpenInference/MCP span conversion should preserve
otel_semconv_version, ai_semantic_convention,
ai_semantic_convention_version, instrumentation_name,
instrumentation_version, and semconv_stability_opt_in. MCP semantic
conventions are a third layer to track for tool/protocol spans, not a footnote
inside generic LLM telemetry.
LangSmith is applicable because current docs describe OpenTelemetry ingestion, LangSmith-specific OTel attribute mapping, run/tree query syntax, message-view trace extraction, datasets, experiments, few-shot evaluator correction loops, and bulk Parquet trace export. It is strongest as an application observability and eval workbench. It is not a complete replacement for a raw local transcript vault, Bedrock invocation logs, protocol logs, or a warehouse.
Standardization Decision
| Need | Best format | Why |
|---|---|---|
| Compliance provenance | Native raw record plus hash | Preserves exact source contract and future re-parsing options |
| Cross-service timing | OpenTelemetry trace/span | Standard parentage, propagation, exporter/collector support |
| LLM/tool/retriever semantics | OpenInference attributes or OTel GenAI gen_ai.* attributes |
AI operation vocabulary on top of OTel; choose per backend and translation path |
| LangChain/LangGraph debugging | LangSmith run tree | Native Messages view, run filters, datasets, feedback, experiments |
| Agent trajectory replay/eval | ATIF-like trajectory plus spans | Keeps multi-step action/observation sequences |
| Skill mining | Curated task episodes | Skills need repeated validated patterns, not raw transcripts |
| Corporate KB mining | Turn/query/retrieval defect rows | The question is findability, not model-call telemetry alone |
| YAML optimization | Artifact plus validator feedback dataset | Deterministic failure codes beat generic chat fine-tuning |
| Reliability metrics | Evaluation rows joined to spans | Pass/fail and failure modes are labels, not trace fields |
Format Gap and Toggle Matrix
| Source | Enablement needed | Native unit | Tool-call representation | Main blind spot |
|---|---|---|---|---|
| Claude Code local JSONL | Local transcript retention; redacted extractor | Session JSONL event/record | Local tool records, usually pairable by sequence/session and sometimes tool IDs | No cloud identity or org fleet metrics |
| Claude Code OTel | CLAUDE_CODE_ENABLE_TELEMETRY=1, OTLP exporters/endpoints, optional prompt/tool content gates |
OTel metric/log/event/span | Tool events/spans when details/content gates are enabled | Subprocesses need their own telemetry config |
| Claude Agent SDK | SDK tracing plus propagated trace context into Claude Code child process | App trace plus child spans | Tool/MCP/subagent work as child spans/events | Local CLI transcript completeness still needs joining |
| Claude Cowork OTel | Admin OTLP endpoint and privacy controls | OTel event grouped by prompt.id |
Tool result events with potentially sensitive arguments | Compliance API and Cowork OTel are not identical coverage |
| Codex CLI OTel | otel.trace_exporter, otel.metrics_exporter, OTLP endpoint/headers/protocol, otel.log_user_prompt=true if needed |
OTel logs/metrics/traces | Tool/function calls as spans/logs where emitted; local session join recommended | Public emitted schema and entrypoint behavior need validation |
| Codex local JSONL/SQLite | Local redacted extractors | Session row, session index row, SQLite log row | Function/tool calls in session rows, logs, and shell snapshots | Local observed schema is not a stable vendor contract |
| Codex Desktop | Likely global ~/.codex/config.toml OTel; verify installed build |
App-server/local session records, TBD | TBD; expect app-server tool events and local records | Exact Desktop export/local schema is unresolved |
| Microsoft Scout | Unknown public telemetry toggles; preserve session history/admin exports if exposed | Preview session/history/memory/tool activity | Shell/browser/MCP/M365/subagent actions need typed tool records | Public export/admin/OTel contract is incomplete |
| Bedrock invocation logs | Enable invocation logging per account/region/destination and payload policy | Cloud model invocation record | Tool calls only inside model payloads, if logged | No local tool execution; bedrock-mantle endpoint gap |
| AgentCore/Strands | ADOT/OTel instrumentation, CloudWatch GenAI observability, session baggage | OTel spans/logs/metrics | Agent/tool/model spans | AgentCore is not a separate schema; it is AWS/ADOT/OTel GenAI transport plus AWS storage/query surfaces |
| AG-UI | Preserve event stream and attach trace/session IDs | Protocol event | First-class tool-call lifecycle events | No model/cloud/local execution proof alone |
| A2A | Preserve JSON-RPC task/message/artifact IDs and attach trace context | Task/message/status/artifact | Delegation as task/message/artifact, not local tool execution | Delegated agent internals need separate telemetry |
| OpenTelemetry GenAI | App/framework instrumentation and collector export | Trace/span/event | Tool spans/events with attributes | No learning labels or turn semantics by default |
| MCP semantic conventions | MCP client/server instrumentation and trace-context propagation | Protocol/tool span | MCP method/server/tool spans with protocol attributes | Host approval logs, raw tool results, and training labels still need joins |
| OpenInference/Phoenix | OpenInference instrumentation or span translation | OTel-compatible AI span | TOOL semantic span kind |
Plain OTel GenAI spans may need translation; otherwise Phoenix can lose AI span semantics or show unknown kinds |
| LangSmith | SDK tracing or OTel ingestion; metadata such as thread_id, ls_provider, ls_model_name; dataset/eval configuration |
Run tree; root run and child runs | Child runs with run_type="tool"; Messages view pairs tool calls/results for supported payload shapes |
Only sees instrumented data; not a full raw desktop-agent vault |
| ATIF | Trajectory export/conversion with steps and outcomes | Trajectory | Action/observation steps | Needs conversion to trace spans for observability backends |
Tool-Call Normalization
Every source should be normalized into one tool_calls row per request/result
pair:
{
"tool_call_id": "tool_hash",
"trace_id": "trace_hash",
"span_id": "span_hash",
"turn_id": "turn_hash",
"source_system": "codex_local_jsonl",
"tool_type": "shell",
"tool_name": "exec_command",
"request_time": "2026-06-07T13:02:10.481Z",
"response_time": "2026-06-07T13:02:12.927Z",
"status": "success",
"arguments_ref": "raw_args_redacted_hash",
"result_ref": "raw_result_redacted_hash",
"side_effects": [
{ "kind": "file_write", "artifact_id": "artifact_hash" }
],
"approval": {
"required": false,
"decision": "not_required"
}
}
Tool calls are not all the same:
- Claude/Codex local records are closest to replay, because they can include the local tool request/result and surrounding assistant turn.
- Claude/Codex OTel is best for timing and fleet metrics, but sensitive tool details often require explicit opt-in.
- Bedrock invocation logs can show that a model requested or described a tool call in the payload, but they do not prove the local tool actually ran.
- AG-UI shows user-interface tool-call lifecycle events and streaming boundaries.
- A2A shows delegated task/message/artifact flow; the delegated agent needs its own trace to prove its internal tool calls.
- LangSmith represents tools as child runs and can render tool calls in the Messages view when the trace payload matches supported extraction rules.
- OpenInference represents tools as semantic spans; Phoenix can display them, but labels and raw provenance still need joins. Plain OTel GenAI tool spans are a different convention and should be translated or dual-emitted before assuming Phoenix/Arize rendering parity.
Bedrock, CloudWatch, and Observability Cost Tradeoffs
Amazon Bedrock model invocation logging can deliver logs to CloudWatch Logs,
S3, or both. AWS documents that it can collect model input data, output data,
and metadata for supported calls in an account and Region, but only for
supported bedrock-runtime operations. CloudWatch log events contain invocation
metadata plus input/output JSON bodies up to 100 KB. S3 receives gzipped JSON
batches and is also the destination for large JSON bodies and binary data.
That creates a real design decision:
| Pattern | Use when | Cost surface | Technical cost |
|---|---|---|---|
| CloudWatch only | Hot operations and incident response inside AWS | Log ingestion, retained storage, Logs Insights scans, optional alarms/dashboards | Fast queries, but higher hot-log cost and AWS-centric analysis |
| S3 only | Durable audit vault, long retention, offline mining | S3 storage class, PUT/GET, Athena/Glue/OpenSearch scans, lifecycle transitions | Cheaper archive, but requires partitioning and ETL |
| CloudWatch plus S3 | Regulated production where hot and cold paths both matter | Both hot-log and object-storage costs | Best coverage, but duplicate retention and redaction policies are mandatory |
| CloudWatch to Firehose/warehouse | Near-real-time analytics outside CloudWatch | CloudWatch delivery/streaming, Firehose ingest, destination indexing/storage | Good fanout, but every destination adds schema and cost governance |
| Prometheus / managed Prometheus | Alerting and SLOs over derived counters, gauges, and histograms | Prometheus scrape/remote-write/OTLP metrics ingest, storage, and cardinality costs | Metrics-only plane; not a store for raw Bedrock invocation JSON, Claude logs, traces, prompts, or tool bodies |
| OTel/OpenInference to Phoenix/Arize/LangSmith | Agent/app debugging, evals, datasets, feedback | SaaS span/GB/retention costs or self-hosted infra/SRE costs | Better AI semantics, but not a substitute for Bedrock audit logs |
Current pricing pages make the shape of the bill clear even when exact numbers vary by Region and plan:
- CloudWatch pricing is usage-based. AWS examples show CloudWatch Logs ingestion and archival charges, Logs Insights scanning, and separate application-observability span ingestion/indexing surfaces.
- S3 pricing separates storage class, request/data retrieval, transfer, and management/query features.
- Firehose pricing is volume-based ingestion/delivery, with optional format conversion and destination features.
- LangSmith pricing is plan/usage based and positions trace retention, bulk data export, datasets, feedback, and enterprise controls as product features.
- Arize pricing separates free/self-hosted Phoenix, free/pro cloud tiers, span counts, ingestion volume, retention, and enterprise support.
The engineering conclusion:
- Use S3 as the Bedrock invocation raw vault for long retention.
- Use CloudWatch for operationally necessary hot logs, not indiscriminate full-content retention.
- Export application/agent spans to OpenInference/Phoenix/Arize or LangSmith for debugging and evaluation.
- Store raw prompt/tool bodies only under explicit policy. Use hashes, byte counts, redacted refs, and sampled content in shared stores.
- Create a warehouse join between Bedrock request IDs, OTel trace IDs, local session IDs, tool call IDs, and eval labels. No single backend gives all of those by default.
Prometheus Boundary
Prometheus should ingest metrics derived from agent and Bedrock telemetry, not the raw telemetry itself. Prometheus can receive OTLP metrics when its OTLP receiver is enabled; traces and logs still need an OTel Collector plus a trace/log backend or warehouse.
Recommended split:
Claude Code / Claude Agent SDK / app OTel
-> metrics pipeline -> Prometheus
-> traces pipeline -> trace backend
-> logs pipeline -> log store / warehouse
Bedrock ModelInvocationLog in CloudWatch Logs or S3
-> parser / ETL
-> derived metrics -> Prometheus
-> raw JSON -> CloudWatch/S3/warehouse
Example derived metrics:
agent_model_invocations_total{source,provider,model,operation,status}
agent_input_tokens_total{source,provider,model}
agent_output_tokens_total{source,provider,model}
agent_tool_calls_total{tool_name,tool_type,status}
bedrock_invocations_total{region,model_id,operation}
bedrock_input_tokens_total{region,model_id,operation}
bedrock_output_tokens_total{region,model_id,operation}
Prometheus labels must stay bounded. Do not use prompts, completions,
requestId, trace_id, user email, local file path, raw tool arguments, or
tool output bodies as labels. Preserve those values in CloudWatch/S3/raw vaults,
trace stores, or warehouse side tables, then use Prometheus for rates, alerts,
SLOs, and fleet health.
Cost Model Inputs
Before enabling full Bedrock/CloudWatch logging, estimate:
monthly_log_gb =
invocations_per_month
* avg_logged_bytes_per_invocation
/ 1_073_741_824
cloudwatch_hot_cost =
monthly_log_gb * region_log_ingest_price
+ retained_gb * region_log_storage_price
+ logs_insights_scanned_gb * region_query_price
s3_archive_cost =
retained_gb_by_storage_class * s3_storage_price
+ put_get_request_counts * request_prices
+ athena_or_opensearch_scan_or_index_cost
The largest variable is not the number of invocations; it is whether you log full prompts, completions, retrieved documents, tool outputs, images, and large JSON bodies. For agentic systems, payload multiplication is common: one user turn can fan out into several model calls and many tool/retrieval events.
Canonical Warehouse Tables
raw_events
{
"raw_event_id": "raw_01jz...",
"source_system": "codex_local_jsonl",
"native_schema_version": "observed-2026-06-07",
"native_timestamp": "2026-06-07T13:02:10.481Z",
"observed_at": "2026-06-07T13:02:11.000Z",
"join_keys": {
"session_id": "sess_hash",
"thread_id": "thread_hash",
"trace_id": "trace_hash",
"tool_call_id": "tool_hash"
},
"payload_redacted": {
"type": "response_item",
"item_type": "tool_call",
"content_hash": "sha256:..."
},
"payload_hash": "sha256:...",
"redaction_version": "stateofai-redaction-v1"
}
agent_spans
{
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7",
"parent_span_id": "b9c7c989f97918e1",
"span_kind": "TOOL",
"name": "shell.exec",
"start_time": "2026-06-07T13:02:10.481Z",
"end_time": "2026-06-07T13:02:12.927Z",
"status": "OK",
"attributes": {
"tool.name": "exec_command",
"agent.system": "codex",
"repo.name": "stateofai",
"git.commit": "unknown-dirty",
"privacy.redaction_version": "stateofai-redaction-v1"
},
"input_ref": "raw_01jz...",
"output_ref": "raw_01jz..."
}
memory_events
{
"memory_event_id": "mem_01jz...",
"trace_id": "trace_hash",
"span_id": "span_hash",
"session_id": "sess_hash",
"agent_id": "agent_hash",
"memory_store_id": "workspace_or_user_store_hash",
"memory_version_id": "version_hash",
"operation": "write",
"scope": "workspace",
"content_ref": "redacted_memory_ref",
"previous_hash": "sha256:...",
"next_hash": "sha256:...",
"audit_actor": "agent_or_user_hash",
"redaction_version": "stateofai-redaction-v1"
}
context_events
{
"context_event_id": "ctx_01jz...",
"trace_id": "trace_hash",
"span_id": "span_hash",
"turn_id": "turn_hash",
"event_type": "compaction",
"compaction_id": "compact_hash",
"tokens_before": 178000,
"tokens_after": 24000,
"context_window_tokens": 200000,
"tool_manifest_tokens": 14000,
"memory_tokens": 9000,
"retrieval_tokens": 22000,
"artifact_refs_created": ["artifact_01jz..."],
"reason": "token_trigger"
}
turns
{
"turn_id": "turn_01jz...",
"session_id": "sess_hash",
"thread_id": "thread_hash",
"root_trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"user_intent_label": "research_publish_article",
"question_hash": "sha256:...",
"retrieval_attempts": 8,
"tool_call_count": 41,
"validation_status": "passed",
"final_artifact_id": "artifact_01jz...",
"elapsed_ms": 4708000
}
Representative Raw Snippets
These examples are intentionally redacted and schema-focused. They show the fields that should exist when telemetry is maximally useful; they are not raw private logs.
Copy/Paste Max-Telemetry Config Appendix
These snippets are intentionally “maximum telemetry” configs for lab verification, not a production default. They can include prompts, tool arguments, tool outputs, file paths, commands, approvals, and errors. Use them only in a controlled environment with a redaction policy and a disposable OTLP collector.
Verification Status
| Harness | Version checked locally | Config contract status | End-to-end ingestion status |
|---|---|---|---|
| Claude Code | 2.1.150 |
Verified against current Claude Code monitoring docs | Not yet collector-verified in this article |
| Codex CLI | 0.135.0 |
Verified against current OpenAI Codex config docs | Not yet collector-verified in this article |
| Codex Desktop / IDE | Not locally version-sampled here | OpenAI says local managed configs apply across desktop app, CLI, and IDE extension, but exact local telemetry behavior still needs app-specific sampling | Unverified |
| Bedrock invocation logging | AWS account/Region dependent | Verified against AWS Bedrock invocation logging docs | Not locally enabled here |
| Strands / AgentCore | Not locally sampled here | OTel support verified from AWS/Strands public docs | Not locally sampled here |
| Langfuse / Weave / Braintrust / OpenLIT | Backend/SDK version dependent | Current docs provide OTel endpoints or SDK config | Not locally sampled here |
| AG-UI / A2A | Protocol version dependent | Event schemas/protocol IDs verified from public docs | They preserve protocol events, not full model/local tool execution by themselves |
Config File Locations
| Tool | macOS / Linux | Windows | Notes |
|---|---|---|---|
| Claude Code managed settings | /Library/Application Support/ClaudeCode/managed-settings.json on macOS; /etc/claude-code/managed-settings.json on Linux/WSL |
C:\Program Files\ClaudeCode\managed-settings.json |
Admin managed settings have high precedence; the legacy Windows C:\ProgramData\ClaudeCode\managed-settings.json path is no longer supported as of Claude Code v2.1.75 |
| Claude Code user/project settings | ~/.claude/settings.json, ~/.claude/settings.local.json, <repo>/.claude/settings.json, <repo>/.claude/settings.local.json |
%USERPROFILE%\.claude\settings.json and project .claude\settings.json |
Use managed settings for fleet telemetry; local settings are easier for lab tests |
| Codex user config/state | $CODEX_HOME/config.toml, default ~/.codex/config.toml |
%USERPROFILE%\.codex\config.toml unless CODEX_HOME is set |
Telemetry keys must live in user-level config, not project .codex/config.toml |
| Codex project config | <repo>/.codex/config.toml |
<repo>\.codex\config.toml |
OpenAI docs say project config cannot override otel |
| Codex managed requirements | /etc/codex/requirements.toml or organization-managed config paths |
Enterprise/admin managed requirements locations vary | Requirements constrain security-sensitive settings; allow_managed_hooks_only belongs here, not in config.toml |
| Claude Agent SDK app config | App/container environment and SDK ClaudeAgentOptions.env |
App/container environment and SDK ClaudeAgentOptions.env |
SDK propagates W3C trace context into Claude Code child process when query() runs inside an active OTel span |
| Strands Agents SDK config | App/container environment plus Python/TypeScript OTel setup | App/container environment plus Python/TypeScript OTel setup | Use strands-agents[otel] for Python or OTel peer deps for TypeScript; config is app code/env, not a fixed host dotfile |
| OTel Collector | Any path you run it from, commonly /etc/otelcol/config.yaml or repo ops/otel-collector.yaml |
Any path, commonly C:\ProgramData\otelcol\config.yaml |
Collector config is the shared sink that makes vendor configs testable |
Claude Code Managed Settings JSON
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_TRACES_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://127.0.0.1:4317",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer REDACTED",
"OTEL_METRIC_EXPORT_INTERVAL": "10000",
"OTEL_LOGS_EXPORT_INTERVAL": "5000",
"OTEL_LOG_USER_PROMPTS": "1",
"OTEL_LOG_TOOL_DETAILS": "1",
"OTEL_LOG_TOOL_CONTENT": "1",
"OTEL_LOG_RAW_API_BODIES": "file:/var/log/claude-code-api-bodies",
"ENABLE_BETA_TRACING_DETAILED": "1",
"BETA_TRACING_ENDPOINT": "http://127.0.0.1:4317",
"OTEL_RESOURCE_ATTRIBUTES": "service.name=claude-code,deployment.environment=lab,agent.telemetry_profile=max"
}
}
Claude Code nuance: current docs say traces require both
CLAUDE_CODE_ENABLE_TELEMETRY=1 and
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1, plus OTEL_TRACES_EXPORTER. Tool
details are gated by OTEL_LOG_TOOL_DETAILS; tool input/output body span
events require OTEL_LOG_TOOL_CONTENT=1 and are truncated. Full raw Messages
API request/response body events require OTEL_LOG_RAW_API_BODIES; use
file:<dir> in lab captures when untruncated bodies are needed. Those bodies
include the full conversation history and should never be enabled casually.
Detailed hook spans also require ENABLE_BETA_TRACING_DETAILED=1 and
BETA_TRACING_ENDPOINT. In interactive CLI sessions, current Claude Code docs
also say detailed hook spans require organization allowlisting; Agent SDK and
non-interactive claude -p sessions are not gated the same way.
Claude Code Shell Export
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4317
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer REDACTED"
export OTEL_METRIC_EXPORT_INTERVAL=10000
export OTEL_LOGS_EXPORT_INTERVAL=5000
export OTEL_LOG_USER_PROMPTS=1
export OTEL_LOG_TOOL_DETAILS=1
export OTEL_LOG_TOOL_CONTENT=1
export OTEL_LOG_RAW_API_BODIES=file:/var/log/claude-code-api-bodies
export ENABLE_BETA_TRACING_DETAILED=1
export BETA_TRACING_ENDPOINT=http://127.0.0.1:4317
export OTEL_RESOURCE_ATTRIBUTES="service.name=claude-code,deployment.environment=lab,agent.telemetry_profile=max"
Claude Agent SDK Python Max Telemetry
The Agent SDK embeds Claude Code as a child process. The key extra behavior is
trace propagation: when query() runs while an application OTel span is active,
the SDK injects TRACEPARENT and TRACESTATE into the child process so the
Claude Code claude_code.interaction span nests under the app span. The CLI
also forwards TRACEPARENT into Bash and PowerShell tool commands unless you
override TRACEPARENT in options.env.
pip install claude-agent-sdk opentelemetry-api opentelemetry-sdk \
opentelemetry-exporter-otlp-proto-http
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from claude_agent_sdk import ClaudeAgentOptions, query
resource = Resource.create({
"service.name": "support-triage-agent",
"service.version": "1.4.0",
"deployment.environment": "lab",
"agent.telemetry_profile": "max",
})
provider = TracerProvider(resource=resource)
provider.add_span_processor(BatchSpanProcessor(
OTLPSpanExporter(
endpoint="http://127.0.0.1:4318/v1/traces",
headers={"Authorization": "Bearer REDACTED"},
)
))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("support-triage-agent")
options = ClaudeAgentOptions(
env={
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1",
"OTEL_TRACES_EXPORTER": "otlp",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://127.0.0.1:4318",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer REDACTED",
"OTEL_LOG_USER_PROMPTS": "1",
"OTEL_LOG_TOOL_DETAILS": "1",
"OTEL_LOG_TOOL_CONTENT": "1",
"OTEL_LOG_RAW_API_BODIES": "file:/var/log/claude-agent-sdk-api-bodies",
"ENABLE_BETA_TRACING_DETAILED": "1",
"BETA_TRACING_ENDPOINT": "http://127.0.0.1:4318",
"OTEL_RESOURCE_ATTRIBUTES": (
"service.name=claude-agent-sdk-child,"
"deployment.environment=lab,"
"agent.telemetry_profile=max,"
"enduser.id_hash=user_hash"
),
}
)
with tracer.start_as_current_span("app.agent_request") as span:
span.set_attribute("session.id", "session_hash")
span.set_attribute("enduser.id_hash", "user_hash")
for message in query("Summarize the ticket and inspect policy docs.", options=options):
print(message)
Fields to verify:
- app root span
app.agent_request; - child
claude_code.interactionspan; - child
claude_code.llm_requestspans; claude_code.tool,claude_code.tool.blocked_on_user, andclaude_code.tool.execution;claude_code.hookonly when detailed beta tracing is enabled;session.id;- propagated
TRACEPARENTin Bash/PowerShell subprocesses; - application end-user attribution via resource attributes.
Claude Agent SDK TypeScript Max Telemetry
npm install @anthropic-ai/claude-agent-sdk \
@opentelemetry/api @opentelemetry/sdk-trace-node \
@opentelemetry/sdk-trace-base @opentelemetry/resources \
@opentelemetry/exporter-trace-otlp-http
import { trace } from "@opentelemetry/api";
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { resourceFromAttributes } from "@opentelemetry/resources";
import { query } from "@anthropic-ai/claude-agent-sdk";
const provider = new NodeTracerProvider({
resource: resourceFromAttributes({
"service.name": "support-triage-agent",
"service.version": "1.4.0",
"deployment.environment": "lab",
"agent.telemetry_profile": "max",
}),
spanProcessors: [
new BatchSpanProcessor(
new OTLPTraceExporter({
url: "http://127.0.0.1:4318/v1/traces",
headers: { Authorization: "Bearer REDACTED" },
})
),
],
});
provider.register();
const tracer = trace.getTracer("support-triage-agent");
await tracer.startActiveSpan("app.agent_request", async (span) => {
span.setAttribute("session.id", "session_hash");
span.setAttribute("enduser.id_hash", "user_hash");
for await (const message of query({
prompt: "Summarize the ticket and inspect policy docs.",
options: {
env: {
CLAUDE_CODE_ENABLE_TELEMETRY: "1",
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA: "1",
OTEL_TRACES_EXPORTER: "otlp",
OTEL_METRICS_EXPORTER: "otlp",
OTEL_LOGS_EXPORTER: "otlp",
OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf",
OTEL_EXPORTER_OTLP_ENDPOINT: "http://127.0.0.1:4318",
OTEL_EXPORTER_OTLP_HEADERS: "Authorization=Bearer REDACTED",
OTEL_LOG_USER_PROMPTS: "1",
OTEL_LOG_TOOL_DETAILS: "1",
OTEL_LOG_TOOL_CONTENT: "1",
OTEL_LOG_RAW_API_BODIES: "file:/var/log/claude-agent-sdk-api-bodies",
ENABLE_BETA_TRACING_DETAILED: "1",
BETA_TRACING_ENDPOINT: "http://127.0.0.1:4318",
OTEL_RESOURCE_ATTRIBUTES:
"service.name=claude-agent-sdk-child,deployment.environment=lab,agent.telemetry_profile=max,enduser.id_hash=user_hash",
},
},
})) {
console.log(message);
}
span.end();
});
Nuance: interactive Claude Code sessions ignore inbound TRACEPARENT; Agent
SDK and claude -p runs honor it. Span names and attributes remain beta and
may change between releases.
Codex User Config TOML
Put this in user config, not project config:
- macOS/Linux:
~/.codex/config.toml, or$CODEX_HOME/config.toml - Windows:
%USERPROFILE%\.codex\config.toml, or%CODEX_HOME%\config.toml
#:schema https://developers.openai.com/codex/config-schema.json
[otel]
environment = "lab"
log_user_prompt = true
metrics_exporter = "otlp-http"
[otel.exporter.otlp-http]
endpoint = "http://127.0.0.1:4318/v1/logs"
protocol = "binary"
headers = { Authorization = "Bearer REDACTED" }
[otel.trace_exporter.otlp-http]
endpoint = "http://127.0.0.1:4318/v1/traces"
protocol = "binary"
headers = { Authorization = "Bearer REDACTED" }
Codex nuance: OpenAI docs say Codex stores local state under CODEX_HOME
defaulting to ~/.codex. Project .codex/config.toml files are read only for
trusted projects, but telemetry keys such as otel are ignored in project
config and must be set in user-level ~/.codex/config.toml. Current reference
docs list OTel log exporter, metrics exporter, trace exporter, TLS options, and
otel.log_user_prompt; OpenAI’s safety article shows Codex logs for user
prompts, approval decisions, tool results, MCP server usage, and network proxy
allow/deny events. A public GitHub issue reported differences between
interactive codex, codex exec, and codex mcp-server in older 0.105.0;
this article has not yet collector-verified those surfaces on local
0.135.0.
Bedrock Invocation Logging
This is not a local host file. It is an AWS account/Region setting configured through Bedrock APIs, console, or IaC. For maximum audit coverage, enable both S3 and CloudWatch destinations, payload logging where policy allows, and KMS encryption. Keep the separate OTel app/agent trace because Bedrock invocation logs do not prove local tool execution.
Representative IaC shape:
{
"loggingConfig": {
"cloudWatchConfig": {
"logGroupName": "/aws/bedrock/model-invocations",
"roleArn": "arn:aws:iam::123456789012:role/BedrockInvocationLoggingRole"
},
"s3Config": {
"bucketName": "company-bedrock-invocation-logs",
"keyPrefix": "bedrock/model-invocations/"
},
"kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/REDACTED",
"logPromptAndCompletion": true
}
}
Strands / AgentCore Python Environment
The Strands SDK has a richer contract than the previous baseline snippet showed. Current docs say Strands traces use OpenTelemetry and capture agent lifecycle, LLM interactions, retrievers, tool usage, and event-loop processing. Install the OTel extra:
pip install 'strands-agents[otel]'
Environment:
export OTEL_SERVICE_NAME=strands-agent
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=lab,agent.framework=strands,agent.telemetry_profile=max,service.version=1.0.0"
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer REDACTED"
export OTEL_SEMCONV_STABILITY_OPT_IN="gen_ai_latest_experimental,gen_ai_tool_definitions,gen_ai_use_latest_invocation_tokens"
Python:
from os import linesep
from strands import Agent
from strands.telemetry import StrandsTelemetry
telemetry = StrandsTelemetry()
# Send traces to OTLP.
telemetry.setup_otlp_exporter()
# Also write local JSONL spans for schema verification.
logfile = open("/tmp/strands-traces.jsonl", "wt")
telemetry.setup_console_exporter(
out=logfile,
formatter=lambda span: span.to_json() + linesep,
)
# Metrics can also be exported through OTel.
telemetry.setup_meter(
enable_console_exporter=True,
enable_otlp_exporter=True,
)
agent = Agent(
model="us.anthropic.claude-sonnet-4-20250514-v1:0",
system_prompt="You are a governed support triage agent.",
)
response = agent("Find the policy and draft a cited answer.")
print(response)
logfile.close()
Fields to verify:
- top-level agent span with
gen_ai.systemandgen_ai.agent.name; - event-loop cycle spans;
- model invocation spans with model ID, prompt/completion token counts, cache token attributes where supported, latency start/end attributes;
- tool spans with
tool.status,gen_ai.tool.name,gen_ai.tool.call.id,gen_ai.operation.name, start/end times, and formatted tool result; - retriever spans when using retrieval;
- custom trace attributes for
session.id,rollout_id,prompt_version,policy_version, and Bedrock request IDs where the app can attach them.
Strands TypeScript Max Telemetry
npm install @strands-agents/sdk \
@opentelemetry/api @opentelemetry/sdk-trace-node \
@opentelemetry/sdk-trace-base @opentelemetry/resources \
@opentelemetry/exporter-trace-otlp-http
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:4318"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer REDACTED"
export OTEL_SEMCONV_STABILITY_OPT_IN="gen_ai_latest_experimental,gen_ai_tool_definitions,gen_ai_use_latest_invocation_tokens"
import { Agent } from "@strands-agents/sdk";
import { setupTracer } from "@strands-agents/sdk/telemetry";
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import { BatchSpanProcessor, ConsoleSpanExporter } from "@opentelemetry/sdk-trace-base";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
const provider = new NodeTracerProvider({
spanProcessors: [
new BatchSpanProcessor(
new OTLPTraceExporter({
url: "http://127.0.0.1:4318/v1/traces",
headers: { Authorization: "Bearer REDACTED" },
})
),
new BatchSpanProcessor(new ConsoleSpanExporter()),
],
});
setupTracer({
provider,
exporters: { otlp: true, console: true },
});
const agent = new Agent({
systemPrompt: "You are a governed support triage agent.",
});
const response = await agent("Find the policy and draft a cited answer.");
console.log(response);
For Bedrock-backed Strands agents, attach session.id, Bedrock request IDs,
model IDs, tool names, tool-call IDs, and guardrail/policy versions as span
attributes, baggage, or custom trace attributes. The SDK emits many spans, but
the app still owns business keys such as turn_id, rollout_id,
dataset_example_id, and policy_version.
Langfuse as OTLP Backend
export OTEL_EXPORTER_OTLP_ENDPOINT="https://cloud.langfuse.com/api/public/otel"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic REDACTED,x-langfuse-ingestion-version=4"
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://cloud.langfuse.com/api/public/otel/v1/traces"
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="Authorization=Basic REDACTED,x-langfuse-ingestion-version=4"
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_RESOURCE_ATTRIBUTES="langfuse.environment=lab,service.name=agent-app"
Langfuse docs state OTLP over HTTP JSON/protobuf is supported and gRPC is not currently supported for this endpoint.
Braintrust as OTLP Backend
export BRAINTRUST_API_KEY=REDACTED
export BRAINTRUST_PARENT="project_name:agent-observability-lab"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.braintrust.dev/otel"
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://api.braintrust.dev/otel/v1/traces"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer REDACTED, x-bt-parent=project_name:agent-observability-lab"
Braintrust docs require braintrust[otel] >= v0.3.5 for Python distributed
tracing and braintrust >= v1.0.0 plus @braintrust/otel >= v0.1.0 for
TypeScript distributed tracing.
W&B Weave OTel Collector
Weave supports sending OTel traces directly or through a collector and maps
OpenTelemetry GenAI, OpenInference, Vercel AI SDK, MLflow, and Traceloop style
attributes. Use wandb.thread_id or supported session/thread attributes to
group turns.
export WANDB_API_KEY=REDACTED
export OTEL_SERVICE_NAME=agent-app
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=lab,wandb.thread_id=thread-lab"
OpenLIT Max Capture
export OTEL_SERVICE_NAME=my-ai-app
export OTEL_DEPLOYMENT_ENVIRONMENT=lab
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer REDACTED"
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true
export OPENLIT_MAX_CONTENT_LENGTH=0
export OPENLIT_DISABLE_METRICS=false
export OPENLIT_DISABLE_EVENTS=false
export OPENLIT_COLLECT_SYSTEM_METRICS=true
export OPENLIT_CAPTURE_DB_PARAMETERS=true
export OTEL_RESOURCE_ATTRIBUTES="service.version=lab,team=ai-platform,cost.center=engineering"
openlit-instrument python your_app.py
OpenLIT docs warn that database parameter capture can expose sensitive values; it should be a lab-only setting unless policy explicitly allows it.
Protocol Harnesses: AG-UI and A2A
AG-UI and A2A do not have a single “turn telemetry on” host config. They are protocol/event contracts. To make them observable, the application must attach trace context and preserve protocol IDs:
{
"traceparent": "00-TRACEID-SPANID-01",
"agui": {
"runId": "run_hash",
"messageId": "message_hash",
"toolCallId": "tool_call_hash"
},
"a2a": {
"taskId": "task_hash",
"contextId": "context_hash",
"messageId": "message_hash"
}
}
AG-UI docs define lifecycle, text message, tool-call, state, activity, reasoning, raw, and custom events. Use those IDs as join keys; do not expect AG-UI alone to prove model internals or local executor side effects.
Claude Code OTel Enablement
CLAUDE_CODE_ENABLE_TELEMETRY=1
OTEL_METRICS_EXPORTER=otlp
OTEL_LOGS_EXPORTER=otlp
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_ENDPOINT=http://collector.internal:4318
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer REDACTED
OTEL_LOG_USER_PROMPTS=1
OTEL_LOG_TOOL_DETAILS=1
OTEL_LOG_TOOL_CONTENT=1
OTEL_METRIC_EXPORT_INTERVAL=10000
Claude Code Event-Like OTel Log
{
"resource": {
"service.name": "claude-code",
"service.version": "redacted"
},
"scope": "claude-code",
"body": {
"event.name": "claude_code.tool.result",
"session.id": "sess_hash",
"tool.name": "Bash",
"tool.input.hash": "sha256:...",
"tool.output.hash": "sha256:...",
"content.redacted": true
},
"attributes": {
"user.account_hash": "user_hash",
"workspace.path_hash": "path_hash",
"privacy.prompt_logged": true,
"privacy.tool_details_logged": true,
"privacy.tool_content_logged": true
},
"time_unix_nano": 1780847584000000000
}
Codex OTel Config
[otel]
log_user_prompt = true
metrics_exporter = "otlp-http"
trace_exporter = "otlp-http"
exporter_otlp_endpoint = "http://collector.internal:4318"
exporter_otlp_headers = { Authorization = "Bearer REDACTED" }
exporter_otlp_protocol = "http/protobuf"
Codex Local JSONL-Like Session Row
{
"type": "response_item",
"thread_id": "thread_hash",
"timestamp": "2026-06-07T13:02:10.481Z",
"item": {
"type": "function_call",
"name": "exec_command",
"call_id": "tool_call_hash",
"arguments_hash": "sha256:...",
"arguments_redacted": true
}
}
Codex Local SQLite Log Row
{
"timestamp": "2026-06-07T13:02:10.481Z",
"thread_id": "thread_hash",
"process_uuid": "process_hash",
"target": "codex_core::exec",
"level": "INFO",
"body_hash": "sha256:...",
"module_path": "codex_core::exec",
"file": "redacted",
"line": 123
}
Bedrock Invocation Log
{
"schemaType": "ModelInvocationLog",
"accountId": "123456789012",
"region": "us-east-1",
"requestId": "aws_request_hash",
"operation": "Converse",
"modelId": "anthropic.claude-redacted",
"input": {
"inputBodyJsonHash": "sha256:...",
"contentRedacted": true
},
"output": {
"outputBodyJsonHash": "sha256:...",
"contentRedacted": true
},
"metadata": {
"inputTokenCount": 1234,
"outputTokenCount": 456,
"latencyMs": 789
}
}
Important boundary: Bedrock invocation logging covers supported
bedrock-runtime calls. AWS documents that calls through other endpoints, such
as the bedrock-mantle Responses API endpoint, are not currently captured by
Bedrock invocation logging.
Strands / AgentCore OTel Span
{
"trace_id": "trace_hash",
"span_id": "span_hash",
"parent_span_id": "parent_hash",
"name": "StrandsAgent.invoke",
"kind": "SPAN_KIND_INTERNAL",
"attributes": {
"gen_ai.system": "bedrock",
"gen_ai.request.model": "anthropic.claude-redacted",
"session.id": "session_hash",
"agent.name": "research_agent",
"tool.name": "retrieve_sources",
"cloud.account.id": "account_hash",
"aws.region": "us-east-1"
},
"status": { "code": "OK" }
}
AG-UI Event
{
"type": "TOOL_CALL_START",
"runId": "agui_run_hash",
"messageId": "msg_hash",
"toolCallId": "tool_call_hash",
"toolCallName": "search_kb",
"parentMessageId": "assistant_msg_hash",
"timestamp": "2026-06-07T13:02:10.481Z"
}
A2A Task Event
{
"jsonrpc": "2.0",
"id": "rpc_hash",
"method": "message/send",
"params": {
"message": {
"messageId": "msg_hash",
"role": "user",
"parts": [{ "kind": "text", "text_hash": "sha256:..." }],
"contextId": "context_hash",
"taskId": "task_hash"
}
}
}
OpenInference Span Attributes
{
"name": "llm.chat",
"attributes": {
"openinference.span.kind": "LLM",
"llm.provider": "openai",
"llm.model_name": "gpt-redacted",
"input.value": "{\"messages\":\"sha256:...\"}",
"output.value": "{\"message\":\"sha256:...\"}",
"llm.token_count.prompt": 1200,
"llm.token_count.completion": 300,
"session.id": "session_hash"
}
}
ATIF-Like Trajectory
{
"trajectory_id": "traj_hash",
"task": {
"task_id": "task_hash",
"intent": "publish_agent_observability_research",
"input_hash": "sha256:..."
},
"steps": [
{
"index": 0,
"type": "llm",
"span_id": "span_hash",
"input_hash": "sha256:...",
"output_hash": "sha256:..."
},
{
"index": 1,
"type": "tool",
"tool_name": "web.search",
"arguments_hash": "sha256:...",
"result_hash": "sha256:..."
}
],
"outcome": {
"status": "passed",
"artifact_id": "artifact_hash",
"evaluator": "human_and_build"
}
}
LangSmith Run Tree
{
"id": "run_hash",
"trace_id": "trace_hash",
"parent_run_id": null,
"name": "research_and_publish",
"run_type": "chain",
"start_time": "2026-06-07T13:02:10.481Z",
"end_time": "2026-06-07T14:20:38.000Z",
"status": "success",
"inputs": { "request_hash": "sha256:..." },
"outputs": { "artifact_url": "https://stateofai.pages.dev/..." },
"extra": {
"metadata": {
"thread_id": "thread_hash",
"ls_provider": "openai",
"ls_model_name": "gpt-redacted",
"task_family": "research_publish"
}
},
"events": [],
"tags": ["agent-observability", "published"],
"feedback_stats": { "correctness": { "passed": 1 } },
"child_runs": [
{
"id": "child_run_hash",
"parent_run_id": "run_hash",
"run_type": "tool",
"name": "search_docs",
"inputs": { "query_hash": "sha256:..." },
"outputs": { "result_count": 10 }
}
]
}
LangSmith bulk export fields documented for Parquet include identifiers and
hierarchy such as id, session_id, trace_id, parent_run_id,
parent_run_ids, and reference_example_id; metadata such as name,
run_type, start_time, end_time, status, is_root, dotted_order, and
trace_tier; run data such as inputs, outputs, error, extra, and
events; tags and feedback; and token/cost fields.
Query Cookbook
LangSmith SDK
List root runs:
from langsmith import Client
client = Client()
root_runs = client.list_runs(project_name="agent-prod", is_root=True)
Find runs in one conversation/thread:
thread_id = "thread_hash"
filter_string = (
'and(in(metadata_key, ["session_id","conversation_id","thread_id"]), '
f'eq(metadata_value, "{thread_id}"))'
)
thread_runs = client.list_runs(
project_name="agent-prod",
filter=filter_string,
is_root=True,
)
Find retrieval spans inside successful traces:
runs = client.list_runs(
project_name="agent-prod",
filter='eq(run_type, "retriever")',
trace_filter='and(eq(feedback_key, "correctness"), eq(feedback_score, 1))',
)
Search all string fields:
runs = client.list_runs(
project_name="agent-prod",
filter='search("missing policy exception")',
)
Warehouse Queries
Needle KB candidates:
select t.turn_id, t.question_hash, a.uri, t.retrieval_attempts, t.elapsed_ms
from turns t
join artifacts a on a.artifact_id = t.final_artifact_id
where t.retrieval_attempts >= 5
and t.validation_status = 'passed'
and a.artifact_type = 'citation';
Skill candidates:
select task_family, count(*) as validated_runs
from training_candidates
where candidate_type = 'skill'
and validation_status = 'passed'
and human_approved = true
group by task_family
having count(*) >= 3;
Reliability by tool:
select tool_name,
count(*) as calls,
avg(case when status = 'error' then 1 else 0 end) as error_rate,
percentile_cont(0.95) within group (order by elapsed_ms) as p95_ms
from tool_calls
group by tool_name
order by error_rate desc, calls desc;
YAML failure coverage:
select schema_name, failure_code, count(*) as failures
from evaluations
where artifact_type = 'yaml'
and evaluator_type = 'deterministic_validator'
group by schema_name, failure_code
order by failures desc;
Conversion Rules
Raw Chat To Skill
Do not train on raw chats. Convert a trace into a skill candidate only when:
- the task family recurs;
- the user intent and repo state can be summarized without sensitive content;
- the tool sequence is stable enough to teach;
- the final artifact passed a deterministic or human validation;
- at least one counterexample explains when not to use the skill.
Trace To KB Defect
Use retrieval churn as the signal:
- many search attempts;
- many query rewrites;
- late discovery of the right source;
- repeated related questions across sessions;
- answer found only through a synonym, acronym, owner name, stale title, or old path.
Trace To YAML Optimization
Keep:
- schema version;
- prompt version;
- generated YAML hash or redacted body;
- validator failure codes;
- corrected YAML;
- final pass/fail;
- field-level coverage tags.
For most domain YAML tasks, start with 10-20 adversarial eval examples, then 30-100 prompt-optimization examples, then 100-300 coverage examples. Fine-tune only after schema-constrained prompting, retrieval, deterministic validation, and prompt optimization fail the reliability target.
Definitions
| Term | Operational definition |
|---|---|
| Trace | One causality tree for a task/request/workflow; identified by trace_id |
| Span | Timed operation inside a trace; identified by span_id and parent |
| Run | LangSmith/platform execution object; root run is trace-like, child run is span-like |
| Rollout | One concrete execution of an agent/workflow/prompt/model configuration against a task, dataset row, or production request |
| Session | Longer user-agent container spanning one or more traces |
| Thread | Conversation grouping key, often used by chat UIs and LangSmith metadata |
| Turn | User-visible exchange, potentially containing many spans/tool calls |
| Message | Role-tagged conversational content |
| Event | Point-in-time lifecycle/status/streaming record |
| Tool call | Model/agent request to external capability plus result/error |
| Artifact | File, structured output, citation, screenshot, dataset row, or report |
| Trajectory | Ordered action/observation episode with terminal outcome |
| Evaluation | Quality label or score linked to run, turn, artifact, or dataset example |
| Feedback | Human or model-provided evaluation signal, often attached after execution |
| Dataset example | Curated input/reference/output row used for evaluation or few-shot prompting |
| Benchmark | Named evaluation protocol with task set, runner, scorer, config, and report conventions |
| Golden set | Small trusted eval set with reviewed expected behavior, used for frequent regression checks |
| Experiment | Controlled comparison across variants such as prompt, model, retrieval config, tool policy, or agent architecture |
| Prompt version | Stable identifier for the exact prompt/template/instruction used in a rollout |
| Dataset | Versioned collection of examples with schema, split, provenance, and intended use |
| Example | One dataset row containing input, reference output/label, metadata, and optional trace/artifact refs |
| Split | Dataset partition such as train, validation, test, golden, canary, or holdout |
| Holdout | Examples withheld from training and prompt optimization for unbiased evaluation |
| Canary set | Small high-risk eval subset run before broader benchmark or production promotion |
| Workload | Stable logical operation or agent node: tool routing, retrieval, summarization, YAML generation, citation formatting |
| Lineage | Provenance chain from raw event through dataset example, training job, model artifact, rollout, and eval |
| Dedupe | Exact/fuzzy/semantic duplicate removal |
| Contamination | Leakage of benchmark/golden/test content into training, prompt selection, retrieval, or judging |
| Human-in-the-loop | Human review/approval/labeling before promotion |
| Judge | Human, deterministic validator, or model evaluator that scores an output |
| Reward model | Model used to score/rank outputs for filtering, preference learning, or RL-style optimization |
| Preference pair | Candidate outputs for the same input with preference/ranking labels |
| SFT | Supervised fine-tuning on instruction/output examples |
| PEFT / LoRA | Parameter-efficient fine-tuning; LoRA creates a small adapter rather than a full checkpoint |
| Adapter | Fine-tuned parameter delta mounted on a base model |
| Model promotion | Approval and deployment gate for prompt/model/adapter candidates |
| Training candidate | Dataset example that passed redaction, licensing, labeling, and split review |
Rollouts, Evals, Benchmarks, and Golden Sets
Rollout is the unit that ties observability to improvement. A rollout records that a specific agent configuration ran on a specific task at a specific time. It should carry:
rollout_id;prompt_version;model_providerandmodel_id;- tool policy and retrieval config;
- dataset/example/task ID when applicable;
- root
trace_id; - produced artifact IDs;
- eval labels and benchmark scores.
Evals attach quality evidence to a rollout. Benchmarks define repeatable collections of evals. Golden sets are the stable high-signal subset used for fast regression checks. Training candidates should only be created after a rollout has enough provenance, redaction, and eval signal to justify reuse.
NVIDIA Data Flywheel / NeMo Mapping
NVIDIA’s Data Flywheel blueprint was deprecated in April 2026. That changes the implementation recommendation: do not build production systems on the archived reference blueprint. It does not invalidate the terminology or architecture pattern. The enduring pattern is production traffic -> workload-tagged logs -> curated datasets -> base/ICL/customized evals -> adapter/model candidates -> human promotion.
In current production planning, treat Data Flywheel as a reference pattern and map it to NeMo Microservices, OTel/OpenInference, a warehouse, and your eval harness.
| NVIDIA term | Standard term | Operational meaning |
|---|---|---|
| Data flywheel | Rollout/eval/training-candidate loop | Production logs become curated datasets, experiments, and model/prompt candidates |
| Production traffic | Raw events, turns, tool calls | Real app interactions captured for replay and curation |
| Log Store | Raw vault / raw_events |
Storage for exact request/response records before curation |
workload_id |
workload, task_family, agent.node_id |
Stable logical operation key; essential for separating agent nodes |
client_id |
app/deployment/tenant ID | Identifies source application or customer context |
| NeMo Datastore | Dataset/artifact registry | Stores eval datasets, fine-tuning datasets, and LoRA artifacts |
| NeMo Customizer | Training/fine-tuning job | Runs SFT/LoRA customization and creates adapter artifacts |
| NeMo Evaluator | Eval runner/judge | Scores candidate outputs or models |
| Deployment Manager / DMS | Runtime orchestration | Starts/stops candidate NIM deployments for experiments |
| NIM | Serving runtime | Hosts base or adapted model for inference/eval |
| Base eval | Baseline benchmark rollout | Unmodified model on held-out examples |
| ICL eval | Few-shot benchmark rollout | Same model with retrieved/selected in-context examples |
| Customized eval | Fine-tuned benchmark rollout | Adapter/customized model evaluated on held-out examples |
| Class-aware stratified split | Split by workload/tool/class label | Keeps minority classes represented in train/eval/holdout |
| LLM-as-judge | Model evaluator | Scores outputs; should be calibrated against golden/human/deterministic checks |
| Tool-calling correctness | Tool-call eval metric | Exact function plus required argument accuracy; semantic match only for long text fields |
| LoRA artifact | Adapter artifact | Fine-tuned parameter delta with lineage to base model and dataset |
| Model promotion | Promotion gate | Human/governed approval after eval, safety, cost, and regression review |
The major curation risk is weak workload tagging. If an agent chain logs intent classification, retrieval, reranking, generation, tool routing, and YAML formatting under one workload ID, the flywheel will mix incompatible examples. That produces noisy training data and misleading evals. Each agent node needs a stable workload label, and every dataset example should keep lineage back to the rollout, trace, turn, tool call, prompt version, and artifact.
Anthropic-Style Agent Eval Mapping
Anthropic’s “Demystifying evals for AI agents” sharpens the distinction between simple prompt evals and agent evals. Single-turn evals grade a prompt/response. Agent evals give the system a task, tools, and an environment, then grade the resulting state, artifacts, tool behavior, and trajectory. That is the reason our schema keeps rollouts, traces, turns, tool calls, artifacts, and evals separate.
For our domains:
| Domain | Benchmark construction | Scoring |
|---|---|---|
| Skill mining | Replay similar validated traces and counterexamples | Did the skill reduce tool churn, avoid known failure modes, and preserve validation? |
| Corporate KB needles | Use hard but verifiable questions with hidden aliases, old names, owners, and permission edge cases | Correct citation, fewer retrieval attempts, lower elapsed time, no fabricated source |
| YAML generation | Build schema fixtures with valid, invalid, ambiguous, and adversarial cases | Deterministic schema validator plus semantic/business-rule checks |
| Finance/source acquisition | Require primary-source ledgers, citation anchors, and published artifacts | Source correctness, build/search verification, no unsupported claims |
| Tool routing | Stratify by function/tool class and include rare tools | Exact function name, required argument accuracy, semantic match only where appropriate |
| Coding/agent tasks | Provide repo/environment fixtures with executable checks | Tests, file state, browser/UI checks, resource usage, unnecessary edits |
Eval design implications:
- use golden sets for fast regression;
- use broader benchmarks for release decisions;
- use production monitoring for drift and unseen failures;
- document infrastructure and resource configuration as benchmark variables;
- calibrate LLM judges against deterministic checks and human labels;
- track trajectory costs such as extra turns, failed tools, retries, latency, and token spend.
Current NeMo Microservices Impact
The current NeMo Microservices stack changes the production implementation option, not the open observability format. It gives NVIDIA ecosystem services for pieces of the lifecycle:
| Service/concept | Role | Observability mapping |
|---|---|---|
| Entity Store / Data Store | Entity, dataset, file, and artifact storage | dataset IDs, artifact IDs, lineage refs |
| Data Designer | Synthetic data and data design workflows | generated examples, curation labels, synthetic provenance |
| Customizer | Fine-tuning/customization | training job spans, dataset version, base model, adapter artifact |
| Evaluator | Model/app/agent evaluation | EVALUATOR spans, eval rows, benchmark/golden-set results |
| Deployment Management | Candidate deployment orchestration | deployment spans, NIM endpoint IDs, resource/runtime metadata |
| NIM | Inference serving | LLM spans with model/endpoint/version/latency/cost attributes |
| Guardrails / Safe Synthesizer | Safety and controlled generation | GUARDRAIL spans, policy version, rejection/rewrite labels |
NeMo Microservices are useful if the organization wants self-hosted or NVIDIA-enterprise customization/evaluation/deployment. They do not replace OpenTelemetry/OpenInference, LangSmith/Phoenix/Arize trace views, Bedrock invocation audit logs, or local Claude/Codex transcript capture.
OpenInference Format and Model Architectures
OpenTelemetry is the transport/correlation layer. OpenInference is the semantic layer that says what each span represents in an AI system.
Required core idea:
{
"trace_id": "trace_hash",
"span_id": "span_hash",
"parent_span_id": "parent_hash",
"name": "retriever.search",
"attributes": {
"openinference.span.kind": "RETRIEVER",
"session.id": "session_hash",
"input.value": "sha256:redacted",
"output.value": "sha256:redacted"
}
}
Useful span kinds:
| Kind | Meaning | Architecture examples |
|---|---|---|
LLM |
Model generation | Chat/completion, reasoning model, local SLM, NIM, Bedrock, Claude, OpenAI |
EMBEDDING |
Vectorization | RAG embedding, semantic memory, clustering, dedupe |
RETRIEVER |
Candidate context fetch | BM25, vector DB, SQL, graph query, KB search, web search |
RERANKER |
Candidate reorder/prune | Cross-encoder, ColBERT, LLM relevance classifier, NVIDIA reranker |
TOOL |
External action | Shell, browser, MCP, API, file edit, database, M365 |
CHAIN |
Orchestration | Router, prompt builder, parser, formatter, validator |
AGENT |
Agent loop/node | Claude/Codex rollout, LangGraph node, Strands agent, A2A delegate |
GUARDRAIL |
Safety/policy | Permission, content filter, NeMo Guardrails, policy engine |
EVALUATOR |
Scoring | LLM judge, deterministic validator, human label ingestion, benchmark scorer |
PROMPT |
Prompt assembly/versioning | System prompt, few-shot selector, template version |
Model architecture mappings:
| Architecture | Typical OTel/OpenInference trace shape |
|---|---|
| Single-call chatbot | rollout -> LLM |
| RAG | rollout -> RETRIEVER -> RERANKER -> PROMPT -> LLM -> EVALUATOR |
| Tool-calling agent | rollout -> AGENT -> repeated LLM / TOOL pairs -> EVALUATOR |
| Graph agent | rollout -> AGENT -> node-level CHAIN or AGENT spans -> nested model/tool spans |
| Router / MoE / model cascade | rollout -> router CHAIN -> selected LLM expert/model spans -> evaluator/cost spans |
| Fine-tuned SLM | rollout -> LLM span with base model, adapter ID, dataset version, prompt version |
| Data-flywheel candidate eval | rollout -> base/ICL/customized LLM spans -> EVALUATOR spans -> promotion decision artifact |
| Guardrailed system | rollout -> pre GUARDRAIL -> model/tool spans -> post GUARDRAIL -> evaluator |
| Protocol agent UI | rollout -> AG-UI protocol spans/events -> agent/model/tool spans |
| Agent-to-agent delegation | rollout -> A2A task span -> delegated agent trace linked by taskId/trace context |
The design point is that traces should reflect the architecture. A RAG trace without retrieval/reranking spans hides the actual failure modes. A tool agent trace without tool-call spans is not replayable. A fine-tuned adapter trace without dataset and adapter lineage cannot support model promotion decisions.
Cross-Vendor Ontology Map
Other frontier labs and enterprise AI platforms have similar lifecycle services, but their terms differ. The open standard should absorb their nouns rather than copy any single vendor taxonomy.
| Platform | Build/runtime terms | Trace/eval terms | Curation/customization terms | Standard mapping |
|---|---|---|---|---|
| NVIDIA NeMo | NIM, Deployment Management, Guardrails | Evaluator | Data Store, Data Designer, Customizer, LoRA artifact | LLM, GUARDRAIL, EVALUATOR, dataset, adapter, deployment |
| OpenAI | Agents SDK, tools | traces, trace grading, graders, agent evals | datasets, fine-tuning/custom models | rollout, TOOL, EVALUATOR, benchmark, training candidate |
| Anthropic | Claude Agent SDK, Claude Code, Managed Agents, Skills | OTel, sessions, prompts, tool results, empirical evals | skills, prompt/test cases, golden evals | session, skill, tool call, rollout, golden set |
| Google Vertex / Gemini | Agent Engine, ADK, Agent Runtime/Registry/Gateway/Identity | Gen AI evaluation, metrics, eval datasets | Model Garden, tuning/customization | deployment, identity, dataset, eval, benchmark |
| AWS Bedrock AgentCore | Runtime, Gateway, Memory, Browser, Code Interpreter, Policy | Observability, online evals, CloudWatch eval results | Optimization, prompt optimization, model customization | trace, tool call, policy/guardrail, eval, promotion loop |
| Microsoft Foundry | Agent Service, external agents, Semantic Kernel, Agent Framework | OTel tracing, Application Insights, trace-to-dataset, evals | datasets, evaluators, model catalog | OTel trace, dataset, eval, external-agent lineage |
| Mistral | Le Chat/agents/API | Explorer, Judges | Campaigns, Datasets, fine-tuning | raw event explorer, judge, annotation campaign, dataset |
| Databricks Mosaic AI | Agent Framework, model serving, Vector Search | MLflow traces, scorers, monitoring | evaluation datasets, Unity Catalog lineage | trace, scorer/eval, retriever, artifact lineage |
| IBM watsonx Orchestrate | agents, tools, ADK, control plane | monitoring, governance, pre-deployment evaluation | policy/evaluation workflows | agent registry, tool calls, guardrails, eval gates |
| LangSmith | LangChain/LangGraph app runs | runs, child runs, feedback, experiments | datasets | trace/span/run, feedback/eval, benchmark |
| Phoenix/Arize | OpenInference instrumentation | spans, traces, annotations, experiments | datasets/evals | open trace/eval semantic layer |
The shared lifecycle is:
observe production traces
-> mine failures and representative examples
-> create datasets / golden sets
-> run evals / trace grading / judges
-> compare variants
-> optimize prompts, skills, tools, retrieval, or models
-> promote through governance
-> monitor drift and regressions
Normalization Rule
Normalize vendor terms into these canonical fields:
| Canonical field | Vendor aliases |
|---|---|
rollout_id |
run, experiment run, session execution, agent execution, evaluation run |
trace_id |
trace, run tree, Application Insights trace, Phoenix trace, LangSmith root run |
span_id |
child run, step, operation, node, tool event |
tool_call_id |
function call ID, tool use ID, action ID, protocol toolCallId |
dataset_example_id |
example, eval case, row, task, sample |
eval_id |
grader result, judge score, scorer output, feedback, annotation |
prompt_version |
template version, skill version, system prompt hash, instruction version |
model_artifact_id |
adapter, custom model, NIM endpoint, deployment, model version |
policy_version |
guardrail config, policy, safety check, permissions profile |
If a platform cannot emit those fields directly, add them at the collector or warehouse. That is the pragmatic difference between a vendor dashboard and a durable self-improvement system.
OpenTelemetry and OpenInference Mapping
OpenTelemetry should carry the transport and correlation contract. The AI
semantic layer must be chosen and versioned: OpenInference for Phoenix/Arize
semantics, OTel GenAI for gen_ai.* model/agent/tool conventions, and MCP
semantic conventions for MCP protocol/tool spans. Vendor-native records should
be preserved in raw_events, then converted into spans and curated tables.
| Concept | OTel / OpenInference / MCP representation | Claude / Codex | Bedrock / Strands / AgentCore | AG-UI / A2A | LangSmith / Phoenix |
|---|---|---|---|---|---|
| Rollout | Root span plus rollout_id, prompt_version, dataset/task refs |
CLI session segment or desktop task episode | AgentCore session or Strands agent execution | UI runId or A2A delegated taskId |
LangSmith experiment run or Phoenix trace with eval metadata |
| Trace | trace_id and root span |
Session/turn trace emitted by OTel or reconstructed from local logs | OTel trace from Strands/AgentCore; Bedrock request joined by requestId |
Protocol run/task metadata attached to trace | LangSmith root run; Phoenix trace |
| Span | span_id, parent, timing, status |
LLM/tool/file/shell/retrieval operation | Model/tool/retrieval span | Lifecycle event promoted to span where useful | LangSmith child run; Phoenix span |
| LLM | openinference.span.kind=LLM; model/token attrs |
Assistant/model response step | Bedrock invocation span and request metadata | Usually app-layer only | run_type="llm" or Phoenix LLM span |
| Tool | OpenInference TOOL, OTel GenAI execute-tool span, or MCP method/tool span; input/output refs |
Bash/MCP/browser/file/function call | Strands tool span; Bedrock payload if model requested tool | AG-UI tool lifecycle; A2A task/message delegation | run_type="tool" or Phoenix TOOL span after translation where needed |
| Retriever | openinference.span.kind=RETRIEVER; document refs |
Search/read/source tools | Bedrock KB or app retriever span | Protocol metadata unless app emits retriever span | run_type="retriever" or Phoenix RETRIEVER span |
| Turn | turn_id, session/thread metadata, message events |
User prompt plus assistant/tool sequence | App-layer conversation ID | AG-UI messages; A2A messages | LangSmith thread metadata; Phoenix session metadata |
| Eval | Eval span/event or warehouse row | Test/build/human label joined to trace | Bedrock/APO/evaluator or external harness | Protocol status plus separate scorer | LangSmith feedback/eval; Phoenix annotation/eval |
| Memory event | Memory read/write span or warehouse row | Local memory/skill/session note if captured | AgentCore/Managed Agent memory read/write | Protocol state/memory only if exposed | Trace metadata or dataset/eval row |
| Context event | Compaction/offload/code-filter span or warehouse row with token counts | CLI compaction, shell/code filtering, artifact refs | Code Interpreter/browser/tool-output offload, memory context | Protocol state snapshot/reduction | Trace metadata or warehouse row |
| Golden set | Dataset split and stable example IDs | Curated local tasks/examples | Bedrock prompt optimization samples or external eval rows | E2E protocol replay cases | LangSmith/Phoenix dataset split |
| Benchmark | Experiment collection and scorer metadata | StateBench/local harness | Bedrock eval/APO or external harness | Protocol conformance/e2e harness | LangSmith/Phoenix experiment |
Minimal OTel emission pattern:
with tracer.start_as_current_span("agent.rollout") as rollout:
rollout.set_attribute("rollout.id", rollout_id)
rollout.set_attribute("prompt.version", prompt_version)
rollout.set_attribute("dataset.example_id", example_id)
with tracer.start_as_current_span("llm.generate") as span:
span.set_attribute("openinference.span.kind", "LLM")
span.set_attribute("llm.provider", "bedrock")
span.set_attribute("llm.model_name", model_id)
with tracer.start_as_current_span("tool.call") as span:
span.set_attribute("openinference.span.kind", "TOOL")
span.set_attribute("tool.name", tool_name)
span.set_attribute("tool.call_id", tool_call_id)
with tracer.start_as_current_span("eval.score") as span:
span.set_attribute("openinference.span.kind", "EVALUATOR")
span.set_attribute("eval.name", "yaml_schema_validator")
span.set_attribute("eval.passed", True)
OSS and China/Asia Ecosystem Gap Map
The standard should now track more than frontier labs and hyperscalers. The open-source and China/Asia ecosystems are important, but they should be mapped by contract strength rather than brand presence.
Detailed gap-ingest pages:
- OSS and Independent Agent Observability/Eval Platforms 2026
- China and Asia Agent Platform Telemetry Gap Map 2026
- Agent Telemetry Config Verification Harness 2026
- Agent Protocol Observability Gaps 2026
- AgentCore, OTel/OpenInference, and the Agent Training Loop 2026
- Agent Telemetry Pipelines: AWS, Dagster, Hugging Face, OTel, OpenInference, and Training 2026
| Ecosystem | Contract level | What it can add | What must be verified |
|---|---|---|---|
| Langfuse | Trace/eval-ready | OTel-aligned tracing, LLM calls, tool invocations, retrieval steps, prompt management, datasets, evals, experiments, annotation, self-hosting | Export fidelity, retention/cost model, exact tool-call input/output redaction controls |
| W&B Weave | Eval/monitoring-ready | LLM traces, online evaluations, experiment tracking, production scoring, model monitoring | Raw trace export shape and whether local desktop-agent actions are captured or only instrumented app calls |
| Braintrust | Eval-first trace-ready | Trace hierarchy/timeline/conversation views, raw JSON trace view, tool spans, datasets, experiments, scorers, human review |
Cross-system trace propagation and non-SDK local transcript joins |
| Helicone | Gateway/request-ready | Request/response logging, cost/latency, routing, dashboards, alerting, prompt management, removal/redaction controls | Multi-step agent/tool trajectory completeness unless paired with app OTel |
| OpenLIT / OpenLLMetry / Traceloop | Instrumentation-ready | OTel-based auto-instrumentation for model/framework calls; Phoenix can translate these conventions into OpenInference | Semantic drift between OTel GenAI, OpenLLMetry/OpenLIT, and OpenInference; tool-call ID consistency |
| DeepEval / Ragas / TruLens / Promptfoo | Evaluation-ready | RAG checks, prompt tests, model/scorer evals, CI gates, regression suites | Dataset lineage, scorer calibration, stable IDs joined to traces and artifacts |
| NVIDIA AI-Q Blueprint | Reference architecture | Phoenix/Weave-style backends, tracing of agent execution, LLM calls, tool invocations, token usage, and dataset construction from traces | Whether the blueprint’s config maps cleanly to your production OTel/OpenInference collectors |
| AgentScope / Alibaba ecosystem | Promising trace bridge | AgentScope Studio traces, token usage metadata, tracing_url export to Phoenix, Langfuse, Alibaba CloudMonitor, or any OTLP endpoint |
Exact emitted span attributes, tool-call payload fields, redaction gates, and production support status |
| Tencent Cloud ADP | Product lifecycle/eval workflow | Conversation history, app analytics, Q&A optimization, workflow/multi-agent mode, knowledge base, plugin marketplace, evaluation set export/upload | Public raw trace schema, OTLP/OpenInference export, stable tool-call IDs, cost/retention terms |
| Baidu Qianfan | Product lifecycle | Agent engine, tools/MCP, model services, enterprise capabilities | Public observability/export contract and eval dataset schema |
| Volcengine ADK / Ark | Trace-promising | Trace IDs, GenAI attributes, multi-agent tracing, SLI-driven full-chain observability articles | Raw event format, OTLP collector behavior, tool-call redaction, English contract availability |
| Huawei ModelArts / Pangu | AI lifecycle/monitoring | Data preprocessing, labeling, training, deployment, monitoring metrics, large-model app/agent development | Agent-specific trace/tool-call schema and export API |
| Coze | Agent builder lifecycle | Workflows, plugins, knowledge, app publishing, bot/agent construction | Logs, trace IDs, eval set export, tool-call payloads, warehouse/API export |
| Moonshot/Kimi / DeepSeek | Model/API provider | Model access, agent-task capable models, web/tool features, pricing and request APIs | Separate agent observability, trace export, and eval-loop contracts |
Contract-Strength Checklist
Do not treat an “agent platform” as production-observable until it passes these checks:
| Requirement | Standard field/table | Why it matters |
|---|---|---|
| Stable trace identity | trace_id, span_id, parent_span_id in agent_spans |
Enables cross-service causality and flame-chart/timeline debugging |
| Stable human/task grouping | session_id, thread_id, turn_id, rollout_id in turns |
Prevents a trace tree from losing the user-visible episode |
| Tool-call pairing | tool_call_id, request/result/error/approval in tool_calls |
Makes local reliability and safety metrics possible |
| Artifact lineage | artifact_id, artifact_type, source refs in artifacts |
Required for YAML generation, citations, screenshots, diffs, and produced files |
| Eval conversion | dataset_example_id, eval_id, scorer/version fields |
Turns logs into golden sets, benchmarks, prompt optimization, and model training inputs |
| Export path | JSONL, Parquet, OTLP, OpenInference, LangSmith-compatible run export, or warehouse API | Prevents dashboard lock-in |
| Privacy controls | redaction_version, content gates, hashes, byte counts, refs |
Lets teams separate hot debugging from safe long-term mining |
| Cost controls | sampling, retention, payload/body toggles, archive tier | Prevents full-content logs from dominating operating cost |
Underdeveloped Standards
Several pieces are still immature across the ecosystem:
tool_call_idis not consistently propagated from UI protocol to model call to local executor to eval result.- State deltas, memory reads/writes, approvals, and permission decisions are not first-class enough in OTel/OpenInference.
- Trace-to-dataset conversion is product-specific. LangSmith, Braintrust, Weave, Phoenix/Arize, Langfuse, and eval libraries each expose useful paths, but there is no single open “curated agent example” contract.
- Chinese cloud platforms often expose agent lifecycle and analytics features before publishing enough raw trace/export detail for cross-vendor standardization.
- X/YouTube/community material is good for finding failure modes, but should be converted into testable eval labels before it drives architecture decisions.
Source Notes
- LangSmith OpenTelemetry docs map OTel attributes such as
langsmith.trace.name,langsmith.span.kind,langsmith.trace.session_id,langsmith.trace.session_name,langsmith.span.tags, andlangsmith.metadata.*into LangSmith fields. - LangSmith trace query docs support filtering by project, trace, run type, dataset/example, parent run, error state, root runs, selected fields, root trace filters, tree filters, metadata, tags, feedback, full-text search, and natural-language query.
- LangSmith dataset docs describe dataset versioning, tagged versions, splits, CSV/JSONL/OpenAI fine-tuning format export, and exporting filtered traces from experiments to datasets.
- LangSmith few-shot evaluator docs describe using corrected evaluator feedback to populate a corrections dataset and insert examples into evaluator prompts.
- Phoenix/OpenInference docs describe OpenInference as OTel-compatible semantic conventions and instrumentation for LLM apps, including integrations for Claude Agent SDK, Bedrock, DSPy, LangChain, MCP, Anthropic, Strands, and others.
- Phoenix translation docs show converting OpenLIT, OpenLLMetry, and OpenTelemetry GenAI attributes into OpenInference format for Phoenix.
Sources
- LangSmith OpenTelemetry tracing: https://docs.langchain.com/langsmith/collector-proxy
- LangSmith distributed tracing: https://docs.langchain.com/langsmith/distributed-tracing
- LangSmith query/export traces: https://docs.langchain.com/langsmith/export-traces
- LangSmith trace query syntax: https://docs.langchain.com/langsmith/trace-query-syntax
- LangSmith metadata parameters: https://docs.langchain.com/langsmith/ls-metadata-parameters
- LangSmith bulk data export: https://docs.langchain.com/langsmith/data-export
- LangSmith messages view trace format: https://docs.langchain.com/langsmith/messages-view-trace-format
- LangSmith datasets: https://docs.langchain.com/langsmith/manage-datasets
- LangSmith few-shot evaluator corrections: https://docs.langchain.com/langsmith/create-few-shot-evaluators
- LangSmith RunTree reference: https://reference.langchain.com/javascript/langsmith/index/RunTree
- LangSmith pricing: https://www.langchain.com/pricing
- Anthropic, Demystifying evals for AI agents: https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents
- Anthropic, Quantifying infrastructure noise in agentic coding evals: https://www.anthropic.com/engineering/infrastructure-noise
- Anthropic, A statistical approach to model evaluations: https://www.anthropic.com/research/statistical-approach-to-model-evals
- Anthropic docs, Create strong empirical evaluations: https://docs.anthropic.com/en/docs/test-and-evaluate/develop-tests
- Anthropic, Effective context engineering for AI agents: https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
- Anthropic, Code execution with MCP: https://www.anthropic.com/engineering/code-execution-with-mcp
- Anthropic, Built-in memory for Claude Managed Agents: https://claude.com/blog/claude-managed-agents-memory
- OpenTelemetry GenAI semantic conventions: https://opentelemetry.io/docs/specs/semconv/gen-ai/
- MCP OTel trace-context SEP: https://modelcontextprotocol.io/seps/414-request-meta
- OpenAI evaluation best practices: https://platform.openai.com/docs/guides/evaluation-best-practices
- NVIDIA NeMo Microservices docs: https://docs.nvidia.com/nemo/microservices/latest/index.html
- NVIDIA NeMo Evaluator: https://developer.nvidia.com/nemo-evaluator/
- OpenAI agent evals: https://platform.openai.com/docs/guides/agent-evals
- OpenAI trace grading: https://platform.openai.com/docs/guides/trace-grading
- OpenAI graders: https://platform.openai.com/docs/guides/graders
- Google Vertex AI agent evaluation: https://docs.cloud.google.com/vertex-ai/generative-ai/docs/models/evaluation-agents
- Microsoft Foundry agent tracing: https://learn.microsoft.com/en-us/azure/ai-foundry/agents/concepts/tracing
- Microsoft Foundry external agents for observability/evaluation: https://learn.microsoft.com/en-us/azure/foundry/agents/how-to/register-external-agent
- Mistral Observability: https://docs.mistral.ai/capabilities/observability
- Databricks evaluate and monitor AI agents: https://docs.databricks.com/aws/en/mlflow3/genai/eval-monitor/
- IBM watsonx Orchestrate governance and observability: https://www.ibm.com/products/watsonx-orchestrate/governance-and-observability
- Langfuse docs: https://langfuse.com/docs
- W&B Weave tracing docs: https://docs.wandb.ai/weave/guides/tracking
- Braintrust trace docs: https://www.braintrust.dev/docs/observe/examine-traces
- Helicone docs: https://docs.helicone.ai/quick-start
- NVIDIA AI-Q Blueprint observability: https://docs.nvidia.com/aiq-blueprint/2.1.0/deployment/observability.html
- AgentScope observability: https://docs.agentscope.io/observe-and-evaluate/observability
- Tencent Cloud Agent Development Platform analytics: https://intl.cloud.tencent.com/document/product/1254/72572
- Baidu Qianfan: https://intl.cloud.baidu.com/product/qianfan.html
- Volcengine ADK tracing: https://volcengine.github.io/veadk-python/observation/tracing/
- Huawei ModelArts: https://doc.hcs.huawei.com/en-us/modelarts/index.html
- Moonshot Kimi API docs: https://platform.moonshot.ai/docs/overview
- Kaggle Standardized Agent Exams: https://x.com/kaggle/status/2039025436164808968
- CoderForge agent-run analysis: https://x.com/lihanc02/status/2032150260638941360
- AgentTrace structured logging paper: https://arxiv.org/abs/2602.10133
- Failure-aware observability paper: https://arxiv.org/abs/2606.01365
- OpenInference overview: https://arize-ai.github.io/openinference/
- Phoenix convention translation: https://arize.com/docs/phoenix/tracing/concepts-tracing/translating-conventions
- Prometheus OTLP metrics ingestion: https://prometheus.io/docs/guides/opentelemetry/
- OpenTelemetry Collector components and connectors: https://opentelemetry.io/docs/collector/components/connector/
- OpenTelemetry Collector transforming telemetry: https://opentelemetry.io/docs/collector/transforming-telemetry/
- Arize pricing: https://arize.com/pricing
- Phoenix: https://phoenix.arize.com/
- Bedrock invocation logging: https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html
- CloudWatch pricing: https://aws.amazon.com/cloudwatch/pricing
- S3 pricing: https://aws.amazon.com/s3/pricing/
- Data Firehose pricing: https://aws.amazon.com/kinesis/data-firehose/pricing/
- Existing synthesis: /findings/agent-log-mining-observability-playbook.md
Brandon Sneider | brandon@brandonsneider.com June 2026