Human approvals
This fixture refund desk demonstrates a durable review pause without model or supplier calls. Its invented ticket ledger lets you inspect checkpoint reuse and approval resume.
Capabilities
| Capability | Kind | Signature | Module | Summary |
|---|---|---|---|---|
assess | skill | (ticket: str) -> dict | examples/python/features/approvals/agent.py | Look the ticket up in the fixture ledger (one recorded child step per case). |
request_refund | traversal | (ticket: str, amount_aud: float, reason: str = 'schedule change') -> dict | examples/python/features/approvals/agent.py | Settle a refund, pausing for a reviewer above ``AUTO_LIMIT_AUD``. |
Commands
python -m atfgraph.worker --module examples.python.features.approvals.agent:app
python -m examples.python.features.approvals.review --ticket NZ-0882 --amount 150
python -m examples.python.features.approvals.review --ticket NZ-0882 --amount 150 # under the desk limit
python -m examples.python.features.approvals.review --ticket QF-4417 --amount 480
python -m examples.python.features.approvals.review --ticket QF-4417 --amount 480 --decision rejected
Files
examples/python/features/approvals/README.mdexamples/python/features/approvals/__init__.pyexamples/python/features/approvals/agent.pyexamples/python/features/approvals/agentnode.yamlexamples/python/features/approvals/review.py
README
This fixture refund desk demonstrates a durable review pause without model or supplier calls. Its invented ticket ledger lets you inspect checkpoint reuse and approval resume.
| Capability | Kind | Shows |
|---|---|---|
assess(ticket) | skill | the one pre-pause step that must not repeat |
request_refund(ticket, amount_aud, reason) | traversal | save_checkpoint/load_checkpoint, request_approval, continuation |
target/debug/atfgraphd # 127.0.0.1:18880
python -m atfgraph.worker --module examples.python.features.approvals.agent:app
python -m examples.python.features.approvals.review --ticket QF-4417 --amount 480
python -m examples.python.features.approvals.review --ticket QF-4417 --amount 480 --decision rejected
python -m examples.python.features.approvals.review --ticket NZ-0882 --amount 150
What the pause actually is
app.request_approval(prompt, operation_key=..., checkpoint=...) saves the request on the server and releases execution capacity:
- The attempt ends, the traverser becomes
waiting, and its lease and worker permit are released. - An authorized caller decides through the SDK, HTTP or Console with
approvedorrejected. - The server queues a continuation with another attempt allowed; this does not consume the failure retry budget.
- The handler starts from the beginning under a fresh lease and the same approval call returns the stored decision.
Code before the pause must handle replay. This example saves the assessed case with expected_revision=0, then loads it on continuation to skip the assessment child. Inspect the path and prepared_on_attempt: 1 versus attempts: 2. For external side effects, a checkpoint alone is insufficient across a crash between action and write; use external idempotency or reconciliation.
Build the prompt from saved data. Reusing (traverser, operation_key) with a changed prompt returns 409 approval_conflict, so avoid clocks, random values or other changing inputs.
Non-admin callers can list/decide approvals only for their own traversers. Repeating the same decision is accepted; changing it after settlement returns 409 approval_decided.
The extended-feature tests use a real local daemon and verify approval recovery after server/worker downtime. Inspect those tests for the precise stop, decide and resume sequence.