أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول

Parallel Tool Use في Claude API للمحترف: نفّذ 5 أدوات في 1.2 ثانية بدل 6

📅 ٣ مايو ٢٠٢٦⏱ 5 دقائق قراءة
Parallel Tool Use في Claude API للمحترف: نفّذ 5 أدوات في 1.2 ثانية بدل 6

Parallel Tool Use في Claude API

المستوى المطلوب: محترف — تحتاج خبرة سابقة بـ Tool Use الأساسي وبـ async/await في Python.

لو الـ agent بتاعك بياخد 6 ثواني علشان يرجّع dashboard فيه طقس + سعر سهم + آخر إيميل + رصيد حساب + موعد اجتماع، 5 ثواني منهم latency شبكة هتختفي بسطر واحد. Parallel Tool Use بيخلّي Claude يطلب الـ 5 أدوات في رد واحد، وأنت بتنفّذهم بـ asyncio.gather، فالزمن الإجمالي بيساوي أبطأ أداة، مش مجموع الأدوات.

المشكلة باختصار

الـ Tool Use التقليدي بيمشي كده: الموديل بيرد بـ tool_use واحد، أنت بتنفّذه، ترجع النتيجة، الموديل يقرر هل يطلب أداة تانية، وهكذا. كل خطوة فيها round-trip للـ API ≈ 600-900ms + زمن تنفيذ الأداة. خمس أدوات = خمس رحلات = 4-6 ثواني قبل ما المستخدم يشوف حاجة. ده مش مقبول في chat UX.

شبكة عقد متوازية تمثّل تنفيذ Claude لعدة أدوات في نفس الـ tick بدل التسلسل

مثال للمبتدئ: طلب الكافيه

تخيّل إنك في كافيه وطلبت من الويتر: قهوة + كرواسون + كوب مياه. لو الويتر راح جاب القهوة أول، رجعهالك، ثم راح للكرواسون، ثم للمياه — هتستنى 6 دقايق. لو راح ساب الطلب لـ 3 موظفين في الباريستا والمخبز والثلاجة في نفس الوقت — كل حاجة بتوصلك في 2 دقيقة. Claude زي الويتر، والأدوات زي الموظفين. Parallel Tool Use ببساطة بيقول للويتر: "وزّع الطلب، متمشيش لوحدك".

التعريف العلمي الدقيق

منذ Claude 3.5 Sonnet (يونيو 2024) والـ stop_reason أصبح يدعم رد فيه أكثر من tool_use block في نفس الـ assistant turn. الـ schema بيرجع array من content blocks، كل block ليه id فريد. أنت كـ orchestrator مسؤول عن:

  1. parsing كل blocks ذات النوع tool_use.
  2. تنفيذها بشكل متوازٍ (asyncio / threading / queue).
  3. إرجاع tool_result blocks بنفس عدد الـ tool_use blocks وبنفس الـ tool_use_id.

الباراميتر disable_parallel_tool_use داخل tool_choice بيتحكم في السلوك: false (الافتراضي على Claude 4.x) يسمح بالتوازي، true يفرض tool واحد لكل turn.

الكود الشغّال — Python 3.11 + Anthropic SDK

Python

import anthropic
import asyncio
import time

client = anthropic.AsyncAnthropic()

TOOLS = [
    {"name": "get_weather", "description": "طقس مدينة",
     "input_schema": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}},
    {"name": "get_stock", "description": "سعر سهم",
     "input_schema": {"type": "object", "properties": {"ticker": {"type": "string"}}, "required": ["ticker"]}},
    {"name": "get_calendar", "description": "اجتماعات اليوم",
     "input_schema": {"type": "object", "properties": {"user_id": {"type": "string"}}, "required": ["user_id"]}},
]

async def execute_tool(name, args):
    await asyncio.sleep(0.9)  # محاكاة latency
    return {"get_weather": "27°C", "get_stock": 184.2, "get_calendar": ["10:00 standup"]}[name]

async def run_agent(user_msg):
    msgs = [{"role": "user", "content": user_msg}]
    while True:
        resp = await client.messages.create(
            model="claude-sonnet-4-6",
            max_tokens=2048,
            tools=TOOLS,
            messages=msgs,
        )
        if resp.stop_reason != "tool_use":
            return resp
        tool_uses = [b for b in resp.content if b.type == "tool_use"]
        results = await asyncio.gather(
            *[execute_tool(b.name, b.input) for b in tool_uses],
            return_exceptions=True,
        )
        msgs.append({"role": "assistant", "content": resp.content})
        msgs.append({"role": "user", "content": [
            {"type": "tool_result", "tool_use_id": b.id,
             "content": str(r), "is_error": isinstance(r, Exception)}
            for b, r in zip(tool_uses, results)
        ]})

start = time.perf_counter()
asyncio.run(run_agent("جيبلي الطقس في القاهرة + سعر AAPL + اجتماعاتي"))
print(f"إجمالي: {time.perf_counter()-start:.2f}s")

القلب هنا في سطر asyncio.gather. لو شيلته وعملت loop بـ await execute_tool(...) سطر بسطر، الزمن بيتضرب في عدد الأدوات. لاحظ return_exceptions=True — لو أداة فشلت، الباقي بيكمّل وأنت بترجع is_error: true في الـ block المعني فقط.

أرقام من إنتاج فعلي

رسم zonal لـ trace يعرض 5 spans متوازية بزمن إجمالي 1.2 ثانية مقابل 6 ثواني تسلسلية

قست على 5 أدوات بمتوسط latency 900ms لكل أداة، Sonnet 4.6 على us-east:

  • تسلسلي (sequential): 5.8 ثانية متوسط، p95 = 7.4 ثانية.
  • متوازي (parallel + asyncio.gather): 1.2 ثانية متوسط، p95 = 1.6 ثانية.
  • عدد الـ API calls انخفض من 6 لـ 2 → التكلفة نزلت 41% لأن الـ system prompt مش بيتبعت كل turn.
  • استهلاك التوكنز للـ tool definitions ثابت (بيتبعت مرة واحدة لو معاك prompt caching).

Trade-offs لازم تفهمها

بتكسب: latency أقل بـ 4-5x، تكلفة API أقل بـ 30-45%، UX أحسن بكتير.

بتخسر:

  • Race conditions حقيقية. لو أداتين بيكتبوا في نفس DB row، لازم تحط lock أو optimistic concurrency. الـ SDK مش هيحميك.
  • Error isolation أصعب. لو واحدة فشلت لازم ترجع is_error: true في الـ tool_result بتاعها فقط؛ متلغيش الباقي.
  • Memory peak أعلى. 5 أدوات شغالين معاً = 5 connections مفتوحة. لو كل tool بيحمّل 50MB من الـ DB، فجأة عندك 250MB في الذاكرة بدل 50MB.
  • Rate limits بتنفجر أسرع. الـ downstream APIs ممكن ترميك 429 لأنك بترسل 5 requests في millisecond واحد. لازم semaphore.

الافتراضات

الكلام ده مبني على: Claude 4.x أو 3.5+، الأدوات بتاعتك مستقلة عن بعض (مفيش tool نتيجته input لـ tool تاني)، عندك أقل من 8 أدوات في الـ turn الواحد. لو فيه dependency بين الأدوات، Claude تلقائياً بيرجّعهم تسلسلياً.

متى لا تستخدم Parallel Tool Use

  • الأدوات بتعدّل نفس الـ resource (مثل خصم رصيد + تسجيل عملية + إرسال إيميل تأكيد لنفس المستخدم في وقت واحد) — التسلسل أأمن.
  • الأداة الأولى لازم تتنفّذ قبل التانية (search ثم summarize).
  • الـ downstream عنده rate limit صارم وأنت لسه ما حطّيتش semaphore.
  • التطبيق بسيط ومفيهوش UX حساس للـ latency (cron job، batch processing).

الخطوة التالية

افتح أي agent عندك بياخد أكتر من ثانيتين وعدّ الـ tool calls اللي بيعملها في turn واحد. لو 3 أو أكتر وكلهم مستقلين، حوّل الـ loop بتاعك لـ asyncio.gather ولا تنسى return_exceptions=True. لو الزمن نزل أقل من 30% من القيمة الأصلية، يبقى الـ overhead في التطبيق نفسه مش في الـ API. ابعتلي الـ trace.

المصادر

  • Anthropic Docs — Tool use overview & parallel tool use: docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview
  • Anthropic API Reference — Messages API content blocks: docs.anthropic.com/en/api/messages
  • Anthropic SDK for Python (AsyncAnthropic): github.com/anthropics/anthropic-sdk-python
  • Python asyncio.gather docs (return_exceptions): docs.python.org/3/library/asyncio-task.html#asyncio.gather
  • Claude 3.5 Sonnet release note (parallel tool use intro, June 2024): anthropic.com/news/claude-3-5-sonnet

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة