فاز 13 · درس 19

پروتکل A2A: ارتباط و همکاری بین ایجنت‌های هوش مصنوعی

نوع
ساختنی
زمان
حدود 75 دقیقه
زبان‌ها
Python (stdlib, Agent Card + Task harness)
پیش‌نیاز
فاز 13 · 06 (مفاهیم پایه‌ای MCP)، فاز 13 · 08 (کلاینت MCP)
دو گوی شیشه‌ای مات و سربسته که از طریق یک خط نوری مستقیم بسته‌های پیام رمزنگاری‌شده را میان یکدیگر مبادله می‌کنند
فهرست مطالب
  1. اهداف یادگیری
  2. صورت مسئله
  3. مفاهیم کلیدی
  4. کارت ایجنت (Agent Card)
  5. کارت‌های ایجنت امضاشده (Signed Agent Cards)
  6. چرخه‌ی حیات تسک
  7. پیام‌ها و بخش‌ها (Messages and Parts)
  8. دست‌سازه‌ها (Artifacts)
  9. سه اتصال پروتکل (Protocol Bindings)
  10. حفظ حالت کدر (Opacity Preservation)
  11. گاه‌شمار
  12. نسبت با MCP
  13. پیاده‌سازی عملی
  14. خروجی این درس
  15. تمرین‌ها
  16. اصطلاحات کلیدی
  17. برای مطالعه‌ی بیشتر

در مسیر توسعه‌ی سیستم‌های هوشمند چندایجنتی، پروتکل MCP به‌خوبی تعامل یک ایجنت با ابزارهای مختلف را استاندارد کرده است. اما چالش جدید زمانی رخ می‌دهد که دو ایجنت مستقل با چارچوب‌های متفاوت بخواهند بدون افشای ساختار داخلی، منطق تصمیم‌گیری و ابزارهای محرمانه‌ی خود، وظایفی را به یکدیگر واگذار کنند و بر سر یک تسک همکاری مشترک داشته باشند.

پروتکل A2A (سرنام Agent2Agent) پاسخی استاندارد به این مسئله است که امکان برقراری ارتباط در قالب جعبه‌سیاه یا کدر (opaque) را بین ایجنت‌ها فراهم می‌سازد. در این درس با معماری این استاندارد، مفهوم کارت ایجنت (Agent Card)، چرخه‌ی حیات تسک‌ها و اتصالات شبکه‌ای آن آشنا می‌شوید تا بدانید چطور وظایف پیچیده را در سطح شبکه‌ای از ایجنت‌های ناهمگن توزیع کنید.

پروتکل MCP ارتباط «ایجنت با ابزار» (agent-to-tool) است؛ در مقابل، A2A (سرنام Agent2Agent) ارتباط «ایجنت با ایجنت» را ممکن می‌کند — پروتکلی باز برای همکاری ایجنت‌های کدر (opaque) که با فریم‌ورک‌های متفاوتی ساخته شده‌اند. گوگل این پروتکل را در آوریل 2025 معرفی کرد، در ژوئن 2025 به بنیاد لینوکس سپرد و در آوریل 2026 با پشتیبانی بیش از 150 سازمان از جمله AWS، Cisco، Microsoft، Salesforce، SAP و ServiceNow به نسخه‌ی 1.0 رساند. این پروتکل پروژه‌ی ACP شرکت IBM را در خود جذب کرد و افزونه‌ی پرداخت AP2 را نیز به آن افزود. در این درس، کارت ایجنت (Agent Card)، چرخه‌ی حیات تسک (Task) و سه اتصال پروتکل (protocol binding) را با نام‌های استاندارد بسته‌ی شبکه‌ی A2A 1.0.1 بررسی می‌کنیم.

اهداف یادگیری

  • تمایز قائل شدن بین سناریوهای ایجنت با ابزار (MCP) و ایجنت با ایجنت (A2A).
  • انتشار یک کارت ایجنت در مسیر /.well-known/agent-card.json به همراه مهارت‌ها (skills) و متادیتای supportedInterfaces.
  • پیمایش چرخه‌ی حیات تسک: TASK_STATE_SUBMITTED، TASK_STATE_WORKING، TASK_STATE_INPUT_REQUIRED و وضعیت‌های پایانی TASK_STATE_COMPLETED، TASK_STATE_FAILED، TASK_STATE_CANCELED و TASK_STATE_REJECTED.
  • استفاده از پیام‌هایی که هر بخش (Part) آن‌ها تنها یکی از فیلدهای text، raw، url یا data را در بر دارد، در کنار دست‌سازه‌ها (Artifacts) به‌عنوان خروجی.

صورت مسئله

یک ایجنت پشتیبانی مشتری باید نوشتن گزارش را به یک ایجنت تخصصی تولید متن واگذار کند. گزینه‌های پیش از A2A:

  • رابط برنامه‌نویسی اختصاصی (Custom REST API): کار می‌کند، اما هر اتصال نیازمند پیاده‌سازی جداگانه و یک‌باره است.
  • کدبیس مشترک: مستلزم این است که هر دو ایجنت روی یک فریم‌ورک مشترک اجرا شوند.
  • پروتکل MCP: مناسب این کار نیست؛ MCP برای فراخوانی ابزارها طراحی شده، نه برای همکاری دو ایجنت با حفظ استدلال درونی و کدر هر یک از آن‌ها.

پروتکل A2A این خلاء را پر می‌کند. این پروتکل تعامل را به‌صورت ارسال یک تسک از یک ایجنت به ایجنت دیگر، همراه با چرخه‌ی حیات، پیام‌ها و دست‌سازه‌ها مدل‌سازی می‌کند. وضعیت داخلی ایجنت فراخوانی‌شده کدر می‌ماند — ایجنت فراخوان فقط گذار وضعیت‌های تسک و خروجی‌های نهایی را می‌بیند.

پروتکل A2A امکانی است برای «گفت‌وگوی ایجنت‌ها در فریم‌ورک‌های مختلف با یکدیگر». این پروتکل جایگزین MCP نیست؛ این دو مکمل یکدیگرند.

مفاهیم کلیدی

کارت ایجنت (Agent Card)

هر ایجنت سازگار با A2A کارتی را در مسیر /.well-known/agent-card.json منتشر می‌کند:

{
  "name": "research-agent",
  "description": "Summarizes academic papers and drafts citations.",
  "version": "1.2.0",
  "supportedInterfaces": [
    {
      "url": "https://research.example.com/a2a",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    }
  ],
  "capabilities": {"streaming": true, "pushNotifications": true},
  "securitySchemes": {
    "bearer": {"httpAuthSecurityScheme": {"scheme": "Bearer"}}
  },
  "securityRequirements": [{"schemes": {"bearer": {"list": []}}}],
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["text/markdown"],
  "skills": [
    {
      "id": "summarize_paper",
      "name": "Summarize a paper",
      "description": "Read a paper PDF and produce a 3-paragraph summary.",
      "tags": ["research", "summarization"],
      "inputModes": ["text/plain", "application/pdf"],
      "outputModes": ["text/markdown"]
    }
  ]
}

شناسایی بر پایه‌ی URL انجام می‌شود: کارت را دریافت کنید، اولین ورودی supportedInterfaces را که کلاینت شما از protocolBinding آن پشتیبانی می‌کند برگزینید و مهارت‌ها را بررسی کنید. حالت‌های ورودی و خروجی از جنس media type هستند.

کارت‌های ایجنت امضاشده (Signed Agent Cards)

یک کارت می‌تواند آرایه‌ای با نام signatures داشته باشد. هر ورودی آن یک JWS (استاندارد RFC 7515) است که روی ساختار متعارف JSON کارت بر اساس RFC 8785 و بدون در نظر گرفتن فیلد signatures محاسبه می‌شود. کلاینت‌های مصرف‌کننده نیز کارت را به همان شیوه به ساختار متعارف تبدیل کرده و امضا را اعتبارسنجی می‌کنند. این سازوکار مانع جعل هویت می‌شود.

چرخه‌ی حیات تسک

TASK_STATE_SUBMITTED
  -> TASK_STATE_WORKING
  -> TASK_STATE_COMPLETED | TASK_STATE_FAILED | TASK_STATE_CANCELED | TASK_STATE_REJECTED

TASK_STATE_WORKING
  -> TASK_STATE_INPUT_REQUIRED
  -> TASK_STATE_WORKING (the client sends a message with the same taskId)

کلاینت‌ها کار را با SendMessage آغاز می‌کنند و سرور تسک را می‌سازد. ایجنت فراخوانی‌شده بین وضعیت‌های مختلف جابه‌جا می‌شود؛ کلاینت‌ها با پرس‌وجوی دوره‌ای (polling) از طریق GetTask یا به‌صورت استریمینگ روی SSE با استفاده از SendStreamingMessage و SubscribeToTask وضعیت را پیگیری می‌کنند. استریم رویدادهای statusUpdate و artifactUpdate را ارسال می‌کند و با رسیدن تسک به وضعیت پایانی، بسته می‌شود. هیچ فلگ finalی در کار نیست.

پیام‌ها و بخش‌ها (Messages and Parts)

یک پیام شامل messageId، یک نقش یا role (شامل ROLE_USER یا ROLE_AGENT) و یک یا چند بخش (Part) است. هر Part دقیقاً شامل یک فیلد محتوایی است و نام همان فیلد، نوع محتوا را تعیین می‌کند. فیلدی به نام kind وجود ندارد.

  • text: محتوای متنی ساده.
  • raw: بایت‌های فایل به‌صورت base64 در JSON، معمولاً همراه با filename و mediaType.
  • url: لینکی به محتوای فایل.
  • data: داده‌ی ساختاریافته‌ی JSON (ورودی ساختاریافته برای ایجنت فراخوانی‌شده).

مثال:

{
  "messageId": "msg-001",
  "role": "ROLE_USER",
  "parts": [
    {"text": "Summarize this paper."},
    {"raw": "...", "filename": "paper.pdf", "mediaType": "application/pdf"},
    {"data": {"targetLength": "3 paragraphs"}, "mediaType": "application/json"}
  ]
}

دست‌سازه‌ها (Artifacts)

خروجی‌ها دست‌سازه (Artifact) هستند، نه رشته‌های متنی خام. دست‌سازه خروجی نام‌دار و نوع‌داری است:

{
  "artifactId": "art-001",
  "name": "summary",
  "parts": [{"text": "...", "mediaType": "text/markdown"}]
}

دست‌سازه‌ها را می‌توان به‌صورت تکه‌تکه (chunks) استریم کرد. هر رویداد artifactUpdate خودِ دست‌سازه را همراه با append و lastChunk ارسال می‌کند. کلاینت فراخوان این تکه‌ها را سرهم و تجمیع می‌کند.

سه اتصال پروتکل (Protocol Bindings)

  1. JSON-RPC 2.0 روی HTTP با شناسه (JSONRPC): متد POST برای درخواست‌ها و SSE برای استریمینگ. نام متدها به‌صورت PascalCase است: SendMessage، SendStreamingMessage، GetTask، ListTasks، CancelTask، SubscribeToTask، CreateTaskPushNotificationConfig، GetTaskPushNotificationConfig، ListTaskPushNotificationConfigs، DeleteTaskPushNotificationConfig و GetExtendedAgentCard.
  2. gRPC با شناسه (GRPC): برای محیط‌های سازمانی که gRPC پروتکل بومی آن‌ها است. نام متدها دقیقاً یکسان است.
  3. HTTP+JSON/REST با شناسه (HTTP+JSON): نشانی‌های منبع‌محور مانند POST /message:send و GET /tasks/{id}.

هر سه اتصال، مدل داده‌ی یکسانی را جابه‌جا می‌کنند. هر ورودی supportedInterfaces نام یک اتصال و protocolVersion آن را مشخص می‌کند. کلاینت‌ها باید هدر A2A-Version: 1.0 را روی تمام درخواست‌ها بفرستند؛ چون سرور درخواست بدون این هدر را به‌صورت نسخه‌ی 0.3 می‌خواند.

POST /a2a HTTP/1.1
Host: research.example.com
Content-Type: application/json
A2A-Version: 1.0

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "SendMessage",
  "params": {
    "message": {
      "messageId": "msg-001",
      "role": "ROLE_USER",
      "parts": [{"text": "Summarize this paper."}]
    }
  }
}

حفظ حالت کدر (Opacity Preservation)

یکی از اصول کلیدی در طراحی: وضعیت درونی ایجنت فراخوانی‌شده کدر (opaque) می‌ماند. ایجنت فراخوان فقط وضعیت تسک و دست‌سازه‌ها را می‌بیند. زنجیره‌ی تفکر (chain-of-thought) ایجنت فراخوانی‌شده، فراخوانی‌های ابزار آن و ارجاع کار به زیرایجنت‌ها همگی مخفی می‌مانند. این رویکرد برعکس پروتکل MCP است که در آن فراخوانی ابزارها کاملاً شفاف و آشکار است.

منطق پشت این طراحی: A2A امکان همکاری رقبای تجاری را بدون افشای ساختار داخلی‌شان فراهم می‌کند. ارتباط A2A می‌تواند در قالب «این ایجنت پشتیبانی مشتری را صدا بزن» پیاده شود، بی‌آنکه فراخواننده متوجه شود آن ایجنت این سرویس را چطور پیاده‌سازی کرده است.

گاه‌شمار

  • 2025-04-09. گوگل پروتکل A2A را معرفی کرد.
  • 2025-06-23. پروژه به بنیاد لینوکس اهدا شد.
  • 2025-08. پروژه‌ی ACP شرکت IBM در آن ادغام شد.
  • 2025-09. افزونه‌ی AP2 (پرداخت ایجنت) عرضه شد.
  • 2026-04. نسخه‌ی 1.0 با بیش از 150 سازمان حامی منتشر شد.

نسبت با MCP

بعد مقایسه MCP A2A
کاربرد ایجنت به ابزار ایجنت به ایجنت
سطح شفافیت فراخوانی ابزارها به‌صورت شفاف استدلال درونی کدر و مخفی
فراخواننده‌ی معمول محیط اجرای ایجنت ایجنتی دیگر
وضعیت نتیجه‌ی فراخوانی ابزار تسک دارای چرخه‌ی حیات
احراز هویت و دسترسی OAuth 2.1 (بخش 13 · 16) securitySchemes به‌همراه securityRequirements در کارت ایجنت
بستر انتقال Stdio / HTTP قابل استریم JSON-RPC / gRPC / HTTP+JSON

وقتی می‌خواهید ابزاری مشخص را صدا بزنید، سراغ MCP بروید. وقتی قصد دارید کل یک تسک را به ایجنت دیگری واگذار کنید، از A2A استفاده کنید. بسیاری از سیستم‌های عملیاتی از هر دو استفاده می‌کنند: ایجنت برای لایه‌ی ابزارهای خود از MCP و برای لایه‌ی همکاری با دیگران از A2A بهره می‌گیرد.

چرخه حیات تسک A2ASendMessage ← TASK_STATE_* ← آرتیفکت
A2A TASK LIFECYCLEOne agent sends a message with SendMessage, and the remote agent opens a Task. The caller watches only its status.state values: TASK_STATE_SUBMITTED, TASK_STATE_WORKING, sometimes TASK_STATE_INPUT_REQUIRED, then TASK_STATE_COMPLETED. The remote agent's internal reasoning stays opaque — the caller sees state changes and, at the end, an artifact returned as the output.ایجنت کلاینتایجنت راه‌دورSendMessageTASK_STATE_SUBMITTEDTASK_STATE_WORKINGTASK_STATE_INPUT_REQUIREDTASK_STATE_COMPLETEDآرتیفکتچرخه حیات تسک (پنهان ماندن وضعیت برای فراخوان)
یک ایجنت پیامی را با SendMessage ارسال می‌کند و ایجنت راه‌دور یک تسک باز می‌کند. فراخواننده تنها مقادیر status.state آن را مشاهده می‌کند: TASK_STATE_SUBMITTED، TASK_STATE_WORKING، گاهی TASK_STATE_INPUT_REQUIRED و در نهایت TASK_STATE_COMPLETED. استدلال درونی ایجنت راه‌دور مبهم و پنهان باقی می‌ماند — فراخواننده تغییرات وضعیت و در پایان، یک آرتیفکت را به عنوان خروجی نهایی می‌بیند.

پیاده‌سازی عملی

فایل code/main.py یک محیط تست و اجرای حداقلی برای A2A پیاده می‌کند: ایجنت نویسنده کارت خود را منتشر می‌کند، ایجنت پژوهشگر درخواستی با متد SendMessage همراه با یک بخش PDF و دستور متنی برای آن می‌فرستد، و تسک مسیر TASK_STATE_WORKING ← TASK_STATE_INPUT_REQUIRED ← TASK_STATE_WORKING ← TASK_STATE_COMPLETED را طی می‌کند تا در نهایت یک دست‌سازه‌ی متنی برگرداند. همه‌ی پیاده‌سازی با کتابخانه‌ی استاندارد پایتون انجام شده و از یک بستر انتقال در حافظه استفاده می‌کند تا تمرکز روی ساختار پیام‌ها بماند.

بخش‌هایی که باید به آن‌ها دقت کنید:

  • ساختار JSON کارت ایجنت.
  • تخصیص شناسه تسک و گذار وضعیت‌ها در سمت سرور.
  • مشخص شدن نوع Part بر اساس نام فیلد محتوایی موجود.
  • شاخه‌ی TASK_STATE_INPUT_REQUIRED در میانه‌ی تسک.
  • بازگرداندن دست‌سازه پس از اتمام کار.

خروجی این درس

خروجی این درس فایل outputs/skill-a2a-agent-spec.md خواهد بود. به کمک این مهارت، برای هر ایجنت جدیدی که قرار است سایر ایجنت‌ها آن را فراخوانی کنند، فایل JSON کارت ایجنت، ساختار مهارت‌ها و طرح اندپوینت‌ها تولید می‌شود.

تمرین‌ها

  1. فایل code/main.py را اجرا کنید. کل چرخه‌ی حیات تسک را دنبال کنید؛ از جمله توقف در وضعیت TASK_STATE_INPUT_REQUIRED که در آن ایجنت فراخوانی‌شده خواستار توضیح بیشتر می‌شود.

  2. قابلیت امضای کارت ایجنت را پیاده کنید. یک ورودی JWS در آرایه‌ی signatures با alg برابر با HS256 قرار دهید که خروجی متعارف JSON کارت را بدون در نظر گرفتن فیلد signatures امضا کند. یک مدل اعتبارسنج بنویسید و بررسی کنید که آیا با دستکاری کارت، خطا می‌دهد یا خیر.

  3. استریمینگ تسک را با SendStreamingMessage پیاده‌سازی کنید: ایجنت نویسنده شیء task، سه تکه از رویداد artifactUpdate و یک statusUpdate با مقدار TASK_STATE_COMPLETED بفرستد و سپس استریم را ببندد. کلاینت فراخوان باید این تکه‌ها را سرهم کند.

  4. یک ایجنت A2A طراحی کنید که یک سرور MCP را کپسوله می‌کند. هر ابزار MCP را به یک مهارت A2A نگاشت کنید. به بده‌بستان‌های فنی دقت کنید — چه میزانی از کدر بودن را از دست می‌دهید؟

  5. اطلاعیه‌ی انتشار نسخه‌ی 1.0 پروتکل A2A را مطالعه کنید و آن قابلیتی را که تا آوریل 2026 در هیچ فریم‌ورکی پیاده نشده بود بیابید. (راهنمایی: به واگذاری چندگامی تسک مربوط است.)

اصطلاحات کلیدی

اصطلاح در گفتگوها چه می‌گویند معنای دقیق فنی
A2A «پروتکل ایجنت به ایجنت» پروتکلی باز برای همکاری کدر بین ایجنت‌ها
Agent Card «فایل /.well-known/agent-card.json» متادیتای منتشرشده برای توصیف مهارت‌ها و supportedInterfaces ایجنت
Skill «یک واحد قابل فراخوانی» عملیاتی نام‌گذاری‌شده که ایجنت پشتیبانی می‌کند (معادل ابزار در MCP)
Task «واحد واگذاری کار» یک کار معین دارای چرخه‌ی حیات و دست‌سازه‌ی نهایی
Message «ورودی تسک» محمل انتقال بخش‌ها یا Partها (text، raw، url، data)
Part «تکه‌ی تایپ‌دار» دقیقاً یکی از فیلدهای text / raw / url / data به همراه mediaType اختیاری؛ بدون فیلدی به نام kind
Artifact «خروجی تسک» خروجی نام‌دار و مشخصی که با اتمام کار بازگردانده می‌شود
AP2 «پروتکل پرداخت ایجنت» افزونه‌ی پرداخت مبتنی بر A2A؛ امضای کارت جزو هسته‌ی پروتکل A2A است (signatures)
Opacity «همکاری جعبه‌سیاه» مخفی ماندن ساختار درونی ایجنت فراخوانی‌شده از دید فراخواننده
TASK_STATE_INPUT_REQUIRED «توقف تسک» وضعیت وقفه زمانی که ایجنت به اطلاعات تکمیلی نیاز دارد

برای مطالعه‌ی بیشتر

سؤالات متداول

پروتکل A2A چه فرقی با MCP دارد؟

پروتکل MCP برای ارتباط ایجنت با ابزارها (agent-to-tool) با فراخوانی شفاف ابزار است، اما A2A برای ارتباط دو ایجنت مستقل (agent-to-agent) با منطق درونی کدر و واگذاری کل تسک طراحی شده است.

کارت ایجنت یا Agent Card چیست و کجا قرار می‌گیرد؟

یک فایل متادیتا با فرمت JSON است که مشخصات، مهارت‌ها و پروتکل‌های ارتباطی ایجنت را شرح می‌دهد و معمولاً در مسیر /.well-known/agent-card.json سرو می‌شود.

چرخه‌ی حیات یک تسک در پروتکل A2A چه وضعیت‌هایی دارد؟

تسک با TASK_STATE_SUBMITTED آغاز شده، به TASK_STATE_WORKING می‌رود، در صورت نیاز به جزئیات به TASK_STATE_INPUT_REQUIRED منتقل می‌شود و در نهایت به یکی از وضعیت‌های پایانی مانند TASK_STATE_COMPLETED می‌رسد.

ما رو توی گوگل بیشتر ببین

با افزودن نکست ادمین به «منابع ترجیحی» گوگل، درس‌ها و مطالب ما را در بخش اخبار برتر جستجو بیشتر می‌بینید.