Most agent stacks already log plenty: prompts, completions, tool calls, latency, token counts. That's useful for debugging. After an incident, though, a security reviewer will ask something the traces can't answer: was this action allowed, for this agent, on behalf of this person, against this record, at this time?
If an agent can change things in systems that matter, each decision should record roughly this:
- The person who delegated or started the action.
- Which agent acted, down to the client or instance. If all agent traffic runs through one shared service account, you can't tell them apart later.
- The task or workflow context, when you have it. Capture it, but don't enforce on declared intent alone.
- The tool, MCP server, connector or API action that was called.
- The target resource, tenant or data class.
- The policy decision: allow or deny, with the policy ID or version and the reason.
- Whether approval was required, and who gave it.
- Timestamps and correlation IDs, so you can join the user request, the agent run, the decision, the tool call and whatever happened downstream.
The simplest place to produce that record is where enforcement happens, at the point where the agent crosses into a real tool. A successful login shows the person authenticated. It doesn't show that the agent may export a file or call a privileged MCP tool ten minutes later. So check each action there, block or allow before the tool runs, and emit the audit event from that same decision. Working out afterwards from a transcript whether something was allowed is much harder to defend.
For a read-only assistant that can't change anything, you can skip most of this.
Disclosure: I work at Permit.io. This is a short version of a post by our CEO, Or Weis, which also covers where an MCP gateway fits as the enforcement point and what NIST's NCCoE concept paper says about access delegation:
Top comments (6)
On the policy decision line, don't stop at the ID/version and reason. Log the evaluated inputs too: delegator, agent, target resource, and the context attributes the rule actually read. Otherwise the reason points at values that never made it into the record.
Agreed. A decision ID without the evaluated inputs next to it just points at values nobody can reconstruct later. I want the delegator, the agent, the target, and the attributes the rule actually read on that same log line.
logging at the enforcement point is the right place, same decision object. one hole I've hit is long-running tool calls where the result lands later. we ended up stamping a correlation id on the decision event and writing a second event when the outcome arrives so the two can join. otherwise your audit trail looks like "allowed" with no idea if the action finished or failed.
One correlation id across the whole agent run is how you stitch tool calls that span minutes. Still log actor, delegator, tool, and resource on each step so a single call stays readable on its own.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.