Skip to content

fix(agent): keep computer-use tools under a subagent whitelist and log misses - #10463

Open
he-yufeng wants to merge 1 commit into
AstrBotDevs:masterfrom
he-yufeng:fix/subagent-toolset-builtin-tools
Open

he-yufeng wants to merge 1 commit into
AstrBotDevs:masterfrom
he-yufeng:fix/subagent-toolset-builtin-tools

Conversation

@he-yufeng

@he-yufeng he-yufeng commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Issue #10456: with a persona tool whitelist on a subagent, the builtin execution tools disappear, and when the whitelist resolves to nothing the subagent runs toolless without a single log line.

The root cause is an asymmetry between the two persona paths. The main agent applies the runtime computer-use tools (_apply_sandbox_tools / _apply_local_env_tools) after the persona whitelist narrowing, and never routes them through the whitelist, so a whitelist only narrows the plugin and MCP tools. The subagent handoff in _build_handoff_toolset built a fresh ToolSet from the whitelist alone. The dashboard checkbox UI only ever writes plugin tool names into the whitelist, so builtin tool names never appear there, and the subagent loses shell/python/file access entirely. Worse, unresolvable names and empty results were dropped silently, so the failure left no trace in the logs (the reporter's subagent emitted pseudo tool-call text and nothing else).

Changes

astrbot/core/astr_agent_tool_exec.py:

  • Seed the whitelist-built toolset with the runtime computer-use tools, so a whitelisted subagent keeps the builtin execution tools, matching the main agent.
  • The seed covers the shipyard_neo browser tools (astrbot_execute_browser, astrbot_execute_browser_batch, astrbot_run_browser_skill) under the same capabilities gate the main agent uses: included when the booted sandbox profile lists browser, or before the first boot when capabilities are still unknown.
  • The seed skips (and logs) runtime tools that were deactivated, in both the whitelist branch and the tools=None branch.
  • An empty whitelist no longer returns early; it flows through the same construction, so it keeps the runtime tools and an empty result still reaches the empty-toolset warning.
  • Whitelist entries that are unknown or resolve to an inactive tool keep their warnings.

Tests

Coverage in tests/unit/test_astr_agent_tool_exec.py:

  • a sandbox-runtime whitelist keeps astrbot_execute_ipython/astrbot_execute_shell alongside the whitelisted plugin tool
  • an unknown whitelist name is skipped with a warning, and an all-miss whitelist returns None with the empty-toolset warning
  • an inactive whitelist entry is skipped with a warning while an explicit builtin name still resolves
  • an empty whitelist keeps the runtime tools under the sandbox runtime, and still returns None with the empty-toolset warning when no runtime is configured
  • a deactivated runtime builtin is skipped with a warning while the rest of the runtime tools stay
  • browser tools follow the main agent gate: present when the sandbox has not booted yet or reports a browser capability, absent when the booted profile does not

Each new assertion fails against the corresponding mutated source (browser gate removed, early return restored, active check removed) and passes with the fix. pytest tests/unit is green (1481 passed), as are ruff format and ruff check on the touched files.

To verify

  • pytest tests/unit/test_astr_agent_tool_exec.py
  • pytest tests/unit (1481 passed)
  • WebUI persona whitelist save plus a subagent task, on an install with computer-use runtime enabled

Fixes #10456

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 4 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="astrbot/core/astr_agent_tool_exec.py" line_range="303" />
<code_context>
+        # plugin tools, so builtin tool names never appear in `tools`).
         toolset = ToolSet()
+        for runtime_tool in runtime_computer_tools.values():
+            toolset.add_tool(runtime_tool)
+        unknown_names: list[str] = []
+        inactive_names: list[str] = []
</code_context>
<issue_to_address>
**Whitelist grants extra capabilities**

When computer-use runtime is enabled and a subagent has a non-empty whitelist that intentionally omits runtime tools, the whitelist-built handoff toolset receives every runtime computer-use tool before checking the selected names, so a user who triggers a subagent configured with only a benign plugin can still have it use runtime capabilities such as sandbox file access; the configured whitelist no longer limits those tools.

Keep runtime tools available only when explicitly permitted by the subagent policy, or introduce a separate setting that clearly opts a subagent into them.
</issue_to_address>

### Comment 2
<location path="astrbot/core/astr_agent_tool_exec.py" line_range="302-303" />
<code_context>
+        # even when the whitelist cannot name them (the dashboard only lists
+        # plugin tools, so builtin tool names never appear in `tools`).
         toolset = ToolSet()
+        for runtime_tool in runtime_computer_tools.values():
+            toolset.add_tool(runtime_tool)
+        unknown_names: list[str] = []
+        inactive_names: list[str] = []
</code_context>
<issue_to_address>
**Disabled builtin tools stay callable**

When a runtime computer-use builtin is deactivated and a subagent has a non-empty whitelist, `_build_handoff_toolset` adds each runtime tool without checking `active`; the full-schema path advertises it and the runner can execute it. A deactivated builtin therefore remains available to the subagent despite the whitelist path’s inactive-tool handling.

Only seed active runtime tools into the whitelist toolset.
</issue_to_address>

### Comment 3
<location path="astrbot/core/astr_agent_tool_exec.py" line_range="294" />
<code_context>
         if not tools:
             return None

</code_context>
<issue_to_address>
**Empty whitelist skips tool setup**

When the subagent whitelist is empty, `_build_handoff_toolset` returns at `if not tools` before seeding runtime tools or reaching the empty-toolset warning, so the caller gets no tools and the missing capabilities are not logged.

Let an empty whitelist continue through toolset construction so runtime tools are seeded and an empty result reaches the warning.

Also at `astrbot/core/astr_agent_tool_exec.py:297-303`, `astrbot/core/astr_agent_tool_exec.py:332-336`.
</issue_to_address>

### Comment 4
<location path="astrbot/core/astr_agent_tool_exec.py" line_range="302-303" />
<code_context>
+        # even when the whitelist cannot name them (the dashboard only lists
+        # plugin tools, so builtin tool names never appear in `tools`).
         toolset = ToolSet()
+        for runtime_tool in runtime_computer_tools.values():
+            toolset.add_tool(runtime_tool)
+        unknown_names: list[str] = []
+        inactive_names: list[str] = []
</code_context>
<issue_to_address>
**Whitelisted subagents still lose browser tools**

When a subagent uses a non-empty persona whitelist and its sandbox runtime supports browser tools, `_get_runtime_computer_tools` omits the sandbox browser tools, so this seed loop never adds them to a whitelisted subagent. Browser tasks then have no browser tools to call, even when the sandbox supports them.

Include the browser tools in the subagent runtime tool set when the sandbox supports them, matching the main agent's capability check.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 4 findings to address first, and this changes the subagent permission boundary by making configured computer-use tools available even when the persona whitelist omits them, potentially enabling shell or code execution that the whitelist was intended to prevent. Reverting stops future access but cannot undo commands, data exposure, or other side effects that occurred while the broader toolset was active.

Blocking findings: astrbot/core/astr_agent_tool_exec.py:303, astrbot/core/astr_agent_tool_exec.py:303, astrbot/core/astr_agent_tool_exec.py:294, astrbot/core/astr_agent_tool_exec.py:303


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread astrbot/core/astr_agent_tool_exec.py Outdated
Comment thread astrbot/core/astr_agent_tool_exec.py Outdated
Comment thread astrbot/core/astr_agent_tool_exec.py Outdated
Comment thread astrbot/core/astr_agent_tool_exec.py Outdated
…g misses

A persona tool whitelist on a subagent silently stripped the builtin
execution tools. The main agent applies the runtime computer-use tools
after the persona whitelist narrowing and never routes them through the
whitelist, so a whitelist only narrows plugin/MCP tools there. The
subagent handoff built its toolset from the whitelist alone, and since
the dashboard checkbox UI only lists plugin tools, builtin names never
appear in the list and the subagent lost shell, python and file access
entirely.

Seed the whitelist-built toolset with the runtime computer-use tools so
both paths agree. The seed now covers the shipyard_neo browser tools
under the same capabilities gate the main agent uses, skips and logs
runtime tools that were deactivated, and an empty whitelist now flows
through the same construction instead of returning early, so it keeps
the runtime tools and an empty result still reaches the warning.
Unknown and inactive whitelist entries keep their warnings too.

Signed-off-by: Yufeng He <[email protected]>
@ngc7331

ngc7331 commented Oct 20, 2026

Copy link
Copy Markdown

Hi, I've recently encountered issue #10456 as well. I then found this PR and built a test docker image base on this. I can confirm the issue is resolved.

I installed living memory plugin which provides recall_long_term_memory tool. The experiment group excludes this tool using whitelist and the control group can use all tools.

With latest v4.29.1 release, the control group reports that it can see all 8 tools (7 built-in + 1 living memory), and the experiment group does not answer the main agent's query but gives this instead:

[23:18:01.652] [Core] [INFO] [runners.tool_loop_agent_runner:1438]: Tool `transfer_to_test` Result: <tool_use>
<tool_name>web_search_tavily</tool_name>
<parameters>
<query>AstrBot issue 10456 tool whitelist regression</query>
</parameters>
</tool_use>

Seems like the web_search_tavily tool is not found so the original tool-call schema is returned.

With this PR, the control group still sees all 8 tools, and the experiment group reports that is can see 7 tools, as expected.

Can we push this forward?

@he-yufeng

Copy link
Copy Markdown
Contributor Author

Thanks for building the image and running the experiment/control split — that is exactly the confirmation this needed, and the two groups showing the whitelist takes effect on v4.29.1 closes the loop on the fix.

On the web_search_tavily echo: when the subagent's whitelist hides the tool the runner has nothing to execute, so it surfaces the original tool_use block back to the caller, which looks like a missing tool rather than a denied one. That naming is a separate contract question from the whitelist itself (a denial message versus an unfound tool), and it is pre-existing on main. Happy to take it as a follow-up that reports an excluded tool explicitly instead of echoing the call, if the maintainers want that distinction here.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 工具白名单会一并关掉框架内置工具,且界面上无法选择内置工具

2 participants