OpenTelemetry can now trace an AI agent from the incoming request down to each tool call, and the default choices decide how much sensitive text ends up in your telemetry backend. A SigNoz walkthrough published October 22, 2026 shows the pattern with an OpenAI Agents demo: workflow spans, agent spans, model calls and tool executions, each with attributes such as token counts and, optionally, tool arguments, tool results and full message content. For debugging that is exactly what you want. For security and privacy it raises two questions this post answers: what do these traces actually record, and what do they not tell you about risk? The post is a vendor tutorial based on one demo app, so we separate what it shows from what it implies.
| Question | Short answer |
|---|---|
| What is recorded? | Workflow, agent, model and tool spans; token usage; optionally prompts, completions, tool arguments and results |
| What is the privacy switch? | OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT (span_only or no_content) |
| Does it detect unsafe actions? | No. It records behaviour; guardrail blocks appear as exception events |
| Is the instrumentation mature? | Uneven for handoffs and guardrails, per the post; pin versions |
| Does data stay local? | Only if your exporter and backend are local. The demo sends to SigNoz Cloud |
What the traces contain
The walkthrough uses the GenAI semantic conventions, the gen_ai.* attribute family. Because those conventions change faster than the HTTP or database ones, the instrumentation lives in a separate repository, open-telemetry/opentelemetry-python-genai, split into two packages. The OpenAI Agents package emits workflow and routing spans (invoke_workflow, invoke_agent, execute_tool); the OpenAI package emits model-call spans (chat) with token usage and prompt context.
The resulting hierarchy starts at the web endpoint, includes HTTP client spans for session lookups, and under the workflow span shows each agent run as alternating chat and execute_tool spans. Key attributes include provider and model names, gen_ai.operation.name, finish reasons, gen_ai.usage.input_tokens and gen_ai.usage.output_tokens, and tool data in gen_ai.tool.call.arguments and gen_ai.tool.call.result. When content capture is on, the spans also hold gen_ai.input.messages, gen_ai.output.messages, gen_ai.system_instructions and gen_ai.tool.definitions.
That list is the privacy story in miniature. System instructions, user messages, and every argument and result of every tool call can land in a trace.
The one privacy control the post documents
The walkthrough's only explicit security control is the content-capture variable, OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT:
span_onlyrecords prompts, completions and tool definitions on spans.no_content"retains model timing, token counts, and span hierarchies while omitting raw message payloads," in the post's description.
The post does not cover credential handling, access control for the telemetry backend, or redaction beyond that toggle, and its demo passes the OpenAI key as an inline environment variable, a convenience the author flags is not a production pattern. Note also that the toggle is described in terms of message payloads; the attribute list shows tool arguments and results as separate attributes, and the post does not say whether no_content removes them. Verify that against your installed version before assuming it does.
Why this matters: a coding agent's tool arguments are file paths, shell commands and file contents. A shell command can contain a token; a file read result can contain a private key. A trace backend then becomes a second copy of everything the agent touched, with its own retention, access list and breach surface. We have seen this class of exposure before: our write-up of the million public URL traces shows how agent activity records can end up reachable by more people than intended.
Guardrails in the trace
The demo defines an input guardrail that sets tripwire_triggered=True for off-topic input, aborting the run before any model or tool call. A FastAPI handler calls span.record_exception(exc) and returns HTTP 400, so the block appears as an exception event on the root span. This is a useful pattern: policy decisions become searchable events rather than silent drops. It also shows the limit of tracing as security tooling. The guardrail in the demo checks for basketball keywords. A trace records that a rule fired; it does not know whether the rules were adequate.
The post also records a quirk worth remembering: in one run the agent made a second, meaningless tool call with {"wins":0,"losses":0}. It did not change the answer, but it is the kind of unplanned action that tool-level spans make visible and that ordinary logs would miss.
What traces do not tell you
Observability and security monitoring overlap but are different jobs. The walkthrough is about debugging, latency and token tracking. For an agent that runs commands on a developer machine, the questions are different:
- Was that command destructive, or did it expose a credential?
- Did the agent read a file outside the project?
- Was the instruction it followed part of the user's request, or text it found in a file or web page?
A span can contain the answer to each, but nothing in the OpenTelemetry conventions classifies it. You still need rules or review on top. The distinction is the one we make in what AI agent monitoring is and in monitor versus block: recording is the first step, deciding is the second, and blocking is a third.
How the demo is wired, and where to look for leaks
The setup in the walkthrough is short, which is part of why this pattern spreads. It needs Python 3.12 or later, an ingestion key for the backend and a model API key. You install the pinned requirements, which include opentelemetry-distro, opentelemetry-exporter-otlp and the two GenAI packages, run opentelemetry-bootstrap --action=install to add FastAPI and HTTPX instrumentation, and start the app under opentelemetry-instrument with the service name, resource attributes, OTLP endpoint and headers, the HTTP/protobuf protocol and the content-capture mode set as environment variables.
Every one of those is a place where a security review can add value. The OTLP headers usually carry the ingestion key, so they belong in a secret store and not in a shell history or a shared .env file. The endpoint decides where captured text goes, so confirm it points at infrastructure you meant. The resource attributes may include environment names that reveal more than you want to share. And the content-capture variable is the one setting that changes whether the trace is a performance record or a transcript.
A quick way to test your own setup is to run one request that includes a harmless fake secret, such as a string that looks like sk-test-1234, then search the backend for it. If it appears in a span attribute, your configuration records content, and you can decide whether to switch to no_content, filter attributes in a collector, or shorten retention. Repeat the test after upgrades, because the post warns the conventions and packages are still changing.
Maturity and caveats
The post is candid about rough edges. Instrumentation coverage for handoffs and guardrails is uneven, so it advises pinning package versions and checking changelogs. opentelemetry-bootstrap does not yet detect the GenAI packages, so they must be installed manually, and it installs a deprecated OpenAI v2 package that can be left alone or removed. A logging auto-instrumentation environment variable is deprecated in newer releases. Its conclusions come from one demo app, and the dashboard metrics come from SigNoz Cloud rather than OpenTelemetry alone. None of this is a criticism; it is a reminder that the conventions are still moving.
What this means if you run AI coding agents
- Decide on content capture deliberately. If you send agent telemetry anywhere, choose
no_contentunless you have a reason and a retention plan for prompts. - Audit tool attributes. Look at a real trace and check whether
gen_ai.tool.call.argumentsand results carry paths, commands or secrets. Redact before export if they do. - Treat the backend as sensitive. Apply access control and retention to it as you would to a log store containing source code.
- Prefer a local collector. Where you can, route telemetry to a collector on the machine or network you control, and strip attributes there.
- Add rules on top. Use a policy layer that evaluates actions, not just a viewer that stores them. Our SOC 2 guide for coding agents covers what auditors ask to see.
- Pin versions. With conventions in flux, an upgrade can change which attributes are emitted. Re-check privacy settings after each bump.
What Beam can and cannot do here
Beam's local collector listens on loopback (normally 127.0.0.1:4319) and accepts OTLP/HTTP JSON at POST /v1/logs; the docs state that protobuf is not supported, so an exporter configured for protobuf will not work as-is. It also accepts Claude Code PreToolUse or PostToolUse payloads and normalized NDJSON. Beam redacts secrets before storing events, keeps the latest 10,000 events and 500 scan reports, and keeps data on-device. The collector API requires a bearer token and should not be exposed publicly. See local-first storage and how it works.
What Beam does not do: it does not replace a tracing backend, it does not instrument your own agent code, and it does not make OpenTelemetry's content settings safe for you. Its flags are heuristic, its deny is hook-based for Claude Code and Codex rather than a kernel sandbox, and missing cached policy fails open. It sees only what you point it at: a hook, a CLI pipe or an OTLP/HTTP forwarder.
Frequently asked questions
What does OpenTelemetry capture for an AI agent?
With the GenAI instrumentation it emits workflow, agent, model (chat) and tool (execute_tool) spans with attributes for provider, model, token usage, finish reasons and, when enabled, tool arguments, tool results and message content.
How do I stop prompts and completions being recorded?
The SigNoz walkthrough names OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT. The value span_only records prompts, completions and tool definitions on spans; no_content keeps timing, token counts and span hierarchy but drops raw message payloads.
Are tool arguments and results also sensitive?
Yes. The walkthrough lists gen_ai.tool.call.arguments and gen_ai.tool.call.result among the key attributes, and a tool call can carry file paths, queries or secrets. Check what your instrumentation records and redact before export.
Does tracing tell me an agent did something unsafe?
No. Traces show what happened, not whether it was risky. The walkthrough records guardrail blocks as exception events, but it covers no credential handling, backend access control or redaction beyond the content toggle.
How mature is the instrumentation?
The post says coverage for handoffs and guardrails is uneven and advises pinning package versions and checking changelogs. Its conclusions come from one demo app.
How does this relate to Beam?
Beam's local collector accepts OTLP/HTTP JSON at POST /v1/logs on loopback, not protobuf, and keeps data on-device. It watches agent actions and flags risk; OpenTelemetry traces are one possible input.
Related reading
- What is AI agent monitoring?
- Monitor versus block for AI agents
- A million public URL traces
- SOC 2 and AI coding agents
- SigNoz walkthrough and opentelemetry-python-genai
Details reflect the SigNoz walkthrough and Beam's documentation as of October 22, 2026; GenAI conventions are still changing. Beam is a local prototype; features described are as documented at the time of writing.

