diff --git a/src/agents/claude_client.py b/src/agents/claude_client.py index 661180d..3cae369 100644 --- a/src/agents/claude_client.py +++ b/src/agents/claude_client.py @@ -54,7 +54,12 @@ async def call_claude(prompt: str, tools: str | None = "WebSearch,WebFetch", mod if tools: cmd.extend(["--allowedTools", tools]) else: - cmd.extend(["--max-turns", "1"]) + cmd.extend(["--max-turns", "1", "--allowedTools", ""]) + cmd.extend(["--append-system-prompt", + "CRITICAL: You are a JSON-only output agent. " + "Output EXCLUSIVELY a single valid JSON object. " + "No explanatory text, no markdown fences, no continuation of previous responses. " + "Start your response with { and end with }."]) process = await asyncio.create_subprocess_exec( *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, @@ -76,8 +81,21 @@ async def call_claude(prompt: str, tools: str | None = "WebSearch,WebFetch", mod if process.returncode != 0: error_msg = stderr.decode("utf-8", errors="replace").strip() - logger.error(f"Claude CLI Fehler (Exit {process.returncode}): {error_msg}") - raise RuntimeError(f"Claude CLI Fehler: {error_msg}") + stdout_msg = stdout.decode("utf-8", errors="replace").strip() + + # Rate-Limit-Fehler kommen als JSON auf stdout, nicht auf stderr + error_type = "cli_error" + rate_limit_keywords = ["hit your limit", "rate limit", "resets", "rate_limit", "overloaded"] + combined_output = f"{error_msg} {stdout_msg}".lower() + if any(kw in combined_output for kw in rate_limit_keywords): + error_type = "rate_limit" + logger.warning(f"Claude CLI Rate-Limit (Exit {process.returncode}): {stdout_msg or error_msg}") + else: + logger.error(f"Claude CLI Fehler (Exit {process.returncode}): {error_msg}") + if stdout_msg: + logger.error(f"Claude CLI stdout bei Fehler: {stdout_msg[:500]}") + + raise RuntimeError(f"Claude CLI Fehler [{error_type}]: {stdout_msg or error_msg}") raw = stdout.decode("utf-8", errors="replace").strip() usage = ClaudeUsage()