Where: framework/eino_tooling.go:41-53
When tool-argument JSON fails to parse, the code synthesizes an error observation and returns without calling guard.recordFailure — while the normal execution paths (:95, :99, :103) all record.
Consequence: if the model repeatedly emits the same malformed-argument tool call, failureGuard never counts it, so neither replanThreshold (2) nor windDownThreshold (4) fires — exactly the loop the guard is meant to break.
(The 1:1 tool_call ↔ tool message pairing itself is correctly preserved.)
Where: framework/eino_tooling.go:41-53
When tool-argument JSON fails to parse, the code synthesizes an error observation and returns without calling guard.recordFailure — while the normal execution paths (:95, :99, :103) all record.
Consequence: if the model repeatedly emits the same malformed-argument tool call, failureGuard never counts it, so neither replanThreshold (2) nor windDownThreshold (4) fires — exactly the loop the guard is meant to break.
(The 1:1 tool_call ↔ tool message pairing itself is correctly preserved.)