Repository navigation
fix(channels): a failed turn tells the chat so in plain words, never the operator's error (#3603) - #3839
Conversation
…the operator's error (#3603) The router posted the execution's own error into the channel: "Authentication failure: Not logged in · Please run /login. Check subscription token or API key configuration." In a Telegram group every member saw it; Slack, WhatsApp and DMs took the same path. A failed turn now sends the fixed line the router's exception branch already used; the error stays on the execution row and in the router's log line. A cancelled turn still sends its cancel reason (#679), or a cancelled line when it has none. Public chat got the same fix in #3478. test_slack_timeout_fix.py's TestErrorMessageRouting re-implemented the old #221 forwarding logic instead of calling the router, so it could not fail; it is replaced by tests that drive the real _run_agent_task. Mutation: restoring the forwarding turns 14 of 19 new tests red. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolves the tests/registry.json conflict by keeping both sides' entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
obasilakis
left a comment
There was a problem hiding this comment.
Slack, Telegram and WhatsApp all reply through this one branch, and the remaining str(e) uses are admin routes. Tests run the real _run_agent_task: 19 pass on the branch, 15 fail with dev's router.
Major
src/backend/adapters/message_router.py:867— a cancelled turn still sendsresult.errorverbatim. On pull-pilot agents a terminated turn keeps the failure body'scontent(docker/base-image/agent_server/services/pull_worker.py:452-461, content set at:270/:284), and the backend stores it as the cancelled row's error (pull_coordination_service.py:715). The chat then gets the operator's error, which the first AC forbids. Always sendCHANNEL_CANCELLED_MESSAGEfor a cancelled turn; it still says the turn was cancelled, as #679 requires.
Traced in code; not reproduced live. If the pull worker already sends a fixed text for terminated turns, this drops to minor.
…#3603) On a pull-pilot agent a terminated turn keeps the failure body's content and the pull sink stores it as the cancelled row's error, so forwarding a cancelled row's error could still post the operator's error to the chat. The cancelled branch now always sends CHANNEL_CANCELLED_MESSAGE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-reply # Conflicts: # tests/registry.json
|
@obasilakis thanks, confirmed in code: Fixed in d99fa6c: a cancelled turn now always sends Tests (
Other paths checked. For inline turns, One path is outside this PR: Also merged |
obasilakis
left a comment
There was a problem hiding this comment.
Approving. The cancelled-turn branch in adapters/message_router.py now always sends CHANNEL_CANCELLED_MESSAGE, and the cancel tests feed operator error text into a cancelled turn and assert the fixed line goes out. The only other reply text in the router is the skill-gate message, which is user-facing. No new findings.
…-reply # Conflicts: # tests/registry.json
obasilakis
left a comment
There was a problem hiding this comment.
Re-checked at 7ed36cc. The only commit since my approval merges origin/dev; the three PR code/test files are byte-identical to 3ac16e4, and the only patch change is the tests/registry.json hunk moving. The ent#934 Telegram album code that came in from dev adds no reply path that sends result.error to a chat (it only logs), so the router's failed/cancelled branch is still the single place a turn error reaches a chat. CI green. Approval stands.
Summary
Changes
src/backend/adapters/message_router.py: two constants,CHANNEL_FAILURE_MESSAGEandCHANNEL_CANCELLED_MESSAGE, used by the failed/cancelled branch and the exception branch.tests/unit/test_3603_channel_failure_reply.py(new, 19 tests).tests/unit/test_slack_timeout_fix.py: removedTestErrorMessageRouting. It copied fix: Slack message router ignores per-agent execution timeout (TIMEOUT-001) #221's old forwarding logic into the test instead of calling the router, so it could never fail; a comment points to the new tests.Test Plan
cd tests && pytest unit/test_3603_channel_failure_reply.py: 19 pass, through the realChannelMessageRouter._run_agent_taskwith only the dispatch stubbed (thetest_3274_channel_quotesetup).TestPaidA2Atests intest_ent751_gate_callers.pyfail locally the same way on a cleandevcheckout, so they're unrelated.Fixes #3603
🤖 Generated with Claude Code