105 lines
2.6 KiB
Markdown
105 lines
2.6 KiB
Markdown
# Agents
|
|
|
|
The agent is the core loop that orchestrates LLM calls and tool execution.
|
|
|
|
## AIAgent Class
|
|
|
|
The main agent is implemented in `run_agent.py`:
|
|
|
|
```python
|
|
class AIAgent:
|
|
def __init__(
|
|
self,
|
|
model: str = "anthropic/claude-sonnet-4",
|
|
api_key: str = None,
|
|
base_url: str = "https://openrouter.ai/api/v1",
|
|
max_turns: int = 20,
|
|
enabled_toolsets: list = None,
|
|
disabled_toolsets: list = None,
|
|
verbose_logging: bool = False,
|
|
):
|
|
# Initialize OpenAI client, load tools based on toolsets
|
|
...
|
|
|
|
def chat(self, user_message: str, task_id: str = None) -> str:
|
|
# Main entry point - runs the agent loop
|
|
...
|
|
```
|
|
|
|
## Agent Loop
|
|
|
|
The core loop in `_run_agent_loop()`:
|
|
|
|
```
|
|
1. Add user message to conversation
|
|
2. Call LLM with tools
|
|
3. If LLM returns tool calls:
|
|
- Execute each tool
|
|
- Add tool results to conversation
|
|
- Go to step 2
|
|
4. If LLM returns text response:
|
|
- Return response to user
|
|
```
|
|
|
|
```python
|
|
while turns < max_turns:
|
|
response = client.chat.completions.create(
|
|
model=model,
|
|
messages=messages,
|
|
tools=tool_schemas,
|
|
)
|
|
|
|
if response.tool_calls:
|
|
for tool_call in response.tool_calls:
|
|
result = await execute_tool(tool_call)
|
|
messages.append(tool_result_message(result))
|
|
turns += 1
|
|
else:
|
|
return response.content
|
|
```
|
|
|
|
## Conversation Management
|
|
|
|
Messages are stored as a list of dicts following OpenAI format:
|
|
|
|
```python
|
|
messages = [
|
|
{"role": "system", "content": "You are a helpful assistant..."},
|
|
{"role": "user", "content": "Search for Python tutorials"},
|
|
{"role": "assistant", "content": None, "tool_calls": [...]},
|
|
{"role": "tool", "tool_call_id": "...", "content": "..."},
|
|
{"role": "assistant", "content": "Here's what I found..."},
|
|
]
|
|
```
|
|
|
|
## Reasoning Context
|
|
|
|
For models that support reasoning (chain-of-thought), the agent:
|
|
1. Extracts `reasoning_content` from API responses
|
|
2. Stores it in `assistant_msg["reasoning"]` for trajectory export
|
|
3. Passes it back via `reasoning_content` field on subsequent turns
|
|
|
|
## Trajectory Export
|
|
|
|
Conversations can be exported for training:
|
|
|
|
```python
|
|
agent = AIAgent(save_trajectories=True)
|
|
agent.chat("Do something")
|
|
# Saves to trajectories/*.jsonl in ShareGPT format
|
|
```
|
|
|
|
## Batch Processing
|
|
|
|
For processing multiple prompts, use `batch_runner.py`:
|
|
|
|
```bash
|
|
python batch_runner.py \
|
|
--dataset_file=prompts.jsonl \
|
|
--batch_size=20 \
|
|
--num_workers=4 \
|
|
--run_name=my_run
|
|
```
|
|
|
|
See `batch_runner.py` for parallel execution with checkpointing.
|