-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathloop.py
More file actions
48 lines (37 loc) · 1.61 KB
/
loop.py
File metadata and controls
48 lines (37 loc) · 1.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
"""agent_loop — the turn engine.
One call per user message: build the system prompt, then iterate
LLM → tool calls → LLM until the model returns a final answer (no tool calls)
or ``max_turns`` is hit. Tool failures come back as tool messages so the model
can recover rather than crashing the loop.
"""
from __future__ import annotations
from ..core.types import Message, Role
from .context import HarnessContext
from .system_prompt import build_system_prompt
async def agent_loop(ctx: HarnessContext, user_text: str) -> str:
"""Run one user turn to completion; return the final assistant text."""
ctx.session.add(Message(role=Role.USER, content=user_text))
system = await build_system_prompt(ctx)
specs = ctx.tools.specs()
for _ in range(ctx.max_turns):
messages = [Message(role=Role.SYSTEM, content=system), *ctx.session.history()]
completion = await ctx.llm.complete(messages, specs)
assistant = Message(
role=Role.ASSISTANT,
content=completion.content,
tool_calls=completion.tool_calls,
)
ctx.session.add(assistant)
if not completion.tool_calls:
return completion.content
for call in completion.tool_calls:
result = await ctx.tools.dispatch(call.name, call.arguments, ctx, call.id)
ctx.session.add(
Message(
role=Role.TOOL,
content=result.content,
tool_call_id=result.call_id,
name=call.name,
)
)
return "(reached max turns without a final answer)"