{"title":"Felåterställning för agenter","slug":"error-recovery","category":"llm-cookbook","summary":"Hur LLM-agenter ska hantera och återställa från fel — ompröva, lagra, lära.","audience":["llm"],"tags":["cookbook","errors","recovery","resilience"],"difficulty":"intermediate","updated":"2026-06-27","word_count":219,"read_minutes":1,"lang":"sv","translated":true,"requested_lang":"sv","content_markdown":"\n# Felåterställning för agenter\n\nFel inträffar. Nätverk går ner, API:er returnerar 500, Mind Keys löper ut.\nDen här guiden visar hur LLM-agenter ska hantera fel elegant och lära sig av dem.\n\n## Principer för felhantering\n\n1. **Försök igen med backoff** — övergående fel löses ofta\n2. **Lagra felet** — lär av mönster\n3. **Degradera elegant** — krascha inte hela sessionen\n4. **Avisera människan** — för fel ni inte kan lösa\n\n## HTTP-felhantering\n\n### Försök igen med exponentiell backoff\n\n```python\nimport time\nimport requests\n\ndef call_with_retry(url, max_retries=3, backoff_base=2):\n    \"\"\"Call URL with exponential backoff.\"\"\"\n    for attempt in range(max_retries):\n        try:\n            r = requests.get(url, headers={\"Authorization\": f\"Bearer {KEY}\"})\n            \n            # Success\n            if r.status_code < 400:\n                return r\n            \n            # Rate limited — wait and retry\n            if r.status_code == 429:\n                wait = int(r.headers.get(\"Retry-After\", 60))\n                print(f\"Rate limited. Waiting {wait}s...\")\n                time.sleep(wait)\n                continue\n            \n            # Server error — retry with backoff\n            if r.status_code >= 500:\n                wait = backoff_base ** attempt\n                print(f\"Server error {r.status_code}. Retrying in {wait}s...\")\n                time.sleep(wait)\n                continue\n            \n            # Client error — don't retry\n            if 400 <= r.status_code < 500:\n                raise ClientError(f\"{r.status_code}: {r.text}\")\n        \n        except requests.RequestException as e:\n            # Network error — retry\n            wait = backoff_base ** attempt\n            print(f\"Network error: {e}. Retrying in {wait}s...\")\n            time.sleep(wait)\n    \n    raise MaxRetriesError(f\"Failed after {max_retries} retries\")\n```\n\n### Auth-felhantering\n\n```python\ndef safe_call(url):\n    \"\"\"Call with auth error handling.\"\"\"\n    try:\n        return call_with_retry(url)\n    except ClientError as e:\n        if \"401\" in str(e):\n            # Mind Key invalid — critical, can't recover\n            store_error(\"auth_invalid\", str(e), \"Check Mind Key\")\n            notify_human(\"My Mind Key is invalid. Please update.\")\n            raise AuthError(\"Cannot continue without valid Mind Key\")\n        elif \"403\" in str(e):\n            store_error(\"forbidden\", str(e), \"Wrong token type?\")\n            raise ForbiddenError(str(e))\n        elif \"404\" in str(e):\n            # Path doesn't exist — don't retry\n            store_error(\"not_found\", str(e), \"Check endpoint path\")\n            raise NotFoundError(str(e))\n        else:\n            raise\n```\n\n## Lagra fel som minnen\n\nNär fel inträffar, lagra dem så framtida sessioner kan lära:\n\n```python\ndef store_error(error_type, error_message, recovery_hint=\"\"):\n    \"\"\"Store an error as a memory for future reference.\"\"\"\n    requests.post(f\"{URL}/memory\",\n        headers={\"Authorization\": f\"Bearer {KEY}\",\n                 \"Content-Type\": \"application/json\"},\n        json={\n            \"category\": \"mistake\",\n            \"key\": f\"error_{error_type}_{int(time.time())}\",\n            \"content\": f\"Error: {error_type}\\nMessage: {error_message}\\nRecovery: {recovery_hint}\",\n            \"tags\": [\"error\", error_type],\n            \"priority\": \"high\"\n        })\n\n# Example\ntry:\n    deploy()\nexcept DeployError as e:\n    store_error(\"deploy_failed\", str(e), \n                \"Check CI logs, verify Docker image exists\")\n    raise\n```\n\n## Vanliga felscenarier\n\n### Scenario 1: Ogiltig Mind Key\n\n```python\n# Detection: 401 on every call\n# Recovery: Cannot recover — need human intervention\n\ndef handle_invalid_mind_key():\n    store_error(\"mind_key_invalid\", \n                \"All API calls returning 401\",\n                \"Mind Key may be revoked. Need new key.\")\n    \n    # Notify human via chat (if possible)\n    try:\n        reply(\"⚠️ My Mind Key is invalid. I cannot access memories. \"\n              \"Please check and update SYNAPSE_MIND_KEY.\")\n    except:\n        pass  # Chat may also fail with bad key\n    \n    # Exit gracefully\n    raise CriticalError(\"Cannot continue without valid Mind Key\")\n```\n\n### Scenario 2: Nätverksfel\n\n```python\n# Detection: ConnectionError, Timeout\n# Recovery: Retry with backoff, then degrade\n\ndef handle_network_error(url, retry=3):\n    for attempt in range(retry):\n        try:\n            return requests.get(url, timeout=10)\n        except (requests.ConnectionError, requests.Timeout) as e:\n            wait = 2 ** attempt\n            print(f\"Network error, retrying in {wait}s: {e}\")\n            time.sleep(wait)\n    \n    # All retries failed — degrade\n    store_error(\"network_failure\", \n                f\"Cannot reach {url}\",\n                \"Check internet connection, Synapse may be down\")\n    \n    # Work offline if possible\n    return work_offline()\n```\n\n### Scenario 3: Hastighetsbegränsad\n\n```python\n# Detection: 429 with Retry-After header\n# Recovery: Wait and retry, or switch to header auth\n\ndef handle_rate_limit(response):\n    retry_after = int(response.headers.get(\"Retry-After\", 60))\n    print(f\"Rate limited. Waiting {retry_after}s...\")\n    time.sleep(retry_after)\n    \n    # If this keeps happening, suggest switching to header auth\n    if has_query_param_auth(url):\n        store_error(\"rate_limited\", \n                    \"Frequent 429s with ?key= auth\",\n                    \"Switch to Authorization: Bearer header (no rate limit)\")\n```\n\n### Scenario 4: Serverfel (5xx)\n\n```python\n# Detection: 500, 502, 503\n# Recovery: Retry with backoff, check /health\n\ndef handle_server_error(url):\n    # Check if server is up\n    health = requests.get(f\"{URL}/health\")\n    if health.status_code != 200:\n        store_error(\"server_down\", \n                    \"Synapse health check failing\",\n                    \"Wait for server recovery\")\n        raise ServerDownError()\n    \n    # Retry with backoff\n    return call_with_retry(url, max_retries=5)\n```\n\n### Scenario 5: Verktygsanrop misslyckas\n\n```python\n# Detection: Tool returns error content\n# Recovery: Try alternative approach, store failure\n\ndef call_tool_safely(tool_name, args, alternatives=None):\n    try:\n        result = call_tool(tool_name, args)\n        if result.get(\"isError\"):\n            raise ToolError(result[\"content\"])\n        return result\n    except ToolError as e:\n        store_error(f\"tool_{tool_name}_failed\",\n                    f\"Args: {args}\\nError: {e}\",\n                    f\"Try: {alternatives or 'no alternatives'}\")\n        \n        # Try alternatives\n        if alternatives:\n            for alt in alternatives:\n                try:\n                    return call_tool(alt, args)\n                except:\n                    continue\n        \n        raise\n```\n\n## Mönster: Strömbrytare\n\nFör upprepade fel, sluta försöka tillfälligt:\n\n```python\nclass CircuitBreaker:\n    def __init__(self, threshold=5, reset_time=300):\n        self.failures = 0\n        self.threshold = threshold\n        self.reset_time = reset_time\n        self.last_failure = 0\n    \n    def call(self, fn, *args, **kwargs):\n        if self.failures >= self.threshold:\n            if time.time() - self.last_failure < self.reset_time:\n                raise CircuitOpenError(\"Circuit breaker open\")\n            else:\n                # Reset\n                self.failures = 0\n        \n        try:\n            result = fn(*args, **kwargs)\n            self.failures = 0  # Reset on success\n            return result\n        except:\n            self.failures += 1\n            self.last_failure = time.time()\n            raise\n\n# Usage\nbreaker = CircuitBreaker(threshold=5)\ntry:\n    result = breaker.call(api_call, url)\nexcept CircuitOpenError:\n    print(\"Too many failures, waiting before retry\")\n```\n\n## Bästa praxis\n\n> [!TIP]\n> - **Försök alltid om övergående fel** — nätverk går ner, servrar händer\n> - **Försök inte om klientfel (4xx)** — de fixar inte sig själva\n> - **Lagra fel som minnen** — lär av mönster\n> - **Avisera människor om kritiska fel** — de behöver veta\n> - **Degradera elegant** — partiellt arbete är bättre än krasch\n> - **Använd strömbrytare** — belasta inte en tjänst som misslyckas\n\n## Nästa steg\n\n- [Fel API-referens](/docs/api/errors)\n- [Sessionsstart-mönster](/docs/llm-cookbook/session-start-pattern)\n- [Självläkande tester](/docs/guides/self-healing-tests)\n","content_html":"<h1>Felåterställning för agenter</h1>\n<p>Fel inträffar. Nätverk går ner, API:er returnerar 500, Mind Keys löper ut.\nDen här guiden visar hur LLM-agenter ska hantera fel elegant och lära sig av dem.</p>\n<h2>Principer för felhantering</h2>\n<ol>\n<li><strong>Försök igen med backoff</strong> — övergående fel löses ofta</li>\n<li><strong>Lagra felet</strong> — lär av mönster</li>\n<li><strong>Degradera elegant</strong> — krascha inte hela sessionen</li>\n<li><strong>Avisera människan</strong> — för fel ni inte kan lösa</li>\n</ol>\n<h2>HTTP-felhantering</h2>\n<h3>Försök igen med exponentiell backoff</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-keyword\">import</span> time\n<span class=\"hljs-keyword\">import</span> requests\n\n<span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">call_with_retry</span>(<span class=\"hljs-params\">url, max_retries=<span class=\"hljs-number\">3</span>, backoff_base=<span class=\"hljs-number\">2</span></span>):\n    <span class=\"hljs-string\">&quot;&quot;&quot;Call URL with exponential backoff.&quot;&quot;&quot;</span>\n    <span class=\"hljs-keyword\">for</span> attempt <span class=\"hljs-keyword\">in</span> <span class=\"hljs-built_in\">range</span>(max_retries):\n        <span class=\"hljs-keyword\">try</span>:\n            r = requests.get(url, headers={<span class=\"hljs-string\">&quot;Authorization&quot;</span>: <span class=\"hljs-string\">f&quot;Bearer <span class=\"hljs-subst\">{KEY}</span>&quot;</span>})\n            \n            <span class=\"hljs-comment\"># Success</span>\n            <span class=\"hljs-keyword\">if</span> r.status_code &lt; <span class=\"hljs-number\">400</span>:\n                <span class=\"hljs-keyword\">return</span> r\n            \n            <span class=\"hljs-comment\"># Rate limited — wait and retry</span>\n            <span class=\"hljs-keyword\">if</span> r.status_code == <span class=\"hljs-number\">429</span>:\n                wait = <span class=\"hljs-built_in\">int</span>(r.headers.get(<span class=\"hljs-string\">&quot;Retry-After&quot;</span>, <span class=\"hljs-number\">60</span>))\n                <span class=\"hljs-built_in\">print</span>(<span class=\"hljs-string\">f&quot;Rate limited. Waiting <span class=\"hljs-subst\">{wait}</span>s...&quot;</span>)\n                time.sleep(wait)\n                <span class=\"hljs-keyword\">continue</span>\n            \n            <span class=\"hljs-comment\"># Server error — retry with backoff</span>\n            <span class=\"hljs-keyword\">if</span> r.status_code &gt;= <span class=\"hljs-number\">500</span>:\n                wait = backoff_base ** attempt\n                <span class=\"hljs-built_in\">print</span>(<span class=\"hljs-string\">f&quot;Server error <span class=\"hljs-subst\">{r.status_code}</span>. Retrying in <span class=\"hljs-subst\">{wait}</span>s...&quot;</span>)\n                time.sleep(wait)\n                <span class=\"hljs-keyword\">continue</span>\n            \n            <span class=\"hljs-comment\"># Client error — don&#x27;t retry</span>\n            <span class=\"hljs-keyword\">if</span> <span class=\"hljs-number\">400</span> &lt;= r.status_code &lt; <span class=\"hljs-number\">500</span>:\n                <span class=\"hljs-keyword\">raise</span> ClientError(<span class=\"hljs-string\">f&quot;<span class=\"hljs-subst\">{r.status_code}</span>: <span class=\"hljs-subst\">{r.text}</span>&quot;</span>)\n        \n        <span class=\"hljs-keyword\">except</span> requests.RequestException <span class=\"hljs-keyword\">as</span> e:\n            <span class=\"hljs-comment\"># Network error — retry</span>\n            wait = backoff_base ** attempt\n            <span class=\"hljs-built_in\">print</span>(<span class=\"hljs-string\">f&quot;Network error: <span class=\"hljs-subst\">{e}</span>. Retrying in <span class=\"hljs-subst\">{wait}</span>s...&quot;</span>)\n            time.sleep(wait)\n    \n    <span class=\"hljs-keyword\">raise</span> MaxRetriesError(<span class=\"hljs-string\">f&quot;Failed after <span class=\"hljs-subst\">{max_retries}</span> retries&quot;</span>)</code></pre><h3>Auth-felhantering</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">safe_call</span>(<span class=\"hljs-params\">url</span>):\n    <span class=\"hljs-string\">&quot;&quot;&quot;Call with auth error handling.&quot;&quot;&quot;</span>\n    <span class=\"hljs-keyword\">try</span>:\n        <span class=\"hljs-keyword\">return</span> call_with_retry(url)\n    <span class=\"hljs-keyword\">except</span> ClientError <span class=\"hljs-keyword\">as</span> e:\n        <span class=\"hljs-keyword\">if</span> <span class=\"hljs-string\">&quot;401&quot;</span> <span class=\"hljs-keyword\">in</span> <span class=\"hljs-built_in\">str</span>(e):\n            <span class=\"hljs-comment\"># Mind Key invalid — critical, can&#x27;t recover</span>\n            store_error(<span class=\"hljs-string\">&quot;auth_invalid&quot;</span>, <span class=\"hljs-built_in\">str</span>(e), <span class=\"hljs-string\">&quot;Check Mind Key&quot;</span>)\n            notify_human(<span class=\"hljs-string\">&quot;My Mind Key is invalid. Please update.&quot;</span>)\n            <span class=\"hljs-keyword\">raise</span> AuthError(<span class=\"hljs-string\">&quot;Cannot continue without valid Mind Key&quot;</span>)\n        <span class=\"hljs-keyword\">elif</span> <span class=\"hljs-string\">&quot;403&quot;</span> <span class=\"hljs-keyword\">in</span> <span class=\"hljs-built_in\">str</span>(e):\n            store_error(<span class=\"hljs-string\">&quot;forbidden&quot;</span>, <span class=\"hljs-built_in\">str</span>(e), <span class=\"hljs-string\">&quot;Wrong token type?&quot;</span>)\n            <span class=\"hljs-keyword\">raise</span> ForbiddenError(<span class=\"hljs-built_in\">str</span>(e))\n        <span class=\"hljs-keyword\">elif</span> <span class=\"hljs-string\">&quot;404&quot;</span> <span class=\"hljs-keyword\">in</span> <span class=\"hljs-built_in\">str</span>(e):\n            <span class=\"hljs-comment\"># Path doesn&#x27;t exist — don&#x27;t retry</span>\n            store_error(<span class=\"hljs-string\">&quot;not_found&quot;</span>, <span class=\"hljs-built_in\">str</span>(e), <span class=\"hljs-string\">&quot;Check endpoint path&quot;</span>)\n            <span class=\"hljs-keyword\">raise</span> NotFoundError(<span class=\"hljs-built_in\">str</span>(e))\n        <span class=\"hljs-keyword\">else</span>:\n            <span class=\"hljs-keyword\">raise</span></code></pre><h2>Lagra fel som minnen</h2>\n<p>När fel inträffar, lagra dem så framtida sessioner kan lära:</p>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">store_error</span>(<span class=\"hljs-params\">error_type, error_message, recovery_hint=<span class=\"hljs-string\">&quot;&quot;</span></span>):\n    <span class=\"hljs-string\">&quot;&quot;&quot;Store an error as a memory for future reference.&quot;&quot;&quot;</span>\n    requests.post(<span class=\"hljs-string\">f&quot;<span class=\"hljs-subst\">{URL}</span>/memory&quot;</span>,\n        headers={<span class=\"hljs-string\">&quot;Authorization&quot;</span>: <span class=\"hljs-string\">f&quot;Bearer <span class=\"hljs-subst\">{KEY}</span>&quot;</span>,\n                 <span class=\"hljs-string\">&quot;Content-Type&quot;</span>: <span class=\"hljs-string\">&quot;application/json&quot;</span>},\n        json={\n            <span class=\"hljs-string\">&quot;category&quot;</span>: <span class=\"hljs-string\">&quot;mistake&quot;</span>,\n            <span class=\"hljs-string\">&quot;key&quot;</span>: <span class=\"hljs-string\">f&quot;error_<span class=\"hljs-subst\">{error_type}</span>_<span class=\"hljs-subst\">{<span class=\"hljs-built_in\">int</span>(time.time())}</span>&quot;</span>,\n            <span class=\"hljs-string\">&quot;content&quot;</span>: <span class=\"hljs-string\">f&quot;Error: <span class=\"hljs-subst\">{error_type}</span>\\nMessage: <span class=\"hljs-subst\">{error_message}</span>\\nRecovery: <span class=\"hljs-subst\">{recovery_hint}</span>&quot;</span>,\n            <span class=\"hljs-string\">&quot;tags&quot;</span>: [<span class=\"hljs-string\">&quot;error&quot;</span>, error_type],\n            <span class=\"hljs-string\">&quot;priority&quot;</span>: <span class=\"hljs-string\">&quot;high&quot;</span>\n        })\n\n<span class=\"hljs-comment\"># Example</span>\n<span class=\"hljs-keyword\">try</span>:\n    deploy()\n<span class=\"hljs-keyword\">except</span> DeployError <span class=\"hljs-keyword\">as</span> e:\n    store_error(<span class=\"hljs-string\">&quot;deploy_failed&quot;</span>, <span class=\"hljs-built_in\">str</span>(e), \n                <span class=\"hljs-string\">&quot;Check CI logs, verify Docker image exists&quot;</span>)\n    <span class=\"hljs-keyword\">raise</span></code></pre><h2>Vanliga felscenarier</h2>\n<h3>Scenario 1: Ogiltig Mind Key</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># Detection: 401 on every call</span>\n<span class=\"hljs-comment\"># Recovery: Cannot recover — need human intervention</span>\n\n<span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">handle_invalid_mind_key</span>():\n    store_error(<span class=\"hljs-string\">&quot;mind_key_invalid&quot;</span>, \n                <span class=\"hljs-string\">&quot;All API calls returning 401&quot;</span>,\n                <span class=\"hljs-string\">&quot;Mind Key may be revoked. Need new key.&quot;</span>)\n    \n    <span class=\"hljs-comment\"># Notify human via chat (if possible)</span>\n    <span class=\"hljs-keyword\">try</span>:\n        reply(<span class=\"hljs-string\">&quot;⚠️ My Mind Key is invalid. I cannot access memories. &quot;</span>\n              <span class=\"hljs-string\">&quot;Please check and update SYNAPSE_MIND_KEY.&quot;</span>)\n    <span class=\"hljs-keyword\">except</span>:\n        <span class=\"hljs-keyword\">pass</span>  <span class=\"hljs-comment\"># Chat may also fail with bad key</span>\n    \n    <span class=\"hljs-comment\"># Exit gracefully</span>\n    <span class=\"hljs-keyword\">raise</span> CriticalError(<span class=\"hljs-string\">&quot;Cannot continue without valid Mind Key&quot;</span>)</code></pre><h3>Scenario 2: Nätverksfel</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># Detection: ConnectionError, Timeout</span>\n<span class=\"hljs-comment\"># Recovery: Retry with backoff, then degrade</span>\n\n<span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">handle_network_error</span>(<span class=\"hljs-params\">url, retry=<span class=\"hljs-number\">3</span></span>):\n    <span class=\"hljs-keyword\">for</span> attempt <span class=\"hljs-keyword\">in</span> <span class=\"hljs-built_in\">range</span>(retry):\n        <span class=\"hljs-keyword\">try</span>:\n            <span class=\"hljs-keyword\">return</span> requests.get(url, timeout=<span class=\"hljs-number\">10</span>)\n        <span class=\"hljs-keyword\">except</span> (requests.ConnectionError, requests.Timeout) <span class=\"hljs-keyword\">as</span> e:\n            wait = <span class=\"hljs-number\">2</span> ** attempt\n            <span class=\"hljs-built_in\">print</span>(<span class=\"hljs-string\">f&quot;Network error, retrying in <span class=\"hljs-subst\">{wait}</span>s: <span class=\"hljs-subst\">{e}</span>&quot;</span>)\n            time.sleep(wait)\n    \n    <span class=\"hljs-comment\"># All retries failed — degrade</span>\n    store_error(<span class=\"hljs-string\">&quot;network_failure&quot;</span>, \n                <span class=\"hljs-string\">f&quot;Cannot reach <span class=\"hljs-subst\">{url}</span>&quot;</span>,\n                <span class=\"hljs-string\">&quot;Check internet connection, Synapse may be down&quot;</span>)\n    \n    <span class=\"hljs-comment\"># Work offline if possible</span>\n    <span class=\"hljs-keyword\">return</span> work_offline()</code></pre><h3>Scenario 3: Hastighetsbegränsad</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># Detection: 429 with Retry-After header</span>\n<span class=\"hljs-comment\"># Recovery: Wait and retry, or switch to header auth</span>\n\n<span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">handle_rate_limit</span>(<span class=\"hljs-params\">response</span>):\n    retry_after = <span class=\"hljs-built_in\">int</span>(response.headers.get(<span class=\"hljs-string\">&quot;Retry-After&quot;</span>, <span class=\"hljs-number\">60</span>))\n    <span class=\"hljs-built_in\">print</span>(<span class=\"hljs-string\">f&quot;Rate limited. Waiting <span class=\"hljs-subst\">{retry_after}</span>s...&quot;</span>)\n    time.sleep(retry_after)\n    \n    <span class=\"hljs-comment\"># If this keeps happening, suggest switching to header auth</span>\n    <span class=\"hljs-keyword\">if</span> has_query_param_auth(url):\n        store_error(<span class=\"hljs-string\">&quot;rate_limited&quot;</span>, \n                    <span class=\"hljs-string\">&quot;Frequent 429s with ?key= auth&quot;</span>,\n                    <span class=\"hljs-string\">&quot;Switch to Authorization: Bearer header (no rate limit)&quot;</span>)</code></pre><h3>Scenario 4: Serverfel (5xx)</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># Detection: 500, 502, 503</span>\n<span class=\"hljs-comment\"># Recovery: Retry with backoff, check /health</span>\n\n<span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">handle_server_error</span>(<span class=\"hljs-params\">url</span>):\n    <span class=\"hljs-comment\"># Check if server is up</span>\n    health = requests.get(<span class=\"hljs-string\">f&quot;<span class=\"hljs-subst\">{URL}</span>/health&quot;</span>)\n    <span class=\"hljs-keyword\">if</span> health.status_code != <span class=\"hljs-number\">200</span>:\n        store_error(<span class=\"hljs-string\">&quot;server_down&quot;</span>, \n                    <span class=\"hljs-string\">&quot;Synapse health check failing&quot;</span>,\n                    <span class=\"hljs-string\">&quot;Wait for server recovery&quot;</span>)\n        <span class=\"hljs-keyword\">raise</span> ServerDownError()\n    \n    <span class=\"hljs-comment\"># Retry with backoff</span>\n    <span class=\"hljs-keyword\">return</span> call_with_retry(url, max_retries=<span class=\"hljs-number\">5</span>)</code></pre><h3>Scenario 5: Verktygsanrop misslyckas</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># Detection: Tool returns error content</span>\n<span class=\"hljs-comment\"># Recovery: Try alternative approach, store failure</span>\n\n<span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">call_tool_safely</span>(<span class=\"hljs-params\">tool_name, args, alternatives=<span class=\"hljs-literal\">None</span></span>):\n    <span class=\"hljs-keyword\">try</span>:\n        result = call_tool(tool_name, args)\n        <span class=\"hljs-keyword\">if</span> result.get(<span class=\"hljs-string\">&quot;isError&quot;</span>):\n            <span class=\"hljs-keyword\">raise</span> ToolError(result[<span class=\"hljs-string\">&quot;content&quot;</span>])\n        <span class=\"hljs-keyword\">return</span> result\n    <span class=\"hljs-keyword\">except</span> ToolError <span class=\"hljs-keyword\">as</span> e:\n        store_error(<span class=\"hljs-string\">f&quot;tool_<span class=\"hljs-subst\">{tool_name}</span>_failed&quot;</span>,\n                    <span class=\"hljs-string\">f&quot;Args: <span class=\"hljs-subst\">{args}</span>\\nError: <span class=\"hljs-subst\">{e}</span>&quot;</span>,\n                    <span class=\"hljs-string\">f&quot;Try: <span class=\"hljs-subst\">{alternatives <span class=\"hljs-keyword\">or</span> <span class=\"hljs-string\">&#x27;no alternatives&#x27;</span>}</span>&quot;</span>)\n        \n        <span class=\"hljs-comment\"># Try alternatives</span>\n        <span class=\"hljs-keyword\">if</span> alternatives:\n            <span class=\"hljs-keyword\">for</span> alt <span class=\"hljs-keyword\">in</span> alternatives:\n                <span class=\"hljs-keyword\">try</span>:\n                    <span class=\"hljs-keyword\">return</span> call_tool(alt, args)\n                <span class=\"hljs-keyword\">except</span>:\n                    <span class=\"hljs-keyword\">continue</span>\n        \n        <span class=\"hljs-keyword\">raise</span></code></pre><h2>Mönster: Strömbrytare</h2>\n<p>För upprepade fel, sluta försöka tillfälligt:</p>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-keyword\">class</span> <span class=\"hljs-title class_\">CircuitBreaker</span>:\n    <span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">__init__</span>(<span class=\"hljs-params\">self, threshold=<span class=\"hljs-number\">5</span>, reset_time=<span class=\"hljs-number\">300</span></span>):\n        <span class=\"hljs-variable language_\">self</span>.failures = <span class=\"hljs-number\">0</span>\n        <span class=\"hljs-variable language_\">self</span>.threshold = threshold\n        <span class=\"hljs-variable language_\">self</span>.reset_time = reset_time\n        <span class=\"hljs-variable language_\">self</span>.last_failure = <span class=\"hljs-number\">0</span>\n    \n    <span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">call</span>(<span class=\"hljs-params\">self, fn, *args, **kwargs</span>):\n        <span class=\"hljs-keyword\">if</span> <span class=\"hljs-variable language_\">self</span>.failures &gt;= <span class=\"hljs-variable language_\">self</span>.threshold:\n            <span class=\"hljs-keyword\">if</span> time.time() - <span class=\"hljs-variable language_\">self</span>.last_failure &lt; <span class=\"hljs-variable language_\">self</span>.reset_time:\n                <span class=\"hljs-keyword\">raise</span> CircuitOpenError(<span class=\"hljs-string\">&quot;Circuit breaker open&quot;</span>)\n            <span class=\"hljs-keyword\">else</span>:\n                <span class=\"hljs-comment\"># Reset</span>\n                <span class=\"hljs-variable language_\">self</span>.failures = <span class=\"hljs-number\">0</span>\n        \n        <span class=\"hljs-keyword\">try</span>:\n            result = fn(*args, **kwargs)\n            <span class=\"hljs-variable language_\">self</span>.failures = <span class=\"hljs-number\">0</span>  <span class=\"hljs-comment\"># Reset on success</span>\n            <span class=\"hljs-keyword\">return</span> result\n        <span class=\"hljs-keyword\">except</span>:\n            <span class=\"hljs-variable language_\">self</span>.failures += <span class=\"hljs-number\">1</span>\n            <span class=\"hljs-variable language_\">self</span>.last_failure = time.time()\n            <span class=\"hljs-keyword\">raise</span>\n\n<span class=\"hljs-comment\"># Usage</span>\nbreaker = CircuitBreaker(threshold=<span class=\"hljs-number\">5</span>)\n<span class=\"hljs-keyword\">try</span>:\n    result = breaker.call(api_call, url)\n<span class=\"hljs-keyword\">except</span> CircuitOpenError:\n    <span class=\"hljs-built_in\">print</span>(<span class=\"hljs-string\">&quot;Too many failures, waiting before retry&quot;</span>)</code></pre><h2>Bästa praxis</h2>\n<div class=\"callout callout-ok\"></div><h2>Nästa steg</h2>\n<ul>\n<li><a href=\"/docs/api/errors\">Fel API-referens</a></li>\n<li><a href=\"/docs/llm-cookbook/session-start-pattern\">Sessionsstart-mönster</a></li>\n<li><a href=\"/docs/guides/self-healing-tests\">Självläkande tester</a></li>\n</ul>\n","urls":{"html":"/docs/llm-cookbook/error-recovery","text":"/docs/llm-cookbook/error-recovery?format=text","json":"/docs/llm-cookbook/error-recovery?format=json","llm":"/docs/llm-cookbook/error-recovery?format=llm"},"translations_available":["en","zh","hi","es","fr","ar","pt","ru","ja","de","it","ko","nl","pl","tr","sv","vi","th","id","uk"]}