في هذه الصفحة
الدّرس 2 من 8
واجهة الرّسائل
ما ستتعلّمه
- إرسال رسائل أحاديّة ومتعدّدة الأدوار
- بناء مصفوفة الرّسائل بشكل صحيح بين الأدوار
- قراءة شكل الإجابة واستخراج ما تحتاج
The Messages API is the front door of the Claude API. Get fluent here and everything else in this course is a variation on the same theme.
The request shape
Every call to Claude follows the same structure. Here is the minimal request:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages: [
{ role: "user", content: "What is the capital of Tunisia?" },
],
});
Three required fields: model, max_tokens, and messages. The model field takes a model ID like claude-sonnet-4-6, claude-opus-4-7, or claude-haiku-4-5. The max_tokens field caps how many tokens Claude can generate — set it high enough for your expected output but not wastefully high. The messages array is the conversation history.
The system prompt
The system prompt sits outside the message array as a top-level parameter. It sets the persona, rules, and constraints that apply to the entire conversation:
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
system: "You are a senior TypeScript developer. Answer concisely. Use code examples when helpful.",
messages: [
{ role: "user", content: "How do I type a function that accepts any Promise?" },
],
});
The system prompt is not a message — it is an instruction layer above the conversation. Put reusable behavior here: persona, formatting rules, safety constraints. Put task-specific content in the user message.
Roles and alternation
Messages alternate between two roles: user and assistant. The array must start with a user message. Consecutive messages of the same role are not allowed — the API will return an error. This alternation reflects a natural conversation: you speak, Claude responds, you speak again.
Multi-turn conversations
Claude is stateless. It does not remember previous calls. To maintain a conversation, you send the full history each time:
const conversationHistory: Anthropic.MessageParam[] = [];
async function chat(userMessage: string): Promise<string> {
conversationHistory.push({ role: "user", content: userMessage });
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
system: "You are a helpful coding tutor.",
messages: conversationHistory,
});
const assistantText =
response.content[0].type === "text" ? response.content[0].text : "";
conversationHistory.push({ role: "assistant", content: assistantText });
return assistantText;
}
// Turn 1
await chat("What is a closure in JavaScript?");
// Turn 2 — Claude sees Turn 1 in context
await chat("Show me an example with a counter.");
// Turn 3 — Claude sees Turns 1 and 2
await chat("Now make it TypeScript with proper types.");
Each call sends the growing array. This means token usage grows with conversation length. For long conversations, you will need to truncate older messages or summarize them to stay within the context window.
The response shape
The response object looks like this:
{
id: "msg_01A2B3C4D5...",
type: "message",
role: "assistant",
model: "claude-sonnet-4-6",
content: [
{ type: "text", text: "The capital of Tunisia is Tunis." }
],
stop_reason: "end_turn",
usage: {
input_tokens: 14,
output_tokens: 12
}
}
Key fields you should always read:
content— An array of content blocks. For text responses, there is one block withtype: "text". Tool use responses have blocks withtype: "tool_use". Always check the type before accessing.text.stop_reason— Why Claude stopped. This is critical for control flow.usage— Token counts for cost tracking. Track these from day one.
Stop reasons
There are four stop reasons, and each one tells you something different:
| Stop reason | Meaning | Your action |
|---|---|---|
end_turn | Claude finished its response naturally | Display the response |
max_tokens | Output was cut off by your max_tokens limit | Increase limit or continue the conversation |
stop_sequence | Claude hit a custom stop sequence you defined | Parse up to that point |
tool_use | Claude wants to call a tool | Execute the tool and continue (Lesson 4) |
The max_tokens stop reason is the one that catches people. If you set max_tokens: 100 and Claude's answer needs 150 tokens, it will stop mid-sentence. Always check for this:
if (response.stop_reason === "max_tokens") {
console.warn("Response was truncated. Consider increasing max_tokens.");
}
Token usage and cost awareness
Every response includes usage.input_tokens and usage.output_tokens. Build the habit of logging these from your first call:
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages: [{ role: "user", content: userInput }],
});
console.log(
`Tokens — in: ${response.usage.input_tokens}, out: ${response.usage.output_tokens}`
);
With Sonnet 4.6 at $3/$15 per million tokens, a 1,000-token input and 500-token output costs $0.003 + $0.0075 = roughly one cent. That adds up at scale, which is why Lessons 6 and 7 exist.
Context window management
Sonnet 4.6 and Opus 4.7 support 1 million tokens of context and up to 128K tokens of output. Haiku 4.5 supports 200K. These are generous limits, but multi-turn conversations can fill them faster than you expect. A practical approach:
- Count tokens as you add messages to the history.
- Set a budget — for example, keep conversation history under 50K tokens.
- Truncate from the front — drop the oldest user/assistant pairs first, keeping the system prompt and the most recent turns intact.
What's next
You now know the shape of every Claude API call. The next lesson — Streaming — teaches you how to get tokens as they are generated instead of waiting for the full response. This is essential for any user-facing application where perceived speed matters.
واجهة الرّسائل هي الباب الأمامي لواجهة Claude. أتقنها وكلّ ما يأتي في هذه الدّورة ليس إلّا تنويعات على نفس النّغمة.
شكل الطّلب
كلّ استدعاء لـ Claude يتبع نفس البنية. ثلاثة حقول مطلوبة: model و max_tokens و messages. حقل model يأخذ معرّف نموذج مثل claude-sonnet-4-6. حقل max_tokens يحدّ عدد الرّموز التي يولّدها Claude. مصفوفة messages هي تاريخ المحادثة.
مطالبة النّظام
مطالبة النّظام تقع خارج مصفوفة الرّسائل كمعامل عُلوي. تضبط الشّخصيّة والقواعد والقيود لكامل المحادثة. ليست رسالة — هي طبقة تعليمات فوق المحادثة. ضع السّلوك القابل لإعادة الاستعمال هنا: الشّخصيّة، قواعد التّنسيق، قيود السّلامة. ضع المحتوى الخاصّ بالمهمّة في رسالة المستخدم.
الأدوار والتّناوب
الرّسائل تتناوب بين دورين: user و assistant. المصفوفة يجب أن تبدأ برسالة user. الرّسائل المتتالية من نفس الدّور غير مسموحة — الواجهة ستُرجع خطأ.
المحادثات المتعدّدة
Claude عديم الحالة. لا يتذكّر الاستدعاءات السّابقة. للحفاظ على محادثة، أرسل التّاريخ الكامل كلّ مرّة. هذا يعني أنّ استهلاك الرّموز ينمو مع طول المحادثة. للمحادثات الطّويلة، ستحتاج لقطع الرّسائل القديمة أو تلخيصها.
شكل الاستجابة
الحقول الأساسيّة: content — مصفوفة كتل محتوى، تحقّق من النّوع قبل الوصول إلى .text. stop_reason — لماذا توقّف Claude، حرج للتّحكّم بالتّدفّق. usage — عدد الرّموز لتتبّع التّكلفة.
أسباب التّوقّف
أربعة أسباب: end_turn (أنهى طبيعيًّا)، max_tokens (قُطع بسبب الحدّ)، stop_sequence (وصل لتسلسل إيقاف مخصّص)، tool_use (يريد استدعاء أداة). سبب max_tokens هو الذي يُفاجئ النّاس — تحقّق منه دائمًا.
إدارة نافذة السّياق
Sonnet 4.6 و Opus 4.7 يدعمان مليون رمز سياق وحتّى 128 ألف رمز مخرج. Haiku 4.5 يدعم 200 ألف. حدود سخيّة، لكنّ المحادثات المتعدّدة تملأها أسرع ممّا تتوقّع. نهج عمليّ: عدّ الرّموز، حدّد ميزانيّة، واقطع من البداية — احذف أقدم أزواج المستخدم/المساعد أوّلًا مع الحفاظ على مطالبة النّظام والأدوار الأخيرة.
ما التّالي
الآن تعرف شكل كلّ استدعاء لواجهة Claude. الدّرس القادم — التّدفّق — يعلّمك كيف تحصل على الرّموز فور توليدها بدل انتظار الاستجابة الكاملة. هذا ضروريّ لأيّ تطبيق يواجه المستخدم حيث السّرعة المحسوسة مهمّة.
جرّب بنفسك
ابنِ مساعدًا متعدّد الأدوار يحفظ محادثة عبر خمس أدوار أو أكثر. اطبع أسباب التّوقّف. اقطع السّياق عند الحاجة.
تأمّل
كيف تقرّر متى تقطع تاريخ المحادثة مقابل البدء من جديد؟ أيّ إشارات تستعمل؟