fix(bridge): convert tool name hyphens to underscores for Python compatibility

Root cause from trace analysis: the LLM writes `web_search()` (valid
Python identifier) but the tool registry has `web-search` (with hyphen).
The EffectBridgeAdapter couldn't find the tool → "Tool not found" error
→ model fabricated fake data instead.

Fixes:
- available_actions(): converts tool names from hyphens to underscores
  (web-search → web_search) so the system prompt lists valid Python names
- execute_action(): tries the original name first, then falls back to
  hyphenated form (web_search → web-search) for tool registry lookup
- Same conversion in router's capability registry builder

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
This commit is contained in:
2026-03-22 23:03:52 -07:00
co-authored by Claude Opus 4.6
parent b1254cf6f9
commit d8f01693f4
2 changed files with 14 additions and 3 deletions
+13 -2
View File
@@ -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,
&parameters,
&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
+1 -1
View File
@@ -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![],