ed@edheltzel: ~/log/approval-before-the-side-effect
ed@edheltzel:~/log$ cat approval-before-the-side-effect.md

Human approval belongs before the side effect

The failure mode I care about is not a wrong summary. It is a correct-looking JSON object that hits production. Dex Horthy’s factors 7, 8, and 11 are the control plane for that. Reading of 12-factor agents, content CC BY-SA 4.0.

Ask people with the same mechanism you ask APIs

LLM APIs make a high-stakes first-token choice: prose or structured data. Horthy’s move is to make human contact a tool too. request_human_input and done_for_now are intents, same as create_issue. The loop saves the thread, notifies someone, and returns. A webhook later appends the answer and starts the loop again.

You might not get a quality bump from “always JSON.” You get a uniform event log. Outer-loop agents, the ones that run for twenty or ninety minutes and then ping a person, need that. The Outer Loop is the longer version of the pitch.

Own the switch statement

Factor 8 is permission to write an ugly if. Fetch git tags: do it, append the result, ask for the next step. Request clarification: break, wait. Deploy backend: do not deploy. Save the selected tool, ask a human, resume later.

That last branch is the feature request Horthy says he files against every framework: interrupt between selection and invocation. Without it you pick from three bad options. Hold the process open. Ban the useful tools. Or yolo.

Your code can also compact tool results, rate limit, sleep, or run an LLM-as-judge on the structured output. None of that belongs inside the model’s hidden loop. It belongs in yours.

Meet people on the channel they already use

Factor 11 is the HumanLayer product-shaped one, and it is still a real design rule if you never buy the product. Slack, email, SMS, a cron, an outage webhook. Same thread id. If a person can approve a deploy from the place they already live, you can give the agent higher-stakes tools without living in the agent’s TUI.

This is not “the agent feels like a coworker.” It is auditability. Who approved, which payload, which thread.

What I actually keep

  • Human input is a tool call, not a special chat mode.
  • Dangerous tools pause after JSON, before I/O.
  • Channels are adapters. The thread is the program.

Prev: an agent should be able to stop and come back. Next: error recovery needs a stopping rule.