Runtime

Conversation Loop

The source component that owns model/tool iteration during a single user turn.

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.

  1. First pass: the model returns a web_search tool call; the loop runs it, appends the result, and calls the model again.
  2. Second pass: the model returns a Slack tool call built on that search result; the loop runs it and appends the outcome.
  3. 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 from api_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.
  • No article currently mentions this concept by name/alias often enough to qualify (see mention-mining policy).