Skip to main content

Audit Log

Concepts

Every request that passes through AIControls is recorded — the identity, the tool or model, the governance decision, and the outcome. The Audit Log is your authoritative trail for security review, incident investigation, and compliance evidence.

What is logged

Every event in the audit log captures:

FieldDescription
TimestampUTC time of the request
IdentityDeveloper email or agent ID, plus team membership at the time of the request
Request typeMCP tool call, LLM request, or a Cross-App Access (XAA) Authorization Server event (token issuance) — shown as a distinct XAA tag in the Audit Log and Events views
Tool / ModelThe MCP tool name (e.g. bash, read_file) or model identifier (e.g. claude-sonnet-4-6)
ServerThe MCP server (datasource) the tool call targeted, e.g. github-mcp. Empty for LLM requests.
DecisionAllow, Deny, Audit, Warn, Warn Ask, or Warn Approve (shown as Pending, awaiting HITL approval)
PolicyThe policy rule that produced the decision, if any
Binding (binding_name)The Access Binding that permitted or governed this request, when the decision was reached through a team→server binding rather than a hand-written policy alone
Grant ID (grant_jti)JWT ID of the Cross-App Access grant that authorized the call, when the request arrived via XAA/ID-JAG — ties the event back to the specific token exchange
Governed agent (client_id)Which governed agent made the call, when multiple governed agents share one Cross-App Access delegator — see Governed agents sharing a delegator
ResourceFile path, repository, namespace, or other resource accessed
Tokens / CostToken count and estimated cost for LLM requests
SessionThe session this request belongs to

MCP tool calls and LLM requests are stored in the same log. The Security Events page (Security → Events, All activity tab) filters by identity, decision, tool or model, request type, and time range; clicking any row opens the full event detail, including request arguments and the policy evaluation trace.

Prompt capture

For LLM requests, the audit log also stores the text of the last user turn — the prompt snippet shown in the event detail drawer. MCP tool calls store their argument values, and intercepted outbound HTTP(S) calls store the first bytes of the request body.

Prompt capture limit (Settings → General → Data Retention & Session Limits) caps how many characters of the prompt are kept per event. The default is 5,000; setting it to 0 disables prompt capture entirely, and the audit log then records the request without its text.

Redaction of sensitive values

Before an audit record is written, AIControls redacts sensitive values from the prompt snippet, the tool arguments, and the outbound HTTP body snippet. Two classes are removed:

  • Credentials — private keys, cloud access keys, source-control and chat tokens, sk- style API keys, database connection strings, and high-entropy api_key=-style assignments.
  • Personal data — email addresses, phone numbers, US Social Security numbers, Indian PAN and Aadhaar numbers, IBANs, and payment card numbers.

Each detected value is replaced by a typed placeholder, so the record still shows what kind of value was there:

DetectedStored as
Email address[REDACTED:EMAIL:@example.com] — the domain is kept
Payment card[REDACTED:CREDIT_CARD:****1234] — the last four digits are kept
Phone number[REDACTED:PHONE]
US SSN[REDACTED:SSN]
Indian PAN[REDACTED:PAN]
Aadhaar number[REDACTED:AADHAAR]
IBAN[REDACTED:IBAN]
Credentials[REDACTED:AWS_KEY:AKIA], [REDACTED:PRIVATE_KEY], …

Some details are worth knowing:

  • Checksums are verified. Payment card, Aadhaar, and IBAN values are only redacted when their check digits validate, so a 16-digit order number or a 12-digit ticket ID stays readable.
  • Phone numbers are matched in international form as well as national form. A number written with a leading + and a country code is redacted whole — the country code is part of the placeholder, not left beside it — in the groupings countries actually use (two five-digit groups, a two-digit area code plus two four-digit groups, three-three-four, and the run of digits with no separators at all). National forms are still matched: 415-555-0134, (415) 555-0134, and ten consecutive digits. Digit runs that are not phone-shaped — timestamps, order IDs, version strings, ports and process IDs — stay readable. Redaction and the content-safety scanner share one definition of what a phone number looks like, so a number that is redacted from the record is also a number the scanner can see.
  • A single occurrence is enough. Content-safety alerting only raises a PII finding once a request contains several email addresses or phone numbers, to avoid noise. Redaction has no such threshold — one address is redacted.
  • Private IP addresses are not redacted. RFC 1918 addresses (10.x, 172.16–31.x, 192.168.x) are kept as-is so audit records stay useful for infrastructure debugging.
  • Email placeholders keep the full domain, not just the top-level domain: alice@acme-internal.example becomes [REDACTED:EMAIL:@acme-internal.example]. The domain is what makes the record useful — it tells you whether an address was internal, a customer's, or a personal webmail account. It is also the part of the trade-off you should weigh: in a small tenant, a retained domain sitting on the same row as the identity and the timestamp can be enough to re-identify the individual. Where that matters, disable prompt capture (set the Prompt capture limit to 0) rather than relying on redaction alone.
Denied requests show no PII findings

The Security tab on a session derives its PII findings from the stored audit record, so it only ever sees redacted text. For a request that was denied, that means a prompt containing five email addresses shows no PII findings there — the addresses were already replaced by placeholders before the finding pass ran.

This is not a detection failure. The block was decided from the original request, before redaction, and the request never reached the model. Read the decision and the policy that produced it — not the absence of a PII finding — when reviewing a denied call. Allowed requests are scanned on the response and are unaffected.

Redaction applies to the audit record only. The request forwarded to the model or MCP server is never altered by it, and policy evaluation and content scanning always see the original text — a policy reading object.llm.currentPrompt (or object.request.hasPII) is unaffected by this setting. If you need the forwarded request de-identified as well, that is a separate control — see content safety policies.

Redact personal data in audit records (Settings → General → Data Retention & Session Limits) turns the personal-data pass off. It is on by default. Turning it off makes the audit log store prompts, tool arguments, and outbound request bodies verbatim, which means the audit database — and every configured audit destination, including object-store export and OpenTelemetry trace export — must be treated as a sensitive-data store. Credential redaction always stays on.

Redaction happens at write time, so it applies to everything downstream: the stored record, the live event stream, exports, and external audit destinations. Events recorded before you upgraded keep whatever text they were stored with; they are not rewritten, and age out under your normal retention window.

Self-hosted: replicas without the admin interface

The toggle is stored in your workspace database and every replica picks it up within a minute. The exception is a replica running with the admin and UI interface switched off, or running purely as an authorization endpoint: those never read the stored setting and stay on the value from their configuration, which defaults to redaction on. The effect is safe but confusing — after turning redaction off you may still see redacted records from part of the fleet. In that topology, set the redaction value in your Helm values rather than in the UI.

Decisions

Each event records a decision — the outcome of evaluating the request against your policies, such as Allow, Deny, Audit, Warn, Warn Ask, or Warn Approve (shown as Pending). The decision is what turns a raw log line into a governance record: it tells you not just that a request happened, but whether it was permitted, blocked, flagged for review, or routed to a human approver, and which policy rule produced that outcome. See Decision Types for the full set of decisions and their meanings.

Retention and export

Audit events are stored in your workspace's SQLite database. The default retention window is 90 days; older events are purged automatically. To extend retention, configure an S3-compatible object store in Settings → Integrations — events are streamed there in real time and retained indefinitely.

Export the current filtered view to CSV from the Security Events toolbar. The export includes all fields in the table view and can be used directly for compliance reporting.

See also