---
title: "End every agent run with a known status · Agent Wranglers"
url: https://agentwranglers.se/playbook/ai-features/agents-in-products/agent-run-status
updated: 2026-10-20
licence: "All rights reserved"
---

# End every agent run with a known status

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Agents in products](https://agentwranglers.se/playbook/ai-features/agents-in-products)
- Rule: End every agent run in one of a fixed set of statuses and show it to the user. Examples are done, waiting for approval, approval expired, step limit, time limit, budget limit and failed.
- How: Wrap the loop in code that owns the stop conditions, not the model. Check the step count, the elapsed time and the spend before each step. When a limit is hit, stop, save the status and tell the user what was done and what was not. Never leave a run silently unfinished. Count runs per status per day, and alert when the share ending on a limit passes a set level, such as 5 in 100.
- Check: Tests run the agent against four fake models. One never finishes, one runs past the time limit, one spends past the budget and one asks for approval. Each run ends with the matching status, and the user sees a message for each.

Example:

```ts
type RunStatus = 'done' | 'waiting_for_approval' | 'expired' | 'step_limit' | 'time_limit' | 'budget_limit' | 'failed';
const MAX_STEPS = 10;
const MAX_RUN_MS = 120_000;

export async function runAgent(run: AgentRun): Promise<RunStatus> {
  const deadline = Date.now() + MAX_RUN_MS;
  for (let step = 0; step < MAX_STEPS; step++) {
    if (Date.now() > deadline) return run.finish('time_limit');
    if (await budgets.isSpent(run.userId)) return run.finish('budget_limit');
    const next = await run.takeStep();
    if (next.kind === 'done' || next.kind === 'waiting_for_approval') return run.finish(next.kind);
  }
  return run.finish('step_limit');
}
```

```python
MAX_STEPS = 10
MAX_RUN_SECONDS = 120

def run_agent(run: AgentRun) -> RunStatus:
    deadline = time.monotonic() + MAX_RUN_SECONDS
    for _ in range(MAX_STEPS):
        if time.monotonic() > deadline:
            return run.finish("time_limit")
        if budgets.is_spent(run.user_id):
            return run.finish("budget_limit")
        step = run.take_step()
        if step.kind in ("done", "waiting_for_approval"):
            return run.finish(step.kind)
    return run.finish("step_limit")
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers ai features playbook: https://agentwranglers.se/playbook/ai-features/agents-in-products/agent-run-status`.

- Previous: [Use a fixed workflow when the steps are known](https://agentwranglers.se/playbook/ai-features/agents-in-products/workflow-before-agent)
- Next: [Record every step of every run](https://agentwranglers.se/playbook/ai-features/agents-in-products/agent-run-trace)
- [Agents in products](https://agentwranglers.se/playbook/ai-features/agents-in-products)
