docs: add spawn_agent per-invocation tool restriction design (ARCH__FUTURE §12)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-05-11 23:23:17 -04:00
parent 4c3d9a7a65
commit 54eef73b74

View File

@@ -1,7 +1,7 @@
# Architecture: Planned Features # Architecture: Planned Features
> What's next and how it's designed to work. > What's next and how it's designed to work.
> Last updated: 2026-04-29 > Last updated: 2026-05-11
For the current task list see `TODO__Agents.md`. For phases and priorities see `ROADMAP.md`. For the current task list see `TODO__Agents.md`. For phases and priorities see `ROADMAP.md`.
@@ -313,4 +313,89 @@ This pattern maps naturally to several existing concepts:
2. Define the schema document — what goes in a wiki page, cross-reference format, category taxonomy 2. Define the schema document — what goes in a wiki page, cross-reference format, category taxonomy
3. Build an ingest tool/script that reads a source and updates wiki pages (LLM-driven) 3. Build an ingest tool/script that reads a source and updates wiki pages (LLM-driven)
4. Build a lint cron job that health-checks the wiki periodically 4. Build a lint cron job that health-checks the wiki periodically
5. Consider Obsidian compatibility for human browsing of the wiki graph 5. Consider Obsidian compatibility for human browsing of the wiki graph
---
## 12. Spawner-Level Tool Restrictions — `spawn_agent` Permission Control
**Status:** Design complete, not yet built.
### Problem
`spawn_agent` currently grants sub-agents the full tool set of whatever role they're assigned. The spawning agent (Inara) cannot restrict a sub-agent to a subset of tools — the role config is the only gate. This means every spawned agent implicitly has access to everything the role allows, including potentially destructive operations (`shell_exec`, `file_write`, `cortex_restart`).
### Design
Add two optional parameters to `spawn_agent`: **`allow_tools`** and **`deny_tools`**.
- **`allow_tools`** — explicit allow list. If set, the sub-agent can *only* use tools in this list (intersected with what the role allows). If omitted, the role's full tool set is available.
- **`deny_tools`** — explicit deny list. If set, these tools are removed from whatever the sub-agent would otherwise have access to. If omitted, nothing is denied beyond what the role already excludes.
**Effective tool set formula:**
```
effective = (role_base_tools ∩ allow_tools) ∩ (role_base_tools \ deny_tools)
```
Where `role_base_tools` is the full tool set the role config grants, `allow_tools` is the spawner's allow list (default: full set), and `deny_tools` is the spawner's deny list (default: empty set).
### Usage Examples
```python
# Research agent — web only, no file access, no shell
spawn_agent(
"Research the latest on Zigbee mesh repeaters",
role="chat",
allow_tools=["web_search", "web_read", "http_fetch"]
)
# Code review — read-only, no shell
spawn_agent(
"Review this file for security issues",
role="coder",
deny_tools=["shell_exec", "file_write", "cortex_restart", "cortex_update"]
)
# Full access (same as today — omit both params)
spawn_agent("Refactor the auth module", role="coder")
# Narrow data migration — just file ops, no web
spawn_agent(
"Migrate the task files to the new format",
role="coder",
allow_tools=["file_read", "file_write", "file_list"]
)
```
### Implementation Plan
**1. Model registry / role config — no changes needed.**
The role config (`role_cfg.get("tools")`) remains the authoritative ceiling. No schema changes at this level.
**2. `spawn_agent` function — new parameters + filtering logic.**
File: `cortex/tools/agents.py`. Add `allow_tools` and `deny_tools` as optional `list[str] | None` parameters. After resolving `tool_list` from `role_cfg.get("tools")`, apply the filter:
```python
if allow_tools is not None:
tool_list = [t for t in tool_list if t in allow_tools]
if deny_tools is not None:
tool_list = [t for t in tool_list if t not in deny_tools]
```
**3. Declaration — update the Gemini `FunctionDeclaration`.**
Add `allow_tools` and `deny_tools` as optional parameters in the declaration so the orchestrator knows they exist.
**4. Confirmation gate behavior — explicit.**
If a sub-agent with restricted tools hits a confirmation gate (e.g., trying `shell_exec` with it denied), the gate blocks as normal — it does not silently fail. The sub-agent returns the "requires user confirmation" message as it already does.
### What Doesn't Change
- Existing `spawn_agent` calls with no `allow_tools`/`deny_tools` continue to work exactly as before
- Role config remains the authoritative max — no security regression
- No schema changes to `model_registry.json`
- No UI changes needed