feat: Added configuration option in agents to indicate the timeout for user input before proceeding (defaults to 5 minutes)

This commit is contained in:
2026-02-18 11:24:47 -07:00
parent b1be9443e7
commit 128a8f9a9c
2 changed files with 21 additions and 6 deletions
+10
View File
@@ -439,6 +439,10 @@ impl Agent {
self.config.summarization_threshold self.config.summarization_threshold
} }
pub fn escalation_timeout(&self) -> u64 {
self.config.escalation_timeout
}
pub fn continuation_count(&self) -> usize { pub fn continuation_count(&self) -> usize {
self.continuation_count self.continuation_count
} }
@@ -655,6 +659,8 @@ pub struct AgentConfig {
pub summarization_model: Option<String>, pub summarization_model: Option<String>,
#[serde(default = "default_summarization_threshold")] #[serde(default = "default_summarization_threshold")]
pub summarization_threshold: usize, pub summarization_threshold: usize,
#[serde(default = "default_escalation_timeout")]
pub escalation_timeout: u64,
} }
fn default_max_auto_continues() -> usize { fn default_max_auto_continues() -> usize {
@@ -677,6 +683,10 @@ fn default_summarization_threshold() -> usize {
4000 4000
} }
fn default_escalation_timeout() -> u64 {
300
}
impl AgentConfig { impl AgentConfig {
pub fn load(path: &Path) -> Result<Self> { pub fn load(path: &Path) -> Result<Self> {
let contents = read_to_string(path) let contents = read_to_string(path)
+11 -6
View File
@@ -11,7 +11,7 @@ use tokio::sync::oneshot;
pub const USER_FUNCTION_PREFIX: &str = "user__"; pub const USER_FUNCTION_PREFIX: &str = "user__";
const ESCALATION_TIMEOUT: Duration = Duration::from_secs(300); const DEFAULT_ESCALATION_TIMEOUT_SECS: u64 = 300;
pub fn user_interaction_function_declarations() -> Vec<FunctionDeclaration> { pub fn user_interaction_function_declarations() -> Vec<FunctionDeclaration> {
vec![ vec![
@@ -206,7 +206,7 @@ async fn handle_escalated(config: &GlobalConfig, action: &str, args: &Value) ->
.collect() .collect()
}); });
let (from_agent_id, from_agent_name, root_queue) = { let (from_agent_id, from_agent_name, root_queue, timeout_secs) = {
let cfg = config.read(); let cfg = config.read();
let agent_id = cfg let agent_id = cfg
.self_agent_id .self_agent_id
@@ -221,7 +221,12 @@ async fn handle_escalated(config: &GlobalConfig, action: &str, args: &Value) ->
.root_escalation_queue .root_escalation_queue
.clone() .clone()
.ok_or_else(|| anyhow!("No escalation queue available; cannot reach parent agent"))?; .ok_or_else(|| anyhow!("No escalation queue available; cannot reach parent agent"))?;
(agent_id, agent_name, queue) let timeout = cfg
.agent
.as_ref()
.map(|a| a.escalation_timeout())
.unwrap_or(DEFAULT_ESCALATION_TIMEOUT_SECS);
(agent_id, agent_name, queue, timeout)
}; };
let escalation_id = new_escalation_id(); let escalation_id = new_escalation_id();
@@ -238,7 +243,8 @@ async fn handle_escalated(config: &GlobalConfig, action: &str, args: &Value) ->
root_queue.submit(request); root_queue.submit(request);
match tokio::time::timeout(ESCALATION_TIMEOUT, rx).await { let timeout = Duration::from_secs(timeout_secs);
match tokio::time::timeout(timeout, rx).await {
Ok(Ok(reply)) => Ok(json!({ "answer": reply })), Ok(Ok(reply)) => Ok(json!({ "answer": reply })),
Ok(Err(_)) => Ok(json!({ Ok(Err(_)) => Ok(json!({
"error": "Escalation was cancelled. The parent agent dropped the request", "error": "Escalation was cancelled. The parent agent dropped the request",
@@ -246,8 +252,7 @@ async fn handle_escalated(config: &GlobalConfig, action: &str, args: &Value) ->
})), })),
Err(_) => Ok(json!({ Err(_) => Ok(json!({
"error": format!( "error": format!(
"Escalation timed out after {} seconds waiting for user response", "Escalation timed out after {timeout_secs} seconds waiting for user response"
ESCALATION_TIMEOUT.as_secs()
), ),
"fallback": "Make your best judgment and proceed", "fallback": "Make your best judgment and proceed",
})), })),