---
title: "Tool Review Loops"
category: 07-tool-use
level: intermediate
stability: stable
description: "Intercept tool calls before execution to allow human review, modification, or rejection."
added: "2026-04"
version: v2
---

# Tool Review Loops
Category: tool-use | Level: intermediate | Stability: stable | Version: v2

## Description
Tool review loops pause an agent after it decides to call a tool but before the tool executes. This gives a human (or an automated policy) the chance to inspect the tool name and arguments, approve them as-is, modify them, or reject the call entirely. In LangGraph this is implemented with `interrupt_before=["tool_node"]`; in the OpenAI Agents SDK it can be approximated with an output guardrail that checks pending tool calls.

## Inputs
- `pending_tool_call`: tool name + arguments generated by the LLM
- `interrupt_before`: LangGraph config listing `tool_node` as interrupt target
- `reviewer`: human or automated policy function
- `thread_id`: run identity for resume after review

## Outputs
- Approved: tool executes with original or modified arguments
- Rejected: tool call cancelled, agent receives rejection message and continues

## Example
```python
# LangGraph: interrupt before tool node
app = graph.compile(
    checkpointer=MemorySaver(),
    interrupt_before=["tools"]
)
config = {"configurable": {"thread_id": "rev-01"}}
app.invoke({"messages": [{"role": "user", "content": "Delete all logs"}]}, config)

# Review pending tool call
state = app.get_state(config)
print(state.values["messages"][-1].tool_calls)  # Show what tool would be called

# Approve and resume
app.invoke(None, config)
```

## Failure Modes
| Cause | Symptom | Mitigation |
|---|---|---|
| Reviewer approves without reading args | Dangerous tool executed | Build UI that surfaces full args with diff highlight |
| Tool call modified incorrectly | Type error on execution | Validate modified args against tool's JSON schema before resume |
| Review loop adds too much latency | Poor UX for non-sensitive tools | Only interrupt for tools tagged as `sensitive=True` |

## Prompt Patterns
**Basic:** `"Pause before any tool that modifies or deletes data."`

**Chain-of-Thought:** `"Classify tool calls as read/write/delete, then interrupt only on write and delete."`

**Constrained Output:** `"Log every tool call with timestamp, args, and reviewer decision for audit trail."`

## Model Comparison
| Capability | GPT-4o | Claude 3.7 Sonnet | Gemini 2.0 Flash |
|---|---|---|---|
| Tool call argument quality | ✅ High | ✅ Very High | ⚠️ Occasional schema errors |
| Sensitivity classification | ✅ Good | ✅ Strong | ⚠️ Moderate |
| LangGraph interrupt usage | ✅ Accurate | ✅ Accurate | ⚠️ May lag API |
| Audit advice quality | ✅ Good | ✅ Strong | ⚠️ Basic |
| Cost | Moderate | Moderate | Low |

## Related
- `tool-guardrails.md` · `human-approval-gates.md` · `approval-before-destructive-tools.md` · `interruptible-agent-flows.md`

## Changelog
- v2 (2026-04): Full expansion
