# Each approval-gated tool call gets its own approval record

> Agno now holds a second `@approval` tool call in the same run until an admin approves it. Earlier releases ran that call under the approval given to the first one, for agents and teams alike.

- Published: 2026-10-08
- Author: Kaustubh Shukla
- Categories: Changelog
- Canonical: https://www.agno.com/blog/each-approval-gated-tool-call-gets-its-own-approval-record
- Markdown: https://www.agno.com/blog/each-approval-gated-tool-call-gets-its-own-approval-record.md

When an Agno run pauses a second time on an `@approval` tool, it now writes a new pending approval record that names only that call, with its arguments and requirements, and `continue_run` waits until an admin resolves it.

Say an agent pays invoices with a `pay_invoice` tool marked `@approval` and `@tool(requires_confirmation=True)`. The run pauses on `INV-1`, an admin approves that record, and your code continues the run by `run_id` with no requirements, which is the flow where approvals are resolved in the database. `INV-1` gets paid, the model calls `pay_invoice` for `INV-2`, and the run pauses again.

In earlier releases nothing appeared for the admin at that second pause. Agno skipped creating a record because an earlier call in the run already had an approval ID, and it then paired the new call with the run's latest record, the approved one for `INV-1`. The next continue paid `INV-2` on the strength of the first decision. We reproduced it offline with a scripted model on both releases.

![Before and Now panels, real output. An agent pays INV-1, then INV-2, both behind @approval, and the admin approves only INV-1. Before: after the first continue INV-1 is paid and the only record is approved INV-1; the second continue completes and pays INV-1 and INV-2 with still only one record. Now: after the first continue the records are approved INV-1 and pending INV-2; the second continue raises ValueError for unresolved HITL requirements and only INV-1 is paid.](https://www.agno.com/images/v3-1-2-approval-records.png)

```text
continue 2 (admin has not approved INV-2):
  -> ValueError: Run has unresolved HITL requirements. Provide the `requirements` parameter (or resolve an admin approval first).
     paid=['INV-1']  records=["approved:['INV-1']", "pending:['INV-2']"]
admin approves 1 record
continue 3: COMPLETED  paid=['INV-1', 'INV-2']  records=["approved:['INV-1']", "approved:['INV-2']"]
```

When a record lists its tool calls, the run-level lookup pairs it only with those calls, so a call with no record of its own blocks the continue. Tools on a team leader get the same fix. For tools on a member agent, the second record used to name the first call and show its arguments, and it names only the new call now. Audit-mode tools no longer block a continue, `metadata["approval"]` holds the record for the call being run on an agent or team leader, and resending `run.requirements` no longer runs a call that already has a result.

See the [cookbook](https://github.com/agno-agi/agno/blob/main/cookbook/02_agents/11_approvals/approval_list_and_resolve.py), and learn more about [approvals](https://docs.agno.com/hitl/approval) in the documentation.
