Every action an AI agent takes — tool calls, policy decisions, trust handshakes, approval workflows — must be recorded in a tamper-proof log. Without it you cannot answer the question every auditor will ask: “What exactly did this agent do, and who authorised it?” The Agent Governance Toolkit provides two complementary audit components:Documentation Index
Fetch the complete documentation index at: https://mintlify.com/microsoft/agent-governance-toolkit/llms.txt
Use this file to discover all available pages before exploring further.
| Class | Module | Best for |
|---|---|---|
AuditLog | agentmesh.governance.audit | Full Merkle-chained log with query, CloudEvents export, and external sinks |
GovernanceAuditLogger | agent_os.audit_logger | Lightweight pluggable-backend logger used internally by govern() |
AuditLog. GovernanceAuditLogger is the lower-level primitive used inside the governance gate.
AuditLog
Import
Constructor
Optional external sink for durable storage. When
None, entries are stored in memory only (suitable for development and testing). In production pass a FileAuditSink or a custom AuditSink implementation.log() — Record an event
AuditEntry.
Event classification. Standard values:
| Value | When |
|---|---|
tool_invocation | Agent successfully called a tool |
tool_blocked | Policy denied a tool call |
policy_evaluation | Policy engine evaluated a request |
policy_violation | Agent violated a governance policy |
rogue_detection | Anomaly detection flagged the agent |
agent_invocation | Agent-to-agent delegation occurred |
trust_handshake | IATP trust handshake completed |
agent_registered | New agent identity registered |
audit_integrity | Chain integrity check completed |
approval_decision | Human approval was requested and resolved |
DID of the acting agent (e.g.
"did:mesh:a3f8c2..." or "did:web:agent.example.com").The action the agent took or attempted (e.g.
"web_search", "delete_file").Resource path or identifier that was accessed (e.g.
"/api/users", "crm/contacts").Arbitrary metadata about the event. Secrets are expected to be stripped by the caller before passing here.
Result of the action:
"success", "failure", "denied", or "error".Human-readable policy result (e.g.
"allowed", "denied by block-destructive").Distributed tracing correlation ID. Used to correlate entries across a multi-agent workflow.
(keyword-only) SHA-256 hex digest of the canonical-JSON serialization of the action’s arguments. Defends against silent mutation of recorded arguments.
(keyword-only) DID of the principal whose approval authorised this action.
(keyword-only) Version identifier of the policy bundle active at decision time.
(keyword-only) UTC datetime when the action was authorised or issued for execution. Paired with
completed_at to compute verifiable execution latency.(keyword-only) UTC datetime when the action’s outcome was recorded.
AuditEntry with entry_id, entry_hash, and previous_hash populated by the Merkle chain.
query() — Search the audit trail
limit entries from the tail of the matching set.
get_entry() — Look up by ID
AuditEntry with the given entry_id, or None if not found.
get_entries_for_agent() — All entries by agent
limit entries for the specified agent DID.
get_entries_by_type() — All entries by type
limit entries of the given event type.
verify_integrity() — Merkle chain verification
previous_hash is verified against the prior entry. Returns (True, None) on success, (False, error_message) on failure.
get_proof() — Merkle inclusion proof
None if the entry is not found.
The
AuditEntry serialized as a dict.List of
(sibling_hash, position) tuples. position is "left" or "right". O(log n) length.Current Merkle root hash.
True if verify_proof(entry.entry_hash, proof, merkle_root) passes.export() — Full log export
ISO 8601 UTC timestamp of the export.
Current Merkle root hash.
Number of entries in the export.
All matching
AuditEntry dicts.export_cloudevents() — CloudEvents v1.0 export
AuditEntry.to_cloudevent().
event_type | CloudEvents type |
|---|---|
tool_invocation | ai.agentmesh.tool.invoked |
tool_blocked | ai.agentmesh.tool.blocked |
policy_evaluation | ai.agentmesh.policy.evaluation |
policy_violation | ai.agentmesh.policy.violation |
trust_handshake | ai.agentmesh.trust.handshake |
trust_score_updated | ai.agentmesh.trust.score.updated |
agent_registered | ai.agentmesh.agent.registered |
agent_verified | ai.agentmesh.agent.verified |
audit_integrity | ai.agentmesh.audit.integrity.verified |
| (other) | ai.agentmesh.{event_type} |
AuditEntry Fields
Every call toaudit.log() returns an AuditEntry (Pydantic BaseModel).
Unique identifier in the format
audit_{16-hex-chars}.UTC datetime when the entry was created.
Event classification string.
DID of the acting agent.
The action the agent took or attempted.
Resource path or identifier, when applicable.
Arbitrary event metadata.
"success", "failure", "denied", or "error".Human-readable policy result.
Policy rule name that fired, when applicable.
SHA-256 hash of the prior entry in the chain.
"" for the first entry.SHA-256 hash of this entry’s canonical fields. Populated by
AuditChain.add_entry().Distributed tracing correlation ID.
Session identifier.
Auto-populated from
SANDBOX_ID or OPENSHELL_SANDBOX_ID environment variables.Auto-populated from
AGT_ENVIRONMENT environment variable.Auto-populated from
OPENSHELL_COMPUTE_DRIVER environment variable.SHA-256 hex digest of the action arguments (keyword-only at log time).
DID of the approver who authorised this action.
Version of the policy bundle active at decision time.
Optional UTC datetime when the action was authorised or issued for execution. Paired with
completed_at to compute verifiable execution latency.Optional UTC datetime when the action’s outcome was recorded.
AuditEntry methods
Merkle Chain Integrity
AuditLog internally delegates to AuditChain (a Merkle audit chain). Every entry is hashed, and that hash is included in the next entry’s hash computation — creating a tamper-evident chain:
- Append-only — entries cannot be removed or reordered without detection.
- Tamper-evident — changing any entry invalidates the root hash.
- Efficient proofs — proving an entry exists requires O(log n) hashes.
External proof verification
External Sinks
In-memory audit is fine for development. In production, useFileAuditSink or implement the AuditSink protocol.
FileAuditSink
content_hash, previous_hash, and an HMAC signature.
Custom sink — PostgreSQL example
GovernanceAuditLogger
GovernanceAuditLogger is a lightweight multi-backend logger used internally by govern() and available for direct use when you need a simple structured logger without the full Merkle chain.
Import
Constructor
add_backend() — Register a backend
log_decision() — Record a governance decision
Identifier of the acting agent.
The action that was evaluated.
The governance decision:
"allow", "deny", "audit", etc.Human-readable explanation.
Evaluation latency in milliseconds.
Additional key-value pairs stored in
AuditEntry.metadata.log() — Write a raw AuditEntry
AuditEntry directly to all registered backends.
flush() — Flush all backends
Built-in backends
| Class | Behaviour |
|---|---|
JsonlFileBackend(path) | Writes JSONL to file. Thread-safe (internal lock). File created with 0o600 permissions on POSIX. |
InMemoryBackend() | Stores entries in backend.entries list. Use in tests. |
LoggingBackend(logger_name="agent_os.audit") | Emits via Python logging at INFO level. |
OpenTelemetry Integration
Route governance audit entries as structured OTel LogRecords:OTelLogsBackend is a safe no-op when opentelemetry-sdk is not installed. Check backend.enabled to confirm it initialised correctly.
OTel logger instrument name.
Explicit
LoggerProvider. When None, uses the global provider.Service name written into the log resource.
| Attribute | Value |
|---|---|
event.domain | "agent_os.governance" |
event.name | "audit_entry" |
agt.agent.id | agent_id |
agt.audit.event_type | event_type |
agt.audit.action | action |
agt.audit.decision | decision |
agt.audit.reason | reason (when non-empty) |
agt.audit.latency_ms | latency_ms |
agt.audit.meta.* | All metadata keys promoted as string attributes |
GovernanceEventSink (Advanced)
For high-throughput SIEM / XDR routing, use theGovernanceEventProcessor with the GovernanceEventSink protocol. This mirrors the OpenTelemetry BatchSpanProcessor pattern with DROP_OLDEST backpressure and per-sink circuit breakers.
GovernanceEventKind values: POLICY_CHECK, POLICY_VIOLATION, TOOL_CALL_BLOCKED, PROMPT_INJECTION_DETECTED, IDENTITY_VERIFIED, IDENTITY_REJECTED, RESOURCE_ACCESS, ESCALATION_REQUESTED, CHECKPOINT_CREATED, ANOMALY_DETECTED, MCP_TOOL_POISONING, CONTENT_VIOLATION.
AuditBackendSinkAdapter
Bridges the legacyAuditBackend write/flush protocol to the batch-oriented GovernanceEventSink, allowing JsonlFileBackend, OTelLogsBackend, and custom backends to work with GovernanceEventProcessor without modification:
Decision BOM
Everyaudit_entry dict in a PolicyDecision is a Decision Bill of Materials (BOM) — a record of every factor that contributed to the governance decision. For on-demand reconstruction of full BOMs from observability signals:
Complete Example
See Also
- govern() — automatically logs every decision
- PolicyEvaluator — the decision engine that produces audit entries
- AgentIdentity — cryptographic agent identity
- Audit and Compliance Specification