حلقهی ایجنت چطور کار میکند
Understand the message lifecycle, tool execution, context window, and architecture that power your SDK agents.
Agent SDK به تو اجازه میدهد حلقهی ایجنتِ خودمختارِ Claude Code را در اپلیکیشنهای خودت جاسازی کنی. این SDK یک پکیجِ مستقل است که کنترلِ برنامهنویسیشده روی ابزارها، دسترسیها، سقفِ هزینه و خروجی میدهد. برای استفاده از آن لازم نیست Claude Code CLI نصب باشد.
وقتی یک ایجنت را شروع میکنی، SDK همان حلقهی اجراییای که Claude Code را پیش میبرد را اجرا میکند: Claude پرامپتت را ارزیابی میکند، ابزارها را برای اقدام فراخوانی میکند، نتیجهها را میگیرد و تا کاملِ شدنِ کار تکرار میکند. این صفحه توضیح میدهد داخلِ آن حلقه چه میگذرد تا بتوانی ایجنتهایت را بهخوبی بسازی، عیبیابی و بهینه کنی.
یک نگاهِ کلی به حلقه
Section titled “یک نگاهِ کلی به حلقه”هر نشستِ ایجنت همان چرخه را دنبال میکند:
- دریافتِ پرامپت. Claude پرامپتت را همراه با سیستمپرامپت، تعریفِ ابزارها و تاریخچهی گفتگو دریافت میکند. SDK یک
SystemMessageبا زیرنوعِ"init"تولید میکند که فرادادهی نشست را در خود دارد. - ارزیابی و پاسخ. Claude وضعیتِ فعلی را ارزیابی میکند و تعیین میکند چطور پیش برود. ممکن است با متن پاسخ بدهد، یک یا چند فراخوانیِ ابزار درخواست کند، یا هر دو. SDK یک
AssistantMessageتولید میکند که متن و هر درخواستِ فراخوانیِ ابزار را در خود دارد. - اجرای ابزارها. SDK هر ابزارِ درخواستشده را اجرا میکند و نتیجهها را جمع میکند. هر مجموعه از نتایجِ ابزار برای تصمیمِ بعدی به Claude بازخورد داده میشود. میتوانی با هوکها فراخوانیهای ابزار را پیش از اجرا رهگیری، تغییر یا مسدود کنی.
- تکرار. مرحلههای ۲ و ۳ بهصورتِ یک چرخه تکرار میشوند. هر چرخهی کامل یک نوبت است. Claude تا وقتی پاسخی بدونِ هیچ فراخوانیِ ابزار تولید کند به فراخوانیِ ابزارها و پردازشِ نتایج ادامه میدهد.
- بازگرداندنِ نتیجه. SDK یک
AssistantMessageِ نهایی با پاسخِ متنی (بدونِ فراخوانیِ ابزار) تولید میکند، و در پیاش یکResultMessageبا متنِ نهایی، مصرفِ توکن، هزینه و شناسهی نشست.
یک پرسشِ سریع («چه فایلهایی اینجاست؟») شاید یک یا دو نوبت طول بکشد، با فراخوانیِ Glob و پاسخ با نتایج. یک کارِ پیچیده («ماژولِ احراز هویت را بازآرایی کن و تستها را بهروز کن») میتواند دهها فراخوانیِ ابزار را در چند نوبت زنجیر کند، با خواندنِ فایلها، ویرایشِ کد و اجرای تستها، در حالی که Claude رویکردش را بر اساسِ هر نتیجه تنظیم میکند.
نوبتها و پیامها
Section titled “نوبتها و پیامها”یک نوبت یک رفتوبرگشت داخلِ حلقه است: Claude خروجیای تولید میکند که شاملِ فراخوانیِ ابزار است، SDK آن ابزارها را اجرا میکند، و نتیجهها بهصورتِ خودکار به Claude بازخورد میشوند. این بدونِ بازگرداندنِ کنترل به کدِ تو اتفاق میافتد. نوبتها تا وقتی Claude خروجیای بدونِ فراخوانیِ ابزار تولید کند ادامه مییابند، و در آن نقطه حلقه پایان میگیرد و نتیجهی نهایی تحویل داده میشود.
ببین یک نشستِ کامل برای پرامپتِ «تستهای شکستخورده در auth.ts را درست کن» چطور به نظر میرسد.
ابتدا SDK پرامپتت را به Claude میفرستد و یک SystemMessage با فرادادهی نشست تولید میکند. بعد حلقه شروع میشود:
- نوبت ۱: Claude برای اجرای
npm testابزارِBashرا فراخوانی میکند. SDK یکAssistantMessageبا فراخوانیِ ابزار تولید میکند، دستور را اجرا میکند، بعد یکUserMessageبا خروجی (سه شکست) تولید میکند. - نوبت ۲: Claude روی
auth.tsوauth.test.tsابزارِReadرا فراخوانی میکند. SDK محتوای فایلها را برمیگرداند و یکAssistantMessageتولید میکند. - نوبت ۳: Claude برای درست کردنِ
auth.tsابزارِEditرا فراخوانی میکند، بعد برای اجرای دوبارهیnpm testابزارِBashرا فراخوانی میکند. هر سه تست پاس میشوند. SDK یکAssistantMessageتولید میکند. - نوبتِ نهایی: Claude یک پاسخِ فقط-متنی بدونِ فراخوانیِ ابزار تولید میکند: «باگِ auth درست شد، الان هر سه تست پاس میشوند.» SDK یک
AssistantMessageِ نهایی با این متن تولید میکند، بعد یکResultMessageبا همان متن بهعلاوهی هزینه و مصرف.
این چهار نوبت بود: سهتا با فراخوانیِ ابزار، یکی پاسخِ نهاییِ فقط-متنی.
میتوانی حلقه را با max_turns / maxTurns سقف بگذاری، که فقط نوبتهای استفاده از ابزار را میشمارد. مثلاً max_turns=2 در حلقهی بالا پیش از مرحلهی ویرایش متوقف میشد. همچنین میتوانی با max_budget_usd / maxBudgetUsd نوبتها را بر اساسِ یک آستانهی هزینه سقف بگذاری.
بدونِ محدودیت، حلقه تا وقتی Claude خودش تمام کند اجرا میشود، که برای کارهای خوشتعریف خوب است ولی روی پرامپتهای بازانتها («این کدبیس را بهتر کن») میتواند طولانی شود. تعیینِ یک بودجه برای ایجنتهای تولیدی یک پیشفرضِ خوب است. برای مرجعِ گزینهها، نوبتها و بودجه را در پایین ببین.
انواعِ پیام
Section titled “انواعِ پیام”همانطور که حلقه اجرا میشود، SDK جریانی از پیامها تولید میکند. هر پیام نوعی دارد که میگوید از کدام مرحلهی حلقه آمده است. پنج نوعِ هستهای اینهاست:
SystemMessage: رویدادهای چرخهی عمرِ نشست. فیلدِsubtypeآنها را تفکیک میکند:"init"اولین پیام است (فرادادهی نشست)، و"compact_boundary"پس از فشردهسازی (compaction) فعال میشود. در TypeScript، مرزِ فشردهسازی بهجای زیرنوعی ازSDKSystemMessage، نوعِ مستقلِ خودش یعنیSDKCompactBoundaryMessageاست.AssistantMessage: پس از هر پاسخِ Claude، شاملِ پاسخِ نهاییِ فقط-متنی، منتشر میشود. بلوکهای محتوای متنی و بلوکهای فراخوانیِ ابزارِ آن نوبت را در خود دارد.UserMessage: پس از هر اجرای ابزار، همراه با محتوای نتیجهی ابزار که به Claude بازفرستاده میشود، منتشر میشود. همچنین برای هر ورودیِ کاربری که وسطِ حلقه استریم میکنی منتشر میشود.StreamEvent: فقط وقتی پیامهای جزئی فعال باشند منتشر میشود. رویدادهای خامِ استریمِ API (دلتای متن، تکههای ورودیِ ابزار) را در خود دارد. Stream responses را ببین.ResultMessage: پایانِ حلقهی ایجنت را نشانه میگذارد. نتیجهی متنیِ نهایی، مصرفِ توکن، هزینه و شناسهی نشست را در خود دارد. فیلدِsubtypeرا بررسی کن تا بفهمی کار موفق بوده یا به یک محدودیت خورده است. تعدادِ اندکی رویدادِ سیستمیِ دنبالهای، مثلِprompt_suggestion، میتوانند پس از آن برسند، پس بهجای متوقف شدن روی نتیجه، جریان را تا انتها پیمایش کن. مدیریتِ نتیجه را ببین.
این پنج نوع کلِ چرخهی عمرِ حلقهی ایجنت را در هر دو SDK پوشش میدهند. TypeScript SDK رویدادهای رصدپذیریِ اضافی هم تولید میکند (رویدادهای هوک، پیشرفتِ ابزار، سقفِ نرخ، اعلانهای وظیفه) که جزئیاتِ بیشتری میدهند ولی برای راندنِ حلقه لازم نیستند. برای فهرستهای کامل، مرجعِ انواعِ پیامِ Python و مرجعِ انواعِ پیامِ TypeScript را ببین.
مدیریتِ پیامها
Section titled “مدیریتِ پیامها”اینکه کدام پیامها را مدیریت میکنی به این بستگی دارد که چه میسازی:
- فقط نتیجههای نهایی:
ResultMessageرا مدیریت کن تا خروجی، هزینه و اینکه کار موفق بوده یا به محدودیت خورده را بگیری. - بهروزرسانیهای پیشرفت:
AssistantMessageرا مدیریت کن تا ببینی Claude در هر نوبت چه میکند، شاملِ اینکه کدام ابزارها را فراخوانده. - استریمِ زنده: پیامهای جزئی را فعال کن (
include_partial_messagesدر Python،includePartialMessagesدر TypeScript) تا پیامهایStreamEventرا در زمانِ واقعی بگیری. Stream responses in real-time را ببین.
اینکه چطور انواعِ پیام را بررسی میکنی به SDK بستگی دارد:
- Python: انواعِ پیام را با
isinstance()در برابرِ کلاسهای واردشده ازclaude_agent_sdkبررسی کن (مثلاًisinstance(message, ResultMessage)). - TypeScript: فیلدِ رشتهایِ
typeرا بررسی کن (مثلاًmessage.type === "result").AssistantMessageوUserMessageپیامِ خامِ API را در یک فیلدِ.messageمیپیچند، پس بلوکهای محتوا درmessage.message.contentهستند، نهmessage.content.
نمونه: بررسیِ انواعِ پیام و مدیریتِ نتیجهها
from claude_agent_sdk import query, AssistantMessage, ResultMessage
async for message in query(prompt="Summarize this project"): if isinstance(message, AssistantMessage): print(f"Turn completed: {len(message.content)} content blocks") if isinstance(message, ResultMessage): if message.subtype == "success": print(message.result) else: print(f"Stopped: {message.subtype}")import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({ prompt: "Summarize this project" })) { if (message.type === "assistant") { console.log(`Turn completed: ${message.message.content.length} content blocks`); } if (message.type === "result") { if (message.subtype === "success") { console.log(message.result); } else { console.log(`Stopped: ${message.subtype}`); } }}اجرای ابزار
Section titled “اجرای ابزار”ابزارها به ایجنتت توانِ اقدام میدهند. بدونِ ابزار، Claude فقط میتواند با متن پاسخ بدهد. با ابزار، Claude میتواند فایلها را بخواند، دستورها را اجرا کند، کد را جستجو کند و با سرویسهای بیرونی تعامل کند.
ابزارهای داخلی
Section titled “ابزارهای داخلی”این SDK همان ابزارهایی را دارد که Claude Code را پیش میبرند:
| دسته | ابزارها | چه میکنند |
|---|---|---|
| عملیاتِ فایل | Read، Edit، Write | خواندن، تغییر و ساختِ فایلها |
| جستجو | Glob، Grep | یافتنِ فایل بر اساسِ الگو، جستجوی محتوا با regex |
| اجرا | Bash | اجرای دستورهای شل، اسکریپتها، عملیاتِ git |
| وب | WebSearch، WebFetch | جستجوی وب، واکشی و تجزیهی صفحهها |
| کشف | ToolSearch | یافتن و بارگذاریِ پویای ابزارها بهصورتِ on-demand بهجای پیشبارگذاریِ همهی آنها |
| هماهنگسازی | Agent، Skill، AskUserQuestion، TaskCreate، TaskUpdate | تولیدِ سابایجنتها، فراخوانیِ Skillها، پرسش از کاربر، رهگیریِ وظیفهها |
فراتر از ابزارهای داخلی، میتوانی:
- سرویسهای بیرونی را متصل کنی با سرورهای MCP (پایگاههای داده، مرورگرها، APIها)
- ابزارهای سفارشی تعریف کنی با هندلرهای ابزارِ سفارشی
- Skillهای پروژه را بار کنی از طریقِ setting sources برای ورکفلوهای قابلِبازاستفاده
دسترسیهای ابزار
Section titled “دسترسیهای ابزار”Claude بر اساسِ کار تعیین میکند کدام ابزارها را فراخوانی کند، ولی تو کنترل میکنی که آیا آن فراخوانیها اجازهی اجرا داشته باشند. میتوانی ابزارهای مشخصی را خودکار تأیید کنی، بعضی را کلاً مسدود کنی، یا برای همهچیز درخواستِ تأیید بگذاری. سه گزینه با هم تعیین میکنند چه چیزی اجرا شود:
allowed_tools/allowedToolsابزارهای فهرستشده را خودکار تأیید میکند. یک ایجنتِ فقط-خواندنی با["Read", "Glob", "Grep"]در فهرستِ ابزارهای مجازش، آن ابزارها را بدونِ پرسش اجرا میکند. ابزارهایی که فهرست نشدهاند همچنان در دسترساند ولی به مجوز نیاز دارند.disallowed_tools/disallowedToolsابزارهای فهرستشده را مسدود میکند، صرفنظر از سایرِ تنظیمات. برای ترتیبی که قواعد پیش از اجرای ابزار بررسی میشوند، Permissions را ببین.permission_mode/permissionModeکنترل میکند برای ابزارهایی که قواعدِ اجازه یا انکار پوششان نمیدهد چه اتفاقی بیفتد. برای حالتهای در دسترس، حالتِ دسترسی را ببین.
همچنین میتوانی ابزارهای منفرد را با قواعدی مثلِ "Bash(npm *)" محدود کنی تا فقط دستورهای مشخصی مجاز باشند. برای نحوِ کاملِ قواعد، Permissions را ببین.
وقتی ابزاری انکار میشود، Claude یک پیامِ ردّ بهعنوانِ نتیجهی ابزار دریافت میکند و معمولاً رویکردی متفاوت امتحان میکند یا گزارش میدهد که نتوانست پیش برود.
اجرای موازیِ ابزار
Section titled “اجرای موازیِ ابزار”وقتی Claude در یک نوبت چند فراخوانیِ ابزار درخواست میکند، هر دو SDK میتوانند بسته به ابزار آنها را همزمان یا متوالی اجرا کنند. ابزارهای فقط-خواندنی (مثلِ Read، Glob، Grep و ابزارهای MCP که فقط-خواندنی علامت خوردهاند) میتوانند همزمان اجرا شوند. ابزارهایی که وضعیت را تغییر میدهند (مثلِ Edit، Write و Bash) برای پرهیز از تداخل متوالی اجرا میشوند.
ابزارهای سفارشی بهصورتِ پیشفرض متوالی اجرا میشوند. برای فعال کردنِ اجرای موازیِ یک ابزارِ سفارشی، readOnlyHint را در حاشیهنویسیهایش تنظیم کن. هر دو SDKِ TypeScript و Python از این نامِ فیلد از MCP SDK استفاده میکنند.
کنترلِ نحوهی اجرای حلقه
Section titled “کنترلِ نحوهی اجرای حلقه”میتوانی محدود کنی که حلقه چند نوبت طول بکشد، چقدر هزینه کند، Claude چقدر عمیق استدلال کند، و اینکه آیا ابزارها پیش از اجرا به تأیید نیاز دارند. همهی اینها فیلدهایی روی ClaudeAgentOptions (Python) / Options (TypeScript) هستند.
نوبتها و بودجه
Section titled “نوبتها و بودجه”| گزینه | چه چیزی را کنترل میکند | پیشفرض |
|---|---|---|
حداکثر نوبت (max_turns / maxTurns) | حداکثر رفتوبرگشتهای استفاده از ابزار | بدونِ محدودیت |
حداکثر بودجه (max_budget_usd / maxBudgetUsd) | حداکثر هزینه پیش از توقف | بدونِ محدودیت |
وقتی هر کدام از این محدودیتها به سقف بخورد، SDK یک ResultMessage با زیرنوعِ خطای متناظر (error_max_turns یا error_max_budget_usd) برمیگرداند. برای نحوهی بررسیِ این زیرنوعها مدیریتِ نتیجه و برای نحو ClaudeAgentOptions / Options را ببین.
سطحِ effort
Section titled “سطحِ effort”گزینهی effort کنترل میکند Claude چقدر استدلال به کار بگیرد. سطوحِ effortِ پایینتر در هر نوبت توکنِ کمتری مصرف میکنند و هزینه را کاهش میدهند. همهی مدلها از پارامترِ effort پشتیبانی نمیکنند. برای اینکه کدام مدلها از آن پشتیبانی میکنند، Effort را ببین.
| سطح | رفتار | خوب برای |
|---|---|---|
"low" | استدلالِ حداقلی، پاسخهای سریع | جستجوی فایل، فهرست کردنِ دایرکتوریها |
"medium" | استدلالِ متوازن | ویرایشهای روتین، کارهای استاندارد |
"high" | تحلیلِ دقیق | بازآراییها، عیبیابی |
"xhigh" | عمقِ استدلالِ گستردهتر | کدنویسی و کارهای ایجنتیک؛ روی Fable 5 و Opus 4.7+ توصیه میشود |
"max" | بیشینهی عمقِ استدلال | مسائلِ چندمرحلهای که به تحلیلِ عمیق نیاز دارند |
اگر effort را تنظیم نکنی، هر دو SDK پارامتر را تنظیمنشده میگذارند و به رفتارِ پیشفرضِ مدل واگذار میکنند.
برای ایجنتهایی که کارهای ساده و خوشتعریف انجام میدهند (مثلِ فهرست کردنِ فایلها یا اجرای یک grepِ منفرد) از effortِ پایینتر استفاده کن تا هزینه و تأخیر کاهش یابد. effort را در گزینههای سطحِبالای query() برای کلِ نشست تنظیم کن، یا برای هر سابایجنت با فیلدِ effort روی AgentDefinition تا سطحِ نشست را بازنویسی کند.
حالتِ دسترسی
Section titled “حالتِ دسترسی”گزینهی حالتِ دسترسی (permission_mode در Python، permissionMode در TypeScript) کنترل میکند که آیا ایجنت پیش از استفاده از ابزارها درخواستِ تأیید میکند:
| حالت | رفتار |
|---|---|
"default" | ابزارهایی که قواعدِ اجازه پوششان نمیدهد کالبکِ تأییدت را فعال میکنند؛ نبودِ کالبک یعنی انکار |
"acceptEdits" | ویرایشهای فایل و دستورهای رایجِ فایلسیستم (mkdir، touch، mv، cp و غیره) را خودکار تأیید میکند؛ سایرِ دستورهای Bash از قواعدِ default پیروی میکنند |
"plan" | Claude کاوش و برنامهریزی میکند بدونِ ویرایشِ فایلهای منبعت؛ ویرایشهای فایل هرگز خودکار تأیید نمیشوند و از کالبکِ canUseToolِ تو میپرسند |
"dontAsk" | هرگز نمیپرسد. ابزارهایی که با قواعدِ دسترسی پیشتأیید شدهاند اجرا میشوند، بقیه انکار میشوند |
"auto" (فقط TypeScript) | از یک دستهبندِ مدل برای تأیید یا انکارِ هر فراخوانیِ ابزار استفاده میکند. برای در دسترس بودن و رفتار، Auto mode را ببین |
"bypassPermissions" | همهی ابزارهای مجاز را بدونِ پرسش اجرا میکند، مگر یک قاعدهی askِ صریح مطابقت کند؛ برای اینکه قواعدِ ask کجای ترتیبِ اولویت مینشینند How permissions are evaluated را ببین. هنگامِ اجرا بهعنوانِ root روی Unix نمیتوان از آن استفاده کرد. فقط در محیطهای جداشدهای به کار ببر که اقداماتِ ایجنت نمیتواند به سیستمهایی که برایت مهماند آسیب بزند |
برای اپلیکیشنهای تعاملی، از "default" با یک کالبکِ تأییدِ ابزار استفاده کن تا درخواستهای تأیید نمایان شوند. برای ایجنتهای خودمختار روی یک ماشینِ توسعه، "acceptEdits" ویرایشهای فایل و دستورهای رایجِ فایلسیستم (mkdir، touch، mv، cp و غیره) را خودکار تأیید میکند و در عینِ حال سایرِ دستورهای Bash را همچنان پشتِ قواعدِ اجازه نگه میدارد. "bypassPermissions" را برای CI، کانتینرها یا سایرِ محیطهای جداشده نگه دار. برای جزئیاتِ کامل، Permissions را ببین.
اگر model را تنظیم نکنی، SDK از پیشفرضِ Claude Code استفاده میکند، که به روشِ احراز هویت و اشتراکت بستگی دارد. برای میخ کردنِ یک مدلِ مشخص یا استفاده از یک مدلِ کوچکتر برای ایجنتهای سریعتر و ارزانتر، آن را صریحاً تنظیم کن (مثلاً model="claude-sonnet-4-6"). برای شناسههای در دسترس، models را ببین.
پنجرهی کانتکست
Section titled “پنجرهی کانتکست”پنجرهی کانتکست کلِ مقدارِ اطلاعاتی است که در طولِ یک نشست برای Claude در دسترس است. بینِ نوبتهای داخلِ یک نشست بازنشانی نمیشود. همهچیز انباشته میشود: سیستمپرامپت، تعریفِ ابزارها، تاریخچهی گفتگو، ورودیهای ابزار و خروجیهای ابزار. محتوایی که بینِ نوبتها یکسان میماند (سیستمپرامپت، تعریفِ ابزارها، CLAUDE.md) بهصورتِ خودکار کشِ پرامپت میشود، که هزینه و تأخیر را برای پیشوندهای تکراری کاهش میدهد.
چه چیزی کانتکست مصرف میکند
Section titled “چه چیزی کانتکست مصرف میکند”اینطور هر مؤلفه در SDK بر کانتکست اثر میگذارد:
| منبع | کِی بار میشود | اثر |
|---|---|---|
| سیستمپرامپت | هر درخواست | هزینهی ثابتِ کوچک، همیشه حاضر |
| فایلهای CLAUDE.md | شروعِ نشست، از طریقِ settingSources | محتوای کامل در هر درخواست (ولی کشِ پرامپت میشود، پس فقط اولین درخواست هزینهی کامل را میپردازد) |
| تعریفِ ابزارها | هر درخواست؛ شِماهای MCP بهصورتِ پیشفرض موکول میشوند | شِماهای ابزارِ داخلی در هر درخواست بار میشوند. Tool search شِماهای ابزارِ MCP را بهصورتِ پیشفرض موکول میکند و روی Vertex AI یا یک ANTHROPIC_BASE_URLِ غیرشخصِاول به بارگذاریِ پیشاپیش برمیگردد. برای ماتریسِ کامل Configure tool search را ببین |
| تاریخچهی گفتگو | در طولِ نوبتها انباشته میشود | با هر نوبت رشد میکند: پرامپتها، پاسخها، ورودیهای ابزار، خروجیهای ابزار |
| توصیفِ Skillها | شروعِ نشست، از طریقِ setting sources | خلاصههای کوتاه؛ محتوای کامل فقط هنگامِ فراخوانی بار میشود |
خروجیهای بزرگِ ابزار کانتکستِ قابلِتوجهی مصرف میکنند. خواندنِ یک فایلِ بزرگ یا اجرای دستوری با خروجیِ پرحرف میتواند در یک نوبت هزاران توکن مصرف کند. کانتکست در طولِ نوبتها انباشته میشود، پس نشستهای طولانیترِ با فراخوانیهای ابزارِ زیاد کانتکستِ بهمراتب بیشتری از نشستهای کوتاه میسازند.
فشردهسازیِ خودکار
Section titled “فشردهسازیِ خودکار”وقتی پنجرهی کانتکست به سقفش نزدیک میشود، SDK بهصورتِ خودکار گفتگو را فشرده میکند: تاریخچهی قدیمیتر را خلاصه میکند تا فضا آزاد شود، و تازهترین تبادلها و تصمیمهای کلیدیات را دستنخورده نگه میدارد. وقتی این اتفاق میافتد، SDK یک پیام با type: "system" و subtype: "compact_boundary" در جریان منتشر میکند (در Python این یک SystemMessage است؛ در TypeScript یک نوعِ جداگانهی SDKCompactBoundaryMessage است).
فشردهسازی پیامهای قدیمیتر را با یک خلاصه جایگزین میکند، پس دستورالعملهای مشخصِ ابتدای گفتگو ممکن است حفظ نشوند. قواعدِ ماندگار باید در CLAUDE.md باشند (که از طریقِ settingSources بار میشود) نه در پرامپتِ اولیه، چون محتوای CLAUDE.md در هر درخواست دوباره تزریق میشود.
میتوانی رفتارِ فشردهسازی را به چند روش سفارشی کنی:
- دستورالعملهای خلاصهسازی در CLAUDE.md: فشردهساز CLAUDE.mdِ تو را مثلِ هر کانتکستِ دیگری میخواند، پس میتوانی بخشی بگنجانی که به آن بگوید هنگامِ خلاصهسازی چه چیزی را حفظ کند. سرتیترِ آن بخش آزاد است (یک رشتهی جادویی نیست)؛ فشردهساز بر اساسِ نیت تطبیق میدهد.
- هوکِ
PreCompact: پیش از وقوعِ فشردهسازی منطقِ سفارشی اجرا کن، مثلاً برای بایگانیِ رونوشتِ کامل. هوک یک فیلدِtriggerدریافت میکند (manualیاauto). هوکها را ببین. - فشردهسازیِ دستی:
/compactرا بهعنوانِ یک رشتهی پرامپت بفرست تا فشردهسازی بهصورتِ on-demand فعال شود. دستورهایی که اینطور فرستاده میشوند ورودیهای SDK هستند، نه میانبرهای فقط-CLI. دستورها در SDK را ببین.
نمونه: دستورالعملهای خلاصهسازی در CLAUDE.md
بخشی به CLAUDE.mdِ پروژهات اضافه کن که به فشردهساز بگوید چه چیزی را حفظ کند. نامِ سرتیتر خاص نیست؛ هر برچسبِ روشنی به کار ببر.
# Summary instructions
When summarizing this conversation, always preserve:- The current task objective and acceptance criteria- File paths that have been read or modified- Test results and error messages- Decisions made and the reasoning behind themکانتکست را بهینه نگه دار
Section titled “کانتکست را بهینه نگه دار”چند راهبرد برای ایجنتهای طولانیاجرا:
- برای زیرکارها از سابایجنتها استفاده کن. هر سابایجنت با یک گفتگوی تازه شروع میشود (بدونِ تاریخچهی پیامِ پیشین، هرچند سیستمپرامپتِ خودش و کانتکستِ سطحِ پروژه مثلِ CLAUDE.md را بار میکند). نوبتهای والد را نمیبیند، و فقط پاسخِ نهاییاش به والد بهعنوانِ نتیجهی ابزار برمیگردد. کانتکستِ ایجنتِ اصلی به اندازهی همان خلاصه رشد میکند، نه به اندازهی کلِ رونوشتِ زیرکار. برای جزئیات، What subagents inherit را ببین.
- در انتخابِ ابزارها گزینشی باش. هر تعریفِ ابزار فضای کانتکست میگیرد. از فیلدِ
toolsرویAgentDefinitionاستفاده کن تا سابایجنتها را به حداقلِ مجموعهی موردِ نیازشان محدود کنی. - مراقبِ هزینههای سرورِ MCP باش. MCP tool search شِماهای ابزارِ MCP را بهصورتِ پیشفرض موکول میکند و آنها را on-demand بار میکند. وقتی tool search خاموش است، روی Vertex AI، یا پشتِ یک
ANTHROPIC_BASE_URLِ غیرشخصِاول، هر سرورِ MCP همهی شِماهای ابزارش را به هر درخواست اضافه میکند، پس چند سرور با ابزارهای زیاد میتوانند پیش از اینکه ایجنت کاری کند کانتکستِ قابلِتوجهی مصرف کنند. - برای کارهای روتین از effortِ پایینتر استفاده کن. برای ایجنتهایی که فقط باید فایل بخوانند یا دایرکتوری فهرست کنند، effort را روی
"low"بگذار. این مصرفِ توکن و هزینه را کاهش میدهد.
برای تفکیکِ دقیقِ هزینههای کانتکستِ هر قابلیت، Understand context costs را ببین.
نشستها و پیوستگی
Section titled “نشستها و پیوستگی”هر تعامل با SDK یک نشست میسازد یا ادامه میدهد. شناسهی نشست را از ResultMessage.session_id (در هر دو SDK در دسترس است) بگیر تا بعداً از سر بگیری. TypeScript SDK آن را بهعنوانِ یک فیلدِ مستقیم روی SystemMessageِ initِ هم نمایش میدهد؛ در Python در SystemMessage.data تو در تو است.
وقتی از سر میگیری، کلِ کانتکست از نوبتهای پیشین بازیابی میشود: فایلهایی که خوانده شدهاند، تحلیلی که انجام شده، و اقداماتی که انجام گرفته. همچنین میتوانی یک نشست را fork کنی تا بدونِ تغییرِ اصل، به رویکردی متفاوت شاخه بزنی.
برای راهنمای کاملِ الگوهای resume، continue و fork، Session management را ببین.
مدیریتِ نتیجه
Section titled “مدیریتِ نتیجه”وقتی حلقه پایان میگیرد، ResultMessage به تو میگوید چه شد و خروجی را میدهد. فیلدِ subtype (در هر دو SDK در دسترس است) راهِ اصلیِ بررسیِ حالتِ خاتمه است.
| زیرنوعِ نتیجه | چه شد | فیلدِ result در دسترس است؟ |
|---|---|---|
success | Claude کار را عادی تمام کرد | بله |
error_max_turns | پیش از اتمام به محدودیتِ maxTurns خورد | نه |
error_max_budget_usd | پیش از اتمام به محدودیتِ maxBudgetUsd خورد | نه |
error_during_execution | یک خطا حلقه را قطع کرد (مثلاً یک شکستِ API یا درخواستِ لغوشده) | نه |
error_max_structured_output_retries | هیچ خروجیِ ساختیافتهی معتبری در حدِ تلاشِ مجدِ پیکربندیشده تولید نشد: هر تلاش از اعتبارسنجی رد شد، یا یک فالبکِ مدل خروجیِ تکمیلشده را بدونِ یک تلاشِ موفقِ مجدد پس گرفت | نه |
فیلدِ result (خروجیِ متنیِ نهایی) فقط روی واریانتِ success حاضر است، پس همیشه پیش از خواندنش subtype را بررسی کن. همهی زیرنوعهای نتیجه total_cost_usd، usage، num_turns و session_id را حمل میکنند تا بتوانی حتی پس از خطا هزینه را رهگیری و از سر بگیری. در Python، total_cost_usd و usage بهصورتِ optional تایپ شدهاند و ممکن است در بعضی مسیرهای خطا None باشند، پس پیش از قالببندیشان محافظت بگذار. برای جزئیاتِ تفسیرِ فیلدهای usage، Tracking costs and usage را ببین.
نتیجه همچنین یک فیلدِ stop_reason دارد (string | null در TypeScript، str | None در Python) که نشان میدهد چرا مدل در نوبتِ نهاییاش از تولید بازایستاد. مقادیرِ رایج end_turn (مدل عادی تمام کرد)، max_tokens (به سقفِ توکنِ خروجی خورد) و refusal (مدل درخواست را رد کرد) هستند. روی زیرنوعهای خطای نتیجه، stop_reason مقدارِ آخرین پاسخِ دستیار پیش از پایانِ حلقه را حمل میکند. برای تشخیصِ ردها، stop_reason === "refusal" (TypeScript) یا stop_reason == "refusal" (Python) را بررسی کن. برای نوعِ کامل، SDKResultMessage (TypeScript) یا ResultMessage (Python) را ببین.
هوکها
Section titled “هوکها”هوکها کالبکهایی هستند که در نقطههای مشخصی از حلقه فعال میشوند: پیش از اجرای یک ابزار، پس از بازگشتش، وقتی ایجنت تمام میکند و غیره. چند هوکِ پرکاربرد اینهاست:
| هوک | کِی فعال میشود | کاربردهای رایج |
|---|---|---|
PreToolUse | پیش از اجرای یک ابزار | اعتبارسنجیِ ورودیها، مسدود کردنِ دستورهای خطرناک |
PostToolUse | پس از بازگشتِ یک ابزار | ممیزیِ خروجیها، فعال کردنِ اثرهای جانبی |
UserPromptSubmit | وقتی یک پرامپت فرستاده میشود | تزریقِ کانتکستِ اضافی به پرامپتها |
Stop | وقتی ایجنت تمام میکند | اعتبارسنجیِ نتیجه، ذخیرهی وضعیتِ نشست |
SubagentStart / SubagentStop | وقتی یک سابایجنت تولید یا تمام میشود | رهگیری و تجمیعِ نتایجِ وظیفههای موازی |
PreCompact | پیش از فشردهسازیِ کانتکست | بایگانیِ رونوشتِ کامل پیش از خلاصهسازی |
هوکها در فرایندِ اپلیکیشنِ تو اجرا میشوند، نه داخلِ پنجرهی کانتکستِ ایجنت، پس کانتکست مصرف نمیکنند. هوکها همچنین میتوانند حلقه را اتصالِکوتاه کنند: یک هوکِ PreToolUse که یک فراخوانیِ ابزار را رد میکند جلوی اجرایش را میگیرد، و Claude بهجایش پیامِ ردّ را دریافت میکند.
هر دو SDK از همهی رویدادهای بالا پشتیبانی میکنند. TypeScript SDK رویدادهای اضافیای دارد که Python هنوز پشتیبانی نمیکند. برای فهرستِ کاملِ رویدادها، در دسترس بودنِ هر-SDK و API کاملِ کالبک، Control execution with hooks را ببین.
همه را کنار هم بگذار
Section titled “همه را کنار هم بگذار”این نمونه مفاهیمِ کلیدیِ این صفحه را در یک ایجنتِ واحد که تستهای شکستخورده را درست میکند ترکیب میکند. ایجنت را با ابزارهای مجاز (خودکار تأییدشده تا ایجنت خودمختار اجرا شود)، تنظیماتِ پروژه و محدودیتهای ایمنی روی نوبتها و سطحِ effortِ استدلال پیکربندی میکند. همینطور که حلقه اجرا میشود، شناسهی نشست را برای از سر گرفتنِ احتمالی میگیرد، نتیجهی نهایی را مدیریت میکند و هزینهی کل را چاپ میکند.
import asynciofrom claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def run_agent(): session_id = None
async for message in query( prompt="Find and fix the bug causing test failures in the auth module", options=ClaudeAgentOptions( allowed_tools=[ "Read", "Edit", "Bash", "Glob", "Grep", ], # Listing tools here auto-approves them (no prompting) setting_sources=[ "project" ], # Load CLAUDE.md, skills, hooks from current directory max_turns=30, # Prevent runaway sessions effort="high", # Thorough reasoning for complex debugging ), ): # Handle the final result if isinstance(message, ResultMessage): session_id = message.session_id # Save for potential resumption
if message.subtype == "success": print(f"Done: {message.result}") elif message.subtype == "error_max_turns": # Agent ran out of turns. Resume with a higher limit. print(f"Hit turn limit. Resume session {session_id} to continue.") elif message.subtype == "error_max_budget_usd": print("Hit budget limit.") else: print(f"Stopped: {message.subtype}") if message.total_cost_usd is not None: print(f"Cost: ${message.total_cost_usd:.4f}")
asyncio.run(run_agent())import { query } from "@anthropic-ai/claude-agent-sdk";
let sessionId: string | undefined;
for await (const message of query({ prompt: "Find and fix the bug causing test failures in the auth module", options: { allowedTools: ["Read", "Edit", "Bash", "Glob", "Grep"], // Listing tools here auto-approves them (no prompting) settingSources: ["project"], // Load CLAUDE.md, skills, hooks from current directory maxTurns: 30, // Prevent runaway sessions effort: "high" // Thorough reasoning for complex debugging }})) { // Save the session ID to resume later if needed if (message.type === "system" && message.subtype === "init") { sessionId = message.session_id; }
// Handle the final result if (message.type === "result") { if (message.subtype === "success") { console.log(`Done: ${message.result}`); } else if (message.subtype === "error_max_turns") { // Agent ran out of turns. Resume with a higher limit. console.log(`Hit turn limit. Resume session ${sessionId} to continue.`); } else if (message.subtype === "error_max_budget_usd") { console.log("Hit budget limit."); } else { console.log(`Stopped: ${message.subtype}`); } console.log(`Cost: $${message.total_cost_usd.toFixed(4)}`); }}گامهای بعدی
Section titled “گامهای بعدی”حالا که حلقه را میفهمی، بسته به اینکه چه میسازی اینجا برو:
- هنوز ایجنتی اجرا نکردهای؟ با quickstart شروع کن تا SDK را نصب کنی و یک نمونهی کامل را سرتاسر در حالِ اجرا ببینی.
- آمادهای به پروژهات وصل شوی؟ CLAUDE.md، Skillها و هوکهای فایلسیستم را بار کن تا ایجنت بهصورتِ خودکار قراردادهای پروژهات را دنبال کند.
- یک رابطِ تعاملی میسازی؟ استریمینگ را فعال کن تا متن و فراخوانیهای ابزارِ زنده را همینطور که حلقه اجرا میشود نشان دهی.
- به کنترلِ سفتتری روی آنچه ایجنت میتواند بکند نیاز داری؟ دسترسیِ ابزار را با permissions قفل کن، و از هوکها برای ممیزی، مسدود کردن یا دگرگون کردنِ فراخوانیهای ابزار پیش از اجرا استفاده کن.
- کارهای طولانی یا گران اجرا میکنی؟ کارِ جداشده را به سابایجنتها بسپار تا کانتکستِ اصلیات لاغر بماند.
برای تصویرِ مفهومیِ گستردهترِ حلقهی ایجنتیک (نه مخصوصِ SDK)، How Claude Code works را ببین.