
PLAYBOOK
How to Investigate AI Agent Activity Across Enterprise Tools
The five questions an agent investigation runs, in order, and the evidence source for each: CloudTrail's 90 days, Entra's seven, Workspace's six months, and the Slack field with nowhere to put an agent.
TL;DR
The constraint on an agent investigation is not tooling. It is the shortest retention window among the systems you have to join, and for most enterprises that window is seven days.
Microsoft Entra keeps audit and sign-in logs for seven days on the free tier and 30 days on P1 and P2. CloudTrail's console Event history holds 90 days and only management events. Google Workspace keeps its audit logs six months. Microsoft 365's unified audit log defaults to 180 days. Those four numbers decide which questions are answerable before anyone opens a tool.
The common fix is another dashboard or wider retention, which makes the haystack bigger without making the needle findable. NIST's own incident-response profile is blunter about what is needed: CSF outcome DE.AE-03, "Information is correlated from multiple sources", rated High priority.
We are not arguing for one all-seeing platform. No single tool sees a procurement agent's SaaS call, its ERP write and its Slack post. Some of them cannot even represent the agent: Slack's audit log says an actor "will always be a user on a workspace".
So do two things. Pick the identifier you will correlate on, then write down the order of questions you will run against it. Check your shortest retention window first, because that is the real deadline.
The order, run against one agent identifier every time: identity (which agent, acting for whom), authorization (what it was allowed to do), tool calls (what it actually did), credential (which key carried it), record (does the story hold together). Each step filters the next, and each has a different evidence source with a different expiry.
Overview
Take a support agent that, for eight months, only ever read account records. This month it started editing them. Nobody approved that change, and nobody would have caught it either, unless whoever went looking already knew which systems to check and in which order.
An enterprise running a dozen agents almost certainly has enough logs. The question, with an unhappy customer on the phone, is whether anyone can answer "who did this, on whose behalf, and under what permission" without opening six tabs and reconciling timestamps by hand. A procurement agent that authenticates through the identity provider, calls a supplier API, writes to the ERP, and posts a summary to a messaging channel leaves four footprints. None of the four systems sees the sequence.
This post is about the sequence an investigation actually runs, and about the part nobody checks until it matters: what each of those logs contains, which field in it can hold an agent, and how long before the record is gone. Two neighbouring questions are answered elsewhere, so this one can stay operational: what agent visibility means, and what it is not is the definition, and whether seeing an action is the same as being able to stop it is visibility against governance.
The test we would apply: can you answer this in five minutes, and does the system tell you honestly when you can't.
Why It's Scattered by Default
Agents reach enterprise systems through several different doors, and each door keeps its own record. An API call with a long-lived key lands in one log. An OAuth grant that inherits a user's scopes lands in another. A service account with no human in the loop, a browser session driving a UI like a person would, a delegated grant borrowing someone's standing access: each is real signal, and each lives in a system with no reason to know the others exist.
No individual log is bad. A cloud audit trail is usually excellent at recording what happened in the cloud. It has no way to say the actor was an agent, or which team it worked for, because from its point of view an API key is an API key. The fragments are individually honest and collectively silent about the one thing you need, which is the agent followed across all of them.
This is not a new problem and it has a name in the standards. NIST SP 800-61r3, published April 2025 as a CSF 2.0 Community Profile for incident response, lists DE.AE-03, "Information is correlated from multiple sources", at High priority, and its recommendations are to "constantly transfer the log data generated by other sources to a relatively small number of log servers" and to "use event correlation technology (e.g., SIEM, SOAR) to gather pieces of related data captured by multiple sources". The same document is realistic about volume under DE.AE-02: organizations "should rely on technical solutions that filter large event datasets down to a subset that is suitable for human viewing and analysis".
What Each Log Holds, and For How Long
Before designing anything, read the defaults you already run on. These are the systems an agent investigation touches most often, and the numbers come from each vendor's own reference page.
| Log source | What it holds | Where an agent can appear | Default window |
|---|---|---|---|
| CloudTrail Event history (console) | management events only, no data or network events | userIdentity; sessionContext.sourceIdentity only if STS is configured to require it | 90 days |
| Google Cloud Audit Logs | Admin Activity always on; Data Access off by default except BigQuery | authenticationInfo.principalEmail, serviceAccountDelegationInfo | _Required 400 days, _Default 30 days |
| Microsoft Entra audit and sign-in logs | directory changes, interactive and service-principal sign-ins | the application or service principal | 7 days Free, 30 days P1 and P2 |
| Microsoft 365 unified audit log | Exchange, SharePoint, OneDrive, Teams, Entra activity | UserId of the acting account | 180 days Standard; 1 year for four workloads on E5; up to 10 years with the add-on |
| Google Workspace audit logs | Admin, Login, Drive, Groups, Calendar, Gmail and OAuth Token events | the OAuth Token log lists third-party apps against a user | 6 months |
| Slack Audit Logs API | actor, action, entity, context | actor only, and it "will always be a user on a workspace" | Enterprise plan only |
Table 1 — Defaults, read from each vendor's own documentation. The right-hand column is the deadline on every question you will ever ask.
Four things in that table change how an investigation goes.
The seven-day floor is the one that hurts. On Entra ID Free, audit and sign-in logs are kept seven days, and Microsoft is explicit that buying your way out afterwards does not work: "Log retention changes aren't retroactive", and on upgrading "only data still within the free retention period (up to seven days) is available". A question asked in March about February is not expensive to answer. It is unanswerable.
CloudTrail's console history is narrower than most people assume. It covers "the past 90 days of management events in an AWS Region", excludes data events entirely, is limited to a single account and Region, and "cannot query multiple attributes", so you get one attribute filter plus a time range. The S3 reads your agent performed are data events, which means they are not there at all unless somebody configured a trail or an event data store.
Google's data-access side has the same shape. Admin Activity logs are always written, so a quick look is reassuring, while "except for BigQuery, Data Access audit logs are disabled by default" covers exactly the reads and writes an agent spends its day on.
And lag is not the same as retention. Google Workspace keeps all seven of its audit log types for six months, but the OAuth Token log, the one that tells you which third-party application holds a grant against which user, arrives after "a couple of hours" while the Admin, Login and Drive logs are "near real time". The log that finds a newly authorized agent is the slowest one in the set.
Figure 1 — Four footprints, four windows. The investigation expires with the first one to close, not the last.
Check the shortest window before you design the process. A five-step investigation sequence is worth nothing if step two reads a log that expired last Tuesday.
The Order You Run Them In
An investigation that starts with "let's check the logs" is already behind. The useful version starts with a fixed sequence, run against one identifier, every time.
Figure 2 — The sequence an investigation actually runs, correlated by a single agent identifier rather than reconstructed after the fact.
Each step below is one question, not a category of telemetry to collect for its own sake. Skip a step and the next has no context. Run them out of order and you will chase the wrong lead.
Who Acted, and On Whose Behalf
Skip to "what happened" and you are already chasing the wrong thread. Ask "which agent, and acting for whom" first, because everything else gets filtered by that answer.
This matters more for agents than for people, because the failure mode is different. If the support agent
acts under its own service identity, every edit is attributable to it. If it borrows a human's session, the
edits disappear into that person's ordinary traffic, and "did the agent do this or did the person" becomes
unanswerable rather than merely inconvenient. The taxonomy names that pattern
aact:identity-model/shared-human-identity, and the log state it leaves behind
aact:audit-granularity/none-distinguishable.
Which of those you get is often decided by a setting nobody revisits. AWS can record the original human
behind an assumed role: sessionContext.sourceIdentity "identifies the original user identity making the
request, whether that user's identity is an IAM user, an IAM role, a user authenticated by using SAML-based
federation, or a user authenticated by using OpenID Connect (OIDC)-compliant web identity federation". It
appears only after an administrator configures STS to require it. Until then the log names the role, and the
role is shared.
Slack is the honest example of the limit. Its Audit Logs API models every event as actor, action, entity and context, and the actor "will always be a user on a workspace and will be identified by their user ID". There is no agent-shaped slot. An agent posting through a user token is that user, permanently, in that record. If you need to tell them apart in Slack, the distinction has to be carried in something you control, such as a dedicated bot identity or the app id, and correlated outside the audit log.
Sometimes step one has no answer, because the actor is not in any registry. That is a different starting point, and it is answered from egress rather than from application logs: our shadow AI detection ingests egress logs from a customer's own proxy, firewall or SIEM and classifies the actors it finds as Governed, Attributed, Unexplained or Unverified. The last two buckets are not a verdict. An Unexplained actor is a name to go and ask about, not evidence of anything, and the investigation below only begins once you can say which agent you are looking at.
What It Was Allowed to Do
Once you know who acted, check what that identity was permitted to do and compare it against what actually happened. The gap between the two is the signal.
A legal-review agent holding read access across a contract repository that has only ever touched a handful of templates has a narrow, boring gap: expected and stable. The support agent that starts editing records has a gap that widened suddenly. Whether the cause is a misconfiguration, a manipulated prompt, or scope nobody removed, the authorization check turns "it did something odd" into "it did something it was not supposed to be able to do", which is a different and more urgent finding.
Whether you can run that comparison at all depends on whether the decision was recorded as data. Google
Cloud does this: authorizationInfo carries the permission that was evaluated and a granted boolean, so
a denial is a queryable fact. On AWS you infer it from errorCode and errorMessage, which means a denied
call and a failed one are distinguishable only by reading text. If your own layer sits in front of the tool
call, record the decision explicitly. It is the cheapest field to add and the one investigations want most.
What It Actually Did
With identity and authorization established, pull the actual calls. Most of what an agent does, it does
through tools, and a useful record answers four things per call: which tool, what action, what data, what
result. Carry the acting human and the permission verdict alongside those and you have reached
aact:audit-granularity/per-action-with-principal-chain, the top of the
taxonomy's audit scale.
{
"agent_id": "spiffe://corp.example/agent/support/account-editor",
"acting_for": "team:support-tier2",
"tool": "crm.accounts",
"action": "update",
"params": { "account_id": "A-88231", "field": "billing_address" },
"permission": "accounts:read",
"granted": false,
"result": "denied",
"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
"ts": "2026-06-22T14:08:11Z"
}That one line, permission accounts:read against an attempted update, is worth more than a week of
dashboard scrolling. It says the boundary held, which moves the investigation from "what got changed" to
"why did the agent try". Without call-level detail you would know only that the CRM saw a write attempt from
somewhere.
Two fields in that record are doing work beyond the obvious. agent_id is a SPIFFE ID, in the documented
spiffe://trust domain/workload identifier form, which gives the agent one name that is not an API key and
not an email address. traceparent is the W3C Trace Context header, a W3C Recommendation since 23 November
2021, 55 characters carrying a 32-hex-character trace ID. Neither costs anything to adopt, and together they
are the join key for everything below.
The granted: false line is the one most trails drop, and it is the reason this step is worth building
rather than reconstructing. A record the agent did not write itself is what our
agent audit trail is for: both identities on every event, the tool and action,
and the verdict alongside them, so a refusal is an event rather than an absence. Whether you use ours or
your own, the test is the same. Query for denials. If the result set is empty, you are reading a log of
the controls that never fired.
Which Credential Carried It
Agents reach systems using tokens, keys and grants, and the credential is worth tracing separately from the call it made. The signal is drift between a credential and the job it was issued for.
A key still being exercised long after the agent it belonged to was retired, or a credential suddenly used against a system it has never touched, is exactly what stays invisible when credential events sit in a secrets manager nobody cross-references against agent activity. Tracing the credential tells you whether the problem is the agent's behaviour or something narrower, such as one key that should have been rotated out.
For third-party agents, the credential trail often lives somewhere unexpected. In Google Workspace it is the OAuth Token log, which lists applications against users, is kept six months, and lags by a couple of hours. That log is frequently the only place an agent somebody authorized last week appears at all, which makes it worth pulling on a schedule rather than during an incident.
Which Identifier Carries the Thread
Everything above depends on one decision: what you correlate on. Get it wrong and each log stays a separate story no matter how good it is.
You need two identifiers, not one. A stable name for the agent, which survives redeploys and does not
change when a credential rotates, and a per-request trace id that ties one action's fragments together
across systems. SPIFFE gives a reasonable shape for the first: the ID is a URI,
spiffe://trust domain/workload identifier, and a workload is "a single piece of software, deployed with a
particular configuration for a single purpose", which describes a deployed agent well enough to be useful.
W3C Trace Context gives the second, and it is already understood by most tracing backends.
A warning about the obvious third option. OpenTelemetry's core semantic-convention registry now marks the
gen_ai.agent.id, gen_ai.agent.name, gen_ai.agent.version and gen_ai.tool.* attributes as
Deprecated, with the GenAI conventions having moved to their own repository, while the
gen_ai.operation.name values such as invoke_agent and execute_tool sit at Development stability. Those
are fine to emit. They are not yet a safe thing to key a six-month investigation process on, and if you
build queries and retention rules around a Development-stability attribute name, you own the migration.
The correlating key matters more than any individual log's quality. A mediocre log tagged with the right agent identity beats an excellent one that cannot say which agent it belongs to.
In Practice
Back to the support agent. On its own, the CRM shows a denied write. The identity provider shows a token issued an hour earlier. Nothing, by itself, looks like an incident.
Followed as one thread, tagged by agent identity, the sequence reads differently. The agent authenticated as
itself, acting for the tier-two support team, held accounts:read, and attempted an update the
authorization layer refused. The credential it used was current and correctly scoped. Nothing was changed.
Somebody's prompt asked the agent to do something its permissions would not allow, and the permissions won.
That is a product or training question, not a security incident.
The reason it resolves in five minutes is not that a tool was clever. It is that the record existed, the identifier was the same in all three places, and none of the three windows had closed. Change any one of those and the same investigation takes an afternoon and ends in a shrug.
Worth noting what NIST calls that record. SP 800-61r3 defines evidence as "grounds for belief or disbelief; data on which to base proof or to establish truth or falsehood", and points out that most incidents never reach a chain-of-custody process yet the data collected is still evidence. An agent cleared by a log is cleared on evidence. An agent paused because nobody could check is paused on a guess.
Frequently Asked Questions
How do I trace what an AI agent did across multiple systems? Pick a stable agent identifier and a per-request trace id, propagate both into every tool call, and run a fixed order of questions against them: identity, authorization, tool calls, credential, then whether the record holds. The hard part is the propagation, not the querying.
How long are agent logs kept? Whatever your shortest source keeps. Entra ID Free is seven days and P1
and P2 are 30. CloudTrail's console Event history is 90 days of management events only. Microsoft 365's
unified audit log defaults to 180 days. Google Workspace audit logs are six months. Google Cloud's
_Default log bucket is 30 days.
Why can't I see my agent's data reads in CloudTrail? Because the console Event history shows management events and not data events. Data events need a trail or an event data store, configured before the fact. The same trap exists on Google Cloud, where Data Access audit logs are disabled by default outside BigQuery.
Which log shows third-party agents connected to Google Workspace? The OAuth Token audit log, which lists applications against the users who authorized them. Retention is six months and the lag is a couple of hours, so it is better used as a scheduled review than as an incident tool.
Can I tell an agent's actions apart from a user's in Slack? Not from the audit log alone. Its actor "will always be a user on a workspace", so an agent acting through a user token is recorded as that user. Give the agent its own app or bot identity if the distinction has to be provable.
Do I need to buy a new tool for this? Usually not. The gap is rarely missing telemetry; it is missing correlation and an agreed order of questions. NIST's incident-response profile says the same thing in control language, recommending log consolidation and event correlation technology rather than more collection.
What is the difference between agent visibility and agent monitoring? Monitoring watches for known conditions and alerts. Visibility is being able to reconstruct a specific past action on demand, which needs identity and retention rather than thresholds. Deciding and enforcing what an agent may do is a third thing again, and it is covered in visibility vs. governance.
What if the agent is not in any registry? Then the sequence above cannot start, and the first job is naming the actor rather than tracing it. Egress logs from a proxy, firewall or SIEM are the usual source, and unmatched activity there is a lead to follow rather than a finding.
How fast should an investigation be? Fast enough that nobody is tempted to skip it. We would hold to five minutes from question to answer for a single action, on the grounds that anything slower gets replaced by an assumption about how the system is supposed to behave.
Conclusion
Agents will keep spreading across clouds, SaaS platforms and internal tools, and no amount of consolidation will make them log through one system. Visibility does not depend on that happening. It depends on a stable agent identity carried into every system an agent touches, and a fixed order of questions run against it.
What it also depends on, and this is the part that gets found out late, is arithmetic. Seven days at the identity provider, 90 at CloudTrail for management events only, 30 in a default Google Cloud log bucket, six months in Workspace. The investigation you designed is only as long-lived as the shortest of those, and the cheapest improvement available to most teams is not a tool. It is routing two or three of those logs somewhere that keeps them longer, before the question arrives.
When the investigation is a lookup instead of a search, an agent's misbehaviour stops being a mystery and starts being a five-minute answer.
Sources
All URLs read 2026-09-29.
- NIST SP 800-61r3: Incident Response Recommendations and Considerations for Cybersecurity Risk Management — April 2025, a CSF 2.0 Community Profile superseding SP 800-61r2; DE.AE-03 "Information is correlated from multiple sources" at High priority, the log-consolidation and event-correlation recommendations, DE.AE-02 on filtering event volume, and the definition of evidence.
- Working with CloudTrail event history, AWS — 90 days of management events per Region, the exclusion of data, Insights and network events, and the single-account, single-Region, one-attribute query limits.
- CloudTrail userIdentity element, AWS —
sessionContext.sourceIdentityand what it identifies, and the fact that an administrator must configure STS to collect it. - Cloud Audit Logs overview, Google Cloud —
authenticationInfo.principalEmail,serviceAccountDelegationInfo,authorizationInfo.permissionand.granted, and Data Access logs disabled by default outside BigQuery. - Cloud Logging quotas and limits, Google Cloud — 400-day retention on the
_Requiredbucket, 30 days on_Default, and the 1 to 3,650 day custom range. - Microsoft Entra data retention — seven days of audit and sign-in logs on Free, 30 days on P1 and P2, and that retention changes are not retroactive.
- Manage audit log retention policies with Microsoft Purview — the Audit (Standard) default moving from 90 to 180 days on 17 October 2023, one year for four workloads under the Premium default, and up to ten years with the add-on licence.
- Data retention and lag times, Google Workspace Admin — six-month retention across the Admin, Login, Drive, Groups, Calendar, Gmail and OAuth Token audit logs, with the OAuth Token log lagging a couple of hours.
- Audit Logs API, Slack — Enterprise plan only, the actor, action, entity and context model, and the actor always being a workspace user identified by user ID.
- W3C Trace Context — W3C Recommendation of 23 November 2021, the 55-character
traceparentheader and its 32-hex-character trace ID. - OpenTelemetry semantic conventions, GenAI attribute registry —
gen_ai.agent.*andgen_ai.tool.*now marked Deprecated in the core registry, withgen_ai.operation.namevalues such asinvoke_agentandexecute_toolat Development stability. - Agent Access Control Taxonomy — the identity model and audit granularity dimensions;
shared-human-identityandnone-distinguishablefor the borrowed-session case,per-action-with-principal-chainfor the tool-call record above. - SPIFFE concepts — the
spiffe://trust domain/workload identifierform, the definition of a workload, and SVIDs as the documents a workload proves identity with.