Skip to content

Agent Loop

The AgentLoop is the intended execution boundary for all tool-calling work. You write the outer LLM loop (calling the model, managing message history, enforcing iteration limits); AgentLoop.process_turn handles everything between LLM responses—concurrent tool dispatch via asyncio.gather and state-change-gated context re-rendering.

Calling ToolRegistry.invoke directly is fine for unit tests, but production loops should go through process_turn to get concurrent dispatch and context management for free.

Turn Lifecycle

flowchart TB
    A["TurnInput<br/>(role, content, tool_calls)"] --> B["Render Context"]
    B --> C["Execute Tool Calls<br/>(concurrent)"]
    C --> D{State changed?}
    D -->|yes| E["Re-render Context"]
    D -->|no| F["Return TurnResult"]
    E --> F

Usage

from hybi.agent import AgentSession, AgentLoop, TurnInput, ToolCall

session = AgentSession.create(hb)
loop = AgentLoop(session)

# Build a turn from parsed LLM output
turn = TurnInput(
    role="assistant",
    content="Let me search for that.",
    tool_calls=[
        ToolCall(id="call_1", name="search", arguments={"query": "kinase inhibitors"}),
        ToolCall(id="call_2", name="list_collections", arguments={}),
    ],
)

# Process the turn
result = await loop.process_turn(turn)

# Inspect results
for tr in result.tool_results:
    print(tr.success, tr.data)

# Context snapshots (empty string if skip_render=True)
print(result.context_before)
print(result.context_after)   # only populated if state_changed
print(result.state_changed)   # True if a mutating tool succeeded
                              # (ingest, mutate, manage, connect, or external)

Single Tool Execution

# Execute one tool call outside the full turn cycle
call = ToolCall(id="call_1", name="explore", arguments={"collection": "drugs"})
result = await loop.execute_tool_call(call)

AgentLoop

hybi.agent.loop.AgentLoop

Executes the per-turn agent cycle.

The loop coordinates between the tool registry and context renderer. The LLM generation step happens externally -- this class handles tool execution and context rendering.

__init__(session)

process_turn(turn, *, skip_render=False) async

Process a single conversational turn.

Parameters:

Name Type Description Default
turn TurnInput

The input for this turn (user/assistant message + optional tool calls).

required
skip_render bool

If True, skip render() calls (for structuring turns).

False

Returns:

Type Description
TurnResult

TurnResult with tool results, context snapshots, and change flag.

execute_tool_call(call) async

Execute a single tool call outside the full turn cycle.


TurnInput

Input for a single agent turn.

hybi.agent.loop.TurnInput dataclass

Input for a single agent turn.


TurnResult

Result of a single agent turn.

hybi.agent.loop.TurnResult dataclass

Result of a single agent turn.