mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Rename multi-agent v2 assignment tool (#25267)
## Summary - rename the multi-agent v2 follow-up task tool surface to assign_task - update core tests and spec-plan expectations - keep rollout-trace classification backward-compatible with legacy followup_task ## Tests - just fmt - just test -p codex-core multi_agents_spec::tests::assign_task_tool_requires_message_and_has_no_output_schema - just test -p codex-rollout-trace - just fix -p codex-core - just fix -p codex-rollout-trace Note: a broad just test -p codex-core run was attempted locally, but this sandbox produced unrelated environment failures around sandbox-exec, missing test_stdio_server, and realtime timeouts.
This commit is contained in:
committed by
GitHub
Unverified
parent
3e7baa00e4
commit
8acaec73b6
@@ -179,7 +179,7 @@ pub fn create_send_message_tool() -> ToolSpec {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_followup_task_tool() -> ToolSpec {
|
||||
pub fn create_assign_task_tool() -> ToolSpec {
|
||||
let properties = BTreeMap::from([
|
||||
(
|
||||
"target".to_string(),
|
||||
@@ -196,7 +196,7 @@ pub fn create_followup_task_tool() -> ToolSpec {
|
||||
]);
|
||||
|
||||
ToolSpec::Function(ResponsesApiTool {
|
||||
name: "followup_task".to_string(),
|
||||
name: "assign_task".to_string(),
|
||||
description: "Send a message to an existing non-root target agent and trigger a turn in that target. If the target is currently mid-turn, the message is queued and will be used to start the target's next turn, after the current turn completes."
|
||||
.to_string(),
|
||||
strict: false,
|
||||
|
||||
@@ -247,15 +247,17 @@ fn send_message_tool_requires_message_and_has_no_output_schema() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn followup_task_tool_requires_message_and_has_no_output_schema() {
|
||||
fn assign_task_tool_requires_message_and_has_no_output_schema() {
|
||||
let ToolSpec::Function(ResponsesApiTool {
|
||||
name,
|
||||
parameters,
|
||||
output_schema,
|
||||
..
|
||||
}) = create_followup_task_tool()
|
||||
}) = create_assign_task_tool()
|
||||
else {
|
||||
panic!("followup_task should be a function tool");
|
||||
panic!("assign_task should be a function tool");
|
||||
};
|
||||
assert_eq!(name, "assign_task");
|
||||
assert_eq!(
|
||||
parameters.schema_type,
|
||||
Some(JsonSchemaType::Single(JsonSchemaPrimitiveType::Object))
|
||||
@@ -263,7 +265,7 @@ fn followup_task_tool_requires_message_and_has_no_output_schema() {
|
||||
let properties = parameters
|
||||
.properties
|
||||
.as_ref()
|
||||
.expect("followup_task should use object params");
|
||||
.expect("assign_task should use object params");
|
||||
assert!(properties.contains_key("target"));
|
||||
assert!(properties.contains_key("message"));
|
||||
assert!(!properties.contains_key("items"));
|
||||
|
||||
@@ -8,8 +8,8 @@ use crate::session::tests::make_session_and_context;
|
||||
use crate::session_prefix::format_subagent_notification_message;
|
||||
use crate::thread_manager::thread_store_from_config;
|
||||
use crate::tools::context::ToolOutput;
|
||||
use crate::tools::handlers::multi_agents_v2::AssignTaskHandler as AssignTaskHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::CloseAgentHandler as CloseAgentHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::FollowupTaskHandler as FollowupTaskHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::ListAgentsHandler as ListAgentsHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::SendMessageHandler as SendMessageHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::SpawnAgentHandler as SpawnAgentHandlerV2;
|
||||
@@ -1413,7 +1413,7 @@ async fn multi_agent_v2_send_message_accepts_root_target_from_child() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn multi_agent_v2_followup_task_rejects_root_target_from_child() {
|
||||
async fn multi_agent_v2_assign_task_rejects_root_target_from_child() {
|
||||
let (mut session, mut turn) = make_session_and_context().await;
|
||||
let manager = thread_manager();
|
||||
let root = manager
|
||||
@@ -1461,11 +1461,11 @@ async fn multi_agent_v2_followup_task_rejects_root_target_from_child() {
|
||||
agent_role: None,
|
||||
});
|
||||
|
||||
let Err(err) = FollowupTaskHandlerV2
|
||||
let Err(err) = AssignTaskHandlerV2
|
||||
.handle(invocation(
|
||||
Arc::new(session),
|
||||
Arc::new(turn),
|
||||
"followup_task",
|
||||
"assign_task",
|
||||
function_payload(json!({
|
||||
"target": "/root",
|
||||
"message": "run this",
|
||||
@@ -1473,7 +1473,7 @@ async fn multi_agent_v2_followup_task_rejects_root_target_from_child() {
|
||||
))
|
||||
.await
|
||||
else {
|
||||
panic!("followup_task should reject the root target");
|
||||
panic!("assign_task should reject the root target");
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
@@ -1868,7 +1868,7 @@ async fn multi_agent_v2_send_message_rejects_interrupt_parameter() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn() {
|
||||
async fn multi_agent_v2_assign_task_completion_notifies_parent_on_every_turn() {
|
||||
let (mut session, mut turn) = make_session_and_context().await;
|
||||
let manager = thread_manager();
|
||||
let root = manager
|
||||
@@ -1923,18 +1923,18 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
|
||||
)
|
||||
.await;
|
||||
|
||||
FollowupTaskHandlerV2
|
||||
AssignTaskHandlerV2
|
||||
.handle(invocation(
|
||||
session,
|
||||
turn,
|
||||
"followup_task",
|
||||
"assign_task",
|
||||
function_payload(json!({
|
||||
"target": agent_id.to_string(),
|
||||
"message": "continue",
|
||||
})),
|
||||
))
|
||||
.await
|
||||
.expect("followup_task should succeed");
|
||||
.expect("assign_task should succeed");
|
||||
|
||||
let second_turn = thread.codex.session.new_default_turn().await;
|
||||
thread
|
||||
@@ -2003,7 +2003,7 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn multi_agent_v2_followup_task_rejects_legacy_items_field() {
|
||||
async fn multi_agent_v2_assign_task_rejects_legacy_items_field() {
|
||||
let (mut session, mut turn) = make_session_and_context().await;
|
||||
let manager = thread_manager();
|
||||
let root = manager
|
||||
@@ -2039,14 +2039,14 @@ async fn multi_agent_v2_followup_task_rejects_legacy_items_field() {
|
||||
let invocation = invocation(
|
||||
session,
|
||||
turn,
|
||||
"followup_task",
|
||||
"assign_task",
|
||||
function_payload(json!({
|
||||
"target": agent_id.to_string(),
|
||||
"items": [{"type": "text", "text": "continue"}],
|
||||
})),
|
||||
);
|
||||
|
||||
let Err(err) = FollowupTaskHandlerV2.handle(invocation).await else {
|
||||
let Err(err) = AssignTaskHandlerV2.handle(invocation).await else {
|
||||
panic!("legacy items field should be rejected in v2");
|
||||
};
|
||||
let FunctionCallError::RespondToModel(message) = err else {
|
||||
|
||||
@@ -28,15 +28,15 @@ use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
pub(crate) use assign_task::Handler as AssignTaskHandler;
|
||||
pub(crate) use close_agent::Handler as CloseAgentHandler;
|
||||
pub(crate) use followup_task::Handler as FollowupTaskHandler;
|
||||
pub(crate) use list_agents::Handler as ListAgentsHandler;
|
||||
pub(crate) use send_message::Handler as SendMessageHandler;
|
||||
pub(crate) use spawn::Handler as SpawnAgentHandler;
|
||||
pub(crate) use wait::Handler as WaitAgentHandler;
|
||||
|
||||
mod assign_task;
|
||||
mod close_agent;
|
||||
mod followup_task;
|
||||
mod list_agents;
|
||||
mod message_tool;
|
||||
mod send_message;
|
||||
|
||||
+5
-5
@@ -1,8 +1,8 @@
|
||||
use super::message_tool::FollowupTaskArgs;
|
||||
use super::message_tool::AssignTaskArgs;
|
||||
use super::message_tool::MessageDeliveryMode;
|
||||
use super::message_tool::handle_message_string_tool;
|
||||
use super::*;
|
||||
use crate::tools::handlers::multi_agents_spec::create_followup_task_tool;
|
||||
use crate::tools::handlers::multi_agents_spec::create_assign_task_tool;
|
||||
use codex_tools::ToolSpec;
|
||||
|
||||
pub(crate) struct Handler;
|
||||
@@ -10,11 +10,11 @@ pub(crate) struct Handler;
|
||||
#[async_trait::async_trait]
|
||||
impl ToolExecutor<ToolInvocation> for Handler {
|
||||
fn tool_name(&self) -> ToolName {
|
||||
ToolName::plain("followup_task")
|
||||
ToolName::plain("assign_task")
|
||||
}
|
||||
|
||||
fn spec(&self) -> ToolSpec {
|
||||
create_followup_task_tool()
|
||||
create_assign_task_tool()
|
||||
}
|
||||
|
||||
async fn handle(
|
||||
@@ -22,7 +22,7 @@ impl ToolExecutor<ToolInvocation> for Handler {
|
||||
invocation: ToolInvocation,
|
||||
) -> Result<Box<dyn crate::tools::context::ToolOutput>, FunctionCallError> {
|
||||
let arguments = function_arguments(invocation.payload.clone())?;
|
||||
let args: FollowupTaskArgs = parse_arguments(&arguments)?;
|
||||
let args: AssignTaskArgs = parse_arguments(&arguments)?;
|
||||
handle_message_string_tool(
|
||||
invocation,
|
||||
MessageDeliveryMode::TriggerTurn,
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Shared argument parsing and dispatch for the v2 text-only agent messaging tools.
|
||||
//!
|
||||
//! `send_message` and `followup_task` share the same submission path and differ only in whether the
|
||||
//! `send_message` and `assign_task` share the same submission path and differ only in whether the
|
||||
//! resulting `InterAgentCommunication` should wake the target immediately.
|
||||
|
||||
use super::*;
|
||||
@@ -40,8 +40,8 @@ pub(crate) struct SendMessageArgs {
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
/// Input for the MultiAgentV2 `followup_task` tool.
|
||||
pub(crate) struct FollowupTaskArgs {
|
||||
/// Input for the MultiAgentV2 `assign_task` tool.
|
||||
pub(crate) struct AssignTaskArgs {
|
||||
pub(crate) target: String,
|
||||
pub(crate) message: String,
|
||||
}
|
||||
@@ -55,7 +55,7 @@ fn message_content(message: String) -> Result<String, FunctionCallError> {
|
||||
Ok(message)
|
||||
}
|
||||
|
||||
/// Handles the shared MultiAgentV2 plain-text message flow for both `send_message` and `followup_task`.
|
||||
/// Handles the shared MultiAgentV2 plain-text message flow for both `send_message` and `assign_task`.
|
||||
pub(crate) async fn handle_message_string_tool(
|
||||
invocation: ToolInvocation,
|
||||
mode: MessageDeliveryMode,
|
||||
|
||||
@@ -38,8 +38,8 @@ use crate::tools::handlers::multi_agents_common::MAX_WAIT_TIMEOUT_MS;
|
||||
use crate::tools::handlers::multi_agents_common::MIN_WAIT_TIMEOUT_MS;
|
||||
use crate::tools::handlers::multi_agents_spec::SpawnAgentToolOptions;
|
||||
use crate::tools::handlers::multi_agents_spec::WaitAgentTimeoutOptions;
|
||||
use crate::tools::handlers::multi_agents_v2::AssignTaskHandler as AssignTaskHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::CloseAgentHandler as CloseAgentHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::FollowupTaskHandler as FollowupTaskHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::ListAgentsHandler as ListAgentsHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::SendMessageHandler as SendMessageHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::SpawnAgentHandler as SpawnAgentHandlerV2;
|
||||
@@ -686,7 +686,7 @@ fn add_collaboration_tools(context: &CoreToolPlanContext<'_>, planned_tools: &mu
|
||||
exposure,
|
||||
));
|
||||
planned_tools.add_arc(override_tool_exposure(
|
||||
multi_agent_v2_handler(FollowupTaskHandlerV2, tool_namespace),
|
||||
multi_agent_v2_handler(AssignTaskHandlerV2, tool_namespace),
|
||||
exposure,
|
||||
));
|
||||
planned_tools.add_arc(override_tool_exposure(
|
||||
|
||||
@@ -766,7 +766,7 @@ async fn multi_agent_feature_selects_one_agent_tool_family() {
|
||||
"wait_agent",
|
||||
"close_agent",
|
||||
"send_message",
|
||||
"followup_task",
|
||||
"assign_task",
|
||||
"list_agents",
|
||||
]);
|
||||
assert_eq!(
|
||||
@@ -790,7 +790,7 @@ async fn multi_agent_feature_selects_one_agent_tool_family() {
|
||||
v2.assert_visible_contains(&[
|
||||
"spawn_agent",
|
||||
"send_message",
|
||||
"followup_task",
|
||||
"assign_task",
|
||||
"wait_agent",
|
||||
"close_agent",
|
||||
"list_agents",
|
||||
@@ -895,7 +895,7 @@ async fn multi_agent_v2_can_use_configured_tool_namespace() {
|
||||
for tool_name in [
|
||||
"spawn_agent",
|
||||
"send_message",
|
||||
"followup_task",
|
||||
"assign_task",
|
||||
"wait_agent",
|
||||
"close_agent",
|
||||
"list_agents",
|
||||
@@ -969,7 +969,7 @@ async fn code_mode_only_can_expose_namespaced_multi_agent_v2_as_normal_tools() {
|
||||
for tool_name in [
|
||||
"spawn_agent",
|
||||
"send_message",
|
||||
"followup_task",
|
||||
"assign_task",
|
||||
"wait_agent",
|
||||
"close_agent",
|
||||
"list_agents",
|
||||
|
||||
@@ -177,7 +177,7 @@ the edges between them.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
RootTool["root ToolCall\nspawn_agent / followup_task / send_message"]
|
||||
RootTool["root ToolCall\nspawn_agent / assign_task / send_message"]
|
||||
ChildInput["child ConversationItem\ninjected task/message"]
|
||||
ChildThread["child AgentThread"]
|
||||
ChildResult["child assistant ConversationItem\nresult message"]
|
||||
|
||||
@@ -267,7 +267,7 @@ fn dispatched_tool_kind(tool_name: &str, _payload: &ToolDispatchPayload) -> Tool
|
||||
"image_generation" | "image_query" => ToolCallKind::ImageGeneration,
|
||||
"spawn_agent" => ToolCallKind::SpawnAgent,
|
||||
"send_message" => ToolCallKind::SendMessage,
|
||||
"followup_task" => ToolCallKind::AssignAgentTask,
|
||||
"assign_task" | "followup_task" => ToolCallKind::AssignAgentTask,
|
||||
"wait_agent" => ToolCallKind::WaitAgent,
|
||||
"close_agent" => ToolCallKind::CloseAgent,
|
||||
other => ToolCallKind::Other {
|
||||
|
||||
Reference in New Issue
Block a user