HITL and Decision Flow
Human-in-the-loop in Tirea is not a separate transport feature. It is part of the core run model: tools can suspend, runs can wait, and external decisions can be forwarded back into the active run for replay.
The Three States That Matter
- A tool call suspends.
- The run transitions to
Waitingif all active tool calls are suspended. - An external decision resumes or cancels the suspended call, and the loop replays that tool call deterministically.
This is why HITL behavior spans runtime, protocol, and storage layers instead of living only in frontend adapters.
Two Inbound Paths
There are two distinct ways to continue work after a suspension:
- Decision forwarding:
an active suspended run receives
ToolCallDecisionpayloads and continues in place - Continuation run: a new run starts with additional user messages, optionally carrying decisions with it
These paths are intentionally different:
- decision forwarding preserves the existing run id and resumes the suspended call;
- continuation starts a new run lineage and is the right choice when the user is adding new intent, not only resolving a pending approval.
Decision Forwarding
Decision forwarding is the canonical HITL path.
Flow:
- A tool returns
Pending(...)or a behavior suspends it before execution. - Suspended call payload is stored in runtime state.
- Client posts a
ToolCallDecisionto the active run. - The loop resolves the decision, marks the call
Resuming, replays it, and commits the resulting effects.
The important property is replay: the original tool call is not mutated in place by the client. The client only submits the decision payload; the runtime owns the actual resumed execution.
Continuation Runs
Continuation is a different mechanism:
- a new user message is appended;
- a new run id is created;
parent_run_idlinks the new run back to the suspended or completed parent.
Use continuation when the user is changing the conversation, not merely approving or denying a specific tool call.
Tool Execution Mode Changes the UX
tool_execution_mode changes how suspension feels from the outside:
| Mode | Practical effect on HITL |
|---|---|
sequential | Simplest mental model; one call is active at a time |
parallel_batch_approval | Multiple calls may suspend in a round, then resume behavior is applied after batch commit |
parallel_streaming | Stream mode can emit activity updates and apply decisions while tools are still in flight |
If your UI needs live progress, rich activity cards, or low-latency approval loops, parallel_streaming is the intended mode.
Durable State and Lineage
HITL depends on persisted runtime state:
__runtracks run lifecycle__tool_call_scope.<call_id>.tool_call_statetracks per-call status__tool_call_scope.<call_id>.suspended_callstores suspended call payloads
Lineage fields keep the larger execution graph understandable:
run_idthread_idparent_run_idparent_thread_id
This matters most once you combine approvals, persisted threads, and sub-agent delegation.
Transport Mapping
The same model appears through multiple transports:
- Run API:
POST /v1/runs/:id/inputsforwards decisions to the active run - AG-UI: protocol adapters forward decisions onto the same runtime channel
- A2A:
decision-only requests map to the same
ToolCallDecisioncontract
The transport changes payload shape and encoding, but the runtime semantics stay the same.
When to Reach for Which Doc
- Use Enable Tool Permission HITL to wire approval behavior
- Use Run API for concrete HTTP payloads
- Use Frontend Interaction and Approval Model for the unified design behind frontend tools and approvals
- Use Run Lifecycle and Phases for full internal state-machine detail
This page is the conceptual bridge between those pieces.