{"title":"التعافي من الأخطاء للوكلاء","slug":"error-recovery","category":"llm-cookbook","summary":"كيف يتعامل وكلاء LLM مع الأخطاء ويتعافون منها — إعادة المحاولة، التخزين، التعلم.","audience":["llm"],"tags":["cookbook","errors","recovery","resilience"],"difficulty":"intermediate","updated":"2026-06-27","word_count":222,"read_minutes":1,"lang":"ar","translated":true,"requested_lang":"ar","content_markdown":"\n# التعافي من الأخطاء للوكلاء\n\nالأخطاء تحدث. الشبكات تفشل، APIs تُرجع 500، Mind Keys تنتهي. يُظهر هذا الدليل\nكيف ينبغي لوكلاء LLM التعامل مع الأخطاء بلطف والتعلّم منها.\n\n## مبادئ معالجة الأخطاء\n\n1. **أعد المحاولة مع تراجع** — الأخطاء العابرة تُحل غالبًا\n2. **خزّن الخطأ** — تعلّم من الأنماط\n3. **تدهور بلطف** — لا تُعطّل الجلسة كاملة\n4. **أبلغ الإنسان** — للأخطاء التي لا تستطيع حلها\n\n## معالجة أخطاء HTTP\n\n### إعادة المحاولة مع تراجع أُسي\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            # نجاح\n            if r.status_code < 400:\n                return r\n            \n            # حد المعدل — انتظر وأعد المحاولة\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            # خطأ خادم — أعد المحاولة مع تراجع\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            # خطأ عميل — لا تعد المحاولة\n            if 400 <= r.status_code < 500:\n                raise ClientError(f\"{r.status_code}: {r.text}\")\n        \n        except requests.RequestException as e:\n            # خطأ شبكة — أعد المحاولة\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### معالجة خطأ المصادقة\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 غير صالح — حرج، لا يمكن التعافي\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            # المسار غير موجود — لا تعد المحاولة\n            store_error(\"not_found\", str(e), \"Check endpoint path\")\n            raise NotFoundError(str(e))\n        else:\n            raise\n```\n\n## تخزين الأخطاء كذكريات\n\nعند وقوع أخطاء، خزّنها حتى تتعلّم الجلسات المستقبلية:\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# مثال\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## سيناريوهات أخطاء شائعة\n\n### السيناريو 1: Mind Key غير صالح\n\n```python\n# الكشف: 401 على كل استدعاء\n# التعافي: لا يمكن التعافي — يحتاج تدخل إنسان\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    # أبلغ الإنسان عبر الدردشة (إن أمكن)\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  # قد تفشل الدردشة أيضًا بمفتاح سيء\n    \n    # اخرج بلطف\n    raise CriticalError(\"Cannot continue without valid Mind Key\")\n```\n\n### السيناريو 2: خطأ شبكة\n\n```python\n# الكشف: ConnectionError، Timeout\n# التعافي: أعد المحاولة مع تراجع، ثم تدهور\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    # فشلت جميع المحاولات — تدهور\n    store_error(\"network_failure\", \n                f\"Cannot reach {url}\",\n                \"Check internet connection, Synapse may be down\")\n    \n    # اعمل دون اتصال إن أمكن\n    return work_offline()\n```\n\n### السيناريو 3: محدود بحد المعدل\n\n```python\n# الكشف: 429 مع ترويسة Retry-After\n# التعافي: انتظر وأعد المحاولة، أو بدّل إلى مصادقة الترويسة\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    # إذا استمر هذا، اقترح التبديل إلى مصادقة الترويسة\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### السيناريو 4: خطأ خادم (5xx)\n\n```python\n# الكشف: 500، 502، 503\n# التعافي: أعد المحاولة مع تراجع، تحقق من /health\n\ndef handle_server_error(url):\n    # تحقق إذا كان الخادم يعمل\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    # أعد المحاولة مع تراجع\n    return call_with_retry(url, max_retries=5)\n```\n\n### السيناريو 5: فشل استدعاء أداة\n\n```python\n# الكشف: الأداة تُرجع محتوى خطأ\n# التعافي: جرب نهجًا بديلًا، خزّن الفشل\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        # جرب البدائل\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## النمط: قاطع الدائرة\n\nللإخفاقات المتكررة، توقف عن المحاولة مؤقتًا:\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                # إعادة تعيين\n                self.failures = 0\n        \n        try:\n            result = fn(*args, **kwargs)\n            self.failures = 0  # إعادة تعيين عند النجاح\n            return result\n        except:\n            self.failures += 1\n            self.last_failure = time.time()\n            raise\n\n# الاستخدام\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## أفضل الممارسات\n\n> [!TIP]\n> - **أعد محاولة الأخطاء العابرة دائمًا** — الشبكات تفشل، الخوادم تتأرجح\n> - **لا تعد محاولة أخطاء العميل (4xx)** — لن تُصلح نفسها\n> - **خزّن الأخطاء كذكريات** — تعلّم من الأنماط\n> - **أبلغ البشر عن الأخطاء الحرجة** — يحتاجون المعرفة\n> - **تدهور بلطف** — العمل الجزئي أفضل من الانهيار\n> - **استخدم قواطع الدائرة** — لا تقصف خدمة فاشلة\n\n## الخطوات التالية\n\n- [مرجع الأخطاء API](/docs/api/errors)\n- [نمط بدء الجلسة](/docs/llm-cookbook/session-start-pattern)\n- [اختبارات ذاتية الإصلاح](/docs/guides/self-healing-tests)\n","content_html":"<h1>التعافي من الأخطاء للوكلاء</h1>\n<p>الأخطاء تحدث. الشبكات تفشل، APIs تُرجع 500، Mind Keys تنتهي. يُظهر هذا الدليل\nكيف ينبغي لوكلاء LLM التعامل مع الأخطاء بلطف والتعلّم منها.</p>\n<h2>مبادئ معالجة الأخطاء</h2>\n<ol>\n<li><strong>أعد المحاولة مع تراجع</strong> — الأخطاء العابرة تُحل غالبًا</li>\n<li><strong>خزّن الخطأ</strong> — تعلّم من الأنماط</li>\n<li><strong>تدهور بلطف</strong> — لا تُعطّل الجلسة كاملة</li>\n<li><strong>أبلغ الإنسان</strong> — للأخطاء التي لا تستطيع حلها</li>\n</ol>\n<h2>معالجة أخطاء HTTP</h2>\n<h3>إعادة المحاولة مع تراجع أُسي</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\"># نجاح</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\"># حد المعدل — انتظر وأعد المحاولة</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\"># خطأ خادم — أعد المحاولة مع تراجع</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\"># خطأ عميل — لا تعد المحاولة</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\"># خطأ شبكة — أعد المحاولة</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>معالجة خطأ المصادقة</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 غير صالح — حرج، لا يمكن التعافي</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\"># المسار غير موجود — لا تعد المحاولة</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>تخزين الأخطاء كذكريات</h2>\n<p>عند وقوع أخطاء، خزّنها حتى تتعلّم الجلسات المستقبلية:</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\"># مثال</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>سيناريوهات أخطاء شائعة</h2>\n<h3>السيناريو 1: Mind Key غير صالح</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># الكشف: 401 على كل استدعاء</span>\n<span class=\"hljs-comment\"># التعافي: لا يمكن التعافي — يحتاج تدخل إنسان</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\"># أبلغ الإنسان عبر الدردشة (إن أمكن)</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\"># قد تفشل الدردشة أيضًا بمفتاح سيء</span>\n    \n    <span class=\"hljs-comment\"># اخرج بلطف</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>السيناريو 2: خطأ شبكة</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># الكشف: ConnectionError، Timeout</span>\n<span class=\"hljs-comment\"># التعافي: أعد المحاولة مع تراجع، ثم تدهور</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\"># فشلت جميع المحاولات — تدهور</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\"># اعمل دون اتصال إن أمكن</span>\n    <span class=\"hljs-keyword\">return</span> work_offline()</code></pre><h3>السيناريو 3: محدود بحد المعدل</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># الكشف: 429 مع ترويسة Retry-After</span>\n<span class=\"hljs-comment\"># التعافي: انتظر وأعد المحاولة، أو بدّل إلى مصادقة الترويسة</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\"># إذا استمر هذا، اقترح التبديل إلى مصادقة الترويسة</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>السيناريو 4: خطأ خادم (5xx)</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># الكشف: 500، 502، 503</span>\n<span class=\"hljs-comment\"># التعافي: أعد المحاولة مع تراجع، تحقق من /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\"># تحقق إذا كان الخادم يعمل</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\"># أعد المحاولة مع تراجع</span>\n    <span class=\"hljs-keyword\">return</span> call_with_retry(url, max_retries=<span class=\"hljs-number\">5</span>)</code></pre><h3>السيناريو 5: فشل استدعاء أداة</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># الكشف: الأداة تُرجع محتوى خطأ</span>\n<span class=\"hljs-comment\"># التعافي: جرب نهجًا بديلًا، خزّن الفشل</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\"># جرب البدائل</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>النمط: قاطع الدائرة</h2>\n<p>للإخفاقات المتكررة، توقف عن المحاولة مؤقتًا:</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\"># إعادة تعيين</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\"># إعادة تعيين عند النجاح</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\"># الاستخدام</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>أفضل الممارسات</h2>\n<div class=\"callout callout-ok\"></div><h2>الخطوات التالية</h2>\n<ul>\n<li><a href=\"/docs/api/errors\">مرجع الأخطاء API</a></li>\n<li><a href=\"/docs/llm-cookbook/session-start-pattern\">نمط بدء الجلسة</a></li>\n<li><a href=\"/docs/guides/self-healing-tests\">اختبارات ذاتية الإصلاح</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"]}