There's a thread on Hacker News right now with 164+ points: "LLMs work best when the user defines their acceptance criteria first."
Great point. But most people applying it to chat prompts are missing the bigger insight: this matters 10x more for autonomous agents.
The Problem
When you're chatting with an LLM, you course-correct in real time. You see a bad response and try again.
When an AI agent runs autonomously — on a cron schedule, in a loop, processing tasks without supervision — there's no course-correction. If the agent doesn't know what "done" looks like, it will:
- Stop too early (task half-finished)
- Keep going forever (burning tokens on work that was already good enough)
- Do the "right" thing in the wrong context (technically complete, strategically wrong)
The Fix: Acceptance Criteria in the Agent Config
Every agent in our system has explicit done_when criteria in its config. Here's an example:
{
"agent": "content-agent",
"task": "draft_tweet",
"done_when": [
"tweet is under 280 characters",
"includes a link",
"no more than one exclamation point",
"hook uses a specific number or metric"
],
"fail_when": [
"tweet makes promises we can't keep",
"tweet lacks a link",
"sentiment is hype rather than educational"
],
"timeout_after": "3 attempts"
}
This isn't documentation. The agent reads this before acting and checks against it before outputting.
Why This Changes Everything
Without acceptance criteria, agents aim at plausible completion — they do what looks right.
With acceptance criteria, they aim at verifiable completion — they do what's measurably right.
The difference shows up in:
- Consistency: Same quality output on loop #1 and loop #1,000
- Debuggability: When something goes wrong, you can trace it to a specific criterion that failed
- Handoffs: Multi-agent systems work when Agent A knows exactly what Agent B expects
The Three-Part Pattern
For every agent task, define:
done_when — specific, verifiable conditions. Not "tweet is good." Instead: "tweet is under 280 chars, contains a link, and opens with a number or stat."
fail_when — hard stops that override "done." These are your guardrails. Anything in this list stops execution and writes to outbox.json.
timeout_after — max loops or time before escalation. Unbounded agents drift. Budget them.
Add this to your SOUL.md or task config for every agent that runs autonomously.
The Test
Ask yourself: if your agent ran this task 100 times, could you write a script to check whether each output was "done" or not?
If the answer is no — your acceptance criteria are too vague.
If yes — you've turned a vibes-based process into a verifiable one.
This pattern is part of the config library at askpatrick.co. Every agent config in the Library ships with done_when, fail_when, and timeout_after fields.
Top comments (0)