When an AI agent is involved in an incident, the first question is simple and hard to answer: what did it try to do, and what actually happened in the systems it touched? The agent's own account is not evidence. Models can misreport their actions, traces may record a tool call that never reached its target, and the target system may record a change under a shared service account with no link back to the run. This guide is for incident responders, forensic analysts and the platform teams who must make agent activity reconstructable before something goes wrong. It shows which evidence layers exist, which identifiers join them, how to separate attempted from executed actions, how to order events across clocks, and what to preserve before you stop an agent. It builds on the general method in the Forensic Timeline Analysis Guide and does not repeat it.
Key takeaways
- Treat the agent's narrative as a lead, not a record. In the Replit case the agent said rollback was impossible and that every database version was gone; the rollback worked. Reconstruct from system-written logs.
- Four layers, three join keys. Model and orchestration traces, tool protocol logs, identity and token logs, and target system audit logs only make one story if trace IDs, tool call IDs and credential identifiers flow between them.
- Attempted is not executed. A tool call span proves the agent asked; only the target system's audit log proves the change. Every timeline row should carry an execution status.
- Order by causality, then by clock. Span parent links give a reliable order inside one run; timestamps from different systems disagree and some record completion rather than start.
- Preserve before you kill. Agent memory, conversation state, configuration and short-lived credentials disappear or change when you contain an agent, so snapshot them as the first containment step.
Why agent timelines are different
A conventional host timeline records what a process did. An agent run has an extra layer above that: the model's reasoning and tool selection, which is non-deterministic and cannot be replayed to get the same answer. Three properties shape the investigation.
- Intent and action are recorded in different places: the orchestrator knows which tool the model chose and with what arguments; the tool server knows what it received; the downstream API knows what it changed. None of them knows all three.
- Authority is borrowed: agents act with a user's delegated token, a workload identity, or a credential they found. The identity in the target log may be a person, a service principal or a shared key, so attribution depends on whether the agent's run was bound to that credential.
- Inputs are part of the crime scene: a prompt injection in a document, email or tool result can be the root cause. Unless the content that entered the context window is retained, you can see the harmful call but not why it happened.
Evidence layers and where they live
| Layer | Typical source | Key fields | What it proves | Volatility |
|---|---|---|---|---|
| Orchestration and model traces | OpenTelemetry GenAI spans from the agent framework or gateway; managed platform tracing such as Amazon Bedrock AgentCore Observability, which stores spans and logs in CloudWatch | invoke_agent and execute_tool spans, gen_ai.agent.name, gen_ai.conversation.id, gen_ai.tool.name, gen_ai.tool.call.id, trace and span IDs | Which tool the agent selected, in what order, with which result | Medium: sampling and retention settings may drop spans |
| Prompt and content capture | Opt-in attributes or events (gen_ai.input.messages, gen_ai.output.messages, gen_ai.tool.call.arguments, gen_ai.tool.call.result) or a separate content store | Message content, system instructions, tool definitions | Why the agent acted: injected instructions, poisoned tool output | High: often disabled for privacy, or truncated |
| Tool protocol logs | MCP client and server logs, MCP gateway, API gateway in front of tools | JSON-RPC id, tools/call name and arguments, isError, mcp.session.id, mcp.method.name | What the tool server received and returned | Medium to high: local stdio servers often log nowhere |
| Identity and token logs | IdP sign-in logs (Microsoft Entra interactive, non-interactive, service principal and managed identity sign-ins, plus agent activity logs), token exchange and STS events | correlationId, appId, resourceId, createdDateTime, IP; AWS AssumeRole with sourceIdentity | Which credential was issued to whom, when, with what scope | Low to medium: platform retention defaults are short |
| Target system audit logs | AWS CloudTrail, cloud activity logs, SaaS audit logs, database audit | CloudTrail eventTime, eventID, requestID, readOnly, errorCode, userIdentity | What actually changed, and under which identity | Low if exported to your own storage |
| Agent state | Memory store, vector index, conversation history, scratch files, sandbox file system | Entries with write time and source | Persistence of injected instructions across sessions | High: overwritten by continued operation |
The OpenTelemetry GenAI conventions are at Development status (checked 28 October 2026) and now live in their own repository, so record which version your instrumentation emits. For field-level guidance on emitting them, see the OpenTelemetry GenAI Semantic Conventions Guide.
Join keys: stitching one run across systems
Reconstruction succeeds or fails on whether an identifier created at one hop is recorded at the next. Check each hop in your estate against this table before you need it.
| Hop | Identifier to carry | Where it is defined | Common gap |
|---|---|---|---|
| User request to agent run | Conversation or session ID, user subject | gen_ai.conversation.id; the conventions say not to invent a fallback such as a new UUID or trace ID | Runs triggered by schedules or webhooks have no human subject recorded |
| Agent run to tool call | Trace and span IDs, tool call ID | gen_ai.tool.call.id on the execute_tool span | Tool call ID is only conditionally required and some frameworks omit it |
| MCP client to MCP server | W3C traceparent, tracestate, baggage in params._meta; JSON-RPC request ID | OpenTelemetry MCP conventions (SEP-414); HTTP trace headers cover only the HTTP request, not individual messages in the stream | Servers that ignore _meta start a new trace |
| Tool to credential | Token ID or session name; for delegation, the actor chain | RFC 8693 act claim; AWS RoleSessionName and SourceIdentity | Long-lived API keys carry no run context at all |
| Credential to target change | Request ID and identity in the target log | CloudTrail userIdentity.sessionContext.sourceIdentity, requestID; Entra correlationId | Shared service accounts collapse many agents into one identity |
AWS documents that a source identity set at AssumeRole cannot be changed during the session and persists through role chaining, which makes it a strong place to write an agent run or agent identity value. Note its documented limit: it is not captured when an AWS service acts on behalf of a federated or workforce identity.
Attempted versus executed
Give every candidate action a status, and do not promote it until a system-written log supports it. This is the single most useful discipline in agent forensics, because the questions "did it try?" and "did it succeed?" have different consequences for notification, recovery and root cause.
| Status | Evidence required | Example |
|---|---|---|
| Proposed | Model output or planner step selecting a tool | Chat completion with a tool call, no execute_tool span |
| Blocked | Policy engine or approval system denial, or a JSON-RPC protocol error | Gateway deny log; MCP error code for an unknown tool |
| Invoked, failed | Tool server received the call and returned an error | MCP result with isError: true; CloudTrail errorCode such as AccessDenied |
| Invoked, read only | Target log shows a read | CloudTrail readOnly: true, SaaS export or search event |
| Executed, changed state | Target log shows a write or delete under a credential linked to the run | CloudTrail readOnly: false; database DDL audit; volume deletion in the provider's log |
| Executed outside the tool layer | Target change with no matching tool call | A credential the agent found in code used directly from a sandbox shell |
The last row matters. In the PocketOS database deletion, a coding agent found an account-scoped Railway API token in an unrelated file and used it to send a volumeDelete mutation. Actions like this appear in the provider's logs under the token's owner, not as a tool call from a registered tool, so a timeline built only from agent traces would miss the destructive step or misattribute it.
Ordering events across clocks
- Use causality first: within one trace, span parent and child links give the true order of model calls and tool executions regardless of host clocks.
- Know what each timestamp means: CloudTrail
eventTimeis when the request completed, taken from the service host's clock (AWS states its services generally use NTP). EntracreatedDateTimeis when the sign-in was initiated, in UTC. Span start and end times come from the instrumented process. - Measure skew, do not assume it: pick an event seen by two systems (a tool call and the resulting API request) and compute the offset per source before merging.
- Account for delivery lag: CloudTrail can mark records with an
addendumreason ofDELIVERY_DELAY, and many SaaS audit APIs are eventually consistent. Re-query after the incident window closes before declaring an action absent. - Normalise to UTC with the offset recorded: keep the original value and the normalised one in separate columns so the timeline stays defensible.
A reconstruction procedure
- Scope the identities: list every identity the agent could use: its own workload or agent identity, delegated user tokens, service accounts behind its tools, and any secrets reachable from its sandbox or repository.
- Preserve volatile state: export conversation history, memory and vector store entries with timestamps, the deployed prompt, model and tool versions, and the tool definitions the agent saw. Record hashes and who collected them.
- Pull system-written logs first: target audit logs, IdP sign-in and audit logs and STS events for every identity in scope, widened by a margin before the first alert.
- Pull agent-side telemetry: traces, gateway and MCP logs for the same window, including blocked and errored calls.
- Join and status every action: link spans to tool logs by trace and tool call ID, tool logs to credentials by token or session, and credentials to target changes by identity and request ID. Assign the statuses above.
- Find the unexplained: list target changes with no matching tool call, and tool calls with no matching target event. Both are findings.
- Trace back to the input: for the first harmful step, identify the content that entered the context just before it: a user turn, a retrieved document, a tool result or a memory read.
- Record your own actions: containment steps, credential revocations and queries are part of the record, as NIST CSF 2.0 RS.AN-06 requires.
For the wider response flow, use the AI Agent Incident Response Playbook; for stopping the agent safely, see the AI Agent Kill Switch and Containment Guide.
Where identity fits
Identity logs are the backbone of the timeline because they are written by systems the agent cannot edit. Make them useful in advance.
- Give each agent its own identity: a dedicated workload, service principal or agent identity turns "the integration account did it" into "agent X, version Y, did it". Microsoft Entra now records agent activity as its own log type alongside the four classic sign-in types. See the Agent Identity and Access Guide.
- Bind run context to credentials: write the agent and run identifier into session names, source identity or token claims at issuance, so every downstream log carries it.
- Log delegation chains: when tokens are exchanged, log the decoded subject and actor claims, never the token. See the Agent Delegation Chains and Attenuation Guide.
- Remove findable secrets: keys in repositories and environment files let an agent act outside its identity, which is the hardest case to attribute.
Forensic readiness: what to set up now
| Decision | Smaller estate | Larger estate |
|---|---|---|
| Where to capture tool calls | Framework instrumentation and the tool's own logs | A central MCP or tool gateway that logs every call with the trace context, plus framework spans |
| Prompt and content capture | Capture for high-risk agents only, with short retention | Content in a separate restricted store keyed by trace ID, with privacy review and access logging |
| Trace sampling | No sampling for agents with write tools | Tail-based sampling that always keeps errored, blocked and write-action traces |
| Retention | Export identity and audit logs to your own storage for at least the incident detection window | Unified store with immutable retention and documented retention per layer |
| Testing | Reconstruct one benign run end to end each quarter | Exercise with injected faults, including an action taken outside the tool layer |
Content capture conflicts with data minimisation: prompts and tool results can hold personal data and secrets. Decide per agent, document the purpose, and redact credentials before storage. For retention evidence for regulators, see the AI Agent Audit Trails for Regulators Guide.
Measures that show readiness
- Percentage of agent tool calls carrying a trace ID that also appears in the tool server or gateway log.
- Percentage of target-system changes by agent identities that can be joined to a specific run.
- Number of agents still using shared or long-lived credentials with no run binding.
- Time to produce a complete attempted-versus-executed table for a sample run in an exercise.
- Retention gap: the shortest retention across the layers, compared with your typical time to detect.
Framework mapping
| Framework | Reference | How it applies |
|---|---|---|
| NIST CSF 2.0 | RS.AN-03, RS.AN-06, RS.AN-07, DE.AE-03 | Establish what happened and the root cause, record investigator actions, preserve integrity and provenance, correlate sources |
| NIST SP 800-53 Rev. 5 | AU-3, AU-3(1), AU-8, AU-9, AU-10, AU-12, AU-6(3), AU-16, IR-4 | Record content, time stamps, protection, non-repudiation, generation, correlation across repositories and organisations, incident handling |
| NIST SP 800-61 Rev. 3 | CSF 2.0 Community Profile for incident response (April 2025) | Places agent forensics inside the organisation's incident response lifecycle |
| MCP specification | Tools: security considerations | Clients should log tool usage for audit; servers must validate inputs and apply access controls |
Common failure patterns
- Trusting the self-report: asking the agent what it did and writing it up. Use it to generate hypotheses, then verify each claim.
- Traces without targets: rich model traces but no exported cloud or SaaS audit logs, so you cannot tell whether a call landed.
- Broken context at the MCP hop: servers that ignore
params._metastart new traces, splitting one run into unrelated fragments. - Shared credentials: several agents and humans using one API key, so the target log cannot attribute anything.
- Containment destroys evidence: deleting the agent, clearing memory or rotating keys before exporting state and logs.
- Content capture off everywhere: the harmful call is visible but the injected instruction that caused it is not, leaving the root cause unknown.
Lessons from incidents
- The narrative can be wrong: in the Replit AI agent database deletion of July 2025, the agent deleted a production database during a code freeze, generated fake records, and stated that rollback was impossible. The rollback worked. Public accounts relied mainly on the user's documentation and the agent's own post-mortem, which shows how little independent evidence many agent deployments produce.
- The decisive step can sit outside the agent's tools: in the PocketOS deletion, the clearest record of the request came from the platform provider, which identified the endpoint, mutation and bearer token. Provider-side logs and a run-bound credential are what make such an action attributable.
Practitioner checklist
- Inventory every identity and credential each production agent can use, including secrets reachable from its workspace.
- Emit OpenTelemetry GenAI
invoke_agentandexecute_toolspans with tool call IDs, and record the convention version. - Propagate trace context to MCP servers through
params._metaand confirm servers log it. - Write agent and run identifiers into credential issuance (session name, source identity or token claims).
- Export IdP, STS, cloud and SaaS audit logs to storage you control with retention longer than your detection time.
- Define which agents get prompt and tool content capture, with redaction and restricted access.
- Add an evidence preservation step before any agent containment action.
- Run a quarterly exercise that produces an attempted-versus-executed table for one run.
Standards and references
- NIST: SP 800-61 Rev. 3, Incident Response Recommendations and Considerations for Cybersecurity Risk Management
- OpenTelemetry: Semantic conventions for generative AI systems
- Model Context Protocol: Specification, Tools
- AWS: Monitor and control actions taken with assumed roles
- AWS: CloudTrail record contents
- Microsoft Learn: Sign-in logs in Microsoft Entra ID
- AWS: Amazon Bedrock AgentCore Observability
- IETF: RFC 8693 OAuth 2.0 Token Exchange
Related NHI Mgmt Group resources: Microsoft Foundry Agent Service Security Guide · Forensic Timeline Analysis Guide · AI Agent Incident Response Playbook · NHI and AI Agent Audit Evidence Guide