Agent Loop docs
agentloop.loop
The provider-independent reason/act/observe loop. These functions are the lower-level API:
they run the full agent loop, while you assemble the client, tool registry, and dependencies
yourself. Agent is the convenience API that assembles those pieces for you.
Constants
DEFAULT_MAX_TOKENS = 16_000MAX_TOKENS_CEILING = 64_000DEFAULT_MAX_ITERATIONS = 50DEFAULT_DEADLINE_SECONDS = 600.0
run_conversation
run_conversation(
transcript,
client,
registry,
deps,
*,
system=None,
max_tokens=16_000,
max_iterations=50,
deadline_seconds=600.0,
observer=None,
hosted_tools=(),
agent_name=None,
conversation_id=None,
correlation_id=None,
parent_id=None,
summary_options=None,
) -> Transcript
Updates and returns the supplied Transcript. Each iteration sends a ModelRequest to
the client. The loop adds the model's response to the transcript, runs any requested local
tools, and adds their results before the next iteration.
If a response ends partway through a tool call or before producing readable content, the
loop discards that response and retries with twice the token allowance, up to the 64,000
ceiling. It never lowers a larger allowance supplied by the caller. If the allowance
cannot grow, it raises LoopBudgetExceeded with kind="max_tokens".
A provider that pauses a turn (StopReason.PAUSED, for example Anthropic's pause_turn while
a hosted tool runs) is continued without sending a user message: the continuation joins the
same assistant message, and each continuation counts as an iteration.
If transcript ends with tool calls that have no results, the loop runs them before the
first model call. It then checks the transcript for invalid message order and raises
TranscriptError if necessary.
The deadline is checked before each model call. A provider call, its retries, or a started
tool batch may finish after it. None disables the deadline. Exhaustion raises
LoopBudgetExceeded; provider errors propagate unchanged.
agentloop supports Anthropic, OpenAI, OpenRouter, and Modal/vLLM. This example uses
OpenAI. Install its support and set the provider credentials:
python -m pip install 'based-models-agentloop[openai-compat]'
export LLM_PROVIDER=openai
export OPENAI_API_KEY='your-key'
The example creates each component explicitly and records the model request and response:
import os
from agentloop import (
Deps, ListObserver, Registry, Settings, Transcript,
build_client, final_text, run_conversation,
)
transcript = Transcript()
transcript.add_user_message("How many days are in a week? Reply with one digit.")
observer = ListObserver()
client = build_client(Settings.from_env(os.environ))
try:
run_conversation(transcript, client, Registry([]), Deps(), observer=observer)
print(final_text(transcript))
print(observer.kinds())
finally:
client.close()
Output:
7
['request', 'response']
Registry([]) supplies no local tools, and Deps() supplies the default dependency
bundle. final_text() reads the last assistant answer from the updated transcript.
run_conversation_result
Accepts the same parameters as run_conversation and returns a ConversationResult with
.transcript, .summary, and .text. The summary records the conversation's status and
usage. A completed answer, refusal, or truncated final answer returns normally; a budget
or provider failure raises an exception with its summary attached as .summary. The agent
and conversation identifiers label the summary. summary_options configures the timeline,
repeated-call detection, and limit warnings. See
Conversation summaries.
ListObserver
An observer for tests and debugging. The example above passes one to
run_conversation(). Its public events list contains ordered (kind, payload) tuples
for requests, responses, retries, and local tool starts and ends. kinds() -> list[str]
returns just the event names.