# Reading the Audit Log & Sessions

Keycard records every authentication, authorization, and credential it handles. The Console surfaces
that record two ways: the **Audit Log** is the zone-wide stream of individual events, and **Sessions**
organizes the same events around one authenticated session so you can follow an agent's activity in
order. They draw from the same underlying events — the difference is the lens.

This page is for reading those views: identifying who and what is on a single decision, tracing one
action from sign-in to issued credential, telling the two views apart, and confirming that a change
like a revocation actually took effect.

> **Note: Audit Log vs. Sessions** - The **Audit Log** answers *"what happened across the Zone?"* — one filterable, searchable row per
event, best for finding a specific decision or auditing broadly.
- **Sessions** answers *"what did this agent do, in order?"* — one session's events laid out as a
timeline, best for following a single run and seeing tool activity in context.
Same events, two views. Most verification tasks start in one and confirm in the other.

## Before you begin

- Sign in to the [Keycard Console](https://console.keycard.ai). Reading these views requires the
  **Viewer** [Role](/admin/roles-and-permissions/) or higher — Viewers can see sessions, users, and
  audit logs.
- Both views are zone-scoped. If the activity you're verifying happened in a [custom Zone](/concepts/zones/),
  switch to that Zone first.
- **Audit Log** and **Sessions** are separate items in the left nav.

## Read a single authorization decision

Open the **Audit Log** from the left nav and select any event to expand its detail. A single event
tells you the whole shape of one decision:

- **Status** — `Success` or `Failure`.
- **Actor Details** — the **identity chain** behind the call. Its **Type** is `identity_chain`, and it
  lists each identity in the delegation path: the [Application](/concepts/applications/) (the agent)
  and the [User](/concepts/users/) it acted for. This is how you read the composite identity on a
  decision — the User, the agent acting for them, and (through the entry below) the Resource they
  reached.
- **Entity** — the [Resource](/concepts/resources/) the call targeted (for example, `Google Calendar API`).
- **Raw Data** — the machine-readable record: the action (such as `credentials:issue`), the requested
  `scopes`, the `resource_path` (for example, `/oauth/2/token`), and — on a failure — the `error_code`.

> **Note: The delegation chain** Keycard's [credentials](/concepts/credentials/#delegation-chaining) carry the full path of delegation.
In a multi-hop flow — **User → agent → MCP server → downstream API** — each hop is its own credential
exchange, and the identity chain lets you trace the original User through every intermediary. The chain
is recorded in the audit trail; it's how a decision stays attributable to a person, not just a token.

## Trace one action end to end

A single action moves through a predictable lifecycle. In the **Audit Log** you'll see the stages as
separate events; in a **Session** timeline you'll see them stitched together in order:

1. **`users:authenticate`** — the caller's identity was verified.
2. **`users:authorize`** — their access was checked against [policy](/admin/access-policies/).
3. **`delegated_grants:create`** — a [grant](/admin/revoke-a-grant/) recorded the User's consent.
4. **`credentials:issue`** — Keycard issued the short-lived credential.

To follow one run, open **Sessions** and select a session. The **Timeline** lays out that session's
events oldest-to-newest, rendering each credential exchange as a delegation hop
(`agent → credentials:issue → Resource`), so a two-hop flow reads as the client getting a token for
the MCP server, then the MCP server getting a token for the downstream Resource. **Session Context**
names the actor and owner, and **Resources Accessed** lists every Resource the session touched.

### Find both sides of a deny

When a call is refused, the Audit Log records both the attempt and the reason. The denied call appears
as a **Failure** event; the `error_code` in its **Raw Data** tells you which kind of denial it was:

- **`access_denied`** — a [policy](/admin/access-policies/) denied the request. The **Error Message**
  names the deciding policy and policy set — for example, *Access to "Google Calendar API" is denied by
  Policy "restrict-calendar-access" in version 1 of Policy Set "default-zone-policies"* — so you can open
  **Policies** and read the rule that forbade it.
- **`insufficient_authorization`** — there was no [grant](/admin/revoke-a-grant/) to satisfy the request
  (the User never consented, or the grant was revoked). This is distinct from a policy denial.

So "both sides" of a deny are always available: the **Failure** event is the call, and the deciding
policy (or missing grant) named in the error is the reason.

## Sessions vs. the Audit Log: when to look at which

Use the **Audit Log** when you're starting from an event — searching by [Actor](/concepts/users/),
action, Resource, or category (`API Call`, `Management Event`, `Service Event`), or filtering to
`Failures` to find every refused call. Use **Sessions** when you're starting from an agent run and want
its activity in order, including the tool calls made during that session.

> **Note: Tool calls live in Sessions** Tool activity shows up in a session's **Timeline**, not as its own audit-log action — the Audit Log's
actions are Keycard operations like `credentials:issue` and `users:authorize`. Whether an individual tool call also produces a `credentials:issue` event depends on whether the server
exchanges a Keycard credential for that call.

## Verify a revocation

A common eval check is revoking access and confirming it took effect. The Audit Log shows both the
change and its consequence:

1. **Revoke the grant.** Follow [Revoke a Grant](/admin/revoke-a-grant/). The grant's **Status** flips
   to **Revoked**.

2. **Trigger the agent again.** Its next credential request has no grant to satisfy it.

3. **Find both sides in the log.** The retry appears as a **Failure** `credentials:issue` event on
   `/oauth/2/token` with `error_code` `insufficient_authorization`, and the grant now shows as
   **Revoked**. From the grant's actions menu, **View in audit log** deep-links straight to the event.

> **Caution: Credentials are short-lived, not killed** Revoking a grant stops the *next* credential from being issued; it does not kill a credential the agent
already holds. An outstanding short-lived token keeps working against the Resource until it expires. See
[what happens after you revoke](/admin/revoke-a-grant/#what-happens-after-you-revoke) for the full
behavior.

## Where export fits

Everything in the Audit Log can be streamed to your own AWS S3 bucket in OCSF (Parquet) format for your
SIEM or data warehouse, delivered within the hour. Setup is a one-time, support-assisted step.

- [Audit Log Export](/admin/audit-log-export/)

## Related

- [Revoke a Grant](/admin/revoke-a-grant/) — withdraw an authorization and confirm it in the log
- [Access Policies](/admin/access-policies/) — the rules that decide `access_denied`
- [Credential Issuance](/concepts/credentials/) — how Keycard issues and chains the credentials you see
- [Audit Log Export](/admin/audit-log-export/) — stream events to your SIEM
- [Roles & Permissions](/admin/roles-and-permissions/) — who can view sessions and audit logs
