When an AI agent does something it should not have done, the first question is who it was acting for and on whose authority, and most agent logs cannot answer it. Framework traces record prompts and latencies, and target systems record that a service account made a change, but nothing ties the two together with the human principal, the delegation chain and the approval. This template gives [Organisation] a ready-to-use audit record schema for AI agents: the fields, their types, whether they are required, and an example record. It is for platform engineers, detection engineers and audit teams. The AI Agent Audit Trails for Regulators Guide explains why each element matters; this page is the schema to implement.
How to use this template
- Replace text in square brackets, such as [Organisation], [SIEM] and [N days], with your own values. Bracketed values are illustrative.
- "Required" fields must be present on every record of that event type; "Conditional" fields are required when the condition applies; "Optional" fields are recommended.
- Field names use an
agent_audit.*namespace that NHI Mgmt Group defined for this template. Where an OpenTelemetry GenAI attribute exists, section 11 maps it, so you can emit traces and audit records from the same instrumentation. - Emit one record per event, not one per run. A run produces several records sharing a
run_id. - Adopt sections 3 to 9 as your logging standard and section 10 as the rule for sensitive content.
1. Purpose
This schema defines the minimum audit record that every AI agent operated by or for [Organisation] must emit, so that any agent action can be attributed to a registered agent, a human or system principal, and an authorisation decision, and so that investigators can reconstruct a run without relying on the agent's own account of it.
2. Scope
The schema applies to internally built agents, agents built on low-code platforms, AI coding agents, and third-party agents that hold credentials in [Organisation] systems, where [Organisation] controls the runtime or gateway. For third-party agents where it does not, the schema is the contractual logging requirement. Chat assistants without tools emit only the session and model call events.
3. Record envelope (all events)
| Field | Type | Level | Content |
|---|---|---|---|
agent_audit.schema_version | string | Required | Version of this schema, for example [1.0] |
event_id | string (UUID) | Required | Unique per record |
event_type | enum | Required | session.start, model.call, tool.call, policy.decision, approval, credential.use, session.end, kill_switch |
timestamp | string (RFC 3339, UTC) | Required | Time the event occurred, from a synchronised clock |
observed_timestamp | string (RFC 3339, UTC) | Optional | Time the record was written, if different |
run_id | string | Required | Correlates all events in one agent run |
conversation_id | string | Conditional | When the run belongs to a longer conversation or thread |
trace_id, span_id | string | Conditional | When distributed tracing is enabled, to join audit records with traces |
environment | enum | Required | [production, staging, development] |
source.host, source.service | string | Required | Where the record was produced (runtime, gateway, MCP server) |
security_relevant | boolean | Required | True for events that should reach the [SIEM] |
4. Agent identity
| Field | Type | Level | Content |
|---|---|---|---|
agent.id | string | Required | Stable ID from the [agent registry], never a display name |
agent.name, agent.version | string | Required | Human-readable name and deployed version |
agent.owner | string | Required | Accountable person or team ID |
agent.workload_identity | string | Required | The non-human identity the agent authenticates as (service principal, workload identity, OAuth client ID) |
agent.config_hash | string | Required | Hash of the system instructions, tool list and policy bundle in force, so changes are provable |
agent.platform | string | Optional | Framework or hosted agent service |
5. Principal and delegation
| Field | Type | Level | Content |
|---|---|---|---|
principal.type | enum | Required | user, service, schedule, agent, external |
principal.id | string | Required | User subject, job ID, ticket ID or upstream agent ID on whose authority the agent acts |
principal.tenant | string | Conditional | For multi-tenant or customer-facing agents |
delegation.chain | array of objects | Conditional | Ordered from originating principal to current actor; each entry has id, type and via (how authority passed: token exchange, A2A task, MCP call). Required when more than one hop exists |
delegation.token_claims | object | Conditional | Decoded, non-secret claims (sub, act, scope, aud, exp, token ID) when OAuth token exchange is used. Never the token itself |
authorisation.mode | enum | Required | own_identity, on_behalf_of, impersonation |
RFC 8693 represents delegation with nested act claims: the outermost names the current actor and nested claims name prior actors. Logging the decoded claims lets an investigator read the full user to agent to service chain.
6. Model call event
| Field | Type | Level | Content |
|---|---|---|---|
model.provider, model.requested, model.returned | string | Required | Provider and model identifiers as requested and as reported |
model.input_sources | array of objects | Required | Each content segment in context with source (user, retrieval, tool output, file, web), trust (trusted or untrusted) and a reference or hash |
model.tokens_in, model.tokens_out | integer | Optional | Usage, for cost and abuse detection |
model.finish_reason | string | Optional | Stop, length, tool call, content filter |
model.content_ref | string | Optional | Pointer to prompt and output content held in a restricted store (see section 10) |
7. Tool call event
| Field | Type | Level | Content |
|---|---|---|---|
tool.name, tool.type | string | Required | Tool as registered, and its type (function, MCP, API, agent) |
tool.call_id | string | Conditional | When the model or provider supplies one |
tool.server | string | Conditional | MCP server or API endpoint, with version or definition hash |
tool.operation | enum | Required | read, write, delete, execute, send, pay |
tool.target_resource | string | Required | The object acted on (record ID, file path, mailbox, repository) |
tool.arguments_redacted | object | Required | Arguments after redaction under section 10 |
tool.credential_ref | string | Required | Which credential was used (key ID, token ID, secret path), never the secret |
tool.untrusted_in_context | boolean | Required | True if untrusted content was in the model context when the call was decided |
8. Policy decision and approval events
| Field | Type | Level | Content |
|---|---|---|---|
policy.engine, policy.version | string | Required | Which policy point decided and the policy bundle version |
policy.decision | enum | Required | allow, deny, require_approval |
policy.rule_id, policy.reason | string | Required | The rule that matched and a short reason |
approval.approver_id | string | Conditional | Required when a human approved or rejected |
approval.shown_summary_hash | string | Conditional | Hash of exactly what the approver was shown |
approval.result, approval.latency_ms | enum, integer | Conditional | Approved, rejected or expired, and time taken |
9. Outcome
| Field | Type | Level | Content |
|---|---|---|---|
outcome.status | enum | Required | success, failure, blocked, partial |
outcome.error_type | string | Conditional | When the operation failed |
outcome.side_effects | array of strings | Conditional | Changes made in the target system, with the target's own event or change ID for correlation |
outcome.data_volume | integer | Optional | Records or bytes read, written or sent |
10. Sensitive content rules
- Records must never contain passwords, access or refresh tokens, API keys, session identifiers, connection strings or encryption keys. Log a reference (key ID, token ID, hash) instead.
- Prompts, model outputs, tool arguments and tool results may contain personal or confidential data. Store them, if at all, in a restricted content store referenced by
model.content_ref, with access limited to [named roles] and retention of [N days]. - Redaction must run before the record leaves the runtime, not in the [SIEM].
- Where content capture is disabled, hashes of inputs and outputs must still be recorded so that content held elsewhere can be matched later.
11. Integrity, retention and example
- Records must be sent to an append-only or write-once store outside the agent's control within [N minutes]. The agent's own identity must not be able to delete or alter them.
- Tamper detection, such as hash chaining or signed batches, must be enabled, and access to logs must itself be logged and reviewed.
- Retention: [N months] for security-relevant records, longer where a regulation requires it.
Example tool.call record (illustrative values):
{
"agent_audit.schema_version": "1.0",
"event_id": "[uuid]",
"event_type": "tool.call",
"timestamp": "2026-11-09T10:42:17.215Z",
"run_id": "[run-id]",
"trace_id": "[trace-id]",
"environment": "production",
"agent": {"id": "agt-0142", "name": "invoice-triage", "version": "3.2.0",
"owner": "team-ap-automation", "workload_identity": "[service principal ID]",
"config_hash": "sha256:[hash]"},
"principal": {"type": "user", "id": "[user subject]"},
"delegation": {"chain": [{"id": "[user subject]", "type": "user", "via": "sign-in"},
{"id": "agt-0142", "type": "agent", "via": "token_exchange"}],
"token_claims": {"sub": "[user subject]", "act": {"sub": "agt-0142"},
"scope": "invoices.read", "jti": "[token id]"}},
"authorisation": {"mode": "on_behalf_of"},
"tool": {"name": "erp.get_invoice", "type": "api", "operation": "read",
"target_resource": "invoice/[id]", "arguments_redacted": {"invoice_id": "[id]"},
"credential_ref": "token:[token id]", "untrusted_in_context": true},
"policy": {"engine": "[policy engine]", "version": "[bundle version]",
"decision": "allow", "rule_id": "ap-read-01", "reason": "read within scope"},
"outcome": {"status": "success", "data_volume": 1},
"security_relevant": true
}
Implementation guidance
Mapping to OpenTelemetry GenAI conventions
The OpenTelemetry GenAI semantic conventions define agent and tool spans. They are at Development status, so pin the version you emit. Mark arguments, results and messages as opt-in content, as the conventions do.
| Schema field | OpenTelemetry attribute | Note |
|---|---|---|
agent.id, agent.name, agent.version | gen_ai.agent.id, gen_ai.agent.name, gen_ai.agent.version | Conditionally required on agent spans (name on invoke_agent; ID and version on create_agent) |
conversation_id | gen_ai.conversation.id | Conditionally required |
model.provider, model.requested | gen_ai.provider.name, gen_ai.request.model | Provider name is required on several GenAI span types; check the span you emit |
tool.name, tool.call_id, tool.type | gen_ai.tool.name, gen_ai.tool.call.id, gen_ai.tool.type | Tool name is required on execute_tool spans |
tool.arguments_redacted | gen_ai.tool.call.arguments | Opt-in in OpenTelemetry; this schema requires a redacted form |
outcome.error_type | error.type | Stable attribute |
| Principal, delegation, policy, approval, credential reference | No GenAI attribute as of November 2026 | Add as custom attributes or emit as separate audit records |
See the OpenTelemetry GenAI Semantic Conventions for Security Teams for instrumentation choices.
Rolling it out
- Start at the chokepoint: emit records from the tool or MCP gateway first, where every call passes, then add runtime fields.
- Pilot with one high-risk agent and test that an investigator can answer five questions from records alone: which agent, for whom, under which rule, with which credential, and what changed.
- Run redaction tests with seeded fake secrets before enabling production forwarding.
- Write detections: tool calls with
untrusted_in_contexttrue and a write or send operation; credential references used outside their expected agent; approval latency under one second. - Version the schema and reject records with unknown versions at ingestion.
Framework mapping
| Section | NIST SP 800-53 Rev. 5 |
|---|---|
| 3 to 9 (record content) | AU-2 Event Logging; AU-3 Content of Audit Records; AU-12 Audit Record Generation |
| 5 (attribution) | AU-10 Non-repudiation |
| 11 (integrity and retention) | AU-9 Protection of Audit Information; AU-11 Audit Record Retention |
The mapping is NHI Mgmt Group's editorial judgement.
Standards and references
- OpenTelemetry: GenAI semantic conventions
- IETF: RFC 8693 OAuth 2.0 Token Exchange
- OWASP: Logging Cheat Sheet
- NIST: SP 800-53 Rev. 5
Related NHI Mgmt Group resources: Audit Readiness for AI Agents and NHIs, AI Agent Observability and Incident Response Guide, Identity Telemetry Requirements, AI Agent Risk Assessment Template.