BeakrGo to website

The ReAct graph

Every agent compiles down to the same three-node cycle -- prepare, call_llm, route_after -- with branches off the router for tools, subagents, or termination. The shape is the familiar ReAct pattern; the interesting part is how data flows between the nodes.

The compiled graph

1NODEpreparebudget · memory2STREAMING NODEcall_llmasync generator3ROUTERroute_afterBRANCH · toolsexecute_toolsBRANCH · subagenthandoffBRANCH · donefinalize → ENDBRANCH · errorfinalize → ENDcycle — re-enter prepare with tool resultsCHANNELSmessagesturnpending_toolsinput_tokensoutput_tokensstop_reasonllm_resp…

Solid arrows are compiled graph edges. Dashed arrows are cycles -- the executor treats them as new super-steps, not direct calls.

The three node kinds

1
prepare -- pre-flight

Runs at the top of every cycle. Checks budget and timeouts, drains any queued user input from Redis, trims working memory (four compression layers), injects a compression notice if something was dropped, and handles ask_user resume if the previous run paused.

2
call_llm -- the async generator

Sends the conversation to the language model and streams the response back token-by-token. If the model refuses or times out, the system automatically retries with a different model.

3
execute_tools -- parallel dispatch

Accepted tool calls flow through the tool executor: policy check, attaching relevant context and citations, then dispatch. Read-only tools run in parallel for speed. Database-writing tools run sequentially for safety. Meta-tools (like delegating to another agent) spawn a separate execution.

Channel reference

messages
Appends new messages each step, never overwrites.
turn
Current turn counter, replaced each step.
pending_tools
Tool calls from the latest model response.
input_tokens / output_tokens
Running total across all model calls in this run.
stop_reason
How the last model call ended: tool use, natural stop, refusal, or token limit.
llm_response
The complete response from the latest model call.