Autonomous Agents and Permissions
Run an agent unattended with limits. Permission modes, budgets, kill switches, durable execution, approvals, rollback.
- Concepts and terms
- Tasks and commands
- Annotated code
- Diagrams
- Defaults and numbers
- Troubleshooting
- Questions and tips
Operator tasks#
| Task | Code |
|---|---|
| Review a plan first | permission mode plan |
| Auto-approve file edits only | permission mode acceptEdits |
| Cap spend and loop turns | max_budget_usd, max_turns |
| Limit the tool set | allowed_tools / disallowed_tools |
| Kill the agent container | kubectl delete pod |
| Trip on repeated calls | CircuitBreaker(threshold= |
| Replay after a crash | workflow(EventLog(<path>), |
| Make an approval retry-safe | k = |
From Lesson 15.10, Lesson 15.13, Lesson 15.14, 15.14 code/main.py, 15.12 code/main.py, 15.15 code/main.py
Control layers#
From Lesson 15.10, Lesson 15.13, Lesson 15.14, Lesson 15.15, Lesson 15.12
Propose, commit, verify#
From Lesson 15.15, 15.15 code/main.py, Lesson 15.16, 15.16 code/main.py
Durable activity#
def activity(name: str): def deco(fn): @functools.wraps(fn) def wrapper(log: EventLog, *args): hit = log.lookup(name, args)done event in log? if hit: return hit["result"]replay, no re-run log.append({"name": name, "args": list(args), "status": "started"}) result = fn(*args)the real side effect log.append({"name": name, "args": list(args), "status": "done", "result": result})log output return result return wrapper return decoFrom 15.12 code/main.py
Governor and breaker#
gov = Governor(max_turns=200, max_budget_usd=50.0)session capsif gov.enable_iter_cap and turn >= gov.max_turns: run.stopped_by = "max_turns"iteration capif gov.enable_session_cap and run.dollars >= gov.max_budget_usd: run.stopped_by = "max_budget_usd"dollar capif gov.enable_velocity and velocity_exceeded(run, gov, now_min): run.stopped_by = "velocity_limit"rolling spend rateif kill_switch["enabled"]: breakexternal off-buttonallowed = breaker.record(f"{a.kind}:{a.payload}")if not allowed: break5 identical calls opened itPermission modes#
plan- User approves the plan. Each action is reviewed first.
default- "Manual". Prompts for shell, destructive and network actions.
acceptEdits- File writes auto-approve. Shell and network still prompt.
auto- A classifier model reviews each action. Blocks escalation.
dontAsk- Never prompts. Unapproved actions are denied.
bypassPermissions- Approves everything. Throwaway containers only.
From Lesson 15.10
Which cap catches what#
- Runaway loop
- Caught by the velocity limit.
- Slow leak
- About 2x expected work. Caught by the daily cap.
- Bad release
- New version uses 5x tokens. Caught by weekly or monthly cap.
- Legitimate surge
- Caught by the hour or day cap with a clear log.
- Slow adversarial drift
- Beats statistical detectors. Hard limits catch it.
- Composed safe actions
- No detector catches them.
From Lesson 15.13, Lesson 15.14
Defaults in the simulators#
| Setting | Default | Note |
|---|---|---|
max_tokens_per_request | 10_000 | Per-call completion cap |
max_turns | 200 | Loop iterations per session |
max_budget_usd | 50.0 | Session dollars, aborts on breach |
velocity_usd_per_min | 5.0 | Rolling spend rate cut-off |
velocity_window_min | 10.0 | Window for the rate |
monthly_cap_usd | 500.0 | Catches slow leaks late |
threshold | 5 | Identical calls that open the breaker |
| Half-open probes | default 1 | 1 to 3 after the cool-down |
Troubleshooting#
| Symptom | Cause | Fix |
|---|---|---|
| Crash re-runs all tool calls | Naive while True loop | Activities plus an event log |
| Replay diverges | Wall clock or random in workflow | Register it as a side effect |
| Approved action runs twice | No idempotency key | One key per proposal |
| Overdraft after resume | Idempotency check only | Add a precondition check |
| "Committed" but no side effect | Status saved, action lost | Verify by re-read, then roll back |
| Approvals with no real review | Plain Approve button | Challenge-and-response checklist |
| Bill tripled after a new tool | No per-tool cap | Per-tool cap, daily-growth alert |
| Agent turns off its canary | Detector in the agent's reach | Keep it where agent cannot write |
From Lesson 15.12, Lesson 15.13, Lesson 15.14, Lesson 15.15, Lesson 15.16
Glossary#
- HITL
- Human-in-the-loop. A person approves before the action.
- METR horizon
- Task length a model completes at 50% reliability.
- Denial of Wallet
- Agent loop that spends with no cap to stop it.
- thread_id
- Key that scopes durable state for one session.
- Lease
- Short claim that a worker runs a run. It expires on crash.
- Blast radius
- Scope of effect if the action goes wrong.
- SAGA
- Compensating transaction that neutralizes the original action.
From Lesson 15.01, Lesson 15.12, Lesson 15.13, Lesson 15.15, Lesson 15.16
Q&A#
- 99% per step, 70 steps?
- The agent still fails half the time.
- Why a stack of caps?
- One monthly cap fires after the wallet is gone.
- Why persist every transition?
- Replay lands anywhere and lease recovery is precise.
- When skip durable execution?
- Short runs with no human input, or read-only work.
- What does
automiss? - Subtle injection and harmful sequences of safe actions.
From Lesson 15.01, Lesson 15.13, Lesson 15.12, Lesson 15.16, Lesson 15.10
Tips#
- Never run
autowithoutmax_budget_usd. - Check the kill switch on every consequential action.
- Re-enable a kill switch only by an explicit human action.
- Give every new tool its own cap and alert.
- Always HITL for irreversible writes. Never for reads.
- Rehearse each rollback end to end at least once.
From Lesson 15.13, Lesson 15.14, Lesson 15.15, Lesson 15.16, Lesson 15.12