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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user