Business

What to Log When an AI Agent Makes a Decision: Fields and Format

Antonio Evans8 min read

A wide illustration of a single decision record rendered as a JSON-like card: key-value pairs stacked in a clean list, connected by thin lines to smaller labeled nodes for input, model, prompt hash, output, reviewer.
Key points

Key points

  1. 1Log six fields per consequential agent decision: exact inputs (including retrieved context and tool results), model identity with immutable version, a hash of the full prompt template plus variables, the raw output, the reviewer identity (human or automated rule), and an ISO 8601 timestamp with timezone.
  2. 2Add a free-text reason field and reason codes so a record explains why the decision happened, not just what happened.
  3. 3Write each record as one JSON line to an append-only store, and link multi-step runs with a correlation ID.
  4. 4Keep a decision log separate from traces and tool logs, because each artifact answers a different question.

Why a trace is not a decision record

Most teams already collect telemetry: spans, latency, token counts, HTTP status codes. None of that answers the question that arrives during an incident: why was this action allowed, and what actually changed? A trace can show that an update_subscription call completed in 180 ms. It cannot show that the caller was the authenticated account owner, that the account was eligible under a specific policy version, and that the billing API confirmed the new state. The distinction is clean: traces carry low-level performance detail, tool logs carry request and response diagnostics, and a decision log carries why the system was allowed to act and what was verified afterward (AI agent decision logs).

That separation also protects privacy. Logging every token is expensive and creates a second copy of every prompt, which your data team will eventually have to govern. Observability guidance for agents recommends storing full metadata for every model and tool call but sampling full prompt text at 1 to 5 percent, while always storing a prompt hash and token counts (observability for AI agents). The hash gives you a join key to the sampled text without keeping sensitive content in the primary log.

The insight most first-search articles miss: you should not store an agent's hidden reasoning as an audit artifact. Reasoning text is unreliable, mutable across model versions, and a liability in discovery. Store the evidence the agent used and the policy verdict it produced instead.

The field schema, one by one

The table below is the working schema. Treat the first six rows as mandatory for any decision that crosses a boundary into a side effect.

FieldWhat it holdsWhat it enables
inputsExact user input plus retrieved context refs and tool results, with content hashesReplay and debugging
modelProvider, model name, immutable version or snapshot ID, decoding configReproducing behavior across releases
prompt_hashSHA-256 of the full template plus resolved variablesDetecting prompt drift and unauthorized template edits
outputRaw model output, or a pointer to it, uneditedAudit and dispute resolution
reviewerIdentity of the human approver, or the ID of the automated rule that gated itAccountability and oversight evidence
timestampISO 8601 with timezone offset, e.g. 2026-03-04T14:22:07.418ZOrdering, retention, incident timelines
reasonShort free text plus reason codes such as account_owner_verifiedExplainability without exposing hidden reasoning
correlation_idRun or trace ID shared across stepsStitching multi-step agent runs
policyPolicy name and version, verdict (allow, hold, block)Showing which rules governed the decision

Three of these deserve emphasis.

The prompt_hash is the field teams skip and then regret. Hashing the full template plus resolved variables means a silent template edit changes the hash, so you can prove which instructions were in force at decision time even if someone later edited the prompt in production. Hashing per-request also lets you group identical prompts to measure cost and latency without storing the text.

The reviewer field must distinguish a named human from an automated gate. This matters because oversight requirements are graded, not binary. For compliance purposes, human authorization (no AI action without explicit approval, logged before execution) is the strongest form, human review of outputs is intermediate, and population-level monitoring is the weakest form that still counts as oversight (human in the loop and AI compliance). A log that says "reviewer": "policy-engine" for a decision that legally required human authorization is evidence of a gap, not a defense.

The reason field should contain policy reason codes and a short operator-facing sentence, not a fabricated summary of what the model was thinking. Design your policy engine to emit codes like refund_below_limit or data_sensitivity_high so the reason is safe to show reviewers, and add a free-text reason_note for what the human decided and why. Human-in-the-loop research is clear that the value arrives when feedback is captured, governed, and reused, rather than left inside a disconnected review screen (HITL at Databricks).

Format: JSON lines in an append-only store

Write each record as a single JSON object on one line. JSON lines append cleanly, stream well, and are trivially ingestible by columnar stores and log pipelines. Several emerging proposals converge on this shape. An IETF draft for an agent audit trail specifies a JSON record structure linked by tamper-evident SHA-256 hash chaining, transport-agnostic and exportable to JSONL, Syslog, and CSV (agent audit trail draft). A separate community specification for agent decision records uses structured JSON serialization with required frontmatter validation (Agent Decision Records).

Here is a complete record for a support agent that changes a renewal status:

{
  "decision_id": "01JQ8Z4T7K9M2",
  "correlation_id": "run_7f3a91",
  "timestamp": "2026-03-04T14:22:07.418Z",
  "tenant_id": "acme-eu",
  "actor": {"type": "human", "id": "user_1192", "auth": "session"},
  "task": {"type": "renewal_status_change", "request_ref": "ticket:88412"},
  "inputs": [
    {"kind": "user_message", "sha256": "9c1f...", "ref": "ticket:88412/msg:3"},
    {"kind": "retrieval", "sha256": "4ab0...", "ref": "kb:renewal-policy#v4"},
    {"kind": "tool_result", "tool": "get_account", "sha256": "77de...", "ref": "crm:acct:4411@v27"}
  ],
  "model": {
    "provider": "example",
    "name": "frontier-small",
    "version": "snapshot-2026-02-11",
    "temperature": 0.0,
    "max_tokens": 800
  },
  "prompt": {
    "template_id": "renewal_agent",
    "prompt_hash": "b3e1c8...",
    "token_count": 1840
  },
  "output": {
    "raw": "{\"action\":\"update_renewal\",\"status\":\"paused\"}",
    "ref": "blob:decisions/01JQ8Z4T7K9M2/output.txt"
  },
  "policy": {"name": "renewal-policy", "version": "v4", "verdict": "allow", "reasons": ["account_owner_verified", "below_risk_threshold"]},
  "reviewer": {"type": "automated_rule", "id": "policy-engine", "version": "v4"},
  "reason": "Account owner requested pause; amount below threshold; no exceptions matched.",
  "action": {"tool": "billing.updateRenewal", "target_ref": "crm:acct:4411", "idempotency_key": "01JQ8Z4T7K9M2-act"},
  "outcome": {"state": "verified", "result_ref": "billing-event:ee91c2", "version_after": 28}
}

Two format decisions are worth copying. First, store references and hashes for large or sensitive inputs and outputs rather than copying content; the pointer respects the retention rules of the system that owns the data. Second, split the record into a planned phase and an outcome phase. Write the decision before the side effect so a timeout or crash is itself recorded, then append the verified result. That pattern turns ambiguity into an explicit unknown state instead of silently implying success, and the idempotency key from the planned record prevents duplicate retries (decision logs, evidence without chain of thought).

Hash chaining is optional at small scale and worth the effort at audit scale. Including the previous record's digest in each new record makes tampering detectable, which is exactly what general log management guidance recommends: centralized collection plus integrity protection such as tamper-evident or write-once storage for records used in investigations (policy decision log format and retention).

Wiring it into the agent loop

Log at decision boundaries, not on every model turn. Good boundaries are selecting a workflow or external tool, classifying a request into a risk tier, changing a record or moving money, denying an action because policy blocked it, escalating to a human, and declaring a long-running task complete (decision boundaries). Retrieval chunks, retries, and draft sentences belong in traces, linked by a stable ID when they matter.

A minimal Python wrapper that emits one JSON line per decision:

import hashlib, json, uuid
from datetime import datetime, timezone

def emit(store, record):
    store.append(json.dumps(record, separators=(",", ":")) + "\n")

def sha(text: str) -> str:
    return hashlib.sha256(text.encode("utf-8")).hexdigest()

def log_decision(store, run_id, prompt_template, variables, model, output, verdict, reviewer):
    rendered = prompt_template.format(**variables)
    record = {
        "decision_id": uuid.uuid4().hex,
        "correlation_id": run_id,
        "timestamp": datetime.now(timezone.utc).isoformat(timespec="milliseconds"),
        "model": model,
        "prompt": {"template_id": model["prompt_id"], "prompt_hash": sha(rendered)},
        "output": {"raw": output},
        "policy": verdict,
        "reviewer": reviewer,
        "reason": verdict["reasons"],
    }
    emit(store, record)
    return record["decision_id"]

store.append should target a file or object store opened in append-only mode, or a queue that writes once. Never update a record in place; corrections are new records that reference the original decision_id.

For team-level operations, a few habits keep the log usable. Set a retention baseline from the strictest regime you operate under: PCI DSS requires at least 12 months of audit log retention with 3 months immediately available; HIPAA requires audit controls without a fixed period; GDPR Article 30 requires records of processing where personal data is involved. Enterprises under multiple regimes should retain for the longest applicable minimum rather than picking one number (retention baselines). Also flag the review tier in each record so an auditor can filter for decisions that required human authorization, which is the distinction regulators care about most (oversight levels).

If your agents run across several providers, Quanta Inference gives you one OpenAI-compatible endpoint for text, image, video, audio, and embedding models, which keeps model metadata and request IDs consistent across the log (Quanta Inference).

Decision rule: which decisions get a full record

Not every agent step deserves the same treatment. Use this routing rule, and encode it in the agent harness so it is not left to developer memory.

SignalLog levelWhat to capture
External side effect (payment, message, record change)Full record, pre and postAll fields, hashes, policy verdict, outcome
Policy denial or escalation to a humanFull recordReason codes, reviewer identity, expiry
High-risk classification per your AI usage policyFull record plus approval eventAuthority chain, approval timestamp
Interpretation step with no side effectLight eventModel, prompt hash, token counts, latency
Retrieval chunk, retry, draft sentenceTrace onlySpan metadata, correlation ID

The middle row is where policy documents and logs meet. Workplace AI policies consistently require human review of AI output before reliance, disclosure when AI was used to perform work, and reporting paths for concerns about outputs (LexisNexis policy template). A decision log is what makes those clauses auditable. If the policy says a human verified the output, the log should carry a reviewer identity and a timestamp, and the reviewer should have had the information, authority, and time to actually influence the outcome (meaningful oversight). That last condition is why the review screen must show safe evidence links, policy reasons, and the expected change on one page.

Log enforcement also needs to be technical. Many policies prohibit inputting confidential data into unapproved tools and require approval before integrating AI with internal systems (sample acceptable use policy). A decision log that records which tool and data reference each agent touched turns those prohibitions into monitorable events. Pair it with a disclosure requirement: Taylor & Francis, for example, asks authors to state the full name of the tool used, how it was used, and the reason (publishing AI policy). Your model and reason fields store exactly those three facts.

Worked example: sizing the log

A support agent handles 40,000 decisions a day. Assume 20 percent are consequential (side effects, denials, escalations) and get full records at roughly 2 KB of JSON each, and 80 percent get light events at roughly 400 bytes.

SegmentCount per dayBytes per recordDaily volume
Full records8,0002,04816.4 MB
Light events32,00040012.8 MB
Total40,000mixedabout 29 MB

That is under 11 GB a year before compression; JSON lines of this shape typically compress well. At those volumes, storing a pre-action record and an outcome append costs almost nothing relative to the model calls themselves, so the real constraint is governance, not storage. The expensive mistake is the reverse: storing full prompts and outputs for every turn, which multiplies volume by an order of magnitude and drags your log into the scope of every privacy review. Sampling prompts at 1 to 5 percent while keeping hashes and token counts for all calls keeps cost predictable (sampling guidance).

Accountability and the audit chain

The strongest argument for the reviewer and reason fields is that oversight claims get tested after the fact. When a workflow claims human-in-the-loop compliance, that claim should mean a named person authorized each action in the execution log, not that a human was available if they chose to look (HITL versus HOTL). Logs that record a delegation chain, in which every agent action maps to a human authorizer in a tamper-evident record, are what distinguish real oversight from a label (delegation chain).

Two governance habits close the loop. First, review a sample of records weekly against the reason codes, looking for decisions where the verdict was allow but the outcome was unknown or rejected downstream. That pattern usually means the policy engine lacks a check, and it is invisible in dashboards that only count successes. Second, feed reviewer corrections back into the policy and prompt as versioned changes, so the policy.version and prompt_hash in future records show the fix took effect.

If your team would rather not build the review queue and record store from scratch, an AI expert engagement can produce the schema, the retention policy, and the reviewer interface as a finished deliverable (Quanta Experts). Either way, start with the six mandatory fields, one JSON line per decision, and the boundary rule. Everything else is an extension.

FAQ

FAQ

How is a decision log different from an OpenTelemetry trace?

A trace answers questions about performance: spans, latency, retries, model calls. A decision log answers why an action was allowed and what was verified afterward, including the policy version, reviewer identity, and outcome. Run both and join them with a shared correlation ID. Keep the full prompt text in traces at a sampled rate, and keep the hash in the decision record.

Should I store the agent's chain of thought in the reason field?

No. Store policy reason codes such as account_owner_verified plus a short operator-facing sentence, and keep hidden reasoning out of the audit artifact because it is unreliable and creates discovery and privacy exposure. If you need to evaluate reasoning quality, do it in a separate, access-controlled evaluation store, never in the primary decision log.

What goes in the prompt hash if the prompt changes every request?

Hash the rendered prompt, meaning the template with all variables filled in. That single digest detects template and variable changes together, and it lets you group identical requests for cost analysis without storing text. Also record the template ID and a separate hash of the template alone if you want to spot edits to the instructions independently of user input.

How long do we keep decision logs?

Set the period from your strictest applicable regime rather than a single house default. PCI DSS calls for at least 12 months with 3 months immediately available, HIPAA requires audit controls without a fixed period, and GDPR requires records of processing where personal data is involved. Teams under several regimes retain for the longest minimum, and hash-chained or write-once storage keeps the records defensible.

Do we need a full record for every step the agent takes?

Only at decision boundaries: choosing a tool or workflow, classifying risk, changing records or moving money, denying an action, escalating to a human, or declaring a task complete. Retrieval chunks, retries, and draft sentences belong in traces. The test is whether an absent teammate could reconstruct the reason, authority, and result of the action from one record.

Sources

Sources

  1. AI Agent Decision Logs: Record Evidence Without Storing Chain of ...
  2. Observability for AI Agents, Logs, Traces and SLOs You Need
  3. Human in the Loop: AI Compliance and Oversight ...
  4. What is Human-in-the-Loop (HITL)?
  5. Agent Audit Trail: A Standard Logging Format for Autonomous AI Systems
  6. Agent Decision Records (AgDR) - A standard for documenting ... - GitHub
  7. Policy Decision Log: Format, Fields, and Retention - Trussed AI
  8. PDF Artificial Intelligence (AI) Driven Tools in the Workplace Policy - LexisNexis
  9. PDF Acceptable Use of Generative AI Tools Sample Policy | Fisher Phillips LLP
  10. AI Policy - Taylor & Francis
  11. Human-in-the-Loop vs Human-on-the-Loop: Enterprise ...
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles