How One Enterprise Backend Team Discovered Their AI Agent Workflows Were Silently Leaking Customer Data Through Tool Call Logs , and the Scrubbing Pipeline They Built to Fix It

How One Enterprise Backend Team Discovered Their AI Agent Workflows Were Silently Leaking Customer Data Through Tool Call Logs ,  and the Scrubbing Pipeline They Built to Fix It

It started with a routine enablement task. A backend platform team at a mid-sized B2B SaaS company , let's call them Meridian Financial Services, a composite based on a real pattern we've seen across multiple enterprise engagements in 2026 , was rolling out centralized OpenTelemetry (OTel) tracing across their microservices estate. The goal was straightforward: unified observability, better latency attribution, and a clean audit trail ahead of their H2 2026 SOC 2 Type II renewal.

What they found instead was a quiet catastrophe hiding in plain sight inside their trace collector.

Their AI agent workflows, which had been powering an internal customer support copilot for about eight months, were emitting full tool call request and response payloads as span attributes into their centralized Jaeger backend. Customer names, account numbers, partial credit card metadata, and support ticket content were all flowing, unredacted, into a system that had read access granted to over 40 internal engineers across three teams.

This is the story of how they found it, why it happens so easily, and the scrubbing pipeline architecture they built to contain it before their auditors arrived.

Why AI Agent Tracing Is a Fundamentally Different Problem

Traditional distributed tracing is well-understood. You instrument HTTP calls, database queries, and message queue interactions. You capture metadata: HTTP method, status code, queue name, row count. The actual content of those interactions is rarely captured verbatim because engineers know not to log SQL query results or HTTP response bodies wholesale.

AI agent workflows break that intuition entirely.

Modern agentic frameworks , whether you're using LangGraph, the OpenAI Assistants API with custom tools, Semantic Kernel, or a bespoke orchestration layer , operate on a loop that looks roughly like this:

  • The LLM receives a user message and a list of available tools.
  • The LLM decides to call a tool (e.g., get_customer_account_details) and emits a structured tool call with arguments.
  • Your backend executes the tool and returns a response object to the LLM.
  • The LLM incorporates the response and either calls another tool or produces a final answer.

When you instrument this loop with OpenTelemetry, the natural thing to do is capture the entire interaction as a span. The tool name becomes a span attribute. The arguments become span attributes. And critically, the tool response becomes a span attribute. That response is often a raw JSON blob pulled directly from your CRM, your billing system, or your support ticketing platform. It contains exactly the kind of data your SOC 2 controls are supposed to protect.

Meridian's team had done nothing wrong in isolation. They followed the OpenTelemetry semantic conventions for generative AI (the gen_ai.* attribute namespace, which became a stable specification in late 2025). They used a popular open-source LLM observability SDK that auto-instrumented their agent framework. The SDK, helpfully, captured everything. That was the problem.

The Discovery: What the Trace Explorer Revealed

The discovery came not from a security scan but from a developer debugging a latency spike. An engineer pulled up a trace in the team's Jaeger UI for a slow agent invocation and noticed the span for tool.response contained a raw JSON payload that included a customer's full name, their account tier, their outstanding invoice amount, and the last four digits of their payment method.

She flagged it immediately. Within 24 hours, the team had run a sampling query across their trace storage backend (they were using a Grafana Tempo instance backed by object storage) and confirmed the scope of the problem:

  • ~340,000 agent invocations had been traced over the prior eight months.
  • Approximately 62% of those traces contained at least one tool call response with identifiable customer data.
  • The data spanned fields including full names, email addresses, company names, contract values, and support ticket body text.
  • Trace data was retained for 90 days by default, meaning a significant volume was still live and accessible.
  • Access to the Jaeger/Tempo backend was controlled by a single SSO group that included developers, SREs, and two contractors.

The team's CISO was notified that afternoon. The SOC 2 audit was scheduled for October 2026. They had roughly four months to remediate, document, and demonstrate controls.

Root Cause Analysis: Three Compounding Failures

Before designing a fix, the team conducted a structured root cause analysis. They identified three distinct failure layers, each of which was individually understandable but collectively catastrophic.

1. Auto-Instrumentation Without Data Classification

The LLM observability SDK they used (a common pattern across tools like Langfuse, Arize Phoenix, and similar platforms) auto-instrumented the agent framework by monkey-patching the tool execution hooks. This is a genuinely useful feature for development environments. In production, however, it meant that no human ever made an explicit decision to capture tool response payloads. The data flowed in because the SDK's default configuration was "capture everything," and nobody had configured it otherwise.

2. No PII Classification at the Tool Layer

The tools themselves , get_customer_account_details, search_support_tickets, lookup_invoice_history , returned rich domain objects directly from their underlying service clients. There was no data classification layer between the service response and the tool return value. The tool functions were written by backend engineers focused on correctness and latency, not on what would happen to the return value downstream in an observability context.

3. Observability Infrastructure Treated as a Low-Risk System

The Grafana Tempo instance had been provisioned by the platform team with broad read access because observability data was historically considered low-sensitivity. Log data, metric labels, and trace metadata had never contained PII in the pre-AI era of the stack. Nobody had updated the access control model when the AI agent system was introduced. The threat model was simply never revisited.

The Architecture They Built: A Four-Layer Scrubbing Pipeline

The team spent three weeks designing and two weeks implementing a scrubbing pipeline they called the Trace Sanitization Gateway (TSG). Rather than patching individual problems, they built a layered defense that addressed the issue at multiple points in the telemetry flow. Here is the architecture they landed on.

Layer 1: SDK-Level Attribute Filtering (At the Source)

The first and most important change was configuring the LLM observability SDK to operate in a schema-allowlist mode rather than capturing all span attributes by default. They defined an explicit allowlist of span attributes that were permitted to flow into the OTel pipeline:

  • gen_ai.request.model
  • gen_ai.usage.input_tokens
  • gen_ai.usage.output_tokens
  • gen_ai.tool.name
  • gen_ai.tool.call_id
  • gen_ai.response.finish_reason
  • Custom internal attributes: meridian.agent.session_id, meridian.agent.workflow_type, meridian.agent.step_index

Critically, gen_ai.tool.arguments and gen_ai.tool.response were excluded from the allowlist entirely. Tool call content would not be captured at the SDK level at all. This alone eliminated the primary data leakage vector.

Layer 2: OTel Collector Processor with Regex-Based PII Scrubbing

Even with the SDK allowlist in place, the team recognized that other instrumentation points (HTTP middleware, custom spans added by individual developers) could still inadvertently capture sensitive data. They implemented a custom OTel Collector processor , a Transform processor pipeline stage , that applied regex-based scrubbing to all span attributes and span events before export.

The scrubbing rules covered:

  • Email addresses (RFC 5322 pattern)
  • US phone numbers (E.164 and common formatted variants)
  • Credit card numbers (Luhn-checkable 13-19 digit sequences)
  • Social Security Numbers
  • UUIDs that matched the format of their internal customer ID scheme (replaced with a deterministic HMAC-SHA256 pseudonym keyed to a secrets-manager-stored rotation key, preserving trace correlation without exposing the raw ID)

The processor was written as a custom Go plugin for the OpenTelemetry Collector Contrib distribution. It ran as a sidecar in each Kubernetes namespace where agent workloads ran, minimizing the blast radius of any single misconfiguration.

Layer 3: Tool Response Hashing for Audit Correlation (Not Storage)

One legitimate need the team had was the ability to correlate a specific agent invocation with its tool responses during a support escalation or incident investigation. Stripping tool responses entirely made that impossible.

Their solution was elegant: instead of storing the tool response payload in the trace, they stored a HMAC-SHA256 hash of the response payload as a span attribute (meridian.tool.response_hash). The actual payload was written to a separate, access-controlled audit log in their existing SIEM (Elastic Security), tagged with the same trace ID and span ID. Access to the SIEM audit log required a separate role with explicit approval workflows, logged access, and a 30-day retention policy aligned to their data minimization requirements.

This meant that during a normal debugging session, engineers could see the trace structure, latencies, and tool names without ever seeing customer data. If a specific incident required examining the actual tool response, an engineer had to request elevated access through their PAM system, and that access event was itself logged.

Layer 4: Retroactive Remediation of Historical Trace Data

The team still had up to 90 days of historical traces in Grafana Tempo containing raw PII. They couldn't simply delete all traces , they needed the structural data for capacity planning and latency analysis. But they needed to remove the sensitive attribute values.

Tempo's architecture stores trace data as Parquet-like blocks in object storage (in their case, S3-compatible MinIO). The team wrote a one-time remediation job in Python using the pyarrow library to:

  1. Enumerate all trace blocks in object storage.
  2. Deserialize each block's span attribute columns.
  3. Apply the same regex scrubbing rules used in the OTel Collector processor.
  4. Replace the scrubbed blocks in place, maintaining all structural metadata (trace IDs, span IDs, parent relationships, timestamps, durations).

The job ran over a weekend, processed approximately 2.1 TB of trace data, and completed without incident. The team retained a cryptographic checksum of each original block (stored in the SIEM, not in Tempo) to demonstrate to auditors that the remediation had been thorough and systematic.

The SOC 2 Story: Turning a Near-Miss Into a Control Narrative

By the time the auditors arrived in October 2026, Meridian's team had not just fixed the problem. They had built a compelling control narrative around it. This is a nuance that many engineering teams miss: auditors are not just looking for the absence of problems. They are looking for evidence of a mature, repeatable process for identifying and remediating risks.

The team presented the following artifacts to their auditors:

  • A documented AI Observability Data Classification Policy that defined which telemetry attributes were permitted to contain what data sensitivity levels.
  • The SDK allowlist configuration checked into version control, with a policy requiring PR review by the security team for any changes to the allowlist.
  • The OTel Collector processor configuration with unit tests demonstrating that each PII pattern was correctly scrubbed.
  • A runbook for the audit log access workflow, including the PAM integration and the approval chain.
  • Evidence of the retroactive remediation job, including the runtime logs, the checksum registry, and a post-remediation sampling audit showing zero PII in the current trace store.
  • A quarterly review process for the scrubbing rule set, owned by the security team, to ensure new PII patterns introduced by new tools or new data sources were captured.

The auditors noted the incident in their report as a self-identified finding with complete remediation, which is among the best possible outcomes for a SOC 2 Type II audit. The certification was renewed without qualification.

Key Lessons for Any Team Running AI Agents in Production

Meridian's experience is not unique. As AI agent workflows become a standard part of enterprise backend architecture in 2026, the collision between LLM observability tooling and data privacy requirements is emerging as one of the most underappreciated operational risks in the industry. Here are the lessons that generalize broadly.

Treat Tool Responses as Production Data, Not Debug Data

The mental model that "observability data is low-sensitivity" was built for a world where traces captured metadata about operations, not the content of those operations. AI agent tool calls fundamentally blur that line. A tool response from a CRM lookup is a production data record. It must be governed as such, regardless of the system it flows into.

Default-Deny for Span Attribute Capture in AI Pipelines

Any LLM observability SDK or auto-instrumentation library should be configured with an explicit allowlist in production environments. The default "capture everything" mode is appropriate for development but is a liability in production. Make this a mandatory item in your AI workload deployment checklist.

Decouple Debugging Capability from Routine Access

The hash-plus-audit-log pattern Meridian used is a powerful design principle. You do not need to give all engineers access to all data in order to give all engineers the ability to debug all systems. Design your observability architecture so that the data needed for routine debugging (latencies, error rates, tool call structure) is separated from the data needed for deep incident investigation (actual payloads), and gate the latter behind an explicit access control workflow.

Your OTel Collector Is a Security Boundary

The OpenTelemetry Collector sits between your application instrumentation and your observability backends. In a world where applications can emit arbitrary sensitive data, the Collector is the right place to enforce data governance at scale. Invest in Collector-level processors as a security control, not just a routing mechanism.

Run a Telemetry PII Audit Before Your Next Compliance Review

If you are running AI agent workloads and have not explicitly audited what is flowing into your trace and log backends, do it now. A simple sampling query against your trace store, looking for patterns like email addresses or long numeric strings in span attribute values, can surface this class of problem in hours. Do not wait for an auditor to find it first.

Conclusion

The Meridian case study is a story about how doing the right thing (enabling centralized observability) can create an unexpected risk (PII leakage through tool call logs) when the threat model of a system changes (the introduction of AI agent workflows) without a corresponding update to the system's governance controls.

The good news is that the fix is architecturally sound and implementable in weeks, not months. The SDK allowlist, the Collector-level scrubbing processor, the hash-plus-audit-log pattern, and the access-controlled SIEM integration together form a reusable blueprint that any team can adapt to their stack.

As AI agents become the connective tissue of enterprise software in 2026, the teams that will navigate compliance and security successfully are not the ones that avoid observability. They are the ones that build observability with the same rigor they apply to every other production system: with explicit data classification, layered controls, and a clear separation between what engineers need to see every day and what they need access to only when things go wrong.

Your traces are a data store. Govern them like one.

Read more

A Beginner's Guide to AI Agent Dependency Pinning: What Enterprise Backend Developers Need to Know Before Third-Party Tool Integration Updates Silently Break Production Workflows

A Beginner's Guide to AI Agent Dependency Pinning: What Enterprise Backend Developers Need to Know Before Third-Party Tool Integration Updates Silently Break Production Workflows

You've spent weeks building a sophisticated AI agent workflow. It routes customer support tickets, calls your internal CRM tool, summarizes data from a third-party analytics API, and hands off tasks to specialized sub-agents. Everything runs beautifully in staging. Then, one quiet Tuesday morning, your on-call engineer gets paged.

By Scott Miller