remove tool_load: use ctl directly

tool_load was a built-in intercept in the agent loop — the only
'tool' that didn't run in toolsrv. Removed entirely:
- Intercept in loop.go (25 lines)
- Script + .meta in data/tools/
- autoLoad references in agent configs

Loading tools is now exclusively via ctl (which already existed):
  echo 'tool_load X' | ollie-9p write .../ctl

System prompt updated to show the ctl pattern.
This commit is contained in:
Levi Neely 2026-08-13 21:44:46 +02:00
parent ef640fb4be
commit a1e78bca80
6 changed files with 8 additions and 67 deletions

View File

@ -580,31 +580,6 @@ func (ag *Agent) execOne(ctx context.Context, call backend.ToolCall) (toolResult
return toolResult{ToolCallID: call.ID, Name: call.Name, Content: result, IsError: isErr}, false
}
// Built-in: tool_load - must be handled specially because tools run inside
// toolsrv and can't load other tools into themselves.
if call.Name == "tool_load" {
var args struct {
Name string `json:"name"`
}
if err := json.Unmarshal(call.Arguments, &args); err != nil {
result = "error: " + err.Error()
isErr = true
} else if args.Name == "" {
result = "error: name is required"
isErr = true
} else if toolServer == nil {
result = "error: no tool server"
isErr = true
} else if err := toolServer.LoadTool(args.Name); err != nil {
result = "error: " + err.Error()
isErr = true
} else {
result = "loaded: " + args.Name
}
ag.emit(Event{Role: "tool", Name: call.Name, Content: result, OutputFormat: toolOutputFormat(rt, call.Name)})
return toolResult{ToolCallID: call.ID, Name: call.Name, Content: result, IsError: isErr}, false
}
if rt.Exec != nil {
out, blocks, err := rt.Exec(ctx, call.Name, call.Arguments)
if err != nil {

View File

@ -26,7 +26,13 @@ Proactively load what you need — don't wait to be told.
## Tools
Tools are loaded at startup. Additional tools can be loaded at runtime via the `tool_load` tool. Once loaded, a tool is a first-class function — call it directly by name.
Tools are loaded at startup. Additional tools can be loaded at runtime via ctl:
```bash
echo "tool_load file_read" | ollie-9p write session/$OLLIE_SESSION_ID/agent/$OLLIE_UNAME/ctl
```
Once loaded, a tool is a first-class function — call it directly by name.
**Important**: Use native tool calls, not shell. For example:
- To read a file: call `file_read` directly, NOT `cat` or `shell` with any command
@ -116,7 +122,7 @@ Your world model is a 9P filesystem. Your session ID is `${OLLIE_SESSION_ID}`. U
| `chat.raw` | read | Full conversation with block markers |
| `statewait` | read | Blocks until state changes; returns new value |
| `cfg` | r/w | Agent config (key=value: backend, model, cwd, temperature, etc.) |
| `ctl` | rdwr | Control: stop, compact, clear, inject, agent, model, tools, tool_load, cwd, name |
| `ctl` | rdwr | Control: stop, compact, clear, inject, agent, model, tools, tool_load, tool_unload, cwd, name |
| `stats` | read | Usage, cost, context size |
| `tools` | r/w | Write: load tool by name. Read: list loaded tools. |
| `proc/` | dir | Detached background processes |

View File

@ -11,7 +11,6 @@
"file_glob",
"file_grep",
"file_write",
"tool_load"
],
"maxSteps": 25,
"temperature": 0.5,

View File

@ -11,7 +11,6 @@
"file_glob",
"file_grep",
"file_write",
"tool_load"
],
"maxSteps": 30,
"temperature": 0.3,

View File

@ -1,20 +0,0 @@
#!/bin/bash
# args_json: {"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Tool name to load into the current session/agent"}}}
# ollie:prompt
# ## tool_load
#
# Load a tool into the current session/agent.
#
# **Args**: `name` (required) — the tool name to load.
#
# ```
# tool_load(name="file_read")
# ```
# ollie:end
set -euo pipefail
# This tool just outputs the name - the actual loading is handled by
# the agent framework when it receives the tool result.
name=$(grep -oP '"name"\s*:\s*"\K[^"]+')
echo "STATUS=ok TOOL_LOAD=$name"

View File

@ -1,18 +0,0 @@
{
"description": "Load a tool into the current session/agent via ollie-9p.",
"prompt": "## tool_load\n\nLoad a tool into the current session/agent by writing its name to\n`session/{sid}/agent/{aid}/tools` via ollie-9p.\n\n**Args**: `name` (required) — the tool name to load.\n\n```\ntool_load(name=\"file_read\")\n```",
"args": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "Tool name to load into the current session/agent"
}
}
},
"tier": "hot",
"scope": "global"
}