Skip to content

Add ensure_valid_tool_response: outbound pre-flight normalizer for circuit breaker prevention#1780

Open
gdeyoung wants to merge 1 commit into
agent0ai:mainfrom
gdeyoung:feature/ensure-valid-tool-response
Open

Add ensure_valid_tool_response: outbound pre-flight normalizer for circuit breaker prevention#1780
gdeyoung wants to merge 1 commit into
agent0ai:mainfrom
gdeyoung:feature/ensure-valid-tool-response

Conversation

@gdeyoung

Copy link
Copy Markdown
Contributor

Summary

Adds ensure_valid_tool_response() to helpers/extract_tools.py — an outbound pre-flight check that normalizes agent output into a valid {tool_name, tool_args} envelope before the framework circuit breaker processes it. This addresses a gap where models that return plain text instead of structured tool calls (or where the agent itself emits malformed JSON) would trip the "N consecutive unusable model responses" safety breaker.

Background

The existing extract_tools.py handles inbound multi-vendor dialect normalization (Anthropic tool_use blocks, DeepSeek singular tool_call, reasoning_content extraction, etc.). But there is a second failure mode: self-inflicted malformation, where the agent emits non-JSON or plain prose instead of a tool-call envelope. The inbound parser cannot fix this because there is nothing to parse.

This PR adds the second layer: an outbound pre-flight check that runs before the circuit breaker counts any strikes.

Function Logic

1. Already valid {tool_name, tool_args} -> pass through unchanged
2. Parseable JSON but not a tool call -> wrap in response()
3. Completely non-JSON (plain prose) -> wrap as response().text
4. Empty/null -> return valid empty response()

Changes

File Change
helpers/extract_tools.py Added ensure_valid_tool_response() (~30 lines)
agent.py Added one-line call at process_tools entry point (line 1411)

Testing

  • Unit tests (6/6): valid tool call passes through, plain text wraps, empty returns empty, malformed JSON wraps, non-tool JSON wraps, None returns empty
  • Integration tests (3/3): full pipeline (ensure_valid_tool_response → json_parse_dirty → normalize_tool_request), plain text wrapping, content preservation
  • Live verification: Across 3 production containers running deepseek-v4-flash (local), GLM-5.2 (Z.AI), MiniMax-M3 (OpenRouter) backends

Related

Full writeup: https://gist.github.com/gdeyoung/[pending] (multi-vendor writeup with both layers documented)

See also: the existing multi-vendor dispatcher writeup at documents/a0-multivendor-tool-call-extraction-writeup.md

Adds ensure_valid_tool_response() to helpers/extract_tools.py as an
outbound pre-flight check that normalizes agent output into a valid
{tool_name, tool_args} envelope before the framework circuit breaker
processes it.

Handles four cases:
1. Already valid tool-call JSON -> pass through
2. Parseable JSON but not a tool call -> wrap in response()
3. Completely non-JSON (plain prose) -> wrap as response().text
4. Empty/null -> return valid empty response()

Threaded into agent.py at process_tools entry point (line 1411).

Verified: 9/9 tests (6 unit + 3 integration) across 3 containers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant