Skip to content

Refactor tool fallback strategies #458

Description

@korotaav48

QuickApps version

latest

Area

Toolsets (REST / DIAL deployment / MCP / internal)

What is the current state?

Tool fallback is configured via ToolFallbackConfig.strategies in the app manifest. Three strategies exist: continue, retry, and stop.

Current problems:

  • continue and retry default to sending LLM instructions instead of the actual error. The actual error message is forwarded only when forward_tool_error_message: true is explicitly set (added in feat: expose MCP and HTTP Tool Errors to the LLM #408). This is backwards — the LLM needs to know what went wrong before it can decide what to do.
  • stop terminates the agent via a hardcoded instruction ("STOP: Execution halted... you MUST NOT proceed further"). This is unreliable — the LLM may ignore it. There is no programmatic stop of the orchestrator loop.
  • The continue strategy conflates two responsibilities: (1) forwarding error context to the LLM, and (2) injecting guidance instructions. These should be independent.
  • RetryStrategyModel requires instructions even though in most cases the error message itself is sufficient context for the LLM to retry correctly.
  • Relevant files: src/quickapp/common/tool_fallback/, src/quickapp/config/tools/tool_fallback.py, src/quickapp/common/tool_fallback/processor.py

Why is this debt?

Why is this debt?

  • Impact today: builders must opt-in to forward_tool_error_message: true to get sensible LLM behavior; the default is to hide the actual error. The stop strategy's LLM-instruction approach is fragile.
  • Risk if left unaddressed: new tool types added in the future (e.g. feat: expose MCP and HTTP Tool Errors to the LLM #408 for MCP/REST) will inherit the same flawed defaults.
  • Features it blocks: a reliable programmatic circuit-breaker for agent loops.

Proposed remediation

  1. Change the default behavior — forward the tool error message as tool response content with no added instructions. Remove forward_tool_error_message field (deprecate it in this release, remove in next major).
  2. Programmatic stop — when the stop strategy fires, raise a dedicated exception that the orchestrator catches and uses to terminate the loop cleanly (similar to how ToolTimeoutError is handled today). No LLM instruction involved.
  3. Keep trigger_on + optional instructions — when trigger_on is set, the user may optionally provide instructions to append to the error message passed to the LLM. This covers the "tell the agent what to do when error X occurs" use case.
  4. Deprecate instructions without trigger_on on continue — a catch-all custom instruction is now unnecessary since the error is forwarded by default.
  5. Revisit retry — relax the requirement that instructions is mandatory, since forwarding the error is sufficient in most cases.

Migration: existing configs using forward_tool_error_message: false (the old default) should be warned at validation time that the behavior has changed; forward_tool_error_message: true configs continue to work as before (field deprecated, no-op).


Alternatives considered

  • Keep forward_tool_error_message as a toggle, flip its default to true — simpler migration, but leaves a confusing field that will need removal anyway.
  • Add a new strategy type instead of changing defaults — avoids breakage but compounds the config complexity.

Additional information

Related: #408 (feat: expose MCP and HTTP Tool Errors to the LLM) — introduced ToolErrorException and forward_tool_error_message, which this refactoring supersedes.

Alternatives considered

No response

Additional information

No response

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions