Class: Ask::Agent::ToolCallRepair
- Inherits:
-
Object
- Object
- Ask::Agent::ToolCallRepair
- Defined in:
- lib/ask/agent/tool_call_repair.rb
Overview
Repairs malformed tool calls before they execute.
When a model emits a tool call with unparseable arguments or an unknown tool name, execution currently fails and the model burns a turn seeing the error. Repair intercepts those calls before execution, asks the model to re-emit them corrected (one internal LLM round-trip), and executes the corrected versions — remapped to the original call ids so tool results stay consistent with the conversation history.
Enable with Session.new(tool_call_repair: true) for the built-in
repair prompt, or pass a callable for full control:
Session.new(tool_call_repair: ->(chat, calls, tools) {
{ calls.keys.first => ToolCallInfo.new(
id: calls.keys.first, name: "bash", arguments: "{}"
) }
})
The callable receives the chat, the malformed calls hash (id => ToolCallInfo), and the available tools; it returns a hash of corrections keyed by the ORIGINAL call ids. Calls without a correction are dropped — the model saw them in the prompt and declined to fix them.
Class Method Summary collapse
-
.repair_info(tool_call, tools) ⇒ String?
Why a call is invalid, in a form the model can act on.
Instance Method Summary collapse
-
#call(chat:, calls:, tools:) ⇒ Hash{String => ToolCallInfo}
Ask the model to correct the malformed calls.
-
#initialize(callable = nil) ⇒ ToolCallRepair
constructor
A new instance of ToolCallRepair.
Constructor Details
#initialize(callable = nil) ⇒ ToolCallRepair
Returns a new instance of ToolCallRepair.
59 60 61 |
# File 'lib/ask/agent/tool_call_repair.rb', line 59 def initialize(callable = nil) @callable = callable end |
Class Method Details
.repair_info(tool_call, tools) ⇒ String?
Why a call is invalid, in a form the model can act on. This is schema-aware: the tool's own validation names what was expected ("unknown parameters: :titile — expected: :project_id, :title"), so the model corrects the call instead of guessing.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/ask/agent/tool_call_repair.rb', line 39 def self.repair_info(tool_call, tools) tool = tools.find { |t| t.respond_to?(:name) && t.name == tool_call.name } return "unknown tool '#{tool_call.name}'" unless tool parsed = if tool_call.arguments.is_a?(Hash) tool_call.arguments else JSON.parse(tool_call.arguments.to_s) end return "arguments must be a JSON object, got #{parsed.class}" unless parsed.is_a?(Hash) return nil unless tool.respond_to?(:validate) tool.validate(parsed.transform_keys(&:to_sym)) rescue JSON::ParserError => e "arguments are not valid JSON: #{e.}" end |
Instance Method Details
#call(chat:, calls:, tools:) ⇒ Hash{String => ToolCallInfo}
Ask the model to correct the malformed calls.
71 72 73 74 75 76 77 |
# File 'lib/ask/agent/tool_call_repair.rb', line 71 def call(chat:, calls:, tools:) if @callable normalize(@callable.call(chat, calls, tools)) else built_in(chat, calls, tools) end end |