From 08f2d9865d372f94ad8f7fd250499c3b344bcda6 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Sat, 11 Apr 2026 10:19:10 -0600 Subject: [PATCH] =?UTF-8?q?wiki:=20refresh=20Internals.md=20=C2=A74.2=20+?= =?UTF-8?q?=20=C2=A79.1=20for=20#56=20tool=20registry=20refactor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Internals.md | 52 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/Internals.md b/Internals.md index 21c6380..8c0b008 100644 --- a/Internals.md +++ b/Internals.md @@ -211,20 +211,26 @@ budget; raising the cap would expose this. See **#51**. ### 4.2 Tool dispatch -Tools are plain functions in `ai.py`, registered into `_TOOL_DISPATCH` at -`ai.py:650`. `_execute_tool()` (`ai.py:664`) is a small function that -looks up the handler by name, calls it, logs the turn to -`investigation.log`, and returns the result string. **The control-flow -tool `submit_report` is NOT in `_TOOL_DISPATCH`** because -`_handle_turn_response()` recognizes it specially: it sets `done = True` -and extracts the summary directly from the tool input. +Tools are plain functions in `ai.py`. They are wired up via a single +`register_tool()` call (`ai.py:172`) that lands the schema in one or +more scope lists (`_DIR_TOOLS`, `_SYNTHESIS_TOOLS`, `_SURVEY_TOOLS`) +and the handler in `_TOOL_DISPATCH`. The registrations live below the +tool implementations in `ai.py` and read top-to-bottom in dir-then- +synthesis-then-survey order. + +`_execute_tool()` looks up the handler by name in `_TOOL_DISPATCH`, +calls it, logs the turn to `investigation.log`, and returns the result +string. **Tools intercepted by the loop body — `submit_report` and +`submit_survey` — register their schema only and have no handler entry.** +`_handle_turn_response()` recognizes `submit_report` specially: it sets +`done = True` and extracts the summary directly from the tool input. `think`, `checkpoint`, and `flag` *are* in dispatch, but they have side effects that just print to stderr or append to `flags.jsonl` — the return value is always `"ok"`. -When you add a tool: write the function, add it to `_TOOL_DISPATCH`, add -its schema to `_DIR_TOOLS`. That's it. +When you add a tool: write the function, then add one `register_tool()` +call below it. That's it. There is no second place to forget. ### 4.3 Pre-loaded context @@ -425,20 +431,26 @@ A cookbook for the kinds of changes that come up most often. ### 9.1 Add a new tool the dir agent can call -1. Write the implementation: `_tool_(args, target, cache)` somewhere - in the tool implementations section of `ai.py` (~lines 486–642). - Return a string. -2. Add it to `_TOOL_DISPATCH` at `ai.py:645`. -3. Add its schema to `_DIR_TOOLS` at `ai.py:151`. The schema must follow - Anthropic tool-use shape: `name`, `description`, `input_schema`. -4. Decide whether the survey should be able to filter it out (default: +1. Write the implementation: `_tool_(args, target, cache)` in the + tool implementations section of `ai.py`. Return a string. +2. Add a `register_tool()` call in the registrations block at the bottom + of the tool implementations section, with `scopes=["dir"]` and + `handler=_tool_`. The schema follows Anthropic tool-use shape: + `name`, `description`, `input_schema`. +3. Decide whether the survey should be able to filter it out (default: yes — leave it out of `_PROTECTED_DIR_TOOLS`) or whether it's control-flow critical (add to `_PROTECTED_DIR_TOOLS`). -5. Update `_DIR_SYSTEM_PROMPT` in `prompts.py` if the agent needs +4. Update `_DIR_SYSTEM_PROMPT` in `prompts.py` if the agent needs instructions on when to use the new tool. -6. There is no unit test for tool registration today (`ai.py` is exempt). - If you want coverage, the test would mock `client.messages.stream` and - assert that the dispatch table contains your tool. +5. There is no unit test for tool registration today (`ai.py` is exempt). + If you want coverage, the test would assert that `_TOOL_DISPATCH` + contains your handler and `_DIR_TOOLS` contains your schema after + importing `luminos_lib.ai`. + +To make a tool available in synthesis or survey instead of (or in +addition to) dir, pass `scopes=["synthesis"]`, `scopes=["survey"]`, or +`scopes=["dir", "synthesis"]`. Tools whose schema differs by scope (like +`submit_report`) get a separate `register_tool()` call per scope. ### 9.2 Add a whole new pass