Conversation
…agent loop reliability ## Summary Found 5 critical bugs in async error handling, context compression, and cron scheduling: **CRITICAL (2):** 1. Role violation after context compression (context_compressor.py:694-728) - Tool message validation missing when merging summary - Causes API crash and data loss after compression 2. Double-execution race condition in cron scheduler (scheduler.py:843-892) - File lock released before job execution completes - Allows duplicate jobs to be executed (DoS, duplicate messages) **HIGH (1):** 3. Unhandled context compression exceptions in main loop (run_agent.py:8204,8262,8338) - Silent crash when summarizer fails during API loop - No graceful degradation **MEDIUM (2):** 4. Error swallowing in auxiliary_client (auxiliary_client.py:2074-2106) - Original error overwritten on retry failure - Lost error context, unreachable fallback logic 5. Session ID change without exception recovery (run_agent.py:6041-6071) - Session state corruption on DB failures - Broken session lineage ## Details Full analysis with code snippets, scenarios, and fixes in: - AUDIT_ITERATION_2.md (400 lines, detailed technical analysis) - AUDIT_ITERATION_2_SUMMARY.txt (visual summary, testing recommendations) ## Recommended Priority 1. Bug NousResearch#1 (Role Violation) - FIX IMMEDIATELY 2. Bug NousResearch#2 (Double Execution) - FIX IMMEDIATELY 3. Bug NousResearch#3 (Unhandled Exceptions) - FIX SOON 4. Bug NousResearch#4 & NousResearch#5 - FIX AFTER critical bugs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…fallback, shutdown message loss
- Strip mcp_ tool prefix in Anthropic OAuth auxiliary client (agent/auxiliary_client.py):
When using Anthropic OAuth mode, build_anthropic_kwargs() prepends mcp_ to all
tool names for Claude Code compatibility. The main agent loop correctly passes
strip_tool_prefix=True when normalizing the response, but the auxiliary client's
AnthropicCompletions.create() at line 514 did not. This caused auxiliary tasks
(vision, web extraction) to return tool calls with mcp_ prefixed names that the
caller couldn't match to registered tools.
- Log warning for silent JSON argument parse failure (agent/anthropic_adapter.py):
When converting OpenAI-format tool_calls to Anthropic format, malformed JSON in
the arguments field silently fell back to an empty dict {} with no logging. This
makes it very difficult to debug "required parameter missing" errors from tools
when the root cause is upstream JSON corruption.
- Log pending messages discarded during gateway shutdown (gateway/run.py):
On shutdown, _pending_messages.clear() silently discarded all queued messages.
Added a warning log with the count of discarded messages for observability.
Co-Authored-By: Claude Code <noreply@anthropic.com>
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused observability work. The OAuth-prefix portion is already present on current main, while the remaining logging work needs adjustment before salvage.
Problems
agent/auxiliary_client.py:1285-1287already passesstrip_tool_prefix=self._is_oauththrough the Anthropic transport. The current transport-level coverage is intests/agent/test_anthropic_mcp_prefix_strip.py, but this PR adds no wrapper-level regression test.- The gateway hunk logs
GatewayRunner._pending_messages, butgateway/run.py:9581-9583documents that map as write-only; queued follow-ups live inadapter._pending_messages(gateway/platforms/base.py:2347). It would not log the discarded user messages described here. - The new parse warning covers one fallback only.
agent/anthropic_adapter.py:1955-1960has another silent malformed-arguments fallback in ordered-block replay. - The added audit reports describe unrelated findings not implemented by this PR.
Suggested changes
- Remove the already-landed OAuth hunk and add a direct auxiliary-wrapper regression test.
- Count adapter-held pending messages before teardown and add a shutdown
caplogtest. - Cover both malformed-argument fallback paths and remove the unrelated audit artifacts.
Automated hermes-sweeper review.
|
|
||
| response = self._client.messages.create(**anthropic_kwargs) | ||
| assistant_message, finish_reason = normalize_anthropic_response(response) | ||
| assistant_message, finish_reason = normalize_anthropic_response( |
There was a problem hiding this comment.
This OAuth normalization behavior is already on current main through the transport path at agent/auxiliary_client.py:1285-1287. Please drop this stale hunk and add a direct auxiliary-wrapper regression test if coverage is still needed.
| try: | ||
| parsed_args = json.loads(args) if isinstance(args, str) else args | ||
| except (json.JSONDecodeError, ValueError): | ||
| logger.warning( |
There was a problem hiding this comment.
Please cover the equivalent malformed-arguments fallback in the ordered-block replay path as well; current main silently falls back at agent/anthropic_adapter.py:1955-1960. A shared helper or matching warning plus caplog coverage would keep the diagnostics consistent.
|
|
||
| self.adapters.clear() | ||
| self._running_agents.clear() | ||
| if self._pending_messages: |
There was a problem hiding this comment.
This runner-level map is not the queue that holds user follow-ups: current gateway/run.py:9581-9583 says actual messages are in adapter._pending_messages. Count the adapters' pending maps before teardown so the warning reports the messages described by this PR.
| @@ -0,0 +1,400 @@ | |||
| # Deep Audit: Async Error Handling and Agent Loop Reliability - Iteration #2 | |||
There was a problem hiding this comment.
This 400-line audit report describes unrelated findings that this PR does not implement. Please remove it from this focused logging/fix change.
Summary
This PR addresses three cross-module boundary issues found during iteration #7 of a deep code audit:
Strip
mcp_tool prefix in auxiliary Anthropic OAuth client (agent/auxiliary_client.py): When using Anthropic OAuth mode,build_anthropic_kwargs()prependsmcp_to all tool names for Claude Code compatibility. The main agent loop correctly passesstrip_tool_prefix=Truetonormalize_anthropic_response()(run_agent.py:8597), but the auxiliary client'sAnthropicCompletions.create()did not (line 514). This caused auxiliary tasks (vision, web extraction) using Anthropic OAuth to return tool calls withmcp_-prefixed names that the caller couldn't match to registered tools.Log warning for silent JSON argument parse failure (
agent/anthropic_adapter.py): When converting OpenAI-format tool_calls to Anthropic format, malformed JSON in theargumentsfield silently fell back to{}with zero logging (line 1011-1012). This makes it very difficult to debug downstream "required parameter missing" errors when the root cause is upstream JSON corruption. Added a warning with the tool name and truncated argument content.Log pending messages discarded during gateway shutdown (
gateway/run.py): On shutdown,_pending_messages.clear()silently discarded all queued messages with no indication. Users sending messages during a/restartwindow would have them silently lost. Added a warning log with the count.Files Changed
agent/auxiliary_client.pystrip_tool_prefix=self._is_oauthto response normalizeragent/anthropic_adapter.pylogger.warning()for JSON parse fallback to{}gateway/run.pyTest plan
mcp_prefixpytest tests/🤖 Generated with Claude Code