diff --git a/crates/goose/src/agents/agent.rs b/crates/goose/src/agents/agent.rs index 0cf3515929aa..8dc45289c39a 100644 --- a/crates/goose/src/agents/agent.rs +++ b/crates/goose/src/agents/agent.rs @@ -449,21 +449,10 @@ impl Agent { ); } }; - let session = match session.as_ref() { - Some(s) => s, - None => { - return ( - request_id, - Err(ErrorData::new( - ErrorCode::INTERNAL_ERROR, - "Session is required".to_string(), - None, - )), - ); - } + let (parent_session_id, parent_working_dir) = match session.as_ref() { + Some(s) => (Some(s.id.clone()), s.working_dir.clone()), + None => (None, std::env::current_dir().unwrap_or_default()), }; - let parent_session_id = session.id.to_string(); - let parent_working_dir = session.working_dir.clone(); // Get extensions from the agent's runtime state rather than global config // This ensures subagents inherit extensions that were dynamically enabled by the parent diff --git a/crates/goose/src/agents/subagent_handler.rs b/crates/goose/src/agents/subagent_handler.rs index ad14f282f1b7..5359573fe248 100644 --- a/crates/goose/src/agents/subagent_handler.rs +++ b/crates/goose/src/agents/subagent_handler.rs @@ -1,5 +1,8 @@ use crate::{ - agents::{subagent_task_config::TaskConfig, AgentEvent, SessionConfig}, + agents::{ + extension::PlatformExtensionContext, subagent_task_config::TaskConfig, Agent, AgentEvent, + SessionConfig, + }, conversation::{message::Message, Conversation}, execution::manager::AgentManager, session::SessionManager, @@ -7,8 +10,8 @@ use crate::{ use anyhow::{anyhow, Result}; use futures::StreamExt; use rmcp::model::{ErrorCode, ErrorData}; -use std::future::Future; use std::pin::Pin; +use std::{future::Future, sync::Arc}; use tracing::debug; /// Standalone function to run a complete subagent task with output options @@ -101,17 +104,35 @@ fn get_agent_messages( .map_err(|e| anyhow!("Failed to create AgentManager: {}", e))?; let parent_session_id = task_config.parent_session_id; let working_dir = task_config.parent_working_dir; - let session = SessionManager::create_session( - working_dir.clone(), - format!("Subagent task for: {}", parent_session_id), - ) - .await - .map_err(|e| anyhow!("Failed to create a session for sub agent: {}", e))?; + let (agent, session_id) = match parent_session_id { + Some(parent_session_id) => { + let session = SessionManager::create_session( + working_dir.clone(), + format!("Subagent task for: {}", parent_session_id), + ) + .await + .map_err(|e| anyhow!("Failed to create a session for sub agent: {}", e))?; + + let agent = agent_manager + .get_or_create_agent(session.id.clone()) + .await + .map_err(|e| anyhow!("Failed to get sub agent session file path: {}", e))?; + (agent, Some(session.id)) + } + None => { + let agent = Arc::new(Agent::new()); + agent + .extension_manager + .set_context(PlatformExtensionContext { + session_id: None, + extension_manager: Some(Arc::downgrade(&agent.extension_manager)), + tool_route_manager: Some(Arc::downgrade(&agent.tool_route_manager)), + }) + .await; + (agent, None) + } + }; - let agent = agent_manager - .get_or_create_agent(session.id.clone()) - .await - .map_err(|e| anyhow!("Failed to get sub agent session file path: {}", e))?; agent .update_provider(task_config.provider) .await @@ -131,17 +152,20 @@ fn get_agent_messages( Conversation::new_unvalidated( vec![Message::user().with_text(text_instruction.clone())], ); - let session_config = SessionConfig { - id: session.id, - working_dir, - schedule_id: None, - execution_mode: None, - max_turns: task_config.max_turns.map(|v| v as u32), - retry_config: None, + let session_config = if let Some(session_id) = session_id { + Some(SessionConfig { + id: session_id, + working_dir, + schedule_id: None, + execution_mode: None, + max_turns: task_config.max_turns.map(|v| v as u32), + retry_config: None, + }) + } else { + None }; - let mut stream = agent - .reply(conversation.clone(), Some(session_config), None) + .reply(conversation.clone(), session_config, None) .await .map_err(|e| anyhow!("Failed to get reply from agent: {}", e))?; while let Some(message_result) = stream.next().await { diff --git a/crates/goose/src/agents/subagent_task_config.rs b/crates/goose/src/agents/subagent_task_config.rs index 3cafea2b8351..d3375c92be30 100644 --- a/crates/goose/src/agents/subagent_task_config.rs +++ b/crates/goose/src/agents/subagent_task_config.rs @@ -15,7 +15,7 @@ pub const GOOSE_SUBAGENT_MAX_TURNS_ENV_VAR: &str = "GOOSE_SUBAGENT_MAX_TURNS"; #[derive(Clone)] pub struct TaskConfig { pub provider: Arc, - pub parent_session_id: String, + pub parent_session_id: Option, pub parent_working_dir: PathBuf, pub extensions: Vec, pub max_turns: Option, @@ -37,7 +37,7 @@ impl TaskConfig { /// Create a new TaskConfig with all required dependencies pub fn new( provider: Arc, - parent_session_id: String, + parent_session_id: Option, parent_working_dir: PathBuf, extensions: Vec, ) -> Self {