From b8e2268628b25e0294da8fae411ca3f218d98860 Mon Sep 17 00:00:00 2001 From: 595650661 <15205536+595650661@users.noreply.github.com> Date: Wed, 3 Jun 2026 11:23:20 +0800 Subject: [PATCH] fix(agent): add MiniMax 'new_sensitive' to content_policy_blocked patterns The MiniMax output-layer safety filter surfaces the error verbatim as `output new_sensitive (1027)` (sometimes with additional provider wrapping like 'Stream stalled mid tool-call: output new_sensitive (1027)'). When the model emits a large tool-call argument block, the upstream filter trips and the SSE stream is truncated mid-flight, producing 'stream stalled mid tool-call' errors. Until now this case was misclassified and retried 3x on the same provider, reproducing the same refusal and burning paid attempts. Adding `new_sensitive` to `_CONTENT_POLICY_BLOCKED_PATTERNS` routes it through the existing is_client_error path: skip 3x retry, activate configured fallback model immediately, surface a clear provider-safety message to the user. Refs #32421 --- agent/error_classifier.py | 8 +++++++ .../test_18028_content_policy_blocked.py | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/agent/error_classifier.py b/agent/error_classifier.py index 2d43806bc07..a64683ba41e 100644 --- a/agent/error_classifier.py +++ b/agent/error_classifier.py @@ -355,6 +355,14 @@ _CONTENT_POLICY_BLOCKED_PATTERNS = [ # echo back; the underscore form is provider-specific enough. "content_filter", "responsibleaipolicyviolation", + # MiniMax output-layer safety filter. The error string is surfaced + # verbatim by MiniMax SDK / OpenAI-compatible endpoints, usually in the + # form "output new_sensitive (1027)" when the model's *output* (often a + # large tool-call argument block) trips the upstream safety filter and + # the SSE stream is truncated mid-flight. ``new_sensitive`` is the + # filter name and is narrow enough that billing / format / auth error + # strings will not collide. See #32421. + "new_sensitive", ] # Auth patterns (non-status-code signals) diff --git a/tests/run_agent/test_18028_content_policy_blocked.py b/tests/run_agent/test_18028_content_policy_blocked.py index 1edf16b87ca..5b0ca093494 100644 --- a/tests/run_agent/test_18028_content_policy_blocked.py +++ b/tests/run_agent/test_18028_content_policy_blocked.py @@ -41,6 +41,27 @@ class TestContentPolicyBlockedClassification: assert result.should_compress is False assert result.should_rotate_credential is False + def test_minimax_output_safety_filter(self): + """#32421 — MiniMax output-layer safety filter (e.g. ``output + new_sensitive (1027)``) trips mid-stream when the model emits a + large tool-call argument block. Must classify as + ``content_policy_blocked`` so the loop aborts the 3x retry burn and + routes to a configured fallback model. + """ + from agent.error_classifier import classify_api_error, FailoverReason + + e = Exception( + "Stream stalled mid tool-call: output new_sensitive (1027) " + "[MiniMax-M2.7] — request was rejected by upstream safety " + "filter, see provider response for details." + ) + result = classify_api_error(e, provider="MiniMax", model="MiniMax-M2.7") + assert result.reason == FailoverReason.content_policy_blocked + assert result.retryable is False + assert result.should_fallback is True + assert result.should_compress is False + assert result.should_rotate_credential is False + class TestContentPolicyTriggersClientErrorAbort: """Mirror the ``is_client_error`` predicate in