fix(core): enforce persona tool boundaries#8786
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors tool filtering and handoff toolset building to ensure permission guards are preserved and persona-specific tool restrictions are correctly applied. Specifically, _build_handoff_toolset now retrieves tools from the full toolset to maintain permission guards, and build_main_agent filters out tools not allowed by the selected persona. Additionally, corresponding unit tests have been added. Feedback on the changes includes a recommendation to optimize the tool filtering logic in build_main_agent to O(N) complexity and a suggestion to add a null check in the new unit test's finally block to prevent AttributeError from masking assertion failures.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| result.provider_request.func_tool.empty() | ||
| ) | ||
| finally: | ||
| if result.reset_coro: |
There was a problem hiding this comment.
If build_main_agent returns None (e.g., due to a configuration or provider resolution failure), result will be None. In the finally block, attempting to access result.reset_coro will raise an AttributeError, which masks the actual test assertion failure (assert result is not None). Adding a null check for result prevents this masking.
| if result.reset_coro: | |
| if result and result.reset_coro: |
| if persona_allowed_tools is not None and req.func_tool: | ||
| for tool in list(req.func_tool): | ||
| if tool.name not in persona_allowed_tools: | ||
| req.func_tool.remove_tool(tool.name) |
There was a problem hiding this comment.
Instead of iterating over the tools and calling remove_tool (which performs a list comprehension internally on every call, leading to tools list in-place in a single
| if persona_allowed_tools is not None and req.func_tool: | |
| for tool in list(req.func_tool): | |
| if tool.name not in persona_allowed_tools: | |
| req.func_tool.remove_tool(tool.name) | |
| if persona_allowed_tools is not None and req.func_tool: | |
| req.func_tool.tools = [ | |
| tool for tool in req.func_tool.tools | |
| if tool.name in persona_allowed_tools | |
| ] |
|
The failing unit job is the FastAPI 0.137 route-introspection issue, not this patch. The log has the same two failures fixed separately in #8783:
Both fail because FastAPI now leaves an #8783 is scoped to that test compatibility issue and its full CI is green. I am keeping this branch focused on the persona/tool-boundary fix instead of mixing the unrelated test stabilization into it. |
Summary
tools=nullaligned with the normal tool manager path so non-builtin tools stay permission-guardedtools=[]late-injection pathFixes #8780.
Fixes #8781.
To verify
python -m py_compile astrbot/core/astr_agent_tool_exec.py astrbot/core/astr_main_agent.py tests/unit/test_astr_agent_tool_exec.py tests/unit/test_astr_main_agent.pypython -m pytest tests/unit/test_astr_agent_tool_exec.py::test_build_handoff_toolset_keeps_permission_guards_for_default_tools tests/unit/test_astr_main_agent.py::TestEnsurePersonaAndSkills::test_persona_empty_tools_filters_late_builtin_tools -qpython -m pytest tests/unit/test_astr_agent_tool_exec.py -qpython -m pytest tests/unit/test_astr_main_agent.py -q -k "persona or web_search or proactive_cron or plugin_tool_fix"python -m ruff check astrbot/core/astr_agent_tool_exec.py astrbot/core/astr_main_agent.py tests/unit/test_astr_agent_tool_exec.py tests/unit/test_astr_main_agent.pypython -m ruff format --check astrbot/core/astr_agent_tool_exec.py astrbot/core/astr_main_agent.py tests/unit/test_astr_agent_tool_exec.py tests/unit/test_astr_main_agent.pygit diff --checkNote
A full local
tests/unit/test_astr_main_agent.pyrun still hits unrelated Windows path-separator expectations in the existing video attachment tests. The targeted persona, tool injection, handoff, ruff, py_compile, and whitespace checks above pass.Summary by Sourcery
Enforce persona tool restrictions and preserve permission guards when building toolsets for main agents and subagents.
Bug Fixes:
Tests: