Default mode: Reason-Act cycle.
Each iteration:
- Build a Request from current messages + tools + system prompt.
- Call the provider — uses
stream/3when the loop was started withon_event:set, translating provider%Streaming.Event{}deltas into Loop tuples ({:content, chunk},{:thinking, chunk}) so they reach the caller in real time; falls back to one-shotquery/2when no event callback is registered. When deltas streamed, the end-of-turn full-text emission is suppressed. - Extract tool calls (native, or TextTagged fallback via
ExAthena.ToolCalls). - If no tool calls: emit
{:content, text}, setfinish_reason: :stop, and halt. - If tool calls: run them (parallel-safe ones concurrently, mutating ones serially), append results, continue.
Budget + mistake-counter checks happen between iterations in the kernel. This mode only implements the turn-by-turn behaviour.