Subagents PR 1: Feature flag + tool skeleton (#46186)
This PR adds the foundation for the subagents feature: - Add `SubagentsFeatureFlag` with staff-disabled default - Create `SubagentTool` struct with input schema for task/summary/context-low prompts - Register `SubagentTool` conditionally when feature flag is enabled - Tool returns stub message 'not yet implemented' for now Release Notes: - N/A --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: Mikayla Maki <mikayla@zed.dev> Co-authored-by: Yara <yara@zed.dev>
This commit is contained in:
6 files changed
+130
-4
No files matched your search
Generated
+1
@@ -172,6 +172,7 @@ dependencies = [
|
||||
"editor",
|
||||
"env_logger 0.11.8",
|
||||
"eval_utils",
|
||||
"feature_flags",
|
||||
"fs",
|
||||
"futures 0.3.31",
|
||||
"git",
|
||||
|
||||
@@ -32,6 +32,7 @@ collections.workspace = true
|
||||
context_server.workspace = true
|
||||
db.workspace = true
|
||||
derive_more.workspace = true
|
||||
feature_flags.workspace = true
|
||||
fs.workspace = true
|
||||
futures.workspace = true
|
||||
git.workspace = true
|
||||
|
||||
@@ -2,11 +2,12 @@ use crate::{
|
||||
ContextServerRegistry, CopyPathTool, CreateDirectoryTool, DbLanguageModel, DbThread,
|
||||
DeletePathTool, DiagnosticsTool, EditFileTool, FetchTool, FindPathTool, GrepTool,
|
||||
ListDirectoryTool, MovePathTool, NowTool, OpenTool, ProjectSnapshot, ReadFileTool,
|
||||
RestoreFileFromDiskTool, SaveFileTool, SystemPromptTemplate, Template, Templates, TerminalTool,
|
||||
ThinkingTool, WebSearchTool,
|
||||
RestoreFileFromDiskTool, SaveFileTool, SubagentTool, SystemPromptTemplate, Template, Templates,
|
||||
TerminalTool, ThinkingTool, WebSearchTool,
|
||||
};
|
||||
use acp_thread::{MentionUri, UserMessageId};
|
||||
use action_log::ActionLog;
|
||||
use feature_flags::{FeatureFlagAppExt as _, SubagentsFeatureFlag};
|
||||
|
||||
use agent_client_protocol as acp;
|
||||
use agent_settings::{
|
||||
@@ -1028,6 +1029,10 @@ impl Thread {
|
||||
self.add_tool(TerminalTool::new(self.project.clone(), environment));
|
||||
self.add_tool(ThinkingTool);
|
||||
self.add_tool(WebSearchTool);
|
||||
|
||||
if cx.has_flag::<SubagentsFeatureFlag>() {
|
||||
self.add_tool(SubagentTool::new());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_tool<T: AgentTool>(&mut self, tool: T) {
|
||||
|
||||
@@ -14,7 +14,7 @@ mod open_tool;
|
||||
mod read_file_tool;
|
||||
mod restore_file_from_disk_tool;
|
||||
mod save_file_tool;
|
||||
|
||||
mod subagent_tool;
|
||||
mod terminal_tool;
|
||||
mod thinking_tool;
|
||||
mod web_search_tool;
|
||||
@@ -38,7 +38,7 @@ pub use open_tool::*;
|
||||
pub use read_file_tool::*;
|
||||
pub use restore_file_from_disk_tool::*;
|
||||
pub use save_file_tool::*;
|
||||
|
||||
pub use subagent_tool::*;
|
||||
pub use terminal_tool::*;
|
||||
pub use thinking_tool::*;
|
||||
pub use web_search_tool::*;
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
use agent_client_protocol as acp;
|
||||
use anyhow::Result;
|
||||
use gpui::{App, SharedString, Task};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{AgentTool, ToolCallEventStream};
|
||||
|
||||
/// Spawns a subagent with its own context window to perform a delegated task.
|
||||
///
|
||||
/// Use this tool when you need to:
|
||||
/// - Perform research that would consume too many tokens in the main context
|
||||
/// - Execute a complex subtask independently
|
||||
/// - Run multiple parallel investigations
|
||||
///
|
||||
/// You control what the subagent does by providing:
|
||||
/// 1. A task prompt describing what the subagent should do
|
||||
/// 2. A summary prompt that tells the subagent how to summarize its work when done
|
||||
/// 3. A "context running out" prompt for when the subagent is low on tokens
|
||||
///
|
||||
/// The subagent has access to the same tools you do. You can optionally restrict
|
||||
/// which tools the subagent can use.
|
||||
///
|
||||
/// IMPORTANT:
|
||||
/// - Maximum 8 subagents can be spawned per turn
|
||||
/// - Subagents cannot use tools you don't have access to
|
||||
/// - If spawning multiple subagents that might write to the filesystem, provide
|
||||
/// guidance on how to avoid conflicts (e.g., assign each to different directories)
|
||||
/// - Instruct subagents to be concise in their summaries to conserve your context
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct SubagentToolInput {
|
||||
/// Short label displayed in the UI while the subagent runs (e.g., "Researching alternatives")
|
||||
pub label: String,
|
||||
|
||||
/// The initial prompt that tells the subagent what task to perform.
|
||||
/// Be specific about what you want the subagent to accomplish.
|
||||
pub task_prompt: String,
|
||||
|
||||
/// The prompt sent to the subagent when it completes its task, asking it
|
||||
/// to summarize what it did and return results. This summary becomes the
|
||||
/// tool result you receive.
|
||||
///
|
||||
/// Example: "Summarize what you found, listing the top 3 alternatives with pros/cons."
|
||||
pub summary_prompt: String,
|
||||
|
||||
/// The prompt sent if the subagent is running low on context (25% remaining).
|
||||
/// Should instruct it to stop and summarize progress so far, plus what's left undone.
|
||||
///
|
||||
/// Example: "Context is running low. Stop and summarize your progress so far,
|
||||
/// and list what remains to be investigated."
|
||||
pub context_low_prompt: String,
|
||||
|
||||
/// Optional: Maximum runtime in milliseconds. If exceeded, the subagent is
|
||||
/// asked to summarize and return. No timeout by default.
|
||||
#[serde(default)]
|
||||
pub timeout_ms: Option<u64>,
|
||||
|
||||
/// Optional: List of tool names the subagent is allowed to use.
|
||||
/// If not provided, the subagent can use all tools available to the parent.
|
||||
/// Tools listed here must be a subset of the parent's available tools.
|
||||
#[serde(default)]
|
||||
pub allowed_tools: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
pub struct SubagentTool;
|
||||
|
||||
impl SubagentTool {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
impl AgentTool for SubagentTool {
|
||||
type Input = SubagentToolInput;
|
||||
type Output = String;
|
||||
|
||||
fn name() -> &'static str {
|
||||
"subagent"
|
||||
}
|
||||
|
||||
fn kind() -> acp::ToolKind {
|
||||
acp::ToolKind::Other
|
||||
}
|
||||
|
||||
fn initial_title(
|
||||
&self,
|
||||
input: Result<Self::Input, serde_json::Value>,
|
||||
_cx: &mut App,
|
||||
) -> SharedString {
|
||||
match input {
|
||||
Ok(input) => format!("Subagent: {}", input.label).into(),
|
||||
Err(_) => "Subagent".into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn run(
|
||||
self: Arc<Self>,
|
||||
input: Self::Input,
|
||||
event_stream: ToolCallEventStream,
|
||||
_cx: &mut App,
|
||||
) -> Task<Result<String>> {
|
||||
event_stream.update_fields(
|
||||
acp::ToolCallUpdateFields::new()
|
||||
.content(vec![format!("Starting subagent: {}", input.label).into()]),
|
||||
);
|
||||
Task::ready(Ok("Subagent tool not yet implemented.".to_string()))
|
||||
}
|
||||
}
|
||||
@@ -35,3 +35,13 @@ pub struct AgentSharingFeatureFlag;
|
||||
impl FeatureFlag for AgentSharingFeatureFlag {
|
||||
const NAME: &'static str = "agent-sharing";
|
||||
}
|
||||
|
||||
pub struct SubagentsFeatureFlag;
|
||||
|
||||
impl FeatureFlag for SubagentsFeatureFlag {
|
||||
const NAME: &'static str = "subagents";
|
||||
|
||||
fn enabled_for_staff() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user