<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Opentelemetry on Café Com Cloud</title><link>https://blog.cafecomcloud.com.br/tags/opentelemetry/</link><description>Recent content in Opentelemetry on Café Com Cloud</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 17 Jul 2026 14:40:00 -0300</lastBuildDate><atom:link href="https://blog.cafecomcloud.com.br/tags/opentelemetry/index.xml" rel="self" type="application/rss+xml"/><item><title>An OpenTelemetry gotcha for anyone instrumenting AI agents</title><link>https://blog.cafecomcloud.com.br/2026/07/17/opentelemetry-gotcha-ai-agents/</link><pubDate>Fri, 17 Jul 2026 14:40:00 -0300</pubDate><guid>https://blog.cafecomcloud.com.br/2026/07/17/opentelemetry-gotcha-ai-agents/</guid><description>&lt;p&gt;If you added OpenTelemetry to an AI agent this year, you probably followed the same path everyone follows. Add the ADOT distro. Run your entrypoint through &lt;code&gt;opentelemetry-instrument&lt;/code&gt;. Point the exporter at CloudWatch. Ship it. And it works. Traces show up, token counts show up, latency shows up. Nothing broken.&lt;/p&gt;
&lt;p&gt;But there&amp;rsquo;s a subtle question hiding in that setup that most people never ask, and getting it wrong is a real security bug. One that just cost the AWS Bedrock AgentCore Python SDK a CVE this week.&lt;/p&gt;
&lt;h2 id="the-design-decision-most-people-miss"&gt;The design decision most people miss
&lt;/h2&gt;&lt;p&gt;OpenTelemetry has semantic conventions for generative AI (the &lt;code&gt;gen_ai.*&lt;/code&gt; namespace). Version 1.41 of the spec makes a deliberate design decision that&amp;rsquo;s easy to miss: it splits the attributes an agent span can carry into two different categories.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Structural attributes&lt;/strong&gt; are metadata about the call. Which model. Which provider. How many input tokens, how many output tokens, how long it took, which guardrail applied. These are safe to emit on every span by default. They tell you about performance and cost without exposing what the agent was working on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Content attributes&lt;/strong&gt; are the message bodies themselves. &lt;code&gt;gen_ai.input.messages&lt;/code&gt; (the prompt). &lt;code&gt;gen_ai.output.messages&lt;/code&gt; (the response). &lt;code&gt;gen_ai.system_instructions&lt;/code&gt; (the system prompt). The spec says these must not be emitted by default. They have to be an explicit opt-in.&lt;/p&gt;
&lt;p&gt;The reason for the split isn&amp;rsquo;t paranoia. If your agent is a customer support bot, the prompt is what your customer wrote in the chat window. If it&amp;rsquo;s a financial-analysis agent, the prompt might include the numbers being analyzed. If it&amp;rsquo;s a medical-summary agent, the prompt might have identifiable patient data. Whatever the domain, the message bodies are customer data. The token counts and latency numbers aren&amp;rsquo;t.&lt;/p&gt;
&lt;h2 id="what-happened-this-week"&gt;What happened this week
&lt;/h2&gt;&lt;p&gt;The AWS Bedrock AgentCore Python SDK, which is the library you use to build agents on Amazon Bedrock&amp;rsquo;s agent runtime, shipped two versions (1.4.8 and 1.5.0) whose OpenTelemetry instrumentation wrote the full user prompt and the full agent response into span attributes on every invocation, without checking the opt-in flag. Those spans then exported to the customer&amp;rsquo;s &lt;code&gt;aws/spans&lt;/code&gt; CloudWatch log group.&lt;/p&gt;
&lt;p&gt;The exposure was local: you needed IAM access to the account and &lt;code&gt;logs:GetLogEvents&lt;/code&gt; on the span log group to read anything. Nothing on the open internet. But once inside, you saw plaintext prompts and plaintext responses. That&amp;rsquo;s CVE-2026-15737, disclosed on July 16, with a fixed release (&lt;code&gt;bedrock-agentcore&lt;/code&gt; 1.5.1) available the same day.&lt;/p&gt;
&lt;p&gt;I want to be clear about the reason for writing this post. It isn&amp;rsquo;t to pick on the AgentCore team. AWS published a clear advisory on the same day the fix shipped, told users exactly what to purge from CloudWatch, made the whole thing consumable through a public GitHub Security Advisory, and got the fix into pip within hours. That&amp;rsquo;s what a mature responsible-disclosure pipeline looks like. Being able to write a post like this one, from public sources, on the same day the CVE lands, is only possible because the transparency is there.&lt;/p&gt;
&lt;p&gt;The reason I&amp;rsquo;m writing is that the same class of mistake is easy to make on every project that instruments an agent with OpenTelemetry, and the fix is a config choice, not a code choice.&lt;/p&gt;
&lt;h2 id="the-check-i-want-to-leave-you-with"&gt;The check I want to leave you with
&lt;/h2&gt;&lt;p&gt;Two questions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Question 1: Do your CloudWatch log groups contain content attributes?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Run this in CloudWatch Logs Insights against your &lt;code&gt;/aws/spans/*&lt;/code&gt; groups, or wherever your agent&amp;rsquo;s OTel exporter lands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fields @timestamp, @message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| filter @message like /gen_ai\.input\.messages|gen_ai\.output\.messages|gen_ai\.prompt|gen_ai\.completion/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| sort @timestamp desc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| limit 100
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If it returns rows, message bodies are landing in your logs. That&amp;rsquo;s either intentional (you opted in) or a design escape (something in your stack has content capture on by default). Either way, worth knowing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Question 2: If content bodies are being captured, who can read them?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The default &lt;code&gt;CloudWatchLogsReadOnlyAccess&lt;/code&gt; managed policy grants read on every log group in the account. If you&amp;rsquo;ve got engineers or contractors with broad read access on the observability side, they can also read every conversation your agent has had. That&amp;rsquo;s a call to make deliberately, not by accident.&lt;/p&gt;
&lt;p&gt;For most agents in production, the right pattern is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Keep content capture off by default.&lt;/li&gt;
&lt;li&gt;Route structural spans (token counts, latency, model id) to your general observability pipeline.&lt;/li&gt;
&lt;li&gt;If you need content for debugging, route it to a separate log group with a stricter KMS key, tighter IAM, and shorter retention.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The instrumentation-side switch is one environment variable. &lt;code&gt;AGENT_OBSERVABILITY_ENABLED=true&lt;/code&gt; gets you structural coverage. Content capture only happens if a library explicitly opts in via its own flag. Traceloop calls it &lt;code&gt;TRACELOOP_TRACE_CONTENT&lt;/code&gt;. Others vary. If you never set the content flag, and your SDK follows the v1.41 opt-in default, you&amp;rsquo;re safe by design.&lt;/p&gt;
&lt;h2 id="fix-and-audit-checklist"&gt;Fix and audit checklist
&lt;/h2&gt;&lt;p&gt;If you&amp;rsquo;re building on Bedrock AgentCore:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Upgrade to &lt;code&gt;bedrock-agentcore&amp;gt;=1.5.1&lt;/code&gt;. The current stable is 1.15.1 (June 25, 2026), so you&amp;rsquo;re 10 minor bumps behind if you&amp;rsquo;re on the affected releases.&lt;/li&gt;
&lt;li&gt;Run the CWL Insights query above on your &lt;code&gt;aws/spans&lt;/code&gt; log groups.&lt;/li&gt;
&lt;li&gt;Purge whatever leaked (delete the affected log streams, or delete the log groups and let AgentCore recreate them).&lt;/li&gt;
&lt;li&gt;Audit who has &lt;code&gt;logs:GetLogEvents&lt;/code&gt; on those groups.&lt;/li&gt;
&lt;li&gt;If you have forked or vendored versions of the SDK, patch them too.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you&amp;rsquo;re building on any other agent framework (LangChain with OTel, Strands Agents, LlamaIndex with observability, your own custom thing), check what your instrumentation does with content by default. Not every library respects the v1.41 opt-in signal. The check takes ten minutes.&lt;/p&gt;
&lt;p&gt;The design decision takes ten seconds. But it&amp;rsquo;s a lot easier to make the right choice on day one than to purge months of CloudWatch spans later.&lt;/p&gt;
&lt;p&gt;See you around,
Leo&lt;/p&gt;</description></item></channel></rss>