Files
temp/docs/reference/actor_runtime.md

125 lines
4.1 KiB
Markdown

# Actor Runtime — Tool-Calling Loop
The **ToolCallingRuntime** provides the execution loop for tool-calling
actors. It maps `ToolRegistry` specs to LLM-provider tool schemas,
sends prompts to the LLM, routes tool call requests through
`ToolCallRouter` / `ToolRunner`, and feeds results back to the LLM
until a final response is produced or the iteration limit is reached.
## Architecture
```
ToolCallingRuntime
|-- ToolRegistry (tool spec source)
|-- ToolRunner (4-stage tool execution)
|-- ToolCallRouter (optional; provider format translation)
|-- LLMCaller (LLM invocation protocol)
+-- ToolActorContext (sandbox, resources, history)
```
## Loop Semantics
```
1. Convert ToolRegistry specs -> provider tool schemas
2. Send prompt + tool schemas to LLM via LLMCaller
3. If LLM returns tool calls:
a. Route each call through ToolCallRouter -> ToolRunner
b. Capture metadata (tool name, inputs, outputs, duration, success)
c. Thread sandbox root + resource bindings into tool inputs
d. Feed tool results back to LLM
e. Increment iteration counter; go to step 2
4. If LLM responds without tool calls:
a. Return final response with complete tool call history
5. If max_iterations reached:
a. Return partial result with terminated_by_limit=True
```
## Safety: Max Iterations
The `max_iterations` parameter (default **25**) prevents infinite loops
when the LLM continuously requests tool calls without producing a final
answer. When the limit is reached the runtime returns a
`ToolCallRunResult` with `terminated_by_limit=True` and whatever content
has been accumulated so far.
## Error Semantics
| Error | Condition | Behavior |
|---|---|---|
| `ValueError` | Empty prompt | Raised immediately |
| `TypeError` | Invalid registry/runner type | Raised at construction |
| `ValueError` | `max_iterations < 1` | Raised at construction |
| Tool not found | LLM calls a tool not in registry | `ToolCallRecord` with `success=False` |
| Tool execution error | Handler raises | `ToolCallRecord` with `success=False`, `error` set |
| Max iterations | Loop count exceeds limit | Returns `terminated_by_limit=True` |
## Tool Call Metadata
Every tool call is recorded as a `ToolCallRecord` containing:
| Field | Type | Description |
|---|---|---|
| `tool_name` | `str` | Name of the tool invoked |
| `inputs` | `dict` | Arguments sent to the tool |
| `output` | `dict` | Output returned by the tool |
| `duration_ms` | `float` | Execution time in milliseconds |
| `success` | `bool` | Whether the call succeeded |
| `error` | `str | None` | Error message if failed |
| `iteration` | `int` | Loop iteration when the call was made |
## Sandbox Threading
When a `ToolActorContext` is provided with a `sandbox_root` and/or
`resource_bindings`, these values are threaded into tool inputs as
default keys (`sandbox_root`, `resource_bindings`) so that tools
receive the execution environment context automatically.
## ToolActorContext
The `ToolActorContext` carries:
- **plan_id** — unique plan identifier
- **phase** — current plan phase (e.g. `execute`, `strategize`)
- **sandbox_root** — filesystem path to the sandbox directory
- **automation_profile** — governing automation profile name
- **resource_bindings** — slot-to-resource mappings from the plan
- **project_resources** — additional project resource metadata
- **tool_call_history** — running list of `ToolCallRecord` entries
## Usage Example
```python
from cleveragents.tool import (
ToolCallingRuntime,
ToolRegistry,
ToolRunner,
ToolActorContext,
)
registry = ToolRegistry()
runner = ToolRunner(registry)
# register tools...
runtime = ToolCallingRuntime(
registry=registry,
runner=runner,
llm_caller=my_llm_caller,
max_iterations=10,
)
context = ToolActorContext(
plan_id="plan-123",
phase="execute",
sandbox_root="/tmp/sandbox",
)
result = runtime.run_tool_loop(
prompt="Implement the feature described in the plan.",
context=context,
)
print(result.content)
print(f"Tool calls: {len(result.tool_call_history)}")
print(f"Iterations: {result.iterations}")
```