mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Rename multi-agent wait tool to wait_agent (#14631)
- rename the multi-agent tool name the model sees to wait_agent - update the model-facing prompts and tool descriptions to match --------- Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
6720caf778
commit
cfd97b36da
@@ -52,7 +52,7 @@ pub(crate) use close_agent::Handler as CloseAgentHandler;
|
||||
pub(crate) use resume_agent::Handler as ResumeAgentHandler;
|
||||
pub(crate) use send_input::Handler as SendInputHandler;
|
||||
pub(crate) use spawn::Handler as SpawnAgentHandler;
|
||||
pub(crate) use wait::Handler as WaitHandler;
|
||||
pub(crate) use wait::Handler as WaitAgentHandler;
|
||||
|
||||
/// Minimum wait timeout to prevent tight polling loops from burning CPU.
|
||||
pub(crate) const MIN_WAIT_TIMEOUT_MS: i64 = 10_000;
|
||||
|
||||
@@ -14,7 +14,7 @@ pub(crate) struct Handler;
|
||||
|
||||
#[async_trait]
|
||||
impl ToolHandler for Handler {
|
||||
type Output = WaitResult;
|
||||
type Output = WaitAgentResult;
|
||||
|
||||
fn kind(&self) -> ToolKind {
|
||||
ToolKind::Function
|
||||
@@ -153,7 +153,7 @@ impl ToolHandler for Handler {
|
||||
|
||||
let statuses_map = statuses.clone().into_iter().collect::<HashMap<_, _>>();
|
||||
let agent_statuses = build_wait_agent_statuses(&statuses_map, &receiver_agents);
|
||||
let result = WaitResult {
|
||||
let result = WaitAgentResult {
|
||||
status: statuses_map.clone(),
|
||||
timed_out: statuses.is_empty(),
|
||||
};
|
||||
@@ -182,14 +182,14 @@ struct WaitArgs {
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub(crate) struct WaitResult {
|
||||
pub(crate) struct WaitAgentResult {
|
||||
pub(crate) status: HashMap<ThreadId, AgentStatus>,
|
||||
pub(crate) timed_out: bool,
|
||||
}
|
||||
|
||||
impl ToolOutput for WaitResult {
|
||||
impl ToolOutput for WaitAgentResult {
|
||||
fn log_preview(&self) -> String {
|
||||
tool_output_json_text(self, "wait")
|
||||
tool_output_json_text(self, "wait_agent")
|
||||
}
|
||||
|
||||
fn success_for_logging(&self) -> bool {
|
||||
@@ -197,11 +197,11 @@ impl ToolOutput for WaitResult {
|
||||
}
|
||||
|
||||
fn to_response_item(&self, call_id: &str, payload: &ToolPayload) -> ResponseInputItem {
|
||||
tool_output_response_item(call_id, payload, self, None, "wait")
|
||||
tool_output_response_item(call_id, payload, self, None, "wait_agent")
|
||||
}
|
||||
|
||||
fn code_mode_result(&self, _payload: &ToolPayload) -> JsonValue {
|
||||
tool_output_code_mode_result(self, "wait")
|
||||
tool_output_code_mode_result(self, "wait_agent")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -737,18 +737,18 @@ async fn resume_agent_rejects_when_depth_limit_exceeded() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn wait_rejects_non_positive_timeout() {
|
||||
async fn wait_agent_rejects_non_positive_timeout() {
|
||||
let (session, turn) = make_session_and_context().await;
|
||||
let invocation = invocation(
|
||||
Arc::new(session),
|
||||
Arc::new(turn),
|
||||
"wait",
|
||||
"wait_agent",
|
||||
function_payload(json!({
|
||||
"ids": [ThreadId::new().to_string()],
|
||||
"timeout_ms": 0
|
||||
})),
|
||||
);
|
||||
let Err(err) = WaitHandler.handle(invocation).await else {
|
||||
let Err(err) = WaitAgentHandler.handle(invocation).await else {
|
||||
panic!("non-positive timeout should be rejected");
|
||||
};
|
||||
assert_eq!(
|
||||
@@ -758,15 +758,15 @@ async fn wait_rejects_non_positive_timeout() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn wait_rejects_invalid_id() {
|
||||
async fn wait_agent_rejects_invalid_id() {
|
||||
let (session, turn) = make_session_and_context().await;
|
||||
let invocation = invocation(
|
||||
Arc::new(session),
|
||||
Arc::new(turn),
|
||||
"wait",
|
||||
"wait_agent",
|
||||
function_payload(json!({"ids": ["invalid"]})),
|
||||
);
|
||||
let Err(err) = WaitHandler.handle(invocation).await else {
|
||||
let Err(err) = WaitAgentHandler.handle(invocation).await else {
|
||||
panic!("invalid id should be rejected");
|
||||
};
|
||||
let FunctionCallError::RespondToModel(msg) = err else {
|
||||
@@ -776,15 +776,15 @@ async fn wait_rejects_invalid_id() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn wait_rejects_empty_ids() {
|
||||
async fn wait_agent_rejects_empty_ids() {
|
||||
let (session, turn) = make_session_and_context().await;
|
||||
let invocation = invocation(
|
||||
Arc::new(session),
|
||||
Arc::new(turn),
|
||||
"wait",
|
||||
"wait_agent",
|
||||
function_payload(json!({"ids": []})),
|
||||
);
|
||||
let Err(err) = WaitHandler.handle(invocation).await else {
|
||||
let Err(err) = WaitAgentHandler.handle(invocation).await else {
|
||||
panic!("empty ids should be rejected");
|
||||
};
|
||||
assert_eq!(
|
||||
@@ -794,7 +794,7 @@ async fn wait_rejects_empty_ids() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn wait_returns_not_found_for_missing_agents() {
|
||||
async fn wait_agent_returns_not_found_for_missing_agents() {
|
||||
let (mut session, turn) = make_session_and_context().await;
|
||||
let manager = thread_manager();
|
||||
session.services.agent_control = manager.agent_control();
|
||||
@@ -803,22 +803,22 @@ async fn wait_returns_not_found_for_missing_agents() {
|
||||
let invocation = invocation(
|
||||
Arc::new(session),
|
||||
Arc::new(turn),
|
||||
"wait",
|
||||
"wait_agent",
|
||||
function_payload(json!({
|
||||
"ids": [id_a.to_string(), id_b.to_string()],
|
||||
"timeout_ms": 1000
|
||||
})),
|
||||
);
|
||||
let output = WaitHandler
|
||||
let output = WaitAgentHandler
|
||||
.handle(invocation)
|
||||
.await
|
||||
.expect("wait should succeed");
|
||||
.expect("wait_agent should succeed");
|
||||
let (content, success) = expect_text_output(output);
|
||||
let result: wait::WaitResult =
|
||||
serde_json::from_str(&content).expect("wait result should be json");
|
||||
let result: wait::WaitAgentResult =
|
||||
serde_json::from_str(&content).expect("wait_agent result should be json");
|
||||
assert_eq!(
|
||||
result,
|
||||
wait::WaitResult {
|
||||
wait::WaitAgentResult {
|
||||
status: HashMap::from([(id_a, AgentStatus::NotFound), (id_b, AgentStatus::NotFound),]),
|
||||
timed_out: false
|
||||
}
|
||||
@@ -827,7 +827,7 @@ async fn wait_returns_not_found_for_missing_agents() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn wait_times_out_when_status_is_not_final() {
|
||||
async fn wait_agent_times_out_when_status_is_not_final() {
|
||||
let (mut session, turn) = make_session_and_context().await;
|
||||
let manager = thread_manager();
|
||||
session.services.agent_control = manager.agent_control();
|
||||
@@ -837,22 +837,22 @@ async fn wait_times_out_when_status_is_not_final() {
|
||||
let invocation = invocation(
|
||||
Arc::new(session),
|
||||
Arc::new(turn),
|
||||
"wait",
|
||||
"wait_agent",
|
||||
function_payload(json!({
|
||||
"ids": [agent_id.to_string()],
|
||||
"timeout_ms": MIN_WAIT_TIMEOUT_MS
|
||||
})),
|
||||
);
|
||||
let output = WaitHandler
|
||||
let output = WaitAgentHandler
|
||||
.handle(invocation)
|
||||
.await
|
||||
.expect("wait should succeed");
|
||||
.expect("wait_agent should succeed");
|
||||
let (content, success) = expect_text_output(output);
|
||||
let result: wait::WaitResult =
|
||||
serde_json::from_str(&content).expect("wait result should be json");
|
||||
let result: wait::WaitAgentResult =
|
||||
serde_json::from_str(&content).expect("wait_agent result should be json");
|
||||
assert_eq!(
|
||||
result,
|
||||
wait::WaitResult {
|
||||
wait::WaitAgentResult {
|
||||
status: HashMap::new(),
|
||||
timed_out: true
|
||||
}
|
||||
@@ -867,7 +867,7 @@ async fn wait_times_out_when_status_is_not_final() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn wait_clamps_short_timeouts_to_minimum() {
|
||||
async fn wait_agent_clamps_short_timeouts_to_minimum() {
|
||||
let (mut session, turn) = make_session_and_context().await;
|
||||
let manager = thread_manager();
|
||||
session.services.agent_control = manager.agent_control();
|
||||
@@ -877,17 +877,21 @@ async fn wait_clamps_short_timeouts_to_minimum() {
|
||||
let invocation = invocation(
|
||||
Arc::new(session),
|
||||
Arc::new(turn),
|
||||
"wait",
|
||||
"wait_agent",
|
||||
function_payload(json!({
|
||||
"ids": [agent_id.to_string()],
|
||||
"timeout_ms": 10
|
||||
})),
|
||||
);
|
||||
|
||||
let early = timeout(Duration::from_millis(50), WaitHandler.handle(invocation)).await;
|
||||
let early = timeout(
|
||||
Duration::from_millis(50),
|
||||
WaitAgentHandler.handle(invocation),
|
||||
)
|
||||
.await;
|
||||
assert!(
|
||||
early.is_err(),
|
||||
"wait should not return before the minimum timeout clamp"
|
||||
"wait_agent should not return before the minimum timeout clamp"
|
||||
);
|
||||
|
||||
let _ = thread
|
||||
@@ -898,7 +902,7 @@ async fn wait_clamps_short_timeouts_to_minimum() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn wait_returns_final_status_without_timeout() {
|
||||
async fn wait_agent_returns_final_status_without_timeout() {
|
||||
let (mut session, turn) = make_session_and_context().await;
|
||||
let manager = thread_manager();
|
||||
session.services.agent_control = manager.agent_control();
|
||||
@@ -923,22 +927,22 @@ async fn wait_returns_final_status_without_timeout() {
|
||||
let invocation = invocation(
|
||||
Arc::new(session),
|
||||
Arc::new(turn),
|
||||
"wait",
|
||||
"wait_agent",
|
||||
function_payload(json!({
|
||||
"ids": [agent_id.to_string()],
|
||||
"timeout_ms": 1000
|
||||
})),
|
||||
);
|
||||
let output = WaitHandler
|
||||
let output = WaitAgentHandler
|
||||
.handle(invocation)
|
||||
.await
|
||||
.expect("wait should succeed");
|
||||
.expect("wait_agent should succeed");
|
||||
let (content, success) = expect_text_output(output);
|
||||
let result: wait::WaitResult =
|
||||
serde_json::from_str(&content).expect("wait result should be json");
|
||||
let result: wait::WaitAgentResult =
|
||||
serde_json::from_str(&content).expect("wait_agent result should be json");
|
||||
assert_eq!(
|
||||
result,
|
||||
wait::WaitResult {
|
||||
wait::WaitAgentResult {
|
||||
status: HashMap::from([(agent_id, AgentStatus::Shutdown)]),
|
||||
timed_out: false
|
||||
}
|
||||
|
||||
@@ -1053,7 +1053,7 @@ fn create_spawn_agent_tool(config: &ToolsConfig) -> ToolSpec {
|
||||
- For code-edit subtasks, decompose work so each delegated task has a disjoint write set.
|
||||
|
||||
### After you delegate
|
||||
- Call wait very sparingly. Only call wait when you need the result immediately for the next critical-path step and you are blocked until it returns.
|
||||
- Call wait_agent very sparingly. Only call wait_agent when you need the result immediately for the next critical-path step and you are blocked until it returns.
|
||||
- Do not redo delegated subagent tasks yourself; focus on integrating results or tackling non-overlapping work.
|
||||
- While the subagent is running in the background, do meaningful non-overlapping work immediately.
|
||||
- Do not repeatedly wait by reflex.
|
||||
@@ -1290,7 +1290,7 @@ fn create_resume_agent_tool() -> ToolSpec {
|
||||
ToolSpec::Function(ResponsesApiTool {
|
||||
name: "resume_agent".to_string(),
|
||||
description:
|
||||
"Resume a previously closed agent by id so it can receive send_input and wait calls."
|
||||
"Resume a previously closed agent by id so it can receive send_input and wait_agent calls."
|
||||
.to_string(),
|
||||
strict: false,
|
||||
defer_loading: None,
|
||||
@@ -1303,7 +1303,7 @@ fn create_resume_agent_tool() -> ToolSpec {
|
||||
})
|
||||
}
|
||||
|
||||
fn create_wait_tool() -> ToolSpec {
|
||||
fn create_wait_agent_tool() -> ToolSpec {
|
||||
let mut properties = BTreeMap::new();
|
||||
properties.insert(
|
||||
"ids".to_string(),
|
||||
@@ -1325,7 +1325,7 @@ fn create_wait_tool() -> ToolSpec {
|
||||
);
|
||||
|
||||
ToolSpec::Function(ResponsesApiTool {
|
||||
name: "wait".to_string(),
|
||||
name: "wait_agent".to_string(),
|
||||
description: "Wait for agents to reach a final status. Completed statuses may include the agent's final message. Returns empty status when timed out. Once the agent reaches a final status, a notification message will be received containing the same completed status."
|
||||
.to_string(),
|
||||
strict: false,
|
||||
@@ -2441,7 +2441,7 @@ pub(crate) fn build_specs_with_discoverable_tools(
|
||||
use crate::tools::handlers::multi_agents::ResumeAgentHandler;
|
||||
use crate::tools::handlers::multi_agents::SendInputHandler;
|
||||
use crate::tools::handlers::multi_agents::SpawnAgentHandler;
|
||||
use crate::tools::handlers::multi_agents::WaitHandler;
|
||||
use crate::tools::handlers::multi_agents::WaitAgentHandler;
|
||||
use std::sync::Arc;
|
||||
|
||||
let mut builder = ToolRegistryBuilder::new();
|
||||
@@ -2835,7 +2835,7 @@ pub(crate) fn build_specs_with_discoverable_tools(
|
||||
);
|
||||
push_tool_spec(
|
||||
&mut builder,
|
||||
create_wait_tool(),
|
||||
create_wait_agent_tool(),
|
||||
false,
|
||||
config.code_mode_enabled,
|
||||
);
|
||||
@@ -2848,7 +2848,7 @@ pub(crate) fn build_specs_with_discoverable_tools(
|
||||
builder.register_handler("spawn_agent", Arc::new(SpawnAgentHandler));
|
||||
builder.register_handler("send_input", Arc::new(SendInputHandler));
|
||||
builder.register_handler("resume_agent", Arc::new(ResumeAgentHandler));
|
||||
builder.register_handler("wait", Arc::new(WaitHandler));
|
||||
builder.register_handler("wait_agent", Arc::new(WaitAgentHandler));
|
||||
builder.register_handler("close_agent", Arc::new(CloseAgentHandler));
|
||||
}
|
||||
|
||||
|
||||
@@ -502,7 +502,7 @@ fn test_build_specs_collab_tools_enabled() {
|
||||
let (tools, _) = build_specs(&tools_config, None, None, &[]).build();
|
||||
assert_contains_tool_names(
|
||||
&tools,
|
||||
&["spawn_agent", "send_input", "wait", "close_agent"],
|
||||
&["spawn_agent", "send_input", "wait_agent", "close_agent"],
|
||||
);
|
||||
assert_lacks_tool_name(&tools, "spawn_agents_on_csv");
|
||||
}
|
||||
@@ -530,7 +530,7 @@ fn test_build_specs_enable_fanout_enables_agent_jobs_and_collab_tools() {
|
||||
&[
|
||||
"spawn_agent",
|
||||
"send_input",
|
||||
"wait",
|
||||
"wait_agent",
|
||||
"close_agent",
|
||||
"spawn_agents_on_csv",
|
||||
],
|
||||
@@ -651,7 +651,7 @@ fn test_build_specs_agent_job_worker_tools_enabled() {
|
||||
"spawn_agent",
|
||||
"send_input",
|
||||
"resume_agent",
|
||||
"wait",
|
||||
"wait_agent",
|
||||
"close_agent",
|
||||
"spawn_agents_on_csv",
|
||||
"report_agent_job_result",
|
||||
|
||||
Reference in New Issue
Block a user