diff --git a/src/bridge/effect_adapter.rs b/src/bridge/effect_adapter.rs index 972ecba9..f83bc45e 100644 --- a/src/bridge/effect_adapter.rs +++ b/src/bridge/effect_adapter.rs @@ -39,11 +39,21 @@ impl EffectExecutor for EffectBridgeAdapter { format!("Thread {}", context.thread_id), ); + // Convert Python identifier (underscores) back to tool name (hyphens). + // Python can't have hyphens in function names, so the system prompt + // lists tools with underscores. We need to try both forms. + let hyphenated = action_name.replace('_', "-"); + let lookup_name = if self.tools.get(action_name).await.is_some() { + action_name + } else { + &hyphenated + }; + // Execute through the existing tool pipeline let result = crate::tools::execute::execute_tool_with_safety( &self.tools, &self.safety, - action_name, + lookup_name, ¶meters, &job_ctx, ) @@ -75,7 +85,8 @@ impl EffectExecutor for EffectBridgeAdapter { Ok(tool_defs .into_iter() .map(|td| ActionDef { - name: td.name, + // Convert hyphens to underscores for valid Python identifiers + name: td.name.replace('-', "_"), description: td.description, parameters_schema: td.parameters, effects: vec![], // Effect classification happens at the engine level diff --git a/src/bridge/router.rs b/src/bridge/router.rs index 5c7a4129..5034ed88 100644 --- a/src/bridge/router.rs +++ b/src/bridge/router.rs @@ -75,7 +75,7 @@ async fn get_or_init_engine(agent: &Agent) -> Result<(), Error> { actions: tool_defs .into_iter() .map(|td| ironclaw_engine::ActionDef { - name: td.name, + name: td.name.replace('-', "_"), description: td.description, parameters_schema: td.parameters, effects: vec![],