The base loop every ChatCLI worker runs: reason about the task, act (call a tool), observe the result, repeat until done or max-turns.
ReAct is the oldest and most essential pattern in ChatCLI. Every invocation of /agent or /coder runs inside it: each specialized agent (FileAgent, CoderAgent, Planner, Refiner, …) executes its own Reason → Act → Observe loop until it solves the task or hits the turn cap.
ReAct is always on. The other six patterns compose around it without replacing it.
The LLM receives the agent’s system prompt + the task + history of observations and produces a response that may contain reasoning text, a <tool_call>, an <agent_call>, or the final answer.
2
Act
If there was a tool/agent call, chatcli executes it (shell, file read, API call, sub-agent dispatch, …) and captures the output.
3
Observe
The tool output goes back into history as a system message — the next LLM turn already sees the result.
4
Repeat
Until the LLM emits a response without tool calls (natural end) or it hits CHATCLI_AGENT_WORKER_MAX_TURNS (default 30).
cli/agent/workers/worker_react.go │ ▼ RunWorkerReAct(ctx, cfg WorkerReActConfig) │ ▼ for turn := 0; turn < maxTurns; turn++ { │ llmResponse := client.SendPrompt(ctx, prompt, history, maxTokens) │ if done(llmResponse) { return } │ toolCalls := parse(llmResponse) │ for _, call := range toolCalls { │ result := execute(call) │ history = append(history, observation(result)) │ } │ }
The ReAct loop was deliberately left intact in the seven-pattern PR. Every new addition (Refine, Verify, Reflexion) plugs in around it via QualityPipeline.Run, not inside it.
The dispatcher also emits AgentEvent{Type: Started|Completed|Failed} via channel (see DispatchWithProgress), consumed by the UI to render the timeline.