| 1 | # Tools |
| 2 | |
| 3 | ## Source Anchors |
| 4 | |
| 5 | - Tool base class: `/a0/helpers/tool.py` |
| 6 | - Core tool contract: `/a0/tools/AGENTS.md` |
| 7 | - Tool dispatch path: `/a0/agent.py` |
| 8 | - Skills tool reference-file behavior: `/a0/tools/skills_tool.py` |
| 9 | - Example profile tool: `/a0/agents/_example/tools/example_tool.py` |
| 10 | - Prompt fragments: `/a0/prompts/AGENTS.md` |
| 11 | |
| 12 | ## Contract |
| 13 | |
| 14 | All tools derive from `helpers.tool.Tool` and implement: |
| 15 | |
| 16 | ```python |
| 17 | from helpers.tool import Tool, Response |
| 18 | |
| 19 | class MyTool(Tool): |
| 20 | async def execute(self, **kwargs) -> Response: |
| 21 | return Response(message="done", break_loop=False) |
| 22 | ``` |
| 23 | |
| 24 | `Response` fields: |
| 25 | |
| 26 | | Field | Meaning | |
| 27 | |---|---| |
| 28 | | `message` | Text appended as the tool result and shown back to the agent. | |
| 29 | | `break_loop` | `True` stops the current message loop. | |
| 30 | | `additional` | Optional metadata added with the tool result. | |
| 31 | |
| 32 | `Tool` instances receive `agent`, `name`, `method`, `args`, `message`, and `loop_data`. Use `self.method` for method-style tools such as `skills_tool:load`. |
| 33 | |
| 34 | ## Locations |
| 35 | |
| 36 | | Location | Use | |
| 37 | |---|---| |
| 38 | | `tools/` | Core framework tools. Use only for bundled framework behavior. | |
| 39 | | `plugins/<plugin>/tools/` | Bundled plugin tools. | |
| 40 | | `usr/plugins/<plugin>/tools/` | User plugin tools. This is the preferred place for custom plugin work. | |
| 41 | | `agents/<profile>/tools/` | Profile-local tools. Verify current discovery before relying on profile examples. | |
| 42 | |
| 43 | Most new tools should be packaged in a plugin, not added directly to root `tools/`. |
| 44 | |
| 45 | ## Prompt Contract |
| 46 | |
| 47 | Every tool needs an agent-facing prompt fragment so the model knows the tool name, JSON shape, arguments, and when to use it. |
| 48 | |
| 49 | Common locations: |
| 50 | |
| 51 | - Core tool prompt: `prompts/agent.system.tool.<tool_name>.md` |
| 52 | - Plugin tool prompt: `plugins/<plugin>/prompts/agent.system.tool.<tool_name>.md` |
| 53 | - User plugin prompt: `usr/plugins/<plugin>/prompts/agent.system.tool.<tool_name>.md` |
| 54 | - Profile override prompt: `agents/<profile>/prompts/agent.system.tool.<tool_name>.md` |
| 55 | |
| 56 | When changing a tool name, argument shape, output behavior, safety rule, or `break_loop` behavior, update its prompt and tests together. |
| 57 | |
| 58 | ## Progress And Interventions |
| 59 | |
| 60 | - Use `await self.set_progress(...)` when progress should be visible through the tool-output update extension. |
| 61 | - `self.add_progress(...)` only accumulates local progress text. |
| 62 | - For long-running or external-result workflows, follow `tools/AGENTS.md` and use `await self.agent.handle_intervention(...)` where pause/intervention flow matters. |
| 63 | - Sanitize and mask secrets before logging or returning outputs. |
| 64 | |
| 65 | ## Core Tool DOX |
| 66 | |
| 67 | Direct files under `tools/*.py` require matching `tools/*.py.dox.md`. The companion file owns purpose, arguments, output, `break_loop`, side effects, prompt contract notes, dependencies, and verification. |
| 68 | |
| 69 | Plugin tool documentation belongs in that plugin's docs or DOX contract, not in root `tools/`. |
| 70 | |
| 71 | ## Verification |
| 72 | |
| 73 | - Run targeted tests for changed tools. |
| 74 | - Run prompt/snapshot tests when tool instructions or output shape changes. |
| 75 | - For direct root tools, verify every `tools/*.py` has a matching `.py.dox.md`. |
| 76 | - If the tool is plugin-scoped, also run plugin-specific checks from the plugin's `AGENTS.md`. |