استخدام Claude Tool Use في TypeScript: شرح Agentic

٢٩ مايو ٢٠٢٦

Claude Tool Use in TypeScript: Agentic Loop Tutorial (2026)

لاستخدام ميزة استخدام الأدوات (tool use) مع Claude API في TypeScript، قم بتثبيت @anthropic-ai/sdk، وعرّف الأدوات باستخدام name، و description، و JSON Schema input_schema، ثم قم بعمل حلقة تكرارية (loop) على client.messages.create حتى يصبح stop_reason هو end_turn، مع تنفيذ الأدوات وإرسال النتائج مرة أخرى ككتل محتوى tool_result في كل دورة tool_use1.

ملخص

ستقوم ببناء سكربت TypeScript بملف واحد (حوالي 140 سطرًا بما في ذلك تعريفات الأدوات والتحقق من صحتها) يحول Claude Sonnet 4.6 إلى وكيل (agent) يمكنه استدعاء وظائفك الخاصة. بيئة التشغيل هي Node 24 LTS، والـ SDK هو @anthropic-ai/sdk@0.98.0، ويتم التحقق من مدخلات الأدوات بواسطة Zod. بحلول النهاية، سيكون لديك حلقة وكيل (agentic loop) تعمل وتوزع المهام على أداتين بالتوازي، وتعالج الأخطاء بوضوح، وتخرج عند end_turn. وقت البناء: 20-25 دقيقة.

ما ستتعلمه

  • كيف يحول Claude messages.create API قائمة من الأدوات إلى حلقة وكيل مدفوعة بـ stop_reason
  • كيفية كتابة JSON Schema صارم لـ input_schema والتحقق من input الخاص بالنموذج باستخدام Zod 4 أثناء التشغيل
  • كيفية عمل استدعاءات الأدوات المتوازية — كتل tool_use متعددة في استجابة واحدة، يتم الرد عليها جميعًا في رسالة مستخدم واحدة
  • قاعدة "يجب أن يأتي tool_result أولاً في مصفوفة محتوى المستخدم" التي تسبب أخطاء 400 عند مخالفتها
  • كيفية تعيين كل stop_reason (end_turn، tool_use، max_tokens، pause_turn، refusal، model_context_window_exceeded) إلى مسار استرداد
  • متى تفرض استخدام الأداة باستخدام tool_choice ومتى تتركها على auto

المتطلبات الأساسية

  • Node.js 24 LTS (LTS نشط اعتبارًا من مايو 2026، مدعوم حتى أبريل 2028)2 — Node 22 في مرحلة الصيانة (Maintenance LTS) يعمل أيضًا، ولكن يوصى بـ Node 24
  • مفتاح Anthropic API من لوحة تحكم منصة Claude، يتم تصديره كـ ANTHROPIC_API_KEY
  • ميزانية بسيطة لـ API — تشغيل التحقق في نهاية هذا البرنامج التعليمي يكلف جزءًا بسيطًا من السنت بأسعار Sonnet 4.6 (3 دولارات لكل مليون توكن مدخلات، 15 دولارًا لكل مليون توكن مخرجات)3

كيف يمكنني استخدام ميزة استخدام الأدوات مع Claude API في TypeScript؟

استخدام الأدوات في Claude API هو عبارة عن حلقة طلب واستجابة: ترسل messages.create مع مصفوفة tools من تعريفات JSON Schema، ويعيد Claude إما إجابة نهائية (stop_reason: "end_turn") أو كتلة واحدة أو أكثر من كتل محتوى tool_use (stop_reason: "tool_use")، ثم يقوم الكود الخاص بك بتشغيل الأدوات، وترسل المخرجات مرة أخرى ككتل tool_result في رسالة المستخدم التالية1. نفس الاستدعاء يستأنف المحادثة؛ Claude لا يحتفظ بحالة الخادم (server-side state) بين الدورات.

معامل tools هو نفس الشكل الذي استخدمه Claude منذ إطلاق الميزة للجميع: كل أداة هي { name, description, input_schema }. الـ name يطابق ^[a-zA-Z0-9_-]{1,64}$، والـ input_schema هو كائن JSON Schema 2020-12، والـ description هو نص عادي — توصي Anthropic بـ 3-4 جمل أو أكثر لأي شيء غير بسيط1.

الخطوة 1 — تجهيز المشروع

mkdir claude-tools-agent && cd claude-tools-agent
npm init -y
npm pkg set type="module"
npm install --save-exact @anthropic-ai/sdk@0.98.0 zod@4.4.3
npm install --save-exact -D TypeScript@6.0.3 tsx@4.22.3 @types/node@24.12.4

خيار --save-exact يكتب "@anthropic-ai/sdk": "0.98.0" (بدون علامة caret) حتى لا يقوم أي npm install مستقبلي بتحديثك بصمت إلى إصدار رئيسي جديد أو إصدار تجريبي. يرسل Anthropic TypeScript SDK تحديثات متكررة تم إنشاؤها بواسطة Stainless، لذا فإن التثبيت الدقيق للإصدار هو الخيار الافتراضي الصحيح لقارئ البرنامج التعليمي الذي سيقوم بتشغيل هذا الكود بعد أسابيع من الآن.

الآن ضع ملف tsconfig.json صارم:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "verbatimModuleSyntax": true,
    "allowImportingTsExtensions": true,
    "noEmit": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*.ts"]
}

هناك علامتان تستحقان التسليط عليهما: noUncheckedIndexedAccess تجعل أي وصول للفهرس في response.content يعيد ContentBlock | undefined، وهو ما يتناسب جيدًا مع .filter(b => b.type === 'tool_use') ويوفر عليك عمليات التحويل باستخدام as؛ أما verbatimModuleSyntax فتتطلب استخدام import type صريح لعمليات استيراد الأنواع فقط، مما يحافظ على نظافة كود JS الناتج تحت محلل ESM الأصلي لـ Node 24.

الخطوة 2 — تعريف أداة مكتوبة باستخدام JSON Schema

أنشئ ملف src/agent.ts وابدأ بأداة طقس واحدة. الشكل مطابق لمصفوفة tools في API: اسم name، وصف description طويل، و input_schema.

import Anthropic from '@anthropic-ai/sdk';
import type {
  MessageParam,
  Tool,
  ToolResultBlockParam,
  ContentBlockParam,
} from '@anthropic-ai/sdk/resources/messages';
import { z } from 'zod';

const client = new Anthropic();

const GetWeatherInput = z.object({
  location: z.string(),
  unit: z.enum(['celsius', 'fahrenheit']).default('fahrenheit'),
});

const tools: Tool[] = [
  {
    name: 'get_weather',
    description:
      'Get the current weather for a city. Returns a short string ' +
      'like "72°F, partly cloudy". Use this whenever the user asks ' +
      'about current weather, conditions, or temperature.',
    input_schema: {
      type: 'object',
      properties: {
        location: {
          type: 'string',
          description: 'City and state, e.g. "San Francisco, CA"',
        },
        unit: {
          type: 'string',
          enum: ['celsius', 'fahrenheit'],
          description: 'Temperature unit (default fahrenheit)',
        },
      },
      required: ['location'],
    },
  },
];

function runWeather(input: unknown): string {
  // The SDK types `input` as `unknown` because the schema is JSON Schema,
  // not a TS type. Zod gives us a runtime check + an inferred TS type.
  const args = GetWeatherInput.parse(input);
  const temp = args.unit === 'celsius' ? '22°C' : '72°F';
  return `${temp}, partly cloudy in ${args.location}`;
}

هناك خياران في التصميم يستحقان التوضيح. أولاً، الـ description مطول عمدًا — وثائق Anthropic نفسها تصف أوصاف الأدوات بأنها "أهم عامل في أداء الأداة على الإطلاق" وتوصي بـ 3-4 جمل على الأقل للأدوات غير البسيطة1. ثانيًا، يقوم الـ SDK بتعريف نوع block.input كـ unknown، وليس كشكل TypeScript المستنتج من المخطط الخاص بك. يقوم Zod هنا بعملية تحقق حقيقية — إذا تخيل Claude حقلاً غير موجود، فسيقوم parse() برمي خطأ، وستلتقطه في مسار الخطأ في الخطوة 6.

ما هي حلقة stop_reason لاستخدام أدوات Claude؟

حلقة الوكيل هي حلقة while (true) تعتمد على stop_reason. بعد كل استدعاء لـ messages.create، تقوم بفحص response.stop_reason: تعني end_turn أن Claude قد انتهى ويمكنك إرجاع نصه النهائي؛ وتعني tool_use أن Claude يريد استدعاء أداة واحدة أو أكثر ويجب عليك الرد بكتل tool_result مطابقة؛ أما max_tokens و pause_turn و refusal فهي مسارات استرداد مغطاة في الخطوة 64.

الخطوة 3 — إضافة حلقة الوكيل

أضف هذا إلى src/agent.ts:

async function runAgent(userMessage: string): Promise<string> {
  const messages: MessageParam[] = [{ role: 'user', content: userMessage }];

  for (let turn = 0; turn < 10; turn++) {
    const response = await client.messages.create({
      model: 'claude-sonnet-4-6',
      max_tokens: 1024,
      tools,
      messages,
    });

    // Always push the assistant turn into history BEFORE we React to it.
    // The next call needs the original tool_use blocks present so that the
    // tool_result blocks we send back have matching tool_use_ids.
    messages.push({ role: 'assistant', content: response.content });

    if (response.stop_reason === 'end_turn') {
      const textBlocks = response.content.filter((b) => b.type === 'text');
      return textBlocks.map((b) => b.text).join('\n');
    }

    if (response.stop_reason === 'tool_use') {
      const toolResults: ToolResultBlockParam[] = response.content
        .filter((b) => b.type === 'tool_use')
        .map((block) => {
          try {
            const output =
              block.name === 'get_weather'
                ? runWeather(block.input)
                : `Unknown tool: ${block.name}`;
            return {
              type: 'tool_result' as const,
              tool_use_id: block.id,
              content: output,
            };
          } catch (err) {
            return {
              type: 'tool_result' as const,
              tool_use_id: block.id,
              content: err instanceof Error ? err.message : String(err),
              is_error: true,
            };
          }
        });

      // CRITICAL: tool_result blocks must come FIRST in the user content
      // array. If you append a text block before them you get a 400 with
      // "tool_use ids were found without tool_result blocks immediately
      // after". Trailing text after the tool_results is fine.
      const content: ContentBlockParam[] = toolResults;
      messages.push({ role: 'user', content });
      continue;
    }

    if (response.stop_reason === 'max_tokens') {
      throw new Error(
        'Response truncated. Retry with a higher max_tokens.',
      );
    }

    throw new Error(`Unexpected stop_reason: ${response.stop_reason`);
  }

  throw new Error('Tool loop exceeded 10 turns — possible infinite loop');
}

const out = await runAgent('What is the weather in Tokyo and Paris?');
console.log(out);

تحديد عدد الدورات (turn < 10) هو أرخص وسيلة لحماية فاتورتك من وكيل قد يخرج عن السيطرة. في بيئة الإنتاج، ستقوم بتتبع إجمالي توكنز المدخلات والمخرجات بدلاً من ذلك، ولكن وضع حد أقصى للدورات هو الإجراء الوقائي الصحيح لمستوى هذا البرنامج التعليمي.

الخطوة 4 — التشغيل ومراقبة الحلقة

export ANTHROPIC_API_KEY="sk-ant-..."
npx tsx src/agent.ts

شكل المخرجات المتوقع — ستختلف الصياغة الدقيقة من Claude، لكن الهيكل مستقر:

Here's the current weather for both cities:

Tokyo: 72°F, partly cloudy
Paris: 72°F, partly cloudy

Both cities are experiencing similar mild conditions today.

ما حدث للتو: أرسل Claude رسالة مساعد واحدة تحتوي على كتلتين tool_use (واحدة لكل مدينة)، قامت حلقتنا بتشغيل runWeather مرتين، وجمعت النتيجتين في رسالة مستخدم واحدة تحتوي على كتلتين tool_result، وكانت استجابة Claude التالية تحتوي على stop_reason: "end_turn" مع ملخص بلغة طبيعية. هذا هو استخدام الأدوات المتوازي — الموضح في الخطوة 5.

كيف يمكنني التعامل مع استدعاءات الأدوات المتوازية من Claude؟

استدعاءات الأدوات المتوازية (Parallel tool calls) هي الوضع الافتراضي في موديلات Claude 4. عندما يحتاج Claude لاستدعاء أداتين للإجابة على سؤال، فإنه يرسل كلي بلوكات tool_use في نفس رسالة المساعد (assistant message)، ويجب أن يتضمن ردك بلوكات tool_result لجميع هذه الأدوات — في رسالة مستخدم (user message) واحدة، مع وضع بلوكات tool_result قبل أي نص1. لإلغاء الاشتراك، قم بتعيين disable_parallel_tool_use: true في كائن tool_choice — على سبيل المثال: tool_choice: { type: 'auto', disable_parallel_tool_use: true }1.

الخطوة 5 — إضافة أداة ثانية لجعل التوازي مرئياً

أضف أداة get_time التي تُرجع الوقت الحالي لمدينة ما. أوضح عرض توضيحي هو طرح سؤال على Claude يتطلب استخدام الأداتين معاً:

const GetTimeInput = z.object({
  timezone: z.string(),
});

tools.push({
  name: 'get_time',
  description:
    'Get the current local time for an IANA timezone string like ' +
    '"America/Los_Angeles" or "Asia/Tokyo". Returns a string like ' +
    '"2026-05-29 18:39:48" (YYYY-MM-DD HH:MM:SS, local to that timezone, ' +
    '24-hour). Use this whenever the user asks what time it is somewhere.',
  input_schema: {
    type: 'object',
    properties: {
      timezone: {
        type: 'string',
        description: 'IANA timezone, e.g. "Asia/Tokyo"',
      },
    },
    required: ['timezone'],
  },
});

function runTime(input: unknown): string {
  const args = GetTimeInput.parse(input);
  // sv-SE renders YYYY-MM-DD HH:MM:SS, which is what the tool description
  // promises. Intl is built into Node, no extra deps needed.
  return new Intl.DateTimeFormat('sv-SE', {
    timeZone: args.timezone,
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
  }).format(new Date());
}

قم بربطها بالموزع (dispatcher) في runAgent:

const output =
  block.name === 'get_weather' ? runWeather(block.input)
  : block.name === 'get_time' ? runTime(block.input)
  : `Unknown tool: ${block.name}`;

الآن قم بتغيير الطلب (prompt) لإجبار استخدام كلتا الأداتين:

const out = await runAgent(
  'What time is it in Tokyo and what is the weather in Paris?',
);

أعد التشغيل باستخدام npx tsx src/agent.ts. سيحتوي response.content في الجولة الأولى على بلوكين tool_use جنباً إلى جنب؛ ستقوم حلقتنا بالتفرع، وتشغيل كليهما، وإرسال رسالة مستخدم واحدة تحتوي على بلوكين tool_result، وتنتهي الجولة الثانية لـ Claude بـ end_turn. إذا قمت بتسجيل response.content.filter(b => b.type === 'tool_use').length بعد الاستدعاء الأول، فسترى القيمة 2.

ما الفرق بين بلوكات tool_use و tool_result؟

تظهر بلوكات tool_use في رسائل المساعد — وهي تصف الاستدعاء الذي يريد Claude إجراءه، مع id، و name، وكائن input. تظهر بلوكات tool_result في رسائل المستخدم — وهي تحمل مخرجات الأداة مرة أخرى إلى Claude، مع الإشارة إلى الاستدعاء الأصلي بواسطة tool_use_id. يجب أن يكون لكل بلوك tool_use في جولة المساعد بلوك tool_result مطابق (نفس الـ tool_use_id) في جولة المستخدم التالية مباشرة، قبل أي نص، وإلا سيعيد الـ API خطأ 4001.

الخطوة 6 — أخطاء الأدوات و stop_reasons غير المتوقعة

تتعامل الحلقة بالفعل مع حالة الخطأ الشائعة — إذا قام runWeather برمي خطأ (بسبب فشل تحليل Zod، أو لأن المدينة غير معروفة)، فإن فرع catch يعيد is_error: true في بلوك tool_result. يرى Claude رسالة الخطأ ويقرر ما إذا كان سيحاول مرة أخرى بمدخلات مختلفة، أو يطلب من المستخدم التوضيح، أو يستسلم.

أربع قيم لـ stop_reason أقل شيوعاً تستحق المعالجة صراحة4:

سبب التوقف (Stop reason)ماذا يعنيالاسترداد (Recovery)
max_tokensتم قطع الاستجابة، ربما في منتصف tool_useأعد محاولة نفس الطلب بقيمة max_tokens أعلى؛ إذا كان آخر بلوك محتوى هو tool_use، فلا يمكنك تشغيل تلك الأداة حتى تحصل على البلوك كاملاً1
pause_turnيتم إرجاعه عندما تصل حلقة أخذ العينات من جانب الخادم إلى حد التكرار الخاص بها أثناء تشغيل أدوات الخادم (الافتراضي 10 تكرارات)؛ أدوات العميل التي حددتها هنا لن ترى هذا أبداً4أضف response.content إلى السجل وأعد الإرسال بنفس المعاملات للمتابعة
refusalرفض Claude الإجابة لأسباب تتعلق بالسلامةاعرض نص الرفض للمستخدم؛ لا تحاول الإعادة تلقائياً، ستحصل فقط على نفس الإجابة4
model_context_window_exceededوصلت الاستجابة إلى نافذة سياق الموديل قبل الوصول إلى max_tokens. متاح افتراضياً في Sonnet 4.5 والموديلات الأحدث، بما في ذلك Sonnet 4.64الاستجابة الجزئية صالحة؛ تعامل معها مثل max_tokens (حذر المستخدم، أو تابع بطلب أقصر)

يلتقط فرع Unexpected stop_reason في حلقتنا أي شيء لم نعالجه صراحة، بما في ذلك refusal و model_context_window_exceeded — قم بترقية هذه إلى بلوكات if مخصصة بمجرد معرفة كيف تريد إظهارها.

التحقق

قم بتشغيل السكريبت النهائي مرة أخرى مع طلب الأدوات المتوازية والتقط الهيكل:

npx tsx src/agent.ts

أنت تبحث عن ثلاثة أشياء:

  1. يخرج السكريبت بكود 0 — لا توجد أخطاء مرفوعة، ولا توجد أخطاء 400 حول فقدان بلوكات tool_result
  2. المخرجات المطبوعة تذكر كلاً من طوكيو وباريس (تم تشغيل أداة واحدة لكل منهما)
  3. استمرت الحلقة لجولتين بالضبط — الجولة الأولى stop_reason: "tool_use"، والجولة الثانية stop_reason: "end_turn"

لتأكيد عدد الجولات برمجياً، قم بتسجيل turn في أعلى الحلقة أو استبدل console.log(out) بـ console.log({ out, turns: ... }). إذا رأيت أكثر من جولتين للطلب أعلاه، فمن المحتمل أن Claude استدعى أداة واحدة، ونظر في النتيجة، وقرر استدعاء أداة أخرى — هذه هي الحلقة الوكيلة (agentic loop) تقوم بعملها، وليست خطأً.

استكشاف الأخطاء وإصلاحها

"tool_use ids were found without tool_result blocks immediately after" — رسالة المساعد التي تحتوي على بلوكات tool_use لم تتبعها مباشرة رسالة مستخدم يبدأ محتواها ببلوكات tool_result المطابقة. السببان الأكثر شيوعاً: إلحاق بلوك نصي قبل الـ tool_result في مصفوفة محتوى المستخدم (يتطلب الـ API وجود الـ tool_result أولاً، ثم النص بعده)، أو تخطي رسالة المساعد تماماً بعد رسالة ذات stop_reason: "tool_use".

"Input tag does not match any valid tag" أو عدم تطابق المخطط (schema mismatch) — قام Claude بإنشاء input لا يطابق الـ input_schema الخاص بك. أضف strict: true إلى تعريف الأداة لجعل الـ API يضمن التحقق من صحة المخطط لأسماء الأدوات والمدخلات5 — لاحظ أن استخدام الأدوات الصارم (strict tool use) يتطلب أيضاً additionalProperties: false في كل مخطط كائن ويدعم فقط مجموعة فرعية مقيدة من JSON Schema، لذا تحقق من وثائق الوضع الصارم قبل التمكين. وتحقق من الـ description الخاص بك — يشير دليل استخدام الأدوات من Anthropic مراراً وتكراراً إلى أن الأوصاف الغامضة هي السبب الجذري للوسائط السيئة1.

الحلقة تعمل للأبد — يستدعي Claude نفس الأداة مراراً وتكراراً لأنه غير راضٍ عن النتيجة. اجعل سلسلة الإرجاع الخاصة بالأداة تتضمن الإجابة التي يحتاجها Claude ("temperature: 22°C, conditions: partly cloudy") بدلاً من مجرد تأكيدات ("weather lookup complete")؛ وحافظ على سقف الجولات في runAgent قصيراً حتى تثق في سطح أدواتك.

429 rate_limit_error — أنت تصل إلى حد الطلبات في الدقيقة الخاص بفئتك. أضف await new Promise(r => setTimeout(r, 1000)) بين الجولات، أو استخدم خطاف الإعادة المدمج في SDK عن طريق تمرير maxRetries: 3 إلى new Anthropic({ maxRetries: 3 }).

كيف أجبر Claude على استخدام أداة معينة؟

قم بتمرير tool_choice في الطلب. الخيار {type: 'auto'} (الافتراضي عند تعيين tools) يترك لـ Claude القرار؛ بينما {type: 'any'} يجبره على استخدام أداة ما ولكن ليس أداة محددة؛ أما {type: 'tool', name: 'get_weather'} فيجبره على استخدام تلك الأداة تحديداً؛ و {type: 'none'} يعطل جميع الأدوات1. لاحظ أن any و tool غير متوافقين مع التفكير الممتد (extended thinking) في Sonnet 4.6 — فقط auto و none هما اللذان يعملان عند تفعيل التفكير الممتد1.

الخطوات التالية ومزيد من القراءة

توفر حزمة أدوات التطوير (SDK) الخاصة بـ Anthropic لـ TypeScript مساعداً تجريبياً (beta helper)، وهو client.beta.messages.toolRunner، الذي يغلف الحلقة اليدوية المذكورة أعلاه ويضيف betaZodTool المعتمد على Zod، والضغط التلقائي للسياقات الطويلة، وإلغاء العمليات المدمج عبر AbortSignal6. إنه الخيار الصحيح للإنتاج بمجرد استيعابك لما تفعله الحلقة اليدوية — لكن الحلقة اليدوية هي ما يعمل في الخلفية، وواجهة messages.create المستقرة وغير التجريبية هي ما تعتمد عليه وكلاء الإنتاج منذ أن أصبح استخدام الأدوات متاحاً بشكل عام (GA) في عام 2024.

إذا كنت تنتقل إلى ما هو أبعد من مجرد سكربت واحد، فإن الخطوة الطبيعية التالية هي عرض نفس مجموعة الأدوات هذه من خلال خادم MCP في TypeScript مع OAuth و HTTP قابل للبث بحيث يمكن لأي عميل يدعم MCP (مثل Claude Code أو Cursor أو واجهتك الخاصة) الاتصال به. إذا كنت ترغب في تقييم المطالبات (prompts) التي تقود وكيلك، فإن promptfoo مع التأكيدات وبوابات CI يمنحك اختبارات تراجع لكل مطالبة. وإذا كنت ترغب في استبدال Sonnet 4.6 بـ GPT-5.4 أو Gemini 2.5 Pro دون تغيير الكود الخاص بك، فإن LiteLLM Proxy يمنحك نفس واجهة Messages API عبر مختلف المزودين.

Footnotes

  1. Anthropic, "How to implement tool use" — https://platform.claude.com/docs/en/agents-and-tools/tool-use/implement-tool-use (verified 2026-05-29) 2 3 4 5 6 7 8 9 10 11

  2. Node.js Release Schedule — https://nodejs.org/en/about/previous-releases (Node 24 LTS, Active LTS through April 2028; verified 2026-05-29)

  3. Anthropic, "Models overview" — https://platform.claude.com/docs/en/about-claude/models/overview (Claude Sonnet 4.6: $3 / $15 per million input/output tokens, 1M context window, 64k max output; verified 2026-05-29)

  4. Anthropic, "Handling stop reasons" — https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons (StopReason values: end_turn, max_tokens, stop_sequence, tool_use, pause_turn, refusal, and model_context_window_exceeded which is available by default on Sonnet 4.5 and newer; the SDK 0.98.0 StopReason type currently enumerates the first six and the seventh value falls through to the loop's "Unexpected stop_reason" branch; verified 2026-05-29) 2 3 4 5

  5. Anthropic, "Strict tool use" — https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use (and the parent "Structured outputs" page at https://platform.claude.com/docs/en/build-with-claude/structured-outputsstrict: true on tool definitions enables grammar-constrained validation on tool names and inputs; requires additionalProperties: false and the supported JSON Schema subset; GA on Sonnet 4.6; verified 2026-05-29)

  6. Anthropic TypeScript SDK helpers — https://GitHub.com/anthropics/anthropic-sdk-TypeScript/blob/main/helpers.md#tool-helpers (client.beta.messages.toolRunner, betaZodTool, ToolError; verified 2026-05-29)


نشرة أسبوعية مجانية

ابقَ على مسار النيرد

بريد واحد أسبوعياً — دورات، مقالات معمّقة، أدوات، وتجارب ذكاء اصطناعي.

بدون إزعاج. إلغاء الاشتراك في أي وقت.