المستوى المطلوب: متوسط — تحتاج تكون عامل request لـ LLM API قبل كده، وتعرف JSON أساسي. مش لازم خبرة سابقة في الـ agents.
Function Calling: خلّي الـ LLM ينفّذ بدل ما يخمّن
لو ربطت شات بوت بموقعك ولقيته بيرد على العميل برقم طلب أو سعر أو حالة شحن مخترعة، ركّز: ده مش bug في النموذج. ده بالظبط اللي بيحصل لمّا تطلب من LLM بيانات حيّة وانت مديتهوش طريقة يجيبها. الحل اسمه Function Calling، وفي المقال ده هتطلع عارف تطبّقه بكود شغّال في أقل من 20 سطر.
المشكلة باختصار
الـ LLM بيتنبّأ بالكلمة اللي بعدها بناءً على الاحتمالات. هو مايعرفش حالة طلب رقمه ORD-10293، فبيولّد جملة تبان صح: "طلبك في الطريق، هيوصل بكرة". الجملة سليمة لغويًا، لكنها اختراع كامل. لو عندك متجر بـ 50 ألف زائر/يوم وشات بوت بيرد على استفسارات الطلبات، كل رد مخترع ده تذكرة دعم زيادة وعميل مكسور الثقة.
الفكرة بمثال: الموظف الجديد
تخيّل موظف استقبال جديد في شركة. عميل اتصل وسأل: "وصل طلبي ولا لسه؟". في إيد الموظف طريقين. الأول إنه يرد من دماغه علشان ميبانش جاهل: "آه وصل، متقلقش". ده بالظبط اللي الـ LLM بيعمله من غير tools — بيجاوب بثقة من بيانات مش موجودة عنده. الطريق التاني إنه يقول "ثانية واحدة"، يرفع سماعة المخزن، يسأل، وبعدين يرد بالإجابة الحقيقية.
Function Calling بيدّي الـ LLM السماعة دي. بدل ما يخمّن، بيقولك: "أنا محتاج أنادي دالة get_order_status وأديها الرقم ده". انت بتنفّذ الدالة وترجّعله النتيجة، وهو يصيغ الرد النهائي على البيانات الصح.
التعريف العلمي
Function Calling (واسمه التاني Tool Use، والمصطلحين مترادفين) هو عقد بين تطبيقك والنموذج. انت بتعرّف للنموذج مجموعة أدوات، كل أداة ليها اسم، وصف بلغة طبيعية، وJSON Schema بيحدد شكل المدخلات. النموذج بيقرر إمتى وبأي وسائط يستدعي الأداة، لكنه مابينفّذش حاجة بنفسه. هو بس بيصدر طلب منظّم (block اسمه tool_use)، كودك ينفّذ العملية، والنتيجة ترجع للمحادثة في block اسمه tool_result. الحلقة دي بتتكرر لحد ما النموذج يبقى عنده كل اللي محتاجه علشان يرد. (المصدر: توثيق Anthropic عن Tool Use).
الكود: tool use على Claude API
هنعرّف أداة واحدة بترجّع حالة طلب. لاحظ إن الدالة الحقيقية get_order_status هي كودك انت — query على الداتابيز أو call على microservice داخلي.
import anthropic
client = anthropic.Anthropic()
tools = [{
"name": "get_order_status",
"description": "يرجّع حالة الطلب الحالية من قاعدة بيانات الطلبات. استخدمه لما العميل يسأل عن طلب برقمه.",
"input_schema": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "رقم الطلب، مثال: ORD-10293"}
},
"required": ["order_id"]
}
}]
def get_order_status(order_id: str) -> dict:
# ده كودك الفعلي — استعلام على الداتابيز بتاعتك
return {"order_id": order_id, "status": "تم الشحن", "eta": "2026-06-20"}
messages = [{"role": "user", "content": "فين طلبي رقم ORD-10293؟"}]
resp = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
messages=messages,
)
# بدل ما يخترع الإجابة، Claude رجّع stop_reason == "tool_use"
if resp.stop_reason == "tool_use":
call = next(b for b in resp.content if b.type == "tool_use")
result = get_order_status(**call.input) # نفّذ الدالة بالوسائط اللي طلبها
messages.append({"role": "assistant", "content": resp.content})
messages.append({"role": "user", "content": [{
"type": "tool_result",
"tool_use_id": call.id,
"content": str(result),
}]})
final = client.messages.create(
model="claude-sonnet-4-6", max_tokens=1024,
tools=tools, messages=messages,
)
print(final.content[0].text)
# -> "طلبك ORD-10293 اتشحن ومتوقع يوصلك يوم 20 يونيو."الفرق الجوهري: الجملة الأخيرة مبنية على status وeta حقيقيين رجعوا من دالتك، مش من خيال النموذج.
الأرقام اللي تهمّك
الـ schema enforcement مش رفاهية. بدون أي إجبار على الشكل، استجابات الـ JSON من النماذج بتفشل في الـ parsing في حوالي 8% إلى 15% من المرات. مع tool use المضبوط، النسبة بتنزل تحت 0.1%؛ التزام الـ schema المعلن عند Anthropic حوالي 99.8% وعند OpenAI Structured Outputs حوالي 99.9% (المصدر: TokenMix Structured Output Guide 2026). الثمن: تعريف الأدوات بيضيف تقريبًا 30 إلى 300 توكن لكل call. الافتراض هنا إن عندك أداة أو أدوات قليلة بـ schema بسيط؛ لو عندك 40 أداة، حجم التعريفات هيبوظ الحساب وهتحتاج تفلتر الأدوات حسب السياق.
trade-offs لازم تاخد بالك منها
- زمن استجابة زيادة: كل استدعاء أداة = round-trip إضافي للنموذج. سؤال محتاج tool واحد بياخد call اتنين بدل واحد. بتكسب الدقة، بتخسر تقريبًا 500 إلى 2000 مللي ثانية.
- تكلفة توكنز: تعريفات الأدوات بتتبعت في كل request. كل أداة زيادة فلوس زيادة على كل رسالة.
- أمان: النموذج بيطلب التنفيذ، انت اللي بتنفّذ. متثقش في وسائط الـ tool call. لو الأداة بتعمل حذف أو تحويل فلوس، اعمل validation و authorization في كودك زي ما بتعمل مع أي input جاي من برّه.
- اللاحتمية: النموذج ممكن يقرر مايستخدمش الأداة، أو يبعت وسيط ناقص. خلّي
requiredواضح في الـ schema، واكتب وصف الأداة كأنك بتشرح لمبرمج جديد.
متى لا تستخدم Function Calling
لو سؤال العميل إجابته نص ثابت معتمد على معرفة النموذج نفسه (زي "إيه سياسة الاسترجاع عندكم؟" والسياسة جوه الـ prompt)، مش محتاج tools — ده تعقيد بزيادة round-trip بدون فايدة. كمان لو انت أصلًا عارف إن كل طلب لازم ينده نفس الـ API بنفس الشكل، اعمل الـ call مباشرة في كودك وحطّ النتيجة في الـ prompt، وخلّي النموذج يصيغ بس. Function Calling بيلمع لمّا القرار بتاع "هل أنده أداة، وأنهي واحدة، وبأي وسائط" نفسه محتاج فهم لغة المستخدم.
المصادر
- Anthropic — Tool use with Claude (Overview)
- Anthropic — How tool use works
- OpenAI — Function calling guide
- TokenMix — Structured Output and JSON Mode Guide 2026 (أرقام التزام الـ schema)
- Agenta — The guide to structured outputs and function calling with LLMs
الخطوة التالية
افتح أكتر سؤال بيتكرر على شات بوتك ومحتاج بيانات حيّة (حالة طلب، رصيد، مواعيد). عرّف أداة واحدة بس ليه بنفس الـ schema اللي فوق، وجرّبها على 20 سؤال حقيقي من الـ logs. قيس كام مرة كان بيخترع قبل، وكام مرة بقى بيجيب الرقم الصح بعد. لو لسه بيخترع، غالبًا وصف الأداة مش واضح كفاية — اكتبه أدق وأعد القياس.