← Back to The Lab
§ Pattern◆September 29, 2026◆5 min

What goes in an approval request: a short reason or a link to the trace?

A reviewer who has to open a trace to understand a request will start approving without opening it. A reviewer who only reads the agent's own explanation is being talked into it. The request needs both, in a specific order.

Share◆X◆LinkedIn◆Facebook◆

> ../patterns/approval_request_contents.md

A reader left a comment on the approval queue post: should the request carry a short justification inline, or just link to the trace? Short answer: both, but they do different jobs, and they should never be mixed together in one block of text. Here is how we lay it out.

§ 01 · Two ways an approval request goes wrong

◆ Link only. The reviewer has to open a trace, scroll through tool calls and work out what happened before they can decide. Nobody does that forty times a day. They start approving from the title. The queue still exists, but it has stopped being a control.

◆ Reason only. The agent writes a tidy paragraph explaining why the action is fine. That paragraph is written by the same system that wants the action approved. It can be wrong, and it is usually persuasive. A reviewer who reads only that is being talked into the answer.

── ◆ ──

§ 02 · Split the request into three parts

◆ Facts the system computed. Amount, recipient, which record changes, whether it can be undone, and which policy rule sent it to a human. The agent does not write any of this. The gate does, from the tool call itself. This is the part the reviewer decides on.

◆ The agent's reason, two lines at most. Labelled as the agent's claim. It shows intent, but it never carries the decision.

◆ A link to the trace. For the cases where the facts and the reason do not match, or something looks off. Most reviews should not need it. If more than one in five do, the facts section is missing something.

◆ On top of that, every request shows its deadline and what happens if nobody answers, as covered in the post on approval timeouts.

── ◆ ──

§ 03 · What it looks like

from dataclasses import dataclass

@dataclass
class ApprovalRequest:
    # computed by the gate from the tool call, never by the agent
    action: str          # "refund.issue"
    target: str          # "order 88214"
    amount: str          # "EUR 340.00"
    reversible: bool     # False
    triggered_by: str    # "amount above the 250 auto-approve limit"
    expires_at: str      # "2026-09-30T09:00Z"
    on_timeout: str      # "reject"

    # written by the agent, shown as a claim
    agent_reason: str    # trimmed to 200 characters

    # for the exceptions
    trace_url: str


def render(req: ApprovalRequest) -> str:
    undoable = "yes" if req.reversible else "no"
    return (
        f"{req.action} on {req.target}\n"
        f"Amount: {req.amount}   Undoable: {undoable}\n"
        f"Why it needs you: {req.triggered_by}\n"
        f"Agent says: {req.agent_reason[:200]}\n"
        f"If nobody answers by {req.expires_at}: {req.on_timeout}\n"
        f"Full trace: {req.trace_url}"
    )

The order matters. The facts come first and the agent's words come after them, with a label that says whose words they are.

── ◆ ──

§ 04 · Check that people actually read it

◆ Time to decision. If most approvals arrive within two or three seconds, nobody is reading. Track it per reviewer, not just as an average.

◆ Rejection and edit rate. A queue with zero rejections over several weeks is either a perfect agent or a rubber stamp. It is rarely the first.

◆ Planted requests. Once in a while, put in a request that should be rejected, with a wrong amount or the wrong recipient, and see whether it gets through. Tell reviewers that this happens, just not when. It is the only test that measures the control itself and not the agent.

── ◆ ──

§ 05 · When to leave the reason out

◆ For high value or hard to undo actions, consider showing the agent's reason only after the reviewer has looked at the facts, or dropping it altogether. A reason read first becomes the frame for everything after it.

◆ We do not have data on where that line should sit. We would start by showing it below the facts for every action type and tighten from there, using the planted requests to see whether it changes what gets through.

── ◆ ──

Facts from the system first. The agent's reason second, short and labelled as a claim. A trace link for the exceptions. A default for when nobody answers. Then measure whether anyone is actually reading.

The reference code for approval gates is in agent-reliability-patterns on GitHub, MIT licensed.

ORBIRESEARCH

Share◆X◆LinkedIn◆Facebook◆