مرجعِ Agent SDK — پایتون
pip install claude-agent-sdkانتخاب بینِ query() و ClaudeSDKClient
Section titled “انتخاب بینِ query() و ClaudeSDKClient”پایتون SDK دو راه برای تعامل با Claude Code فراهم میکند:
مقایسهی سریع
Section titled “مقایسهی سریع”| قابلیت | query() | ClaudeSDKClient |
|---|---|---|
| نشست | بهصورتِ پیشفرض یک نشستِ جدید میسازد | همان نشست را دوباره استفاده میکند |
| گفتگو | یک تبادلِ واحد | چند تبادل در همان کانتکست |
| اتصال | خودکار مدیریت میشود | کنترلِ دستی |
| Streaming Input | ✅ پشتیبانیشده | ✅ پشتیبانیشده |
| Interrupts | ❌ پشتیبانینشده | ✅ پشتیبانیشده |
| Hooks | ✅ پشتیبانیشده | ✅ پشتیبانیشده |
| Custom Tools | ✅ پشتیبانیشده | ✅ پشتیبانیشده |
| ادامهی چت | دستی از طریقِ continue_conversation یا resume | ✅ خودکار |
| مورد استفاده | تسکهای یکباره | گفتگوهای پیوسته |
کِی از query() استفاده کنیم (تسکهای یکباره)
Section titled “کِی از query() استفاده کنیم (تسکهای یکباره)”بهترین برای:
- پرسشهای یکباره که به تاریخچهی گفتگو نیاز نداری
- تسکهای مستقل که به کانتکستِ تبادلهای پیشین نیاز ندارند
- اسکریپتهای اتوماسیونِ ساده
- وقتی هر بار یک شروعِ تازه میخواهی
کِی از ClaudeSDKClient استفاده کنیم (گفتگوی پیوسته)
Section titled “کِی از ClaudeSDKClient استفاده کنیم (گفتگوی پیوسته)”بهترین برای:
- ادامهی گفتگو - وقتی نیاز داری Claude کانتکست را به یاد بسپارد
- پرسشهای پیگیری - ساختن روی پاسخهای پیشین
- اپلیکیشنهای تعاملی - رابطهای چت، REPLها
- منطقِ پاسخمحور - وقتی اقدامِ بعدی به پاسخِ Claude بستگی دارد
- کنترلِ نشست - مدیریتِ صریحِ چرخهی حیاتِ گفتگو
query()
Section titled “query()”بهصورتِ پیشفرض برای هر تعامل با Claude Code یک نشستِ جدید میسازد. یک async iterator برمیگرداند که پیامها را همانطور که میرسند yield میکند. هر فراخوانیِ query() بدونِ حافظهای از تعاملهای پیشین تازه شروع میشود، مگر اینکه continue_conversation=True یا resume را در ClaudeAgentOptions پاس بدهی. نشستها را ببین.
async def query( *, prompt: str | AsyncIterable[dict[str, Any]], options: ClaudeAgentOptions | None = None, transport: Transport | None = None) -> AsyncIterator[Message]پارامترها
Section titled “پارامترها”| پارامتر | نوع | توضیح |
|---|---|---|
prompt | str | AsyncIterable[dict] | پرامپتِ ورودی بهصورتِ رشته یا async iterable برای حالتِ streaming |
options | ClaudeAgentOptions | None | آبجکتِ پیکربندیِ اختیاری (در صورتِ None، پیشفرض ClaudeAgentOptions()) |
transport | Transport | None | transportِ سفارشیِ اختیاری برای ارتباط با پروسهی CLI |
بازگشتی
Section titled “بازگشتی”یک AsyncIterator[Message] برمیگرداند که پیامهای گفتگو را yield میکند.
مثال - با options
Section titled “مثال - با options”import asynciofrom claude_agent_sdk import query, ClaudeAgentOptions
async def main(): options = ClaudeAgentOptions( system_prompt="You are an expert Python developer", permission_mode="acceptEdits", cwd="/home/user/project", )
async for message in query(prompt="Create a Python web server", options=options): print(message)
asyncio.run(main())tool()
Section titled “tool()”دکوراتور برای تعریفِ ابزارهای MCP با ایمنیِ نوع.
def tool( name: str, description: str, input_schema: type | dict[str, Any], annotations: ToolAnnotations | None = None) -> Callable[[Callable[[Any], Awaitable[dict[str, Any]]]], SdkMcpTool[Any]]پارامترها
Section titled “پارامترها”| پارامتر | نوع | توضیح |
|---|---|---|
name | str | شناسهی یکتای ابزار |
description | str | توضیحِ خوانا برای انسان دربارهی کاری که ابزار انجام میدهد |
input_schema | type | dict[str, Any] | schemaِ تعریفکنندهی پارامترهای ورودیِ ابزار (پایین را ببین) |
annotations | ToolAnnotations | None | annotationهای اختیاریِ ابزارِ MCP که نکتههای رفتاری به clientها میدهند |
گزینههای input schema
Section titled “گزینههای input schema”-
نگاشتِ نوعِ ساده (توصیهشده):
{"text": str, "count": int, "enabled": bool} -
قالبِ JSON Schema (برای اعتبارسنجیِ پیچیده):
{"type": "object","properties": {"text": {"type": "string"},"count": {"type": "integer", "minimum": 0},},"required": ["text"],}
بازگشتی
Section titled “بازگشتی”یک تابعِ دکوراتور که پیادهسازیِ ابزار را wrap میکند و یک نمونهی SdkMcpTool برمیگرداند.
from claude_agent_sdk import toolfrom typing import Any
@tool("greet", "Greet a user", {"name": str})async def greet(args: dict[str, Any]) -> dict[str, Any]: return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}ToolAnnotations
Section titled “ToolAnnotations”از mcp.types دوباره export شده (بهصورتِ from claude_agent_sdk import ToolAnnotations هم در دسترس است). همهی فیلدها نکتههای اختیاریاند؛ clientها نباید برای تصمیمهای امنیتی به آنها تکیه کنند.
| فیلد | نوع | پیشفرض | توضیح |
|---|---|---|---|
title | str | None | None | عنوانِ خوانا برای انسان برای ابزار |
readOnlyHint | bool | None | False | اگر True باشد، ابزار محیطِ خود را تغییر نمیدهد |
destructiveHint | bool | None | True | اگر True باشد، ابزار ممکن است بهروزرسانیهای مخرب انجام دهد (فقط وقتی readOnlyHint برابرِ False است معنادار است) |
idempotentHint | bool | None | False | اگر True باشد، فراخوانیهای مکررِ با همان آرگومانها اثرِ اضافی ندارند (فقط وقتی readOnlyHint برابرِ False است معنادار است) |
openWorldHint | bool | None | True | اگر True باشد، ابزار با موجودیتهای بیرونی تعامل دارد (مثلاً web search). اگر False باشد، دامنهی ابزار بسته است (مثلاً یک ابزارِ حافظه) |
from claude_agent_sdk import tool, ToolAnnotationsfrom typing import Any
@tool( "search", "Search the web", {"query": str}, annotations=ToolAnnotations(readOnlyHint=True, openWorldHint=True),)async def search(args: dict[str, Any]) -> dict[str, Any]: return {"content": [{"type": "text", "text": f"Results for: {args['query']}"}]}create_sdk_mcp_server()
Section titled “create_sdk_mcp_server()”یک سرورِ MCPِ in-process بساز که درونِ اپلیکیشنِ پایتونِ تو اجرا میشود.
def create_sdk_mcp_server( name: str, version: str = "1.0.0", tools: list[SdkMcpTool[Any]] | None = None) -> McpSdkServerConfigپارامترها
Section titled “پارامترها”| پارامتر | نوع | پیشفرض | توضیح |
|---|---|---|---|
name | str | - | شناسهی یکتای سرور |
version | str | "1.0.0" | رشتهی نسخهی سرور |
tools | list[SdkMcpTool[Any]] | None | None | فهرستِ توابعِ ابزار که با دکوراتورِ @tool ساخته شدهاند |
بازگشتی
Section titled “بازگشتی”یک آبجکتِ McpSdkServerConfig برمیگرداند که میتوان آن را به ClaudeAgentOptions.mcp_servers پاس داد.
from claude_agent_sdk import tool, create_sdk_mcp_server
@tool("add", "Add two numbers", {"a": float, "b": float})async def add(args): return {"content": [{"type": "text", "text": f"Sum: {args['a'] + args['b']}"}]}
@tool("multiply", "Multiply two numbers", {"a": float, "b": float})async def multiply(args): return {"content": [{"type": "text", "text": f"Product: {args['a'] * args['b']}"}]}
calculator = create_sdk_mcp_server( name="calculator", version="2.0.0", tools=[add, multiply], # Pass decorated functions)
# Use with Claudeoptions = ClaudeAgentOptions( mcp_servers={"calc": calculator}, allowed_tools=["mcp__calc__add", "mcp__calc__multiply"],)list_sessions()
Section titled “list_sessions()”نشستهای گذشته را بههمراه فراداده فهرست میکند. بر اساسِ دایرکتوریِ پروژه فیلتر کن یا نشستها را در همهی پروژهها فهرست کن. همگام (synchronous)؛ بلافاصله برمیگردد.
def list_sessions( directory: str | None = None, limit: int | None = None, include_worktrees: bool = True) -> list[SDKSessionInfo]پارامترها
Section titled “پارامترها”| پارامتر | نوع | پیشفرض | توضیح |
|---|---|---|---|
directory | str | None | None | دایرکتوریای که نشستهایش فهرست شوند. وقتی حذف شود، نشستها را در همهی پروژهها برمیگرداند |
limit | int | None | None | بیشینهی تعدادِ نشستهایی که برگردانده میشوند |
include_worktrees | bool | True | وقتی directory درونِ یک مخزنِ git است، نشستها را از همهی مسیرهای worktree بگنجان |
نوعِ بازگشتی: SDKSessionInfo
Section titled “نوعِ بازگشتی: SDKSessionInfo”| ویژگی | نوع | توضیح |
|---|---|---|
session_id | str | شناسهی یکتای نشست |
summary | str | عنوانِ نمایشی: عنوانِ سفارشی، خلاصهی خودکارتولیدشده، یا اولین پرامپت |
last_modified | int | زمانِ آخرین تغییر، به میلیثانیه از epoch |
file_size | int | None | اندازهی فایلِ نشست به بایت (None برای backendهای ذخیرهسازیِ remote) |
custom_title | str | None | عنوانِ نشست که کاربر تنظیم کرده |
first_prompt | str | None | اولین پرامپتِ معنادارِ کاربر در نشست |
git_branch | str | None | شاخهی git در پایانِ نشست |
cwd | str | None | دایرکتوریِ کاریِ نشست |
tag | str | None | برچسبِ نشست که کاربر تنظیم کرده (tag_session() را ببین) |
created_at | int | None | زمانِ ساختِ نشست، به میلیثانیه از epoch |
۱۰ نشستِ اخیرِ یک پروژه را چاپ کن. نتایج بر اساسِ last_modified نزولی مرتب میشوند، پس اولین آیتم تازهترین است. برای جستوجو در همهی پروژهها directory را حذف کن.
from claude_agent_sdk import list_sessions
for session in list_sessions(directory="/path/to/project", limit=10): print(f"{session.summary} ({session.session_id})")get_session_messages()
Section titled “get_session_messages()”پیامهای یک نشستِ گذشته را بازیابی میکند. همگام؛ بلافاصله برمیگردد.
def get_session_messages( session_id: str, directory: str | None = None, limit: int | None = None, offset: int = 0) -> list[SessionMessage]پارامترها
Section titled “پارامترها”| پارامتر | نوع | پیشفرض | توضیح |
|---|---|---|---|
session_id | str | الزامی | شناسهی نشستی که پیامهایش بازیابی شود |
directory | str | None | None | دایرکتوریِ پروژه برای جستوجو. وقتی حذف شود، همهی پروژهها را جستوجو میکند |
limit | int | None | None | بیشینهی تعدادِ پیامهایی که برگردانده میشوند |
offset | int | 0 | تعدادِ پیامهایی که از ابتدا رد شوند |
نوعِ بازگشتی: SessionMessage
Section titled “نوعِ بازگشتی: SessionMessage”| ویژگی | نوع | توضیح |
|---|---|---|
type | Literal["user", "assistant"] | نقشِ پیام |
uuid | str | شناسهی یکتای پیام |
session_id | str | شناسهی نشست |
message | Any | محتوای خامِ پیام |
parent_tool_use_id | None | رزرو برای استفادهی آینده |
from claude_agent_sdk import list_sessions, get_session_messages
sessions = list_sessions(limit=1)if sessions: messages = get_session_messages(sessions[0].session_id) for msg in messages: print(f"[{msg.type}] {msg.uuid}")get_session_info()
Section titled “get_session_info()”فرادادهی یک نشستِ واحد را بر اساسِ ID میخواند، بدونِ پویشِ کلِ دایرکتوریِ پروژه. همگام؛ بلافاصله برمیگردد.
def get_session_info( session_id: str, directory: str | None = None,) -> SDKSessionInfo | Noneپارامترها
Section titled “پارامترها”| پارامتر | نوع | پیشفرض | توضیح |
|---|---|---|---|
session_id | str | الزامی | UUIDِ نشستی که جستوجو شود |
directory | str | None | None | مسیرِ دایرکتوریِ پروژه. وقتی حذف شود، همهی دایرکتوریهای پروژه را جستوجو میکند |
یک SDKSessionInfo برمیگرداند، یا None اگر نشست پیدا نشود.
فرادادهی یک نشستِ واحد را بدونِ پویشِ دایرکتوریِ پروژه جستوجو کن. وقتی از یک اجرای پیشین یک session ID داری مفید است.
from claude_agent_sdk import get_session_info
info = get_session_info("550e8400-e29b-41d4-a716-446655440000")if info: print(f"{info.summary} (branch: {info.git_branch}, tag: {info.tag})")rename_session()
Section titled “rename_session()”یک نشست را با افزودنِ یک ورودیِ custom-title تغییرِ نام میدهد. فراخوانیهای مکرر امناند؛ تازهترین عنوان برنده است. همگام.
def rename_session( session_id: str, title: str, directory: str | None = None,) -> Noneپارامترها
Section titled “پارامترها”| پارامتر | نوع | پیشفرض | توضیح |
|---|---|---|---|
session_id | str | الزامی | UUIDِ نشستی که تغییرِ نام شود |
title | str | الزامی | عنوانِ جدید. پس از حذفِ فاصلهها باید ناخالی باشد |
directory | str | None | None | مسیرِ دایرکتوریِ پروژه. وقتی حذف شود، همهی دایرکتوریهای پروژه را جستوجو میکند |
اگر session_id یک UUIDِ معتبر نباشد یا title خالی باشد ValueError میدهد؛ اگر نشست پیدا نشود FileNotFoundError.
تازهترین نشست را تغییرِ نام بده تا بعداً راحتتر پیدایش کنی. عنوانِ جدید در خواندنهای بعدی در SDKSessionInfo.custom_title ظاهر میشود.
from claude_agent_sdk import list_sessions, rename_session
sessions = list_sessions(directory="/path/to/project", limit=1)if sessions: rename_session(sessions[0].session_id, "Refactor auth module")tag_session()
Section titled “tag_session()”یک نشست را برچسب میزند. برای پاککردنِ برچسب None پاس بده. فراخوانیهای مکرر امناند؛ تازهترین برچسب برنده است. همگام.
def tag_session( session_id: str, tag: str | None, directory: str | None = None,) -> Noneپارامترها
Section titled “پارامترها”| پارامتر | نوع | پیشفرض | توضیح |
|---|---|---|---|
session_id | str | الزامی | UUIDِ نشستی که برچسب بخورد |
tag | str | None | الزامی | رشتهی برچسب، یا None برای پاککردن. پیش از ذخیره Unicode-sanitize میشود |
directory | str | None | None | مسیرِ دایرکتوریِ پروژه. وقتی حذف شود، همهی دایرکتوریهای پروژه را جستوجو میکند |
اگر session_id یک UUIDِ معتبر نباشد یا tag پس از sanitize خالی باشد ValueError میدهد؛ اگر نشست پیدا نشود FileNotFoundError.
یک نشست را برچسب بزن، سپس در خواندنِ بعدی بر اساسِ آن برچسب فیلتر کن. برای پاککردنِ یک برچسبِ موجود None پاس بده.
from claude_agent_sdk import list_sessions, tag_session
# Tag a sessiontag_session("550e8400-e29b-41d4-a716-446655440000", "needs-review")
# Later: find all sessions with that tagfor session in list_sessions(directory="/path/to/project"): if session.tag == "needs-review": print(session.summary)کلاسها
Section titled “کلاسها”ClaudeSDKClient
Section titled “ClaudeSDKClient”یک نشستِ گفتگو را در طولِ چند تبادل نگه میدارد. این معادلِ پایتونیِ نحوهی کارِ درونیِ تابعِ query()ِ تایپاسکریپت است — یک آبجکتِ client میسازد که میتواند گفتگوها را ادامه دهد.
قابلیتهای کلیدی
Section titled “قابلیتهای کلیدی”- پیوستگیِ نشست: کانتکستِ گفتگو را در طولِ چند فراخوانیِ
query()نگه میدارد - همان گفتگو: نشست پیامهای پیشین را حفظ میکند
- پشتیبانیِ Interrupt: میتواند اجرا را در میانهی تسک متوقف کند
- چرخهی حیاتِ صریح: تو کنترل میکنی که نشست کِی شروع و کِی پایان یابد
- جریانِ پاسخمحور: میتواند به پاسخها واکنش نشان دهد و پیگیری بفرستد
- ابزارها و hookهای سفارشی: از ابزارهای سفارشی (ساختهشده با دکوراتورِ
@tool) و hookها پشتیبانی میکند
class ClaudeSDKClient: def __init__(self, options: ClaudeAgentOptions | None = None, transport: Transport | None = None) async def connect(self, prompt: str | AsyncIterable[dict] | None = None) -> None async def query(self, prompt: str | AsyncIterable[dict], session_id: str = "default") -> None async def receive_messages(self) -> AsyncIterator[Message] async def receive_response(self) -> AsyncIterator[Message] async def interrupt(self) -> None async def set_permission_mode(self, mode: str) -> None async def set_model(self, model: str | None = None) -> None async def rewind_files(self, user_message_id: str) -> None async def get_mcp_status(self) -> McpStatusResponse async def reconnect_mcp_server(self, server_name: str) -> None async def toggle_mcp_server(self, server_name: str, enabled: bool) -> None async def stop_task(self, task_id: str) -> None async def get_server_info(self) -> dict[str, Any] | None async def disconnect(self) -> None| متد | توضیح |
|---|---|
__init__(options) | client را با پیکربندیِ اختیاری مقداردهیِ اولیه کن |
connect(prompt) | به Claude با یک پرامپتِ اولیه یا استریمِ پیامِ اختیاری وصل شو |
query(prompt, session_id) | یک درخواستِ جدید در حالتِ streaming بفرست |
receive_messages() | همهی پیامهای Claude را بهصورتِ یک async iterator دریافت کن |
receive_response() | پیامها را تا و شاملِ یک ResultMessage دریافت کن |
interrupt() | سیگنالِ interrupt بفرست (فقط در حالتِ streaming کار میکند) |
set_permission_mode(mode) | permission mode را برای نشستِ فعلی تغییر بده |
set_model(model) | مدلِ نشستِ فعلی را تغییر بده. برای بازگشت به پیشفرض None پاس بده |
rewind_files(user_message_id) | فایلها را به وضعیتشان در پیامِ کاربرِ مشخصشده بازگردان. نیازمندِ enable_file_checkpointing=True است. File checkpointing را ببین |
get_mcp_status() | وضعیتِ همهی سرورهای MCPِ پیکربندیشده را بگیر. McpStatusResponse را برمیگرداند |
reconnect_mcp_server(server_name) | اتصال به سرورِ MCPی که ناموفق بود یا قطع شد را دوباره امتحان کن |
toggle_mcp_server(server_name, enabled) | یک سرورِ MCP را در میانهی نشست فعال یا غیرفعال کن. غیرفعالکردن ابزارهایش را حذف میکند |
stop_task(task_id) | یک تسکِ پسزمینهی در حالِ اجرا را متوقف کن. یک TaskNotificationMessage با وضعیتِ "stopped" در استریمِ پیام به دنبالش میآید |
get_server_info() | اطلاعاتِ سرور شاملِ session ID و قابلیتها را بگیر |
disconnect() | از Claude قطع شو |
پشتیبانیِ Context Manager
Section titled “پشتیبانیِ Context Manager”میتوان client را بهعنوانِ یک async context manager برای مدیریتِ خودکارِ اتصال استفاده کرد:
async with ClaudeSDKClient() as client: await client.query("Hello Claude") async for message in client.receive_response(): print(message)مهم: هنگامِ پیمایش روی پیامها، از
breakبرای خروجِ زودهنگام پرهیز کن چون میتواند مشکلاتِ پاکسازیِ asyncio ایجاد کند. بهجای آن بگذار پیمایش بهطورِ طبیعی کامل شود یا از flagها برای ردیابیِ اینکه آنچه را که میخواستی پیدا کردهای استفاده کن.
مثال - ادامهی یک گفتگو
Section titled “مثال - ادامهی یک گفتگو”import asynciofrom claude_agent_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
async def main(): async with ClaudeSDKClient() as client: # First question await client.query("What's the capital of France?")
# Process response async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(f"Claude: {block.text}")
# Follow-up question - the session retains the previous context await client.query("What's the population of that city?")
async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(f"Claude: {block.text}")
# Another follow-up - still in the same conversation await client.query("What are some famous landmarks there?")
async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(f"Claude: {block.text}")
asyncio.run(main())مثال - ورودیِ streaming با ClaudeSDKClient
Section titled “مثال - ورودیِ streaming با ClaudeSDKClient”import asynciofrom claude_agent_sdk import ClaudeSDKClient
async def message_stream(): """Generate messages dynamically.""" yield { "type": "user", "message": {"role": "user", "content": "Analyze the following data:"}, } await asyncio.sleep(0.5) yield { "type": "user", "message": {"role": "user", "content": "Temperature: 25°C, Humidity: 60%"}, } await asyncio.sleep(0.5) yield { "type": "user", "message": {"role": "user", "content": "What patterns do you see?"}, }
async def main(): async with ClaudeSDKClient() as client: # Stream input to Claude await client.query(message_stream())
# Process response async for message in client.receive_response(): print(message)
# Follow-up in same session await client.query("Should we be concerned about these readings?")
async for message in client.receive_response(): print(message)
asyncio.run(main())مثال - استفاده از interruptها
Section titled “مثال - استفاده از interruptها”import asynciofrom claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, ResultMessage
async def interruptible_task(): options = ClaudeAgentOptions(allowed_tools=["Bash"], permission_mode="acceptEdits")
async with ClaudeSDKClient(options=options) as client: # Start a long-running task await client.query("Count from 1 to 100 slowly, using the bash sleep command")
# Let it run for a bit await asyncio.sleep(2)
# Interrupt the task await client.interrupt() print("Task interrupted!")
# Drain the interrupted task's messages (including its ResultMessage) async for message in client.receive_response(): if isinstance(message, ResultMessage): print(f"Interrupted task finished with subtype={message.subtype!r}") # subtype is "error_during_execution" for interrupted tasks
# Send a new command await client.query("Just say hello instead")
# Now receive the new response async for message in client.receive_response(): if isinstance(message, ResultMessage) and message.subtype == "success": print(f"New result: {message.result}")
asyncio.run(interruptible_task())مثال - کنترلِ پیشرفتهی دسترسی
Section titled “مثال - کنترلِ پیشرفتهی دسترسی”from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptionsfrom claude_agent_sdk.types import ( PermissionResultAllow, PermissionResultDeny, ToolPermissionContext,)
async def custom_permission_handler( tool_name: str, input_data: dict, context: ToolPermissionContext) -> PermissionResultAllow | PermissionResultDeny: """Custom logic for tool permissions."""
# Block writes to system directories if tool_name == "Write" and input_data.get("file_path", "").startswith("/system/"): return PermissionResultDeny( message="System directory write not allowed", interrupt=True )
# Redirect sensitive file operations if tool_name in ["Write", "Edit"] and "config" in input_data.get("file_path", ""): safe_path = f"./sandbox/{input_data['file_path']}" return PermissionResultAllow( updated_input={**input_data, "file_path": safe_path} )
# Allow everything else return PermissionResultAllow(updated_input=input_data)
async def main(): options = ClaudeAgentOptions( can_use_tool=custom_permission_handler, allowed_tools=["Read", "Write", "Edit"] )
async with ClaudeSDKClient(options=options) as client: await client.query("Update the system config file")
async for message in client.receive_response(): # Will use sandbox path instead print(message)
asyncio.run(main())انواع (Types)
Section titled “انواع (Types)”SdkMcpTool
Section titled “SdkMcpTool”تعریفِ یک ابزارِ SDK MCP که با دکوراتورِ @tool ساخته شده.
@dataclassclass SdkMcpTool(Generic[T]): name: str description: str input_schema: type[T] | dict[str, Any] handler: Callable[[T], Awaitable[dict[str, Any]]] annotations: ToolAnnotations | None = None| ویژگی | نوع | توضیح |
|---|---|---|
name | str | شناسهی یکتای ابزار |
description | str | توضیحِ خوانا برای انسان |
input_schema | type[T] | dict[str, Any] | schema برای اعتبارسنجیِ ورودی |
handler | Callable[[T], Awaitable[dict[str, Any]]] | تابعِ async که اجرای ابزار را رسیدگی میکند |
annotations | ToolAnnotations | None | annotationهای اختیاریِ ابزارِ MCP (مثلِ readOnlyHint، destructiveHint، openWorldHint). از mcp.types |
Transport
Section titled “Transport”کلاسِ پایهی انتزاعی برای پیادهسازیهای transportِ سفارشی. از این برای ارتباط با پروسهی Claude روی یک کانالِ سفارشی استفاده کن (مثلاً یک اتصالِ remote بهجای یک subprocessِ محلی).
from abc import ABC, abstractmethodfrom collections.abc import AsyncIteratorfrom typing import Any
class Transport(ABC): @abstractmethod async def connect(self) -> None: ...
@abstractmethod async def write(self, data: str) -> None: ...
@abstractmethod def read_messages(self) -> AsyncIterator[dict[str, Any]]: ...
@abstractmethod async def close(self) -> None: ...
@abstractmethod def is_ready(self) -> bool: ...
@abstractmethod async def end_input(self) -> None: ...| متد | توضیح |
|---|---|
connect() | transport را وصل کن و برای ارتباط آماده شو |
write(data) | دادهی خام (JSON + newline) را روی transport بنویس |
read_messages() | async iterator که پیامهای JSONِ parseشده را yield میکند |
close() | اتصال را ببند و منابع را پاکسازی کن |
is_ready() | اگر transport بتواند بفرستد و دریافت کند True برمیگرداند |
end_input() | استریمِ ورودی را ببند (مثلاً بستنِ stdin برای transportهای subprocess) |
Import: from claude_agent_sdk import Transport
ClaudeAgentOptions
Section titled “ClaudeAgentOptions”dataclassِ پیکربندی برای queryهای Claude Code.
@dataclassclass ClaudeAgentOptions: tools: list[str] | ToolsPreset | None = None allowed_tools: list[str] = field(default_factory=list) system_prompt: str | SystemPromptPreset | None = None mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict) strict_mcp_config: bool = False permission_mode: PermissionMode | None = None continue_conversation: bool = False resume: str | None = None max_turns: int | None = None max_budget_usd: float | None = None disallowed_tools: list[str] = field(default_factory=list) model: str | None = None fallback_model: str | None = None betas: list[SdkBeta] = field(default_factory=list) output_format: dict[str, Any] | None = None permission_prompt_tool_name: str | None = None cwd: str | Path | None = None cli_path: str | Path | None = None settings: str | None = None add_dirs: list[str | Path] = field(default_factory=list) env: dict[str, str] = field(default_factory=dict) extra_args: dict[str, str | None] = field(default_factory=dict) max_buffer_size: int | None = None debug_stderr: Any = sys.stderr # Deprecated stderr: Callable[[str], None] | None = None can_use_tool: CanUseTool | None = None hooks: dict[HookEvent, list[HookMatcher]] | None = None user: str | None = None include_partial_messages: bool = False include_hook_events: bool = False fork_session: bool = False agents: dict[str, AgentDefinition] | None = None setting_sources: list[SettingSource] | None = None sandbox: SandboxSettings | None = None plugins: list[SdkPluginConfig] = field(default_factory=list) max_thinking_tokens: int | None = None # Deprecated: use thinking instead thinking: ThinkingConfig | None = None effort: EffortLevel | None = None enable_file_checkpointing: bool = False session_store: SessionStore | None = None session_store_flush: SessionStoreFlushMode = "batched"| ویژگی | نوع | پیشفرض | توضیح |
|---|---|---|---|
tools | list[str] | ToolsPreset | None | None | پیکربندیِ ابزارها. برای ابزارهای پیشفرضِ Claude Code از {"type": "preset", "preset": "claude_code"} استفاده کن |
allowed_tools | list[str] | [] | ابزارهایی که بدونِ پرامپت خودکار تأیید شوند. این Claude را به فقط همین ابزارها محدود نمیکند؛ ابزارهای فهرستنشده به permission_mode و can_use_tool سرریز میکنند. برای مسدودکردنِ ابزارها از disallowed_tools استفاده کن. Permissions را ببین |
system_prompt | str | SystemPromptPreset | None | None | پیکربندیِ system prompt. برای پرامپتِ سفارشی یک رشته پاس بده، یا برای system promptِ Claude Code از {"type": "preset", "preset": "claude_code"} استفاده کن. برای گسترشِ preset مقدارِ "append" را اضافه کن |
mcp_servers | dict[str, McpServerConfig] | str | Path | {} | پیکربندیهای سرورِ MCP یا مسیرِ فایلِ پیکربندی |
strict_mcp_config | bool | False | وقتی True باشد، فقط از سرورهای پاسدادهشده در mcp_servers استفاده کن و .mcp.jsonِ پروژه، تنظیماتِ کاربر، سرورهای MCPِ ارائهشده توسطِ plugin و connectorهای claude.ai را نادیده بگیر. به پرچمِ CLIِ --strict-mcp-config نگاشته میشود |
permission_mode | PermissionMode | None | None | permission mode برای استفاده از ابزار |
continue_conversation | bool | False | تازهترین گفتگو را ادامه بده |
resume | str | None | None | session ID برای resume |
max_turns | int | None | None | بیشینهی نوبتهای ایجنتیک (رفتوبرگشتهای استفاده از ابزار) |
max_budget_usd | float | None | None | وقتی برآوردِ هزینهی سمتِ client به این مقدارِ دلاری برسد، query را متوقف کن. در برابرِ همان برآوردِ total_cost_usd مقایسه میشود؛ برای ملاحظاتِ دقت ردیابی هزینه و مصرف را ببین |
disallowed_tools | list[str] | [] | ابزارهایی که deny شوند. یک نامِ خالی مثلِ "Bash" ابزار را از کانتکستِ Claude حذف میکند. یک قاعدهی scopeدار مثلِ "Bash(rm *)" ابزار را در دسترس میگذارد و فراخوانیهای مطابق را در هر permission mode، از جمله bypassPermissions، deny میکند. Permissions را ببین |
enable_file_checkpointing | bool | False | ردیابیِ تغییرِ فایل را برای rewinding فعال کن. File checkpointing را ببین |
model | str | None | None | aliasِ مدلِ Claude یا نامِ کاملِ مدل. مقادیرِ پذیرفتهشده و IDهای مخصوصِ provider را ببین |
fallback_model | str | None | None | مدلِ fallback برای استفاده در صورتِ شکستِ مدلِ اصلی |
betas | list[SdkBeta] | [] | قابلیتهای بتا که فعال شوند. برای گزینههای موجود SdkBeta را ببین |
output_format | dict[str, Any] | None | None | قالبِ خروجی برای پاسخهای ساختاریافته (مثلاً {"type": "json_schema", "schema": {...}}). برای جزئیات Structured outputs را ببین |
permission_prompt_tool_name | str | None | None | نامِ ابزارِ MCP برای پرامپتهای دسترسی |
cwd | str | Path | None | None | دایرکتوریِ کاریِ فعلی |
cli_path | str | Path | None | None | مسیرِ سفارشی به فایلِ اجراییِ Claude Code CLI |
settings | str | None | None | مسیرِ فایلِ تنظیمات |
add_dirs | list[str | Path] | [] | دایرکتوریهای اضافی که Claude میتواند به آنها دسترسی داشته باشد |
env | dict[str, str] | {} | متغیرهای محیطی که روی محیطِ بهارثرسیدهی پروسه merge میشوند. برای متغیرهایی که CLIِ زیربنایی میخواند Environment variables و برای متغیرهای مرتبط با timeout بخشِ رسیدگی به پاسخهای کند یا متوقفشدهی API را ببین |
extra_args | dict[str, str | None] | {} | آرگومانهای CLIِ اضافی که مستقیماً به CLI پاس داده شوند |
max_buffer_size | int | None | None | بیشینهی بایت هنگامِ buffer کردنِ stdoutِ CLI |
debug_stderr | Any | sys.stderr | منسوخ - آبجکتِ فایلمانند برای خروجیِ debug. بهجای آن از callbackِ stderr استفاده کن |
stderr | Callable[[str], None] | None | None | تابعِ callback برای خروجیِ stderr از CLI |
can_use_tool | CanUseTool | None | None | تابعِ callbackِ دسترسیِ ابزار. برای جزئیات انواعِ Permission را ببین |
hooks | dict[HookEvent, list[HookMatcher]] | None | None | پیکربندیهای hook برای رهگیریِ eventها |
user | str | None | None | شناسهی کاربر |
include_partial_messages | bool | False | eventهای streamingِ پیامِ جزئی را بگنجان. وقتی فعال باشد، پیامهای StreamEvent yield میشوند |
include_hook_events | bool | False | eventهای چرخهی حیاتِ hook را بهعنوانِ آبجکتهای HookEventMessage در استریمِ پیام بگنجان |
fork_session | bool | False | هنگامِ resume با resume، بهجای ادامهی نشستِ اصلی به یک session IDِ جدید fork کن |
agents | dict[str, AgentDefinition] | None | None | سابایجنتهای تعریفشده بهصورتِ برنامهنویسیشده |
plugins | list[SdkPluginConfig] | [] | pluginهای سفارشی را از مسیرهای محلی بارگذاری کن. برای جزئیات Plugins را ببین |
sandbox | SandboxSettings | None | None | رفتارِ sandbox را بهصورتِ برنامهنویسیشده پیکربندی کن. برای جزئیات Sandbox settings را ببین |
setting_sources | list[SettingSource] | None | None (پیشفرضِ CLI: همهی منابع) | کنترل کن که کدام تنظیماتِ فایلسیستم بارگذاری شوند. برای غیرفعالکردنِ تنظیماتِ user، project و local مقدارِ [] پاس بده. تنظیماتِ managed policy صرفنظر از این بارگذاری میشوند. Use Claude Code features را ببین |
skills | list[str] | Literal["all"] | None | None | skillهای در دسترسِ نشست. برای فعالکردنِ هر skillِ کشفشده "all" پاس بده، یا فهرستی از نامهای skill. وقتی تنظیم شود، SDK ابزارِ Skill را بهصورتِ خودکار به allowed_tools اضافه میکند. اگر tools را هم پاس میدهی، "Skill" را در آن فهرست بگنجان. Skills را ببین |
max_thinking_tokens | int | None | None | منسوخ - بیشینهی توکن برای بلاکهای thinking. بهجای آن از thinking استفاده کن |
thinking | ThinkingConfig | None | None | رفتارِ extended thinking را کنترل میکند. بر max_thinking_tokens اولویت دارد |
effort | EffortLevel | None | None | سطحِ effort برای عمقِ thinking. تنظیمِ سطحِ effort را ببین |
session_store | SessionStore | None | None | رونوشتِ transcriptهای نشست را به یک backendِ بیرونی بفرست تا هر host بتواند آنها را resume کند. پایداریِ نشستها در ذخیرهسازیِ بیرونی را ببین |
session_store_flush | Literal["batched", "eager"] | "batched" | کِی ورودیهای transcriptِ رونوشتشده به session_store فلاش شوند. "batched" یکبار در هر نوبت یا وقتی buffer پر شود فلاش میکند؛ "eager" پس از هر frame یک فلاشِ پسزمینه تریگر میکند. وقتی session_store برابرِ None باشد نادیده گرفته میشود |
رسیدگی به پاسخهای کند یا متوقفشدهی API
Section titled “رسیدگی به پاسخهای کند یا متوقفشدهی API”subprocessِ CLI چند متغیرِ محیطی میخواند که timeoutهای API و تشخیصِ توقف (stall) را کنترل میکنند. آنها را از طریقِ ClaudeAgentOptions.env پاس بده:
options = ClaudeAgentOptions( env={ "API_TIMEOUT_MS": "120000", "CLAUDE_CODE_MAX_RETRIES": "2", "CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS": "120000", },)API_TIMEOUT_MS: timeoutِ هر-درخواست روی clientِ Anthropic، به میلیثانیه. پیشفرض600000. روی حلقهی اصلی و همهی سابایجنتها اعمال میشود.CLAUDE_CODE_MAX_RETRIES: بیشینهی retryهای API. پیشفرض10. هر retry پنجرهیAPI_TIMEOUT_MSِ خودش را میگیرد، پس بدترین حالتِ زمانِ کلی تقریباًAPI_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1)بهعلاوهی backoff است.CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS: watchdogِ توقف برای سابایجنتهایی که باrun_in_backgroundراهاندازی شدهاند. پیشفرض600000. روی هر stream event ریست میشود؛ هنگامِ توقف سابایجنت را abort میکند، تسک را failed علامت میزند، و خطا را با هر نتیجهی جزئی به والد سرریز میکند. روی سابایجنتهای همگام اعمال نمیشود.CLAUDE_ENABLE_STREAM_WATCHDOG=1باCLAUDE_STREAM_IDLE_TIMEOUT_MS: وقتی headerها رسیدهاند اما بدنهی پاسخ از streaming بازمیایستد، درخواست را abort میکند. وقتیCLAUDE_ENABLE_STREAM_WATCHDOGتنظیم نشده باشد، پیشفرض روی Anthropic APIِ مستقیم سمتِ سرور کنترل میشود و روی سایرِ providerها خاموش است.CLAUDE_STREAM_IDLE_TIMEOUT_MSپیشفرضِ300000دارد و به همان مقدارِ کمینه clamp میشود. درخواستِ abortشده از مسیرِ retryِ عادی عبور میکند.
OutputFormat
Section titled “OutputFormat”پیکربندی برای اعتبارسنجیِ خروجیِ ساختاریافته. این را بهعنوانِ یک dict به فیلدِ output_format روی ClaudeAgentOptions پاس بده:
# Expected dict shape for output_format{ "type": "json_schema", "schema": {...}, # Your JSON Schema definition}| فیلد | الزامی | توضیح |
|---|---|---|
type | بله | برای اعتبارسنجیِ JSON Schema باید "json_schema" باشد |
schema | بله | تعریفِ JSON Schema برای اعتبارسنجیِ خروجی |
SystemPromptPreset
Section titled “SystemPromptPreset”پیکربندی برای استفاده از system promptِ presetِ Claude Code با افزودههای اختیاری.
class SystemPromptPreset(TypedDict): type: Literal["preset"] preset: Literal["claude_code"] append: NotRequired[str] exclude_dynamic_sections: NotRequired[bool]| فیلد | الزامی | توضیح |
|---|---|---|
type | بله | برای استفاده از یک system promptِ preset باید "preset" باشد |
preset | بله | برای استفاده از system promptِ Claude Code باید "claude_code" باشد |
append | خیر | دستورالعملهای اضافی برای الحاق به system promptِ preset |
exclude_dynamic_sections | خیر | کانتکستِ هر-نشستی مثلِ دایرکتوریِ کاری، پرچمِ git-repo و مسیرهای auto-memory را از system prompt به اولین پیامِ کاربر منتقل میکند. استفادهی مجددِ prompt-cache را بینِ کاربران و ماشینها بهبود میدهد. Modify system prompts را ببین |
SettingSource
Section titled “SettingSource”کنترل میکند که SDK تنظیمات را از کدام منابعِ پیکربندیِ مبتنیبر فایلسیستم بارگذاری کند.
SettingSource = Literal["user", "project", "local"]| مقدار | توضیح | مکان |
|---|---|---|
"user" | تنظیماتِ سراسریِ کاربر | ~/.claude/settings.json |
"project" | تنظیماتِ مشترکِ پروژه (تحتِ کنترلِ نسخه) | .claude/settings.json |
"local" | تنظیماتِ محلیِ پروژه (خارج از کنترلِ نسخه) | .claude/settings.local.json |
رفتارِ پیشفرض
Section titled “رفتارِ پیشفرض”وقتی setting_sources حذف شود یا None باشد، query() همان تنظیماتِ فایلسیستمِ Claude Code CLI را بارگذاری میکند: user، project و local. تنظیماتِ managed policy در همهی حالتها بارگذاری میشوند. برای ورودیهایی که صرفنظر از این گزینه خوانده میشوند و نحوهی غیرفعالکردنشان، What settingSources does not control را ببین.
چرا از setting_sources استفاده کنیم
Section titled “چرا از setting_sources استفاده کنیم”غیرفعالکردنِ تنظیماتِ فایلسیستم:
# Do not load user, project, or local settings from diskfrom claude_agent_sdk import query, ClaudeAgentOptions
async for message in query( prompt="Analyze this code", options=ClaudeAgentOptions( setting_sources=[] ),): print(message)بارگذاریِ صریحِ همهی تنظیماتِ فایلسیستم:
from claude_agent_sdk import query, ClaudeAgentOptions
async for message in query( prompt="Analyze this code", options=ClaudeAgentOptions( setting_sources=["user", "project", "local"] ),): print(message)بارگذاریِ فقط منابعِ تنظیماتِ مشخص:
# Load only project settings, ignore user and localasync for message in query( prompt="Run CI checks", options=ClaudeAgentOptions( setting_sources=["project"] # Only .claude/settings.json ),): print(message)محیطهای تست و CI:
# Ensure consistent behavior in CI by excluding local settingsasync for message in query( prompt="Run tests", options=ClaudeAgentOptions( setting_sources=["project"], # Only team-shared settings permission_mode="bypassPermissions", ),): print(message)اپلیکیشنهای فقط-SDK:
# Define everything programmatically.# Pass [] to opt out of filesystem setting sources.async for message in query( prompt="Review this PR", options=ClaudeAgentOptions( setting_sources=[], agents={...}, mcp_servers={...}, allowed_tools=["Read", "Grep", "Glob"], ),): print(message)بارگذاریِ دستورالعملهای پروژهی CLAUDE.md:
# Load project settings to include CLAUDE.md filesasync for message in query( prompt="Add a new feature following project conventions", options=ClaudeAgentOptions( system_prompt={ "type": "preset", "preset": "claude_code", # Use Claude Code's system prompt }, setting_sources=["project"], # Loads CLAUDE.md from project allowed_tools=["Read", "Write", "Edit"], ),): print(message)اولویتِ تنظیمات
Section titled “اولویتِ تنظیمات”وقتی چند منبع بارگذاری شوند، تنظیمات با این اولویت merge میشوند (از بالاترین به پایینترین):
- تنظیماتِ local (
.claude/settings.local.json) - تنظیماتِ project (
.claude/settings.json) - تنظیماتِ user (
~/.claude/settings.json)
گزینههای برنامهنویسیشده مثلِ agents و allowed_tools بر تنظیماتِ فایلسیستمِ user، project و local غلبه میکنند. تنظیماتِ managed policy بر گزینههای برنامهنویسیشده اولویت دارند.
AgentDefinition
Section titled “AgentDefinition”پیکربندی برای یک سابایجنت که بهصورتِ برنامهنویسیشده تعریف شده.
@dataclassclass AgentDefinition: description: str prompt: str tools: list[str] | None = None disallowedTools: list[str] | None = None model: str | None = None skills: list[str] | None = None memory: Literal["user", "project", "local"] | None = None mcpServers: list[str | dict[str, Any]] | None = None initialPrompt: str | None = None maxTurns: int | None = None background: bool | None = None effort: EffortLevel | int | None = None permissionMode: PermissionMode | None = None| فیلد | الزامی | توضیح |
|---|---|---|
description | بله | توضیحِ زبانِ طبیعی دربارهی اینکه کِی از این ایجنت استفاده شود |
prompt | بله | system promptِ ایجنت |
tools | خیر | آرایهی نامهای ابزارِ مجاز. اگر حذف شود، همهی ابزارها به ارث میرسند |
disallowedTools | خیر | آرایهی نامهای ابزار که از مجموعهی ابزارِ ایجنت حذف شوند |
model | خیر | override مدل برای این ایجنت. یک alias مثلِ "sonnet"، "opus"، "haiku" یا "inherit"، یا یک model IDِ کامل را میپذیرد. اگر حذف شود، از مدلِ اصلی استفاده میکند |
skills | خیر | فهرستِ نامهای skill که هنگامِ راهاندازی پیشبارگذاری در کانتکستِ ایجنت شوند. skillهای فهرستنشده از طریقِ ابزارِ Skill قابلِفراخوانی میمانند |
memory | خیر | منبعِ حافظه برای این ایجنت: "user"، "project" یا "local" |
mcpServers | خیر | سرورهای MCPِ در دسترسِ این ایجنت. هر ورودی یک نامِ سرور یا یک dictِ inlineِ {name: config} است |
initialPrompt | خیر | وقتی این ایجنت بهعنوانِ ایجنتِ thread اصلی اجرا میشود، بهصورتِ خودکار بهعنوانِ اولین نوبتِ کاربر submit میشود |
maxTurns | خیر | بیشینهی تعدادِ نوبتهای ایجنتیک پیش از توقفِ ایجنت |
background | خیر | این ایجنت را هنگامِ فراخوانی بهصورتِ یک تسکِ پسزمینهی non-blocking اجرا کن |
effort | خیر | سطحِ تلاشِ استدلال برای این ایجنت. یک سطحِ نامگذاریشده یا یک عددِ صحیح را میپذیرد. EffortLevel را ببین |
permissionMode | خیر | permission mode برای اجرای ابزار درونِ این ایجنت. PermissionMode را ببین |
PermissionMode
Section titled “PermissionMode”permission modeها برای کنترلِ اجرای ابزار.
PermissionMode = Literal[ "default", # Standard permission behavior "acceptEdits", # Auto-accept file edits "plan", # Planning mode - explore without editing "dontAsk", # Deny anything not pre-approved instead of prompting "bypassPermissions", # Bypass permission checks; explicit ask rules still prompt (use with caution)]EffortLevel
Section titled “EffortLevel”سطوحِ effort برای هدایتِ عمقِ thinking.
EffortLevel = Literal[ "low", # Minimal thinking, fastest responses "medium", # Moderate thinking "high", # Deep reasoning "xhigh", # Extended reasoning (Opus 4.8 and Opus 4.7; falls back to "high" on other models) "max", # Maximum effort]CanUseTool
Section titled “CanUseTool”aliasِ نوع برای توابعِ callbackِ دسترسیِ ابزار.
CanUseTool = Callable[ [str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]]این callback اینها را دریافت میکند:
tool_name: نامِ ابزاری که فراخوانی میشودinput_data: پارامترهای ورودیِ ابزارcontext: یکToolPermissionContextبا اطلاعاتِ اضافی
یک PermissionResult برمیگرداند (یا PermissionResultAllow یا PermissionResultDeny).
ToolPermissionContext
Section titled “ToolPermissionContext”اطلاعاتِ کانتکست که به callbackهای دسترسیِ ابزار پاس داده میشود.
@dataclassclass ToolPermissionContext: signal: Any | None = None # Future: abort signal support suggestions: list[PermissionUpdate] = field(default_factory=list) blocked_path: str | None = None decision_reason: str | None = None title: str | None = None display_name: str | None = None description: str | None = None| فیلد | نوع | توضیح |
|---|---|---|
signal | Any | None | رزرو برای پشتیبانیِ آیندهی abort signal |
suggestions | list[PermissionUpdate] | پیشنهادهای بهروزرسانیِ دسترسی از CLI. پرامپتهای Bash شاملِ یک پیشنهاد با مقصدِ localSettings هستند، پس برگرداندنِ آن در updated_permissions قاعده را در .claude/settings.local.json مینویسد و در طولِ نشستها پایدار میماند. |
blocked_path | str | None | مسیرِ فایلی که درخواستِ دسترسی را تریگر کرد، در صورتِ امکان. مثلاً وقتی یک فرمانِ Bash تلاش میکند به مسیری بیرونِ دایرکتوریهای مجاز دسترسی پیدا کند |
decision_reason | str | None | دلیلِ تریگرشدنِ این درخواستِ دسترسی. وقتی یک hookِ PreToolUse مقدارِ "ask" برگرداند، از permissionDecisionReasonِ آن فوروارد میشود |
title | str | None | جملهی کاملِ پرامپتِ دسترسی، مثلِ Claude wants to read foo.txt. وقتی موجود است بهعنوانِ متنِ اصلیِ پرامپت استفاده کن |
display_name | str | None | عبارتِ اسمیِ کوتاه برای اقدامِ ابزار، مثلِ Read file، مناسب برای برچسبِ دکمه |
description | str | None | زیرنویسِ خوانا برای انسان برای UIِ دسترسی |
PermissionResult
Section titled “PermissionResult”نوعِ union برای نتایجِ callbackِ دسترسی.
PermissionResult = PermissionResultAllow | PermissionResultDenyPermissionResultAllow
Section titled “PermissionResultAllow”نتیجهای که نشان میدهد فراخوانیِ ابزار باید allow شود.
@dataclassclass PermissionResultAllow: behavior: Literal["allow"] = "allow" updated_input: dict[str, Any] | None = None updated_permissions: list[PermissionUpdate] | None = None| فیلد | نوع | پیشفرض | توضیح |
|---|---|---|---|
behavior | Literal["allow"] | "allow" | باید “allow” باشد |
updated_input | dict[str, Any] | None | None | ورودیِ تغییریافته برای استفاده بهجای اصلی |
updated_permissions | list[PermissionUpdate] | None | None | بهروزرسانیهای دسترسی که اعمال شوند |
PermissionResultDeny
Section titled “PermissionResultDeny”نتیجهای که نشان میدهد فراخوانیِ ابزار باید deny شود.
@dataclassclass PermissionResultDeny: behavior: Literal["deny"] = "deny" message: str = "" interrupt: bool = False| فیلد | نوع | پیشفرض | توضیح |
|---|---|---|---|
behavior | Literal["deny"] | "deny" | باید “deny” باشد |
message | str | "" | پیامِ توضیحدهندهی اینکه چرا ابزار deny شد |
interrupt | bool | False | اینکه آیا اجرای فعلی interrupt شود |
PermissionUpdate
Section titled “PermissionUpdate”پیکربندی برای بهروزرسانیِ دسترسیها بهصورتِ برنامهنویسیشده.
@dataclassclass PermissionUpdate: type: Literal[ "addRules", "replaceRules", "removeRules", "setMode", "addDirectories", "removeDirectories", ] rules: list[PermissionRuleValue] | None = None behavior: Literal["allow", "deny", "ask"] | None = None mode: PermissionMode | None = None directories: list[str] | None = None destination: ( Literal["userSettings", "projectSettings", "localSettings", "session"] | None ) = None| فیلد | نوع | توضیح |
|---|---|---|
type | Literal[...] | نوعِ عملیاتِ بهروزرسانیِ دسترسی |
rules | list[PermissionRuleValue] | None | قواعد برای عملیاتِ add/replace/remove |
behavior | Literal["allow", "deny", "ask"] | None | رفتار برای عملیاتِ مبتنیبر قاعده |
mode | PermissionMode | None | حالت برای عملیاتِ setMode |
directories | list[str] | None | دایرکتوریها برای عملیاتِ add/remove دایرکتوری |
destination | Literal[...] | None | اینکه بهروزرسانیِ دسترسی کجا اعمال شود |
PermissionRuleValue
Section titled “PermissionRuleValue”یک قاعده برای add، replace یا remove در یک بهروزرسانیِ دسترسی.
@dataclassclass PermissionRuleValue: tool_name: str rule_content: str | None = NoneToolsPreset
Section titled “ToolsPreset”پیکربندیِ ابزارهای preset برای استفاده از مجموعهی ابزارِ پیشفرضِ Claude Code.
class ToolsPreset(TypedDict): type: Literal["preset"] preset: Literal["claude_code"]ThinkingConfig
Section titled “ThinkingConfig”رفتارِ extended thinking را کنترل میکند. یک union از سه پیکربندی:
ThinkingDisplay = Literal["summarized", "omitted"]
class ThinkingConfigAdaptive(TypedDict): type: Literal["adaptive"] display: NotRequired[ThinkingDisplay]
class ThinkingConfigEnabled(TypedDict): type: Literal["enabled"] budget_tokens: int display: NotRequired[ThinkingDisplay]
class ThinkingConfigDisabled(TypedDict): type: Literal["disabled"]
ThinkingConfig = ThinkingConfigAdaptive | ThinkingConfigEnabled | ThinkingConfigDisabled| نوع | فیلدها | توضیح |
|---|---|---|
adaptive | type, display | Claude خودش بهصورتِ تطبیقی تصمیم میگیرد کِی فکر کند |
enabled | type, budget_tokens, display | thinking را با یک بودجهی توکنِ مشخص فعال کن |
disabled | type | thinking را غیرفعال کن |
فیلدِ اختیاریِ display کنترل میکند که متنِ thinking بهصورتِ "summarized" برگردانده شود یا "omitted". روی Claude Opus 4.7 و بالاتر، پیشفرضِ API برابرِ "omitted" است، پس برای دریافتِ محتوای thinking در خروجیهای ThinkingBlock مقدارِ "summarized" را تنظیم کن.
چون اینها کلاسهای TypedDict هستند، در زمانِ اجرا plain dict اند. یا آنها را بهصورتِ dict literal بساز یا کلاس را مثلِ یک constructor فراخوانی کن؛ هر دو یک dict تولید میکنند. فیلدها را با config["budget_tokens"] دسترسی بگیر، نه config.budget_tokens:
from claude_agent_sdk import ClaudeAgentOptions, ThinkingConfigEnabled
# Option 1: dict literal (recommended, no import needed)options = ClaudeAgentOptions(thinking={"type": "enabled", "budget_tokens": 20000})
# Option 2: constructor-style (returns a plain dict)config = ThinkingConfigEnabled(type="enabled", budget_tokens=20000)print(config["budget_tokens"]) # 20000# config.budget_tokens would raise AttributeErrorSdkBeta
Section titled “SdkBeta”نوعِ Literal برای قابلیتهای بتای SDK.
SdkBeta = Literal["context-1m-2025-08-07"]برای فعالکردنِ قابلیتهای بتا با فیلدِ betas در ClaudeAgentOptions استفاده کن.
McpSdkServerConfig
Section titled “McpSdkServerConfig”پیکربندی برای سرورهای SDK MCP که با create_sdk_mcp_server() ساخته شدهاند.
class McpSdkServerConfig(TypedDict): type: Literal["sdk"] name: str instance: Any # MCP Server instanceMcpServerConfig
Section titled “McpServerConfig”نوعِ union برای پیکربندیهای سرورِ MCP.
McpServerConfig = ( McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig)McpStdioServerConfig
Section titled “McpStdioServerConfig”class McpStdioServerConfig(TypedDict): type: NotRequired[Literal["stdio"]] # Optional for backwards compatibility command: str args: NotRequired[list[str]] env: NotRequired[dict[str, str]]McpSSEServerConfig
Section titled “McpSSEServerConfig”class McpSSEServerConfig(TypedDict): type: Literal["sse"] url: str headers: NotRequired[dict[str, str]]McpHttpServerConfig
Section titled “McpHttpServerConfig”class McpHttpServerConfig(TypedDict): type: Literal["http"] url: str headers: NotRequired[dict[str, str]]McpServerStatusConfig
Section titled “McpServerStatusConfig”پیکربندیِ یک سرورِ MCP، آنطور که توسطِ get_mcp_status() گزارش میشود. این union همهی نوعِ transportهای McpServerConfig بهعلاوهی یک نوعِ فقط-خروجیِ claudeai-proxy برای سرورهایی است که از طریقِ claude.ai پراکسی میشوند.
McpServerStatusConfig = ( McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfigStatus | McpClaudeAIProxyServerConfig)McpSdkServerConfigStatus شکلِ serializableِ McpSdkServerConfig است که فقط فیلدهای type ("sdk") و name (str) را دارد؛ instanceِ in-process حذف میشود. McpClaudeAIProxyServerConfig فیلدهای type ("claudeai-proxy")، url (str) و id (str) را دارد.
McpStatusResponse
Section titled “McpStatusResponse”پاسخ از ClaudeSDKClient.get_mcp_status(). فهرستِ وضعیتِ سرورها را زیرِ کلیدِ mcpServers wrap میکند.
class McpStatusResponse(TypedDict): mcpServers: list[McpServerStatus]McpServerStatus
Section titled “McpServerStatus”وضعیتِ یک سرورِ MCPِ متصل، که در McpStatusResponse قرار دارد.
class McpServerStatus(TypedDict): name: str status: McpServerConnectionStatus # "connected" | "failed" | "needs-auth" | "pending" | "disabled" serverInfo: NotRequired[McpServerInfo] error: NotRequired[str] config: NotRequired[McpServerStatusConfig] scope: NotRequired[str] tools: NotRequired[list[McpToolInfo]]| فیلد | نوع | توضیح |
|---|---|---|
name | str | نامِ سرور |
status | str | یکی از "connected"، "failed"، "needs-auth"، "pending" یا "disabled" |
serverInfo | dict (اختیاری) | نام و نسخهی سرور ({"name": str, "version": str}) |
error | str (اختیاری) | پیامِ خطا اگر سرور نتوانست وصل شود |
config | McpServerStatusConfig (اختیاری) | پیکربندیِ سرور. همان شکلِ McpServerConfig (stdio، SSE، HTTP یا SDK)، بهعلاوهی یک نوعِ claudeai-proxy برای سرورهای متصل از طریقِ claude.ai |
scope | str (اختیاری) | scopeِ پیکربندی |
tools | list (اختیاری) | ابزارهای ارائهشده توسطِ این سرور، هرکدام با فیلدهای name، description و annotations |
SdkPluginConfig
Section titled “SdkPluginConfig”پیکربندی برای بارگذاریِ pluginها در SDK.
class SdkPluginConfig(TypedDict): type: Literal["local"] path: str| فیلد | نوع | توضیح |
|---|---|---|
type | Literal["local"] | باید "local" باشد (فعلاً فقط pluginهای محلی پشتیبانی میشوند) |
path | str | مسیرِ مطلق یا نسبی به دایرکتوریِ plugin |
مثال:
plugins = [ {"type": "local", "path": "./my-plugin"}, {"type": "local", "path": "/absolute/path/to/plugin"},]برای اطلاعاتِ کامل دربارهی ساخت و استفاده از pluginها، Plugins را ببین.
انواعِ پیام (Message Types)
Section titled “انواعِ پیام (Message Types)”Message
Section titled “Message”نوعِ union از همهی پیامهای ممکن.
Message = ( UserMessage | AssistantMessage | SystemMessage | ResultMessage | StreamEvent | RateLimitEvent)UserMessage
Section titled “UserMessage”پیامِ ورودیِ کاربر.
@dataclassclass UserMessage: content: str | list[ContentBlock] uuid: str | None = None parent_tool_use_id: str | None = None tool_use_result: dict[str, Any] | None = None| فیلد | نوع | توضیح |
|---|---|---|
content | str | list[ContentBlock] | محتوای پیام بهصورتِ متن یا content block |
uuid | str | None | شناسهی یکتای پیام |
parent_tool_use_id | str | None | tool use ID اگر این پیام یک پاسخِ نتیجهی ابزار باشد |
tool_use_result | dict[str, Any] | None | دادهی نتیجهی ابزار در صورتِ امکان |
AssistantMessage
Section titled “AssistantMessage”پیامِ پاسخِ assistant با content blockها.
@dataclassclass AssistantMessage: content: list[ContentBlock] model: str parent_tool_use_id: str | None = None error: AssistantMessageError | None = None usage: dict[str, Any] | None = None message_id: str | None = None| فیلد | نوع | توضیح |
|---|---|---|
content | list[ContentBlock] | فهرستِ content blockها در پاسخ |
model | str | مدلی که پاسخ را تولید کرد |
parent_tool_use_id | str | None | tool use ID اگر این یک پاسخِ تودرتو باشد |
error | AssistantMessageError | None | نوعِ خطا اگر پاسخ به یک خطا برخورد کرد |
usage | dict[str, Any] | None | مصرفِ توکنِ هر-پیامی (همان کلیدهای ResultMessage.usage) |
message_id | str | None | API message ID. چند پیام از یک نوبت همان ID را به اشتراک میگذارند |
AssistantMessageError
Section titled “AssistantMessageError”نوعِ خطاهای ممکن برای پیامهای assistant.
AssistantMessageError = Literal[ "authentication_failed", "billing_error", "rate_limit", "invalid_request", "server_error", "max_output_tokens", "unknown",]SystemMessage
Section titled “SystemMessage”پیامِ سیستم با فراداده.
@dataclassclass SystemMessage: subtype: str data: dict[str, Any]ResultMessage
Section titled “ResultMessage”پیامِ نتیجهی نهایی با اطلاعاتِ هزینه و مصرف.
@dataclassclass ResultMessage: subtype: str duration_ms: int duration_api_ms: int is_error: bool num_turns: int session_id: str stop_reason: str | None = None total_cost_usd: float | None = None usage: dict[str, Any] | None = None result: str | None = None structured_output: Any = None model_usage: dict[str, Any] | None = None permission_denials: list[Any] | None = None deferred_tool_use: DeferredToolUse | None = None errors: list[str] | None = None api_error_status: int | None = None uuid: str | None = Noneفیلدِ subtype تعیین میکند کدام فیلدهای دیگر پر میشوند. یکی از "success"، "error_during_execution"، "error_max_turns"، "error_max_budget_usd" یا "error_max_structured_output_retries" است. dataclassِ پایتون همهی نوعها را در یک شکل flatten میکند، پس فیلدهایی که برای subtypeِ برگشتی صدق نمیکنند None اند.
چند فیلد وقتی گفتگو با یک خطا پایان مییابد جزئیاتِ تشخیصی حمل میکنند:
is_error: وقتی گفتگو در یک وضعیتِ خطا پایان یابدTrueاست. روی subtypeهایerror_*همیشهTrueاست. رویsubtype="success"وقتیTrueاست که درخواستِ نهاییِ مدل ناموفق باشد، یعنی حلقهی ایجنت کامل شده ولی آخرین فراخوانیِ API یک خطا برگردانده است.api_error_status: کدِ وضعیتِ HTTPِ خطای پایاندهندهی API. وقتی نوبت بدونِ آن پایان یابدNoneاست. فقط رویsubtype="success"پر میشود.result: متنِ پیامِ نهاییِ assistant رویsubtype="success"، یاNoneروی subtypeهایerror_*. وقتیsubtype="success"وis_error=Trueباشد، این رشتهی خطای API را در صورتِ موجودبودن نگه میدارد ولی میتواند خالی باشد، پس برای جزئیاتapi_error_statusو محتوایAssistantMessageِ پیشین را بررسی کن.errors: رشتههای خطای سطحِ حلقه مثلِ پیامِ max-turns. فقط روی subtypeهایerror_*پر میشود.
dictِ usage وقتی موجود باشد این کلیدها را در بر دارد:
| کلید | نوع | توضیح |
|---|---|---|
input_tokens | int | کلِ توکنهای ورودیِ مصرفشده. |
output_tokens | int | کلِ توکنهای خروجیِ تولیدشده. |
cache_creation_input_tokens | int | توکنهای استفادهشده برای ساختِ ورودیهای جدیدِ cache. |
cache_read_input_tokens | int | توکنهای خواندهشده از ورودیهای موجودِ cache. |
dictِ model_usage نامهای مدل را به مصرفِ هر-مدلی نگاشت میکند. کلیدهای dictِ درونی از camelCase استفاده میکنند چون مقدار بدونِ تغییر از پروسهی CLIِ زیربنایی پاس داده میشود، مطابقِ نوعِ تایپاسکریپتِ ModelUsage:
| کلید | نوع | توضیح |
|---|---|---|
inputTokens | int | توکنهای ورودی برای این مدل. |
outputTokens | int | توکنهای خروجی برای این مدل. |
cacheReadInputTokens | int | توکنهای خواندنِ cache برای این مدل. |
cacheCreationInputTokens | int | توکنهای ساختِ cache برای این مدل. |
webSearchRequests | int | درخواستهای web search که این مدل انجام داده. |
costUSD | float | هزینهی برآوردی به دلار برای این مدل، محاسبهشده سمتِ client. برای ملاحظاتِ هزینه ردیابی هزینه و مصرف را ببین. |
contextWindow | int | اندازهی context window برای این مدل. |
maxOutputTokens | int | حدِ بیشینهی توکنِ خروجی برای این مدل. |
StreamEvent
Section titled “StreamEvent”stream event برای بهروزرسانیهای جزئیِ پیام در حینِ streaming. فقط وقتی include_partial_messages=True در ClaudeAgentOptions باشد دریافت میشود. از طریقِ from claude_agent_sdk.types import StreamEvent ایمپورت کن.
@dataclassclass StreamEvent: uuid: str session_id: str event: dict[str, Any] # The raw Claude API stream event parent_tool_use_id: str | None = None| فیلد | نوع | توضیح |
|---|---|---|
uuid | str | شناسهی یکتای این event |
session_id | str | شناسهی نشست |
event | dict[str, Any] | دادهی خامِ stream eventِ Claude API |
parent_tool_use_id | str | None | parent tool use ID اگر این event از یک سابایجنت باشد |
RateLimitEvent
Section titled “RateLimitEvent”وقتی وضعیتِ rate limit تغییر میکند منتشر میشود (مثلاً از "allowed" به "allowed_warning"). از این برای هشدار به کاربران پیش از رسیدن به یک حدِ سخت، یا برای back off وقتی وضعیت "rejected" است استفاده کن.
@dataclassclass RateLimitEvent: rate_limit_info: RateLimitInfo uuid: str session_id: str| فیلد | نوع | توضیح |
|---|---|---|
rate_limit_info | RateLimitInfo | وضعیتِ فعلیِ rate limit |
uuid | str | شناسهی یکتای event |
session_id | str | شناسهی نشست |
RateLimitInfo
Section titled “RateLimitInfo”وضعیتِ rate limit که توسطِ RateLimitEvent حمل میشود.
RateLimitStatus = Literal["allowed", "allowed_warning", "rejected"]RateLimitType = Literal[ "five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet", "overage"]
@dataclassclass RateLimitInfo: status: RateLimitStatus resets_at: int | None = None rate_limit_type: RateLimitType | None = None utilization: float | None = None overage_status: RateLimitStatus | None = None overage_resets_at: int | None = None overage_disabled_reason: str | None = None raw: dict[str, Any] = field(default_factory=dict)| فیلد | نوع | توضیح |
|---|---|---|
status | RateLimitStatus | وضعیتِ فعلی. "allowed_warning" یعنی نزدیکشدن به حد؛ "rejected" یعنی به حد رسیدهای |
resets_at | int | None | timestampِ یونیکس وقتی پنجرهی rate limit ریست میشود |
rate_limit_type | RateLimitType | None | اینکه کدام پنجرهی rate limit صدق میکند |
utilization | float | None | کسرِ rate limitِ مصرفشده (۰٫۰ تا ۱٫۰) |
overage_status | RateLimitStatus | None | وضعیتِ مصرفِ overageِ pay-as-you-go، در صورتِ امکان |
overage_resets_at | int | None | timestampِ یونیکس وقتی پنجرهی overage ریست میشود |
overage_disabled_reason | str | None | چرا overage در دسترس نیست، اگر وضعیت "rejected" باشد |
raw | dict[str, Any] | dictِ خامِ کامل از CLI، شاملِ فیلدهایی که بالا مدل نشدهاند |
TaskStartedMessage
Section titled “TaskStartedMessage”وقتی یک تسکِ پسزمینه شروع میشود منتشر میشود. یک تسکِ پسزمینه هر چیزی است که بیرونِ نوبتِ اصلی ردیابی میشود: یک فرمانِ Bashِ پسزمینهشده، یک watchِ Monitor، یک سابایجنتِ ساختهشده از طریقِ ابزارِ Agent، یا یک ایجنتِ remote. فیلدِ task_type میگوید کدام است. این نامگذاری ربطی به تغییرِ نامِ ابزارِ Task به Agent ندارد.
@dataclassclass TaskStartedMessage(SystemMessage): task_id: str description: str uuid: str session_id: str tool_use_id: str | None = None task_type: str | None = None| فیلد | نوع | توضیح |
|---|---|---|
task_id | str | شناسهی یکتای تسک |
description | str | توضیحِ تسک |
uuid | str | شناسهی یکتای پیام |
session_id | str | شناسهی نشست |
tool_use_id | str | None | tool use IDِ مرتبط |
task_type | str | None | کدام نوع تسکِ پسزمینه: "local_bash" برای Bashِ پسزمینه و watchهای Monitor، "local_agent" یا "remote_agent" |
TaskUsage
Section titled “TaskUsage”دادهی توکن و زمانبندی برای یک تسکِ پسزمینه.
class TaskUsage(TypedDict): total_tokens: int tool_uses: int duration_ms: intTaskProgressMessage
Section titled “TaskProgressMessage”بهصورتِ دورهای با بهروزرسانیهای پیشرفت برای یک تسکِ پسزمینهی در حالِ اجرا منتشر میشود.
@dataclassclass TaskProgressMessage(SystemMessage): task_id: str description: str usage: TaskUsage uuid: str session_id: str tool_use_id: str | None = None last_tool_name: str | None = None| فیلد | نوع | توضیح |
|---|---|---|
task_id | str | شناسهی یکتای تسک |
description | str | توضیحِ وضعیتِ فعلی |
usage | TaskUsage | مصرفِ توکن برای این تسک تا کنون |
uuid | str | شناسهی یکتای پیام |
session_id | str | شناسهی نشست |
tool_use_id | str | None | tool use IDِ مرتبط |
last_tool_name | str | None | نامِ آخرین ابزاری که تسک استفاده کرد |
TaskNotificationMessage
Section titled “TaskNotificationMessage”وقتی یک تسکِ پسزمینه کامل میشود، ناموفق میشود یا متوقف میشود منتشر میشود. تسکهای پسزمینه شاملِ فرمانهای Bashِ run_in_background، watchهای Monitor و سابایجنتهای پسزمینهاند.
@dataclassclass TaskNotificationMessage(SystemMessage): task_id: str status: TaskNotificationStatus # "completed" | "failed" | "stopped" output_file: str summary: str uuid: str session_id: str tool_use_id: str | None = None usage: TaskUsage | None = None| فیلد | نوع | توضیح |
|---|---|---|
task_id | str | شناسهی یکتای تسک |
status | TaskNotificationStatus | یکی از "completed"، "failed" یا "stopped" |
output_file | str | مسیرِ فایلِ خروجیِ تسک |
summary | str | خلاصهی نتیجهی تسک |
uuid | str | شناسهی یکتای پیام |
session_id | str | شناسهی نشست |
tool_use_id | str | None | tool use IDِ مرتبط |
usage | TaskUsage | None | مصرفِ توکنِ نهایی برای تسک |
انواعِ Content Block
Section titled “انواعِ Content Block”ContentBlock
Section titled “ContentBlock”نوعِ union از همهی content blockها.
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlockTextBlock
Section titled “TextBlock”content blockِ متنی.
@dataclassclass TextBlock: text: strThinkingBlock
Section titled “ThinkingBlock”content blockِ thinking (برای مدلهایی با قابلیتِ thinking).
@dataclassclass ThinkingBlock: thinking: str signature: strToolUseBlock
Section titled “ToolUseBlock”blockِ درخواستِ استفاده از ابزار.
@dataclassclass ToolUseBlock: id: str name: str input: dict[str, Any]ToolResultBlock
Section titled “ToolResultBlock”blockِ نتیجهی اجرای ابزار.
@dataclassclass ToolResultBlock: tool_use_id: str content: str | list[dict[str, Any]] | None = None is_error: bool | None = Noneانواعِ خطا
Section titled “انواعِ خطا”ClaudeSDKError
Section titled “ClaudeSDKError”کلاسِ پایهی استثنا برای همهی خطاهای SDK.
class ClaudeSDKError(Exception): """Base error for Claude SDK."""CLINotFoundError
Section titled “CLINotFoundError”وقتی Claude Code CLI نصب نشده یا پیدا نشود raise میشود.
class CLINotFoundError(CLIConnectionError): def __init__( self, message: str = "Claude Code not found", cli_path: str | None = None ): """ Args: message: Error message (default: "Claude Code not found") cli_path: Optional path to the CLI that was not found """CLIConnectionError
Section titled “CLIConnectionError”وقتی اتصال به Claude Code ناموفق باشد raise میشود.
class CLIConnectionError(ClaudeSDKError): """Failed to connect to Claude Code."""ProcessError
Section titled “ProcessError”وقتی پروسهی Claude Code ناموفق باشد raise میشود.
class ProcessError(ClaudeSDKError): def __init__( self, message: str, exit_code: int | None = None, stderr: str | None = None ): self.exit_code = exit_code self.stderr = stderrCLIJSONDecodeError
Section titled “CLIJSONDecodeError”وقتی parse کردنِ JSON ناموفق باشد raise میشود.
class CLIJSONDecodeError(ClaudeSDKError): def __init__(self, line: str, original_error: Exception): """ Args: line: The line that failed to parse original_error: The original JSON decode exception """ self.line = line self.original_error = original_errorانواعِ Hook
Section titled “انواعِ Hook”برای راهنمای جامعِ استفاده از hookها با مثال و الگوهای رایج، راهنمای Hooks را ببین.
HookEvent
Section titled “HookEvent”نوعِ eventهای hookِ پشتیبانیشده.
HookEvent = Literal[ "PreToolUse", # Called before tool execution "PostToolUse", # Called after tool execution "PostToolUseFailure", # Called when a tool execution fails "UserPromptSubmit", # Called when user submits a prompt "Stop", # Called when stopping execution "SubagentStop", # Called when a subagent stops "PreCompact", # Called before message compaction "Notification", # Called for notification events "SubagentStart", # Called when a subagent starts "PermissionRequest", # Called when a permission decision is needed]HookCallback
Section titled “HookCallback”تعریفِ نوع برای توابعِ callbackِ hook.
HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]پارامترها:
input: ورودیِ hookِ قویاً تایپشده با discriminated unionها بر اساسِhook_event_name(HookInputرا ببین)tool_use_id: شناسهی tool useِ اختیاری (برای hookهای مرتبط با ابزار)context: کانتکستِ hook با اطلاعاتِ اضافی
یک HookJSONOutput برمیگرداند که ممکن است شامل اینها باشد:
decision:"block"برای مسدودکردنِ اقدامsystemMessage: پیامِ هشدار که به کاربر نشان داده میشودhookSpecificOutput: دادهی خروجیِ مخصوصِ hook
HookContext
Section titled “HookContext”اطلاعاتِ کانتکست که به callbackهای hook پاس داده میشود.
class HookContext(TypedDict): signal: Any | None # Future: abort signal supportHookMatcher
Section titled “HookMatcher”پیکربندی برای تطبیقِ hookها با eventها یا ابزارهای مشخص.
@dataclassclass HookMatcher: matcher: str | None = ( None # Tool name or pattern to match (e.g., "Bash", "Write|Edit") ) hooks: list[HookCallback] = field( default_factory=list ) # List of callbacks to execute timeout: float | None = ( None # Timeout in seconds for all hooks in this matcher (default: 60) )HookInput
Section titled “HookInput”نوعِ union از همهی نوعِ ورودیهای hook. نوعِ واقعی به فیلدِ hook_event_name بستگی دارد.
HookInput = ( PreToolUseHookInput | PostToolUseHookInput | PostToolUseFailureHookInput | UserPromptSubmitHookInput | StopHookInput | SubagentStopHookInput | PreCompactHookInput | NotificationHookInput | SubagentStartHookInput | PermissionRequestHookInput)BaseHookInput
Section titled “BaseHookInput”فیلدهای پایهای که در همهی نوعِ ورودیهای hook حضور دارند.
class BaseHookInput(TypedDict): session_id: str transcript_path: str cwd: str permission_mode: NotRequired[str]| فیلد | نوع | توضیح |
|---|---|---|
session_id | str | شناسهی نشستِ فعلی |
transcript_path | str | مسیرِ فایلِ transcriptِ نشست |
cwd | str | دایرکتوریِ کاریِ فعلی |
permission_mode | str (اختیاری) | permission modeِ فعلی |
PreToolUseHookInput
Section titled “PreToolUseHookInput”دادهی ورودی برای eventهای hookِ PreToolUse.
class PreToolUseHookInput(BaseHookInput): hook_event_name: Literal["PreToolUse"] tool_name: str tool_input: dict[str, Any] tool_use_id: str agent_id: NotRequired[str] agent_type: NotRequired[str]| فیلد | نوع | توضیح |
|---|---|---|
hook_event_name | Literal["PreToolUse"] | همیشه “PreToolUse” |
tool_name | str | نامِ ابزاری که میخواهد اجرا شود |
tool_input | dict[str, Any] | پارامترهای ورودیِ ابزار |
tool_use_id | str | شناسهی یکتا برای این tool use |
agent_id | str (اختیاری) | شناسهی سابایجنت، وقتی hook درونِ یک سابایجنت اجرا میشود حضور دارد |
agent_type | str (اختیاری) | نوعِ سابایجنت، وقتی hook درونِ یک سابایجنت اجرا میشود حضور دارد |
PostToolUseHookInput
Section titled “PostToolUseHookInput”دادهی ورودی برای eventهای hookِ PostToolUse.
class PostToolUseHookInput(BaseHookInput): hook_event_name: Literal["PostToolUse"] tool_name: str tool_input: dict[str, Any] tool_response: Any tool_use_id: str agent_id: NotRequired[str] agent_type: NotRequired[str]| فیلد | نوع | توضیح |
|---|---|---|
hook_event_name | Literal["PostToolUse"] | همیشه “PostToolUse” |
tool_name | str | نامِ ابزاری که اجرا شد |
tool_input | dict[str, Any] | پارامترهای ورودی که استفاده شدند |
tool_response | Any | پاسخ از اجرای ابزار |
tool_use_id | str | شناسهی یکتا برای این tool use |
agent_id | str (اختیاری) | شناسهی سابایجنت، وقتی hook درونِ یک سابایجنت اجرا میشود حضور دارد |
agent_type | str (اختیاری) | نوعِ سابایجنت، وقتی hook درونِ یک سابایجنت اجرا میشود حضور دارد |
PostToolUseFailureHookInput
Section titled “PostToolUseFailureHookInput”دادهی ورودی برای eventهای hookِ PostToolUseFailure. وقتی اجرای یک ابزار ناموفق باشد فراخوانی میشود.
class PostToolUseFailureHookInput(BaseHookInput): hook_event_name: Literal["PostToolUseFailure"] tool_name: str tool_input: dict[str, Any] tool_use_id: str error: str is_interrupt: NotRequired[bool] agent_id: NotRequired[str] agent_type: NotRequired[str]| فیلد | نوع | توضیح |
|---|---|---|
hook_event_name | Literal["PostToolUseFailure"] | همیشه “PostToolUseFailure” |
tool_name | str | نامِ ابزاری که ناموفق بود |
tool_input | dict[str, Any] | پارامترهای ورودی که استفاده شدند |
tool_use_id | str | شناسهی یکتا برای این tool use |
error | str | پیامِ خطا از اجرای ناموفق |
is_interrupt | bool (اختیاری) | اینکه آیا شکست ناشی از یک interrupt بوده |
agent_id | str (اختیاری) | شناسهی سابایجنت، وقتی hook درونِ یک سابایجنت اجرا میشود حضور دارد |
agent_type | str (اختیاری) | نوعِ سابایجنت، وقتی hook درونِ یک سابایجنت اجرا میشود حضور دارد |
UserPromptSubmitHookInput
Section titled “UserPromptSubmitHookInput”دادهی ورودی برای eventهای hookِ UserPromptSubmit.
class UserPromptSubmitHookInput(BaseHookInput): hook_event_name: Literal["UserPromptSubmit"] prompt: str| فیلد | نوع | توضیح |
|---|---|---|
hook_event_name | Literal["UserPromptSubmit"] | همیشه “UserPromptSubmit” |
prompt | str | پرامپتِ submitشدهی کاربر |
StopHookInput
Section titled “StopHookInput”دادهی ورودی برای eventهای hookِ Stop.
class StopHookInput(BaseHookInput): hook_event_name: Literal["Stop"] stop_hook_active: bool| فیلد | نوع | توضیح |
|---|---|---|
hook_event_name | Literal["Stop"] | همیشه “Stop” |
stop_hook_active | bool | اینکه آیا stop hook فعال است |
SubagentStopHookInput
Section titled “SubagentStopHookInput”دادهی ورودی برای eventهای hookِ SubagentStop.
class SubagentStopHookInput(BaseHookInput): hook_event_name: Literal["SubagentStop"] stop_hook_active: bool agent_id: str agent_transcript_path: str agent_type: str| فیلد | نوع | توضیح |
|---|---|---|
hook_event_name | Literal["SubagentStop"] | همیشه “SubagentStop” |
stop_hook_active | bool | اینکه آیا stop hook فعال است |
agent_id | str | شناسهی یکتای سابایجنت |
agent_transcript_path | str | مسیرِ فایلِ transcriptِ سابایجنت |
agent_type | str | نوعِ سابایجنت |
PreCompactHookInput
Section titled “PreCompactHookInput”دادهی ورودی برای eventهای hookِ PreCompact.
class PreCompactHookInput(BaseHookInput): hook_event_name: Literal["PreCompact"] trigger: Literal["manual", "auto"] custom_instructions: str | None| فیلد | نوع | توضیح |
|---|---|---|
hook_event_name | Literal["PreCompact"] | همیشه “PreCompact” |
trigger | Literal["manual", "auto"] | چه چیزی compaction را تریگر کرد |
custom_instructions | str | None | دستورالعملهای سفارشی برای compaction |
NotificationHookInput
Section titled “NotificationHookInput”دادهی ورودی برای eventهای hookِ Notification.
class NotificationHookInput(BaseHookInput): hook_event_name: Literal["Notification"] message: str title: NotRequired[str] notification_type: str| فیلد | نوع | توضیح |
|---|---|---|
hook_event_name | Literal["Notification"] | همیشه “Notification” |
message | str | محتوای پیامِ نوتیفیکیشن |
title | str (اختیاری) | عنوانِ نوتیفیکیشن |
notification_type | str | نوعِ نوتیفیکیشن |
SubagentStartHookInput
Section titled “SubagentStartHookInput”دادهی ورودی برای eventهای hookِ SubagentStart.
class SubagentStartHookInput(BaseHookInput): hook_event_name: Literal["SubagentStart"] agent_id: str agent_type: str| فیلد | نوع | توضیح |
|---|---|---|
hook_event_name | Literal["SubagentStart"] | همیشه “SubagentStart” |
agent_id | str | شناسهی یکتای سابایجنت |
agent_type | str | نوعِ سابایجنت |
PermissionRequestHookInput
Section titled “PermissionRequestHookInput”دادهی ورودی برای eventهای hookِ PermissionRequest. به hookها امکان میدهد تصمیمهای دسترسی را بهصورتِ برنامهنویسیشده رسیدگی کنند.
class PermissionRequestHookInput(BaseHookInput): hook_event_name: Literal["PermissionRequest"] tool_name: str tool_input: dict[str, Any] permission_suggestions: NotRequired[list[Any]]| فیلد | نوع | توضیح |
|---|---|---|
hook_event_name | Literal["PermissionRequest"] | همیشه “PermissionRequest” |
tool_name | str | نامِ ابزاری که دسترسی درخواست میکند |
tool_input | dict[str, Any] | پارامترهای ورودیِ ابزار |
permission_suggestions | list[Any] (اختیاری) | بهروزرسانیهای دسترسیِ پیشنهادی از CLI |
HookJSONOutput
Section titled “HookJSONOutput”نوعِ union برای مقادیرِ بازگشتیِ callbackِ hook.
HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutputSyncHookJSONOutput
Section titled “SyncHookJSONOutput”خروجیِ hookِ همگام با فیلدهای کنترل و تصمیم.
class SyncHookJSONOutput(TypedDict): # Control fields continue_: NotRequired[bool] # Whether to proceed (default: True) suppressOutput: NotRequired[bool] # Hide stdout from transcript stopReason: NotRequired[str] # Message when continue is False
# Decision fields decision: NotRequired[Literal["block"]] systemMessage: NotRequired[str] # Warning message for user reason: NotRequired[str] # Feedback for Claude
# Hook-specific output hookSpecificOutput: NotRequired[HookSpecificOutput]HookSpecificOutput
Section titled “HookSpecificOutput”یک TypedDict که نامِ eventِ hook و فیلدهای مخصوصِ event را در بر دارد. شکل به مقدارِ hookEventName بستگی دارد. برای جزئیاتِ کاملِ فیلدهای موجود برای هر eventِ hook، کنترلِ اجرا با hookها را ببین.
یک discriminated union از نوعِ خروجیهای مخصوصِ event. فیلدِ hookEventName تعیین میکند کدام فیلدها معتبرند.
class PreToolUseHookSpecificOutput(TypedDict): hookEventName: Literal["PreToolUse"] permissionDecision: NotRequired[Literal["allow", "deny", "ask", "defer"]] permissionDecisionReason: NotRequired[str] updatedInput: NotRequired[dict[str, Any]] additionalContext: NotRequired[str]
class PostToolUseHookSpecificOutput(TypedDict): hookEventName: Literal["PostToolUse"] additionalContext: NotRequired[str] updatedToolOutput: NotRequired[Any] updatedMCPToolOutput: NotRequired[Any] # Deprecated: use updatedToolOutput, which works for all tools
class PostToolUseFailureHookSpecificOutput(TypedDict): hookEventName: Literal["PostToolUseFailure"] additionalContext: NotRequired[str]
class UserPromptSubmitHookSpecificOutput(TypedDict): hookEventName: Literal["UserPromptSubmit"] additionalContext: NotRequired[str]
class NotificationHookSpecificOutput(TypedDict): hookEventName: Literal["Notification"] additionalContext: NotRequired[str]
class SubagentStartHookSpecificOutput(TypedDict): hookEventName: Literal["SubagentStart"] additionalContext: NotRequired[str]
class PermissionRequestHookSpecificOutput(TypedDict): hookEventName: Literal["PermissionRequest"] decision: dict[str, Any]
HookSpecificOutput = ( PreToolUseHookSpecificOutput | PostToolUseHookSpecificOutput | PostToolUseFailureHookSpecificOutput | UserPromptSubmitHookSpecificOutput | NotificationHookSpecificOutput | SubagentStartHookSpecificOutput | PermissionRequestHookSpecificOutput)AsyncHookJSONOutput
Section titled “AsyncHookJSONOutput”خروجیِ hookِ async که اجرای hook را به تعویق میاندازد.
class AsyncHookJSONOutput(TypedDict): async_: Literal[True] # Set to True to defer execution asyncTimeout: NotRequired[int] # Timeout in millisecondsمثالِ استفاده از Hook
Section titled “مثالِ استفاده از Hook”این مثال دو hook ثبت میکند: یکی که فرمانهای bashِ خطرناک مثلِ rm -rf / را مسدود میکند، و دیگری که همهی استفادههای ابزار را برای ممیزی لاگ میکند. hookِ امنیتی فقط روی فرمانهای Bash اجرا میشود (از طریقِ matcher)، در حالی که hookِ لاگکردن روی همهی ابزارها اجرا میشود.
from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, HookContextfrom typing import Any
async def validate_bash_command( input_data: dict[str, Any], tool_use_id: str | None, context: HookContext) -> dict[str, Any]: """Validate and potentially block dangerous bash commands.""" if input_data["tool_name"] == "Bash": command = input_data["tool_input"].get("command", "") if "rm -rf /" in command: return { "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "Dangerous command blocked", } } return {}
async def log_tool_use( input_data: dict[str, Any], tool_use_id: str | None, context: HookContext) -> dict[str, Any]: """Log all tool usage for auditing.""" print(f"Tool used: {input_data.get('tool_name')}") return {}
options = ClaudeAgentOptions( hooks={ "PreToolUse": [ HookMatcher( matcher="Bash", hooks=[validate_bash_command], timeout=120 ), # 2 min for validation HookMatcher( hooks=[log_tool_use] ), # Applies to all tools (default 60s timeout) ], "PostToolUse": [HookMatcher(hooks=[log_tool_use])], })
async for message in query(prompt="Analyze this codebase", options=options): print(message)انواعِ ورودی/خروجیِ ابزار
Section titled “انواعِ ورودی/خروجیِ ابزار”مستنداتِ schemaهای ورودی/خروجی برای همهی ابزارهای توکارِ Claude Code. هرچند پایتون SDK اینها را بهعنوانِ نوع export نمیکند، آنها ساختارِ ورودی و خروجیِ ابزارها را در پیامها نشان میدهند.
نامِ ابزار: Agent (پیشتر Task، که هنوز بهعنوانِ alias پذیرفته میشود)
ورودی:
{ "description": str, # A short (3-5 word) description of the task "prompt": str, # The task for the agent to perform "subagent_type": str, # The type of specialized agent to use}خروجی:
{ "result": str, # Final result from the subagent "usage": dict | None, # Token usage statistics "total_cost_usd": float | None, # Estimated total cost in USD "duration_ms": int | None, # Execution duration in milliseconds}AskUserQuestion
Section titled “AskUserQuestion”نامِ ابزار: AskUserQuestion
در حینِ اجرا از کاربر پرسشهای شفافسازی میپرسد. برای جزئیاتِ استفاده رسیدگی به تأییدها و ورودیِ کاربر را ببین.
ورودی:
{ "questions": [ # Questions to ask the user (1-4 questions) { "question": str, # The complete question to ask the user "header": str, # Very short label displayed as a chip/tag (max 12 chars) "options": [ # The available choices (2-4 options) { "label": str, # Display text for this option (1-5 words) "description": str, # Explanation of what this option means } ], "multiSelect": bool, # Set to true to allow multiple selections } ], "answers": dict[str, str | list[str]] | None, # User answers populated by the permission system. Multi-select # answers may be a list of labels or a comma-joined string}خروجی:
{ "questions": [ # The questions that were asked { "question": str, "header": str, "options": [{"label": str, "description": str}], "multiSelect": bool, } ], "answers": dict[str, str], # Maps question text to answer string # Multi-select answers are comma-separated}نامِ ابزار: Bash
ورودی:
{ "command": str, # The command to execute "timeout": int | None, # Optional timeout in milliseconds (max 600000) "description": str | None, # Clear, concise description (5-10 words) "run_in_background": bool | None, # Set to true to run in background}خروجی:
{ "output": str, # Combined stdout and stderr output "exitCode": int, # Exit code of the command "killed": bool | None, # Whether command was killed due to timeout "shellId": str | None, # Shell ID for background processes}Monitor
Section titled “Monitor”نامِ ابزار: Monitor
یک اسکریپتِ پسزمینه اجرا میکند و هر خطِ stdout را بهعنوانِ یک event به Claude تحویل میدهد تا بتواند بدونِ polling واکنش نشان دهد. Monitor از همان قواعدِ دسترسیِ Bash پیروی میکند. برای رفتار و در دسترسبودنِ provider مرجعِ ابزارِ Monitor را ببین.
ورودی:
{ "command": str, # Shell script; each stdout line is an event, exit ends the watch "description": str, # Short description shown in notifications "timeout_ms": int | None, # Kill after this deadline (default 300000, max 3600000) "persistent": bool | None, # Run for the lifetime of the session; stop with TaskStop}خروجی:
{ "taskId": str, # ID of the background monitor task "timeoutMs": int, # Timeout deadline in milliseconds (0 when persistent) "persistent": bool | None, # True when running until TaskStop or session end}نامِ ابزار: Edit
ورودی:
{ "file_path": str, # The absolute path to the file to modify "old_string": str, # The text to replace "new_string": str, # The text to replace it with "replace_all": bool | None, # Replace all occurrences (default False)}خروجی:
{ "message": str, # Confirmation message "replacements": int, # Number of replacements made "file_path": str, # File path that was edited}نامِ ابزار: Read
ورودی:
{ "file_path": str, # The absolute path to the file to read "offset": int | None, # The line number to start reading from "limit": int | None, # The number of lines to read}خروجی (فایلهای متنی):
{ "content": str, # File contents with line numbers "total_lines": int, # Total number of lines in file "lines_returned": int, # Lines actually returned}خروجی (تصاویر):
{ "image": str, # Base64 encoded image data "mime_type": str, # Image MIME type "file_size": int, # File size in bytes}نامِ ابزار: Write
ورودی:
{ "file_path": str, # The absolute path to the file to write "content": str, # The content to write to the file}خروجی:
{ "message": str, # Success message "bytes_written": int, # Number of bytes written "file_path": str, # File path that was written}نامِ ابزار: Glob
ورودی:
{ "pattern": str, # The glob pattern to match files against "path": str | None, # The directory to search in (defaults to cwd)}خروجی:
{ "matches": list[str], # Array of matching file paths "count": int, # Number of matches found "search_path": str, # Search directory used}نامِ ابزار: Grep
ورودی:
{ "pattern": str, # The regular expression pattern "path": str | None, # File or directory to search in "glob": str | None, # Glob pattern to filter files "type": str | None, # File type to search "output_mode": str | None, # "content", "files_with_matches", or "count" "-i": bool | None, # Case insensitive search "-n": bool | None, # Show line numbers "-B": int | None, # Lines to show before each match "-A": int | None, # Lines to show after each match "-C": int | None, # Lines to show before and after "head_limit": int | None, # Limit output to first N lines/entries "multiline": bool | None, # Enable multiline mode}خروجی (حالتِ content):
{ "matches": [ { "file": str, "line_number": int | None, "line": str, "before_context": list[str] | None, "after_context": list[str] | None, } ], "total_matches": int,}خروجی (حالتِ files_with_matches):
{ "files": list[str], # Files containing matches "count": int, # Number of files with matches}NotebookEdit
Section titled “NotebookEdit”نامِ ابزار: NotebookEdit
ورودی:
{ "notebook_path": str, # Absolute path to the Jupyter notebook "cell_id": str | None, # The ID of the cell to edit "new_source": str, # The new source for the cell "cell_type": "code" | "markdown" | None, # The type of the cell "edit_mode": "replace" | "insert" | "delete" | None, # Edit operation type}خروجی:
{ "message": str, # Success message "edit_type": "replaced" | "inserted" | "deleted", # Type of edit performed "cell_id": str | None, # Cell ID that was affected "total_cells": int, # Total cells in notebook after edit}WebFetch
Section titled “WebFetch”نامِ ابزار: WebFetch
ورودی:
{ "url": str, # The URL to fetch content from "prompt": str, # The prompt to run on the fetched content}خروجی:
{ "bytes": int, # Size of the fetched content in bytes "code": int, # HTTP response code "codeText": str, # HTTP response code text "result": str, # Processed result from applying the prompt to the content "durationMs": int, # Time to fetch and process the content, in milliseconds "url": str, # URL that was fetched}WebSearch
Section titled “WebSearch”نامِ ابزار: WebSearch
ورودی:
{ "query": str, # The search query to use "allowed_domains": list[str] | None, # Only include results from these domains "blocked_domains": list[str] | None, # Never include results from these domains}خروجی:
{ "query": str, # The search query "results": list[str | {"tool_use_id": str, "content": list[{"title": str, "url": str}]}], "durationSeconds": float, # Search duration in seconds}TodoWrite
Section titled “TodoWrite”نامِ ابزار: TodoWrite
ورودی:
{ "todos": [ { "content": str, # The task description "status": "pending" | "in_progress" | "completed", # Task status "activeForm": str, # Active form of the description } ]}خروجی:
{ "message": str, # Success message "stats": {"total": int, "pending": int, "in_progress": int, "completed": int},}TaskCreate
Section titled “TaskCreate”نامِ ابزار: TaskCreate
ورودی:
{ "subject": str, # Short task title "description": str, # Detailed task body "activeForm": str | None, # Present-tense label shown while in progress "metadata": dict | None, # Arbitrary caller metadata}خروجی:
{ "task": {"id": str, "subject": str}, # Created task with assigned ID}TaskUpdate
Section titled “TaskUpdate”نامِ ابزار: TaskUpdate
ورودی:
{ "taskId": str, # ID of the task to patch "status": Literal["pending", "in_progress", "completed", "deleted"] | None, "subject": str | None, "description": str | None, "activeForm": str | None, "addBlocks": list[str] | None, # Task IDs this task now blocks "addBlockedBy": list[str] | None, # Task IDs that now block this task "owner": str | None, "metadata": dict | None,}خروجی:
{ "success": bool, "taskId": str, "updatedFields": list[str], # Names of fields that changed "error": str | None, "statusChange": {"from": str, "to": str} | None,}TaskGet
Section titled “TaskGet”نامِ ابزار: TaskGet
ورودی:
{ "taskId": str, # ID of the task to read}خروجی:
{ "task": { "id": str, "subject": str, "description": str, "status": Literal["pending", "in_progress", "completed"], "blocks": list[str], "blockedBy": list[str], } | None, # None when the ID is not found}TaskList
Section titled “TaskList”نامِ ابزار: TaskList
ورودی:
{}خروجی:
{ "tasks": [ { "id": str, "subject": str, "status": Literal["pending", "in_progress", "completed"], "owner": str | None, "blockedBy": list[str], } ],}BashOutput
Section titled “BashOutput”نامِ ابزار: BashOutput
ورودی:
{ "bash_id": str, # The ID of the background shell "filter": str | None, # Optional regex to filter output lines}خروجی:
{ "output": str, # New output since last check "status": "running" | "completed" | "failed", # Current shell status "exitCode": int | None, # Exit code when completed}KillBash
Section titled “KillBash”نامِ ابزار: KillBash
ورودی:
{ "shell_id": str # The ID of the background shell to kill}خروجی:
{ "message": str, # Success message "shell_id": str, # ID of the killed shell}ExitPlanMode
Section titled “ExitPlanMode”نامِ ابزار: ExitPlanMode
ورودی:
{ "plan": str # The plan to run by the user for approval}خروجی:
{ "message": str, # Confirmation message "approved": bool | None, # Whether user approved the plan}ListMcpResources
Section titled “ListMcpResources”نامِ ابزار: ListMcpResourcesTool
ورودی:
{ "server": str | None # Optional server name to filter resources by}خروجی:
{ "resources": [ { "uri": str, "name": str, "description": str | None, "mimeType": str | None, "server": str, } ], "total": int,}ReadMcpResource
Section titled “ReadMcpResource”نامِ ابزار: ReadMcpResourceTool
ورودی:
{ "server": str, # The MCP server name "uri": str, # The resource URI to read}خروجی:
{ "contents": [ {"uri": str, "mimeType": str | None, "text": str | None, "blob": str | None} ], "server": str,}قابلیتهای پیشرفته با ClaudeSDKClient
Section titled “قابلیتهای پیشرفته با ClaudeSDKClient”ساختِ یک رابطِ گفتگوی پیوسته
Section titled “ساختِ یک رابطِ گفتگوی پیوسته”from claude_agent_sdk import ( ClaudeSDKClient, ClaudeAgentOptions, AssistantMessage, TextBlock,)import asyncio
class ConversationSession: """Maintains a single conversation session with Claude."""
def __init__(self, options: ClaudeAgentOptions | None = None): self.client = ClaudeSDKClient(options) self.turn_count = 0
async def start(self): await self.client.connect() print("Starting conversation session. Claude will remember context.") print( "Commands: 'exit' to quit, 'interrupt' to stop current task, 'new' for new session" )
while True: user_input = input(f"\n[Turn {self.turn_count + 1}] You: ")
if user_input.lower() == "exit": break elif user_input.lower() == "interrupt": await self.client.interrupt() print("Task interrupted!") continue elif user_input.lower() == "new": # Disconnect and reconnect for a fresh session await self.client.disconnect() await self.client.connect() self.turn_count = 0 print("Started new conversation session (previous context cleared)") continue
# Send message - the session retains all previous messages await self.client.query(user_input) self.turn_count += 1
# Process response print(f"[Turn {self.turn_count}] Claude: ", end="") async for message in self.client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(block.text, end="") print() # New line after response
await self.client.disconnect() print(f"Conversation ended after {self.turn_count} turns.")
async def main(): options = ClaudeAgentOptions( allowed_tools=["Read", "Write", "Bash"], permission_mode="acceptEdits" ) session = ConversationSession(options) await session.start()
# Example conversation:# Turn 1 - You: "Create a file called hello.py"# Turn 1 - Claude: "I'll create a hello.py file for you..."# Turn 2 - You: "What's in that file?"# Turn 2 - Claude: "The hello.py file I just created contains..." (remembers!)# Turn 3 - You: "Add a main function to it"# Turn 3 - Claude: "I'll add a main function to hello.py..." (knows which file!)
asyncio.run(main())استفاده از Hookها برای تغییرِ رفتار
Section titled “استفاده از Hookها برای تغییرِ رفتار”from claude_agent_sdk import ( ClaudeSDKClient, ClaudeAgentOptions, HookMatcher, HookContext,)import asynciofrom typing import Any
async def pre_tool_logger( input_data: dict[str, Any], tool_use_id: str | None, context: HookContext) -> dict[str, Any]: """Log all tool usage before execution.""" tool_name = input_data.get("tool_name", "unknown") print(f"[PRE-TOOL] About to use: {tool_name}")
# You can modify or block the tool execution here if tool_name == "Bash" and "rm -rf" in str(input_data.get("tool_input", {})): return { "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "Dangerous command blocked", } } return {}
async def post_tool_logger( input_data: dict[str, Any], tool_use_id: str | None, context: HookContext) -> dict[str, Any]: """Log results after tool execution.""" tool_name = input_data.get("tool_name", "unknown") print(f"[POST-TOOL] Completed: {tool_name}") return {}
async def user_prompt_modifier( input_data: dict[str, Any], tool_use_id: str | None, context: HookContext) -> dict[str, Any]: """Add context to user prompts.""" original_prompt = input_data.get("prompt", "")
# Add a timestamp as additional context for Claude to see from datetime import datetime
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return { "hookSpecificOutput": { "hookEventName": "UserPromptSubmit", "additionalContext": f"[Submitted at {timestamp}] Original prompt: {original_prompt}", } }
async def main(): options = ClaudeAgentOptions( hooks={ "PreToolUse": [ HookMatcher(hooks=[pre_tool_logger]), HookMatcher(matcher="Bash", hooks=[pre_tool_logger]), ], "PostToolUse": [HookMatcher(hooks=[post_tool_logger])], "UserPromptSubmit": [HookMatcher(hooks=[user_prompt_modifier])], }, allowed_tools=["Read", "Write", "Bash"], )
async with ClaudeSDKClient(options=options) as client: await client.query("List files in current directory")
async for message in client.receive_response(): # Hooks will automatically log tool usage pass
asyncio.run(main())مانیتورینگِ پیشرفتِ بلادرنگ
Section titled “مانیتورینگِ پیشرفتِ بلادرنگ”from claude_agent_sdk import ( ClaudeSDKClient, ClaudeAgentOptions, AssistantMessage, ToolUseBlock, ToolResultBlock, TextBlock,)import asyncio
async def monitor_progress(): options = ClaudeAgentOptions( allowed_tools=["Write", "Bash"], permission_mode="acceptEdits" )
async with ClaudeSDKClient(options=options) as client: await client.query("Create 5 Python files with different sorting algorithms")
# Monitor progress in real-time async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, ToolUseBlock): if block.name == "Write": file_path = block.input.get("file_path", "") print(f"Creating: {file_path}") elif isinstance(block, ToolResultBlock): print("Completed tool execution") elif isinstance(block, TextBlock): print(f"Claude says: {block.text[:100]}...")
print("Task completed!")
asyncio.run(monitor_progress())مثالهای استفاده
Section titled “مثالهای استفاده”عملیاتِ پایهای فایل (با query)
Section titled “عملیاتِ پایهای فایل (با query)”from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ToolUseBlockimport asyncio
async def create_project(): options = ClaudeAgentOptions( allowed_tools=["Read", "Write", "Bash"], permission_mode="acceptEdits", cwd="/home/user/project", )
async for message in query( prompt="Create a Python project structure with setup.py", options=options ): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, ToolUseBlock): print(f"Using tool: {block.name}")
asyncio.run(create_project())رسیدگی به خطا
Section titled “رسیدگی به خطا”from claude_agent_sdk import query, CLINotFoundError, ProcessError, CLIJSONDecodeError
try: async for message in query(prompt="Hello"): print(message)except CLINotFoundError: print( "Claude Code CLI not found. Try reinstalling: pip install --force-reinstall claude-agent-sdk" )except ProcessError as e: print(f"Process failed with exit code: {e.exit_code}")except CLIJSONDecodeError as e: print(f"Failed to parse response: {e}")حالتِ streaming با client
Section titled “حالتِ streaming با client”from claude_agent_sdk import ClaudeSDKClientimport asyncio
async def interactive_session(): async with ClaudeSDKClient() as client: # Send initial message await client.query("What's the weather like?")
# Process responses async for msg in client.receive_response(): print(msg)
# Send follow-up await client.query("Tell me more about that")
# Process follow-up response async for msg in client.receive_response(): print(msg)
asyncio.run(interactive_session())استفاده از ابزارهای سفارشی با ClaudeSDKClient
Section titled “استفاده از ابزارهای سفارشی با ClaudeSDKClient”from claude_agent_sdk import ( ClaudeSDKClient, ClaudeAgentOptions, tool, create_sdk_mcp_server, AssistantMessage, TextBlock,)import asynciofrom typing import Any
# Define custom tools with @tool decorator@tool("calculate", "Perform mathematical calculations", {"expression": str})async def calculate(args: dict[str, Any]) -> dict[str, Any]: try: result = eval(args["expression"], {"__builtins__": {}}) return {"content": [{"type": "text", "text": f"Result: {result}"}]} except Exception as e: return { "content": [{"type": "text", "text": f"Error: {str(e)}"}], "is_error": True, }
@tool("get_time", "Get current time", {})async def get_time(args: dict[str, Any]) -> dict[str, Any]: from datetime import datetime
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") return {"content": [{"type": "text", "text": f"Current time: {current_time}"}]}
async def main(): # Create SDK MCP server with custom tools my_server = create_sdk_mcp_server( name="utilities", version="1.0.0", tools=[calculate, get_time] )
# Configure options with the server options = ClaudeAgentOptions( mcp_servers={"utils": my_server}, allowed_tools=["mcp__utils__calculate", "mcp__utils__get_time"], )
# Use ClaudeSDKClient for interactive tool usage async with ClaudeSDKClient(options=options) as client: await client.query("What's 123 * 456?")
# Process calculation response async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(f"Calculation: {block.text}")
# Follow up with time query await client.query("What time is it now?")
async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(f"Time: {block.text}")
asyncio.run(main())پیکربندیِ Sandbox
Section titled “پیکربندیِ Sandbox”SandboxSettings
Section titled “SandboxSettings”پیکربندی برای رفتارِ sandbox. از این برای فعالکردنِ command sandboxing و پیکربندیِ محدودیتهای شبکه بهصورتِ برنامهنویسیشده استفاده کن.
class SandboxSettings(TypedDict, total=False): enabled: bool autoAllowBashIfSandboxed: bool excludedCommands: list[str] allowUnsandboxedCommands: bool network: SandboxNetworkConfig ignoreViolations: SandboxIgnoreViolations enableWeakerNestedSandbox: bool| ویژگی | نوع | پیشفرض | توضیح |
|---|---|---|---|
enabled | bool | False | حالتِ sandbox را برای اجرای فرمان فعال کن |
autoAllowBashIfSandboxed | bool | True | وقتی sandbox فعال است فرمانهای bash را خودکار تأیید کن |
excludedCommands | list[str] | [] | فرمانهایی که همیشه محدودیتهای sandbox را دور میزنند (مثلاً ["docker"]). اینها بهصورتِ خودکار و بدونِ دخالتِ مدل، بدونِ sandbox اجرا میشوند |
allowUnsandboxedCommands | bool | True | به مدل اجازه بده درخواستِ اجرای فرمانها بیرونِ sandbox را بدهد. وقتی True باشد، مدل میتواند dangerouslyDisableSandbox را در ورودیِ ابزار تنظیم کند، که به سیستمِ دسترسی بازمیگردد |
network | SandboxNetworkConfig | None | پیکربندیِ sandboxِ مخصوصِ شبکه |
ignoreViolations | SandboxIgnoreViolations | None | پیکربندی کن که کدام نقضهای sandbox نادیده گرفته شوند |
enableWeakerNestedSandbox | bool | False | یک sandboxِ تودرتوی ضعیفتر را برای سازگاری فعال کن |
مثالِ استفاده
Section titled “مثالِ استفاده”from claude_agent_sdk import query, ClaudeAgentOptions, SandboxSettings
sandbox_settings: SandboxSettings = { "enabled": True, "autoAllowBashIfSandboxed": True, "network": {"allowLocalBinding": True},}
async for message in query( prompt="Build and test my project", options=ClaudeAgentOptions(sandbox=sandbox_settings),): print(message)SandboxNetworkConfig
Section titled “SandboxNetworkConfig”پیکربندیِ مخصوصِ شبکه برای حالتِ sandbox. این تنظیمات وقتی enabled در SandboxSettingsِ والد برابرِ True باشد، روی فرمانهای Bashِ sandboxشده اعمال میشوند. آنها ابزارِ WebFetch را محدود نمیکنند، که بهجای آن از قواعدِ دسترسی استفاده میکند.
class SandboxNetworkConfig(TypedDict, total=False): allowedDomains: list[str] deniedDomains: list[str] allowManagedDomainsOnly: bool allowUnixSockets: list[str] allowAllUnixSockets: bool allowLocalBinding: bool allowMachLookup: list[str] httpProxyPort: int socksProxyPort: int| ویژگی | نوع | پیشفرض | توضیح |
|---|---|---|---|
allowedDomains | list[str] | [] | نامدامنههایی که پروسههای sandboxشده میتوانند به آنها دسترسی داشته باشند |
deniedDomains | list[str] | [] | نامدامنههایی که پروسههای sandboxشده نمیتوانند به آنها دسترسی داشته باشند. بر allowedDomains اولویت دارد |
allowManagedDomainsOnly | bool | False | فقط managed-settings: وقتی در managed settings تنظیم شود، allowedDomains را از منابعِ تنظیماتِ غیر-managed نادیده بگیر. وقتی از طریقِ SDK options تنظیم شود اثری ندارد |
allowUnixSockets | list[str] | [] | مسیرهای Unix socket که پروسهها میتوانند به آنها دسترسی داشته باشند (مثلاً Docker socket) |
allowAllUnixSockets | bool | False | دسترسی به همهی Unix socketها را مجاز کن |
allowLocalBinding | bool | False | به پروسهها اجازه بده به پورتهای محلی bind شوند (مثلاً برای dev serverها) |
allowMachLookup | list[str] | [] | فقط macOS: نامهای سرویسِ XPC/Mach که مجاز شوند. از یک wildcardِ انتهایی پشتیبانی میکند |
httpProxyPort | int | None | پورتِ HTTP proxy برای درخواستهای شبکه |
socksProxyPort | int | None | پورتِ SOCKS proxy برای درخواستهای شبکه |
SandboxIgnoreViolations
Section titled “SandboxIgnoreViolations”پیکربندی برای نادیدهگرفتنِ نقضهای مشخصِ sandbox.
class SandboxIgnoreViolations(TypedDict, total=False): file: list[str] network: list[str]| ویژگی | نوع | پیشفرض | توضیح |
|---|---|---|---|
file | list[str] | [] | الگوهای مسیرِ فایل که نقضهایشان نادیده گرفته شوند |
network | list[str] | [] | الگوهای شبکه که نقضهایشان نادیده گرفته شوند |
Fallbackِ دسترسی برای فرمانهای بدونِ sandbox
Section titled “Fallbackِ دسترسی برای فرمانهای بدونِ sandbox”وقتی allowUnsandboxedCommands فعال باشد، مدل میتواند با تنظیمِ dangerouslyDisableSandbox: True در ورودیِ ابزار، درخواستِ اجرای فرمانها بیرونِ sandbox را بدهد. این درخواستها به سیستمِ دسترسیِ موجود بازمیگردند، یعنی handlerِ can_use_toolِ تو فراخوانی میشود و به تو امکان میدهد منطقِ مجوزدهیِ سفارشی پیاده کنی.
from claude_agent_sdk import ( query, ClaudeAgentOptions, HookMatcher, PermissionResultAllow, PermissionResultDeny, ToolPermissionContext,)
async def can_use_tool( tool: str, input: dict, context: ToolPermissionContext) -> PermissionResultAllow | PermissionResultDeny: # Check if the model is requesting to bypass the sandbox if tool == "Bash" and input.get("dangerouslyDisableSandbox"): # The model is requesting to run this command outside the sandbox print(f"Unsandboxed command requested: {input.get('command')}")
if is_command_authorized(input.get("command")): return PermissionResultAllow() return PermissionResultDeny( message="Command not authorized for unsandboxed execution" ) return PermissionResultAllow()
# Required: dummy hook keeps the stream open for can_use_toolasync def dummy_hook(input_data, tool_use_id, context): return {"continue_": True}
async def prompt_stream(): yield { "type": "user", "message": {"role": "user", "content": "Deploy my application"}, }
async def main(): async for message in query( prompt=prompt_stream(), options=ClaudeAgentOptions( sandbox={ "enabled": True, "allowUnsandboxedCommands": True, # Model can request unsandboxed execution }, permission_mode="default", can_use_tool=can_use_tool, hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]}, ), ): print(message)این الگو به تو امکان میدهد:
- ممیزیِ درخواستهای مدل: وقتی مدل درخواستِ اجرای بدونِ sandbox میدهد لاگ کن
- پیادهسازیِ allowlist: فقط به فرمانهای مشخص اجازهی اجرای بدونِ sandbox بده
- افزودنِ ورکفلوهای تأیید: برای عملیاتِ ممتاز مجوزِ صریح بخواه
همچنین ببین
Section titled “همچنین ببین”- مرورِ کلیِ SDK - مفاهیمِ کلیِ SDK
- مرجعِ TypeScript SDK - مستنداتِ TypeScript SDK
- مرجعِ CLI - رابطِ خطِ فرمان
- ورکفلوهای رایج - راهنماهای گامبهگام