Human-in-the-Loop Tools for the Agent SDK
Kenny Rogers ·

The Agent SDK(opens in new tab) now supports a fourth tool type: human-in-the-loop (HITL) tools. They let your agent handle routine calls automatically and pause for a human when stakes are high, all controlled by a single hook.
Install the SDK, define your HITL tool, and follow the cookbook recipe(opens in new tab) for a working implementation.
Auto-resolve or escalate, per call
Regular tools always execute. Manual tools always pause. HITL tools do both: your onToolCalled hook inspects the input and decides.
Return a value and the agent keeps going (like a regular tool). Return null and the loop pauses with status: 'awaiting_hitl', surfacing the pending call to your application. You resume by calling callModel again with a function_call_output item containing the human's decision.
This pattern fits anywhere the decision depends on data: dollar thresholds, risk scores, content policy flags, compliance checks. The branching logic lives in one function, not scattered across your application code.
Post-process human responses before the model sees them
An optional second hook, onResponseReceived, fires when a human supplies a result for a paused call. It transforms the raw input before passing it to the model.
Use it to stamp metadata, normalize formats, validate against business rules, or enrich the response with context the human didn't need to provide manually. If it throws, the error surfaces to the model as { error: ..., originalOutput: ... } so nothing gets silently swallowed.
How the pause and resume cycle works
Here's the full lifecycle:
- The model calls your HITL tool during an agent loop.
onToolCalledruns. If it returns a value, the agent continues. If it returnsnull, the loop pauses.- Your application reads the pending calls via
getToolCalls()and presents them to the user. - The user makes a decision.
- You call
callModelagain with the decision as afunction_call_outputitem. onResponseReceived(if defined) transforms the response.- The model receives the result and the agent loop resumes.
The SDK handles all the state tracking, hook dispatch, and schema validation. You wrote zero loop code.
When to use HITL vs requireApproval
Both pause for human input. The difference is in the decision logic.
HITL (onToolCalled) | requireApproval | |
|---|---|---|
| When it pauses | Only when your hook returns null | Always, before any execution |
| Decision type | Data-driven (thresholds, scoring, policy) | Binary yes/no consent |
| Auto-resolve | Return a value to skip human review | Not available |
| Post-processing | onResponseReceived transforms the response | Not available |
Use requireApproval when every invocation needs explicit human consent regardless of input (think: "delete this database," "send this email"). Use HITL when some calls can proceed automatically and others need a human (think: "approve this payment if it's under $100").
Start building
The HITL tools cookbook recipe(opens in new tab) walks through a complete implementation: defining the tool, detecting pauses, collecting human input, and resuming the loop.
For the full type signatures and API surface, see the tools documentation(opens in new tab) and the API reference(opens in new tab).
Get your API key(opens in new tab) and tell us what you're building on Discord(opens in new tab).