Conversation Loop
What it is
The source component that owns model/tool iteration during a single user turn.
In plain terms
A journalist keeps firing follow-up questions at a source until one answer finally closes the story out, however many rounds of back-and-forth it takes. Conversation Loop referees that same exchange between the model and its tools during a single user message, however many rounds it takes before someone finally stops and settles for the answer in hand.
Why it matters
run_conversation is the function actually responsible for one user turn end to end, sequencing turn context construction, the model call, and tool dispatch. A bug here shows up identically across desktop chat, Telegram replies, and cron output, since all three transports route through this same code path. Calling it a ‘loop’ rather than a single call matters mechanically too: it can iterate several times within one turn whenever the model chains multiple tool calls before finishing.
How it works
conversation_loop.py’s run_conversation function — which started life, per its own module docstring, as the roughly 3,900-line body pulled out of run_agent.py, and later had its once-per-turn setup code split out again into turn_context.py — first calls build_turn_context once, then drops into a while loop gated by api_call_count against agent.max_iterations and the remaining balance in agent.iteration_budget. Each pass calls the model and inspects assistant_message.tool_calls: when the list isn’t empty, agent._execute_tool_calls (agent/tool_executor.py) runs the batch and the results get appended to messages before the model is called again; when it’s empty, assistant_message.content becomes the final answer and the loop breaks. If the budget runs out first, a step outside this loop asks the model for one last toolless summary instead.
A concrete example
Finding today’s top AI headlines and posting them to Slack takes three passes through this loop.
- First pass: the model returns a web_search tool call; the loop runs it, appends the result, and calls the model again.
- Second pass: the model returns a Slack tool call built on that search result; the loop runs it and appends the outcome.
- Third pass: the model replies with plain text confirming the post went out, with no tool_calls attached, so the loop stops and returns that text as the answer.
How it connects
This note belongs to the Runtime family. Its closest neighboring concepts are: Turn Context, Tool Executor, Personal OS.
Source evidence
vendor/hermes-agent/agent/conversation_loop.py:593-603#run_conversation— Verified Source Map evidence for run_conversation. The conversation loop injects the active prompt, plus any ephemeral prompt, as the first system message, builds provider request kwargs fromapi_messages, and sends the representative streaming branch through LLM execution middleware to_interruptible_streaming_api_call.
Workflows
- No first-pass workflow mapping yet; this concept still appears in the vault graph through articles and source evidence.
Related articles
- No article currently mentions this concept by name/alias often enough to qualify (see mention-mining policy).
