By the time you're trying to trace a specific rogue transaction after the fact, you're already doing forensics with whatever logging happened to be in place — which is why the real fix is architectural, not investigative. Give every agent-initiated action a trace ID at the moment it starts, propagate that ID through every service the agent's request touches, and attach it to the resulting database write. Do that, and "which agent run caused this write" becomes a lookup instead of an investigation.
Building traceability into agent-to-ERP writes
1. Generate a trace ID when the agent's task begins. Using OpenTelemetry (or any tracer following the W3C Trace Context traceparent header format), create a root span for the agent run and propagate its trace ID through every subsequent tool call.
2. Tag the ERP write itself with that trace ID. Whether the write goes through a REST API, a message queue, or a direct DB call, store the trace ID in an audit column alongside the transaction — this is what lets you join "this specific invoice change" back to "this specific agent run."
3. Log the reasoning, not just the action. Alongside the trace ID, persist the tool call arguments and (if available) the model's stated justification for the action — an audit trail that only says what changed, without why, still leaves you guessing when something looks wrong.
# pip install opentelemetry-api opentelemetry-sdk
from opentelemetry import trace
tracer = trace.get_tracer("erp-agent")
def apply_invoice_update(agent_name: str, invoice_id: str, changes: dict, reasoning: str):
with tracer.start_as_current_span("erp.invoice.update") as span:
trace_id = format(span.get_span_context().trace_id, "032x")
span.set_attribute("agent.name", agent_name)
span.set_attribute("erp.invoice_id", invoice_id)
# Write the trace_id and reasoning into the audit log alongside the DB write
audit_log.write(
trace_id=trace_id, agent=agent_name,
invoice_id=invoice_id, changes=changes, reasoning=reasoning
)
erp_db.update_invoice(invoice_id, changes)
| Logging Approach | Can You Attribute a Rogue Write? |
|---|---|
| Standard app logs only ("update succeeded") | No — no link between the write and the agent run that caused it |
| Trace-ID-tagged audit log with reasoning captured | Yes — the exact agent run, its tool call, and its stated justification are all joinable via the trace ID |
None of this replaces having a human approve high-risk writes before they happen — traceability tells you what occurred and why after the fact, but a human-in-the-loop gate on financially significant ERP actions prevents the rogue write from landing in the first place. Treat tracing as the safety net, and approval gates as the actual guardrail.
Practical Challenge
Instrument a mock ERP write function with an OpenTelemetry span like the one above, then write a query that reconstructs "which agent run changed invoice #4471, and what did it claim its reasoning was" using only the audit log.
Concept Check
Sources & Further Reading
- OpenTelemetry: Context Propagation — the mechanism for carrying a trace ID across service boundaries, which this article's attribution approach depends on.
- OpenTelemetry: Traces — reference on spans, trace IDs, and how distributed traces are assembled.
- W3C Trace Context Specification — the standard
traceparentheader format that OpenTelemetry and most modern tracers implement.
AI