//! Subagent tool filtering: maps a subagent's allowed tool names to //! concrete Tool trait objects and OpenAI-style tool definitions. //! //! Flow: load `all_tools()` → if `allowed_tools` is empty, use all (minus //! orchestration tools `hive_mind` / `workflow_run`); else filter by //! membership → derive `ToolDef`s for the LLM request body. //! //! Orchestration tools are excluded from subagents because the subagent //! should not be able to spawn its own sub-subagents or run workflows. use crate::dto::provider::request::ToolDef; use crate::tool::{all_tools, tool_defs}; use tracing; /// Build the tool list for a subagent from its allowlist. /// /// Flow: /// 1. Load all available tools from `tool::all_tools()`. /// 2. If `allowed_tools` is empty (no restriction), include every tool /// except `hive_mind` and `workflow_run`. /// 3. Otherwise, filter by membership in `allowed_tools`, still excluding /// the two orchestration tools. /// 4. Derive OpenAI-compatible JSON schema definitions (`ToolDef`) from /// the filtered list. /// /// An empty allowlist means "no restriction" (matches /// `build_subagent_context`'s default for non-reviewer roles). /// /// Return: `(tool impls, schema defs)` for the subagent to use. pub(crate) fn build_subagent_tools( allowed_tools: &[String], ) -> (Vec>, Vec) { tracing::debug!("[subagent] building tools from {} allowed entries", allowed_tools.len()); // Load all registered tools from the global tool registry. let all = all_tools(); let total = all.len(); // Filter: empty allowlist = unrestricted (minus orchestration tools). // Otherwise, keep only tools in the allowlist. let filtered: Vec> = if allowed_tools.is_empty() { all.into_iter() .filter(|t| t.name() != "hive_mind" && t.name() != "workflow_run") .collect() } else { all.into_iter() .filter(|t| { allowed_tools.contains(&t.name().to_string()) && t.name() != "hive_mind" && t.name() != "workflow_run" }) .collect() }; tracing::debug!( "[subagent] filtered {} tools (from {total} total) for subagent", filtered.len(), ); // Generate OpenAI-compatible tool definitions for the LLM request. let defs = tool_defs(&filtered); (filtered, defs) }