Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion codex-rs/core/src/agent/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,12 @@ impl AgentControl {
/// Interrupt the current task for an existing agent thread.
pub(crate) async fn interrupt_agent(&self, agent_id: ThreadId) -> CodexResult<String> {
let state = self.upgrade()?;
state.send_op(agent_id, Op::Interrupt).await
self.handle_thread_request_result(
agent_id,
&state,
state.send_op(agent_id, Op::Interrupt).await,
)
.await
}

async fn handle_thread_request_result(
Expand Down Expand Up @@ -232,6 +237,12 @@ impl AgentControl {
self.state.agent_metadata_for_thread(agent_id)
}

pub(crate) fn ensure_agent_known(&self, agent_id: ThreadId) -> CodexResult<AgentMetadata> {
self.state
.agent_metadata_for_thread(agent_id)
.ok_or(CodexErr::ThreadNotFound(agent_id))
}

pub(crate) async fn list_live_agent_subtree_thread_ids(
&self,
agent_id: ThreadId,
Expand Down
20 changes: 12 additions & 8 deletions codex-rs/core/src/tools/handlers/multi_agents_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,26 +302,30 @@ pub fn create_close_agent_tool_v1() -> ToolSpec {
strict: false,
defer_loading: None,
parameters: JsonSchema::object(properties, Some(vec!["target".to_string()]), Some(false.into())),
output_schema: Some(close_agent_output_schema()),
output_schema: Some(agent_previous_status_output_schema(
"The agent status observed before shutdown was requested.",
)),
})],
})
}

pub fn create_close_agent_tool_v2() -> ToolSpec {
pub fn create_interrupt_agent_tool_v2() -> ToolSpec {
let properties = BTreeMap::from([(
"target".to_string(),
JsonSchema::string(Some(
"Agent id or canonical task name to close (from spawn_agent).".to_string(),
"Agent id or canonical task name to interrupt (from spawn_agent).".to_string(),
)),
)]);

ToolSpec::Function(ResponsesApiTool {
name: "close_agent".to_string(),
description: "Close an agent and any open descendants when they are no longer needed, and return the target agent's previous status before shutdown was requested. Completed agents remain open and count toward the concurrency limit until closed. Don't keep agents open for too long if they are not needed anymore.".to_string(),
name: "interrupt_agent".to_string(),
description: "Interrupt an agent's current turn, if any, and return its previous status. The agent remains available for messages and follow-up tasks.".to_string(),
strict: false,
defer_loading: None,
parameters: JsonSchema::object(properties, Some(vec!["target".to_string()]), Some(false.into())),
output_schema: Some(close_agent_output_schema()),
output_schema: Some(agent_previous_status_output_schema(
"The agent status observed before the interrupt request was handled.",
)),
})
}

Expand Down Expand Up @@ -501,12 +505,12 @@ fn wait_output_schema_v2() -> Value {
})
}

fn close_agent_output_schema() -> Value {
fn agent_previous_status_output_schema(previous_status_description: &str) -> Value {
json!({
"type": "object",
"properties": {
"previous_status": {
"description": "The agent status observed before shutdown was requested.",
"description": previous_status_description,
"allOf": [agent_status_output_schema()]
}
},
Expand Down
Loading
Loading