mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-07-09 16:08:31 +00:00
parent
8a26b5c9a4
commit
9d7e131340
3 changed files with 27 additions and 7 deletions
|
|
@ -43,7 +43,7 @@ from deerflow.agents.thread_state import ThreadState
|
|||
from deerflow.config.agents_config import load_agent_config, validate_agent_name
|
||||
from deerflow.config.app_config import AppConfig, get_app_config
|
||||
from deerflow.models import create_chat_model
|
||||
from deerflow.skills.tool_policy import filter_tools_by_skill_allowed_tools
|
||||
from deerflow.skills.tool_policy import SKILL_LOADING_TOOL_NAMES, filter_tools_by_skill_allowed_tools
|
||||
from deerflow.skills.types import Skill
|
||||
from deerflow.tracing import build_tracing_callbacks
|
||||
|
||||
|
|
@ -504,7 +504,7 @@ def _make_lead_agent(config: RunnableConfig, *, app_config: AppConfig):
|
|||
# Keep the bootstrap skill set intentionally narrow so agent creation
|
||||
# remains deterministic before the custom agent's own config exists.
|
||||
raw_tools = get_available_tools(model_name=model_name, subagent_enabled=subagent_enabled, app_config=resolved_app_config) + [setup_agent]
|
||||
filtered = filter_tools_by_skill_allowed_tools(raw_tools, skills_for_tool_policy)
|
||||
filtered = filter_tools_by_skill_allowed_tools(raw_tools, skills_for_tool_policy, always_allowed_tool_names=SKILL_LOADING_TOOL_NAMES)
|
||||
final_tools, setup = assemble_deferred_tools(filtered, enabled=resolved_app_config.tool_search.enabled)
|
||||
return create_agent(
|
||||
model=create_chat_model(name=model_name, thinking_enabled=thinking_enabled, app_config=resolved_app_config, attach_tracing=False),
|
||||
|
|
@ -531,7 +531,7 @@ def _make_lead_agent(config: RunnableConfig, *, app_config: AppConfig):
|
|||
extra_tools = [update_agent] if agent_name else []
|
||||
# Default lead agent (unchanged behavior)
|
||||
raw_tools = get_available_tools(model_name=model_name, groups=agent_config.tool_groups if agent_config else None, subagent_enabled=subagent_enabled, app_config=resolved_app_config)
|
||||
filtered = filter_tools_by_skill_allowed_tools(raw_tools + extra_tools, skills_for_tool_policy)
|
||||
filtered = filter_tools_by_skill_allowed_tools(raw_tools + extra_tools, skills_for_tool_policy, always_allowed_tool_names=SKILL_LOADING_TOOL_NAMES)
|
||||
final_tools, setup = assemble_deferred_tools(filtered, enabled=resolved_app_config.tool_search.enabled)
|
||||
return create_agent(
|
||||
model=create_chat_model(name=model_name, thinking_enabled=thinking_enabled, reasoning_effort=reasoning_effort, app_config=resolved_app_config, attach_tracing=False),
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ class NamedTool(Protocol):
|
|||
name: str
|
||||
|
||||
|
||||
SKILL_LOADING_TOOL_NAMES = frozenset({"read_file"})
|
||||
|
||||
|
||||
def allowed_tool_names_for_skills(skills: list[Skill]) -> set[str] | None:
|
||||
"""Return the union of explicit skill allowed-tools declarations.
|
||||
|
||||
|
|
@ -36,9 +39,15 @@ def allowed_tool_names_for_skills(skills: list[Skill]) -> set[str] | None:
|
|||
return allowed
|
||||
|
||||
|
||||
def filter_tools_by_skill_allowed_tools[ToolT: NamedTool](tools: list[ToolT], skills: list[Skill]) -> list[ToolT]:
|
||||
def filter_tools_by_skill_allowed_tools[ToolT: NamedTool](
|
||||
tools: list[ToolT],
|
||||
skills: list[Skill],
|
||||
*,
|
||||
always_allowed_tool_names: set[str] | frozenset[str] = frozenset(),
|
||||
) -> list[ToolT]:
|
||||
allowed = allowed_tool_names_for_skills(skills)
|
||||
if allowed is None:
|
||||
return tools
|
||||
|
||||
return [tool for tool in tools if tool.name in allowed]
|
||||
allowed_with_framework_tools = allowed | set(always_allowed_tool_names)
|
||||
return [tool for tool in tools if tool.name in allowed_with_framework_tools]
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ def test_make_lead_agent_filters_tools_from_available_skills(monkeypatch):
|
|||
monkeypatch.setattr(lead_agent_module, "apply_prompt_template", lambda **kwargs: "mock_prompt")
|
||||
monkeypatch.setattr(lead_agent_module, "create_agent", lambda **kwargs: kwargs)
|
||||
monkeypatch.setattr(lead_agent_module, "load_agent_config", lambda x: AgentConfig(name="test", skills=["restricted", "legacy"]))
|
||||
monkeypatch.setattr(lead_agent_module, "_load_enabled_skills_for_tool_policy", lambda available_skills, *, app_config: [_make_skill("restricted", ["read_file"]), _make_skill("legacy", None)])
|
||||
monkeypatch.setattr(lead_agent_module, "_load_enabled_skills_for_tool_policy", lambda available_skills, *, app_config: [_make_skill("restricted", ["web_search"]), _make_skill("legacy", None)])
|
||||
monkeypatch.setattr("deerflow.tools.get_available_tools", lambda **kwargs: [NamedTool("bash"), NamedTool("read_file"), NamedTool("web_search")])
|
||||
|
||||
mock_app_config = MagicMock()
|
||||
|
|
@ -204,7 +204,18 @@ def test_make_lead_agent_filters_tools_from_available_skills(monkeypatch):
|
|||
|
||||
agent_kwargs = lead_agent_module.make_lead_agent({"configurable": {"agent_name": "test"}})
|
||||
|
||||
assert [tool.name for tool in agent_kwargs["tools"]] == ["read_file"]
|
||||
assert [tool.name for tool in agent_kwargs["tools"]] == ["read_file", "web_search"]
|
||||
|
||||
|
||||
def test_skill_allowed_tools_default_does_not_preserve_read_file_for_subagents():
|
||||
from deerflow.skills.tool_policy import filter_tools_by_skill_allowed_tools
|
||||
|
||||
tools = [NamedTool("read_file"), NamedTool("dataagent_query"), NamedTool("bash")]
|
||||
skills = [_make_skill("data-query", ["dataagent_query"])]
|
||||
|
||||
filtered = filter_tools_by_skill_allowed_tools(tools, skills)
|
||||
|
||||
assert [tool.name for tool in filtered] == ["dataagent_query"]
|
||||
|
||||
|
||||
def test_make_lead_agent_all_legacy_skills_preserve_all_tools(monkeypatch):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue