Files
2026-07-13 12:59:43 +08:00

239 lines
8.4 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Lesson 11 - Agent-to-Agent (A2A) Protocol"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install agent-framework azure-ai-projects azure-identity python-dotenv"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import dotenv\n",
"from agent_framework import tool, AgentResponseUpdate, WorkflowBuilder\n",
"from agent_framework.foundry import FoundryChatClient\n",
"from azure.identity import DefaultAzureCredential\n",
"\n",
"dotenv.load_dotenv()\n",
"\n",
"endpoint = os.getenv(\"AZURE_AI_PROJECT_ENDPOINT\")\n",
"deployment_name = os.getenv(\"AZURE_AI_MODEL_DEPLOYMENT_NAME\")\n",
"\n",
"missing = [k for k, v in {\n",
" \"AZURE_AI_PROJECT_ENDPOINT\": endpoint,\n",
" \"AZURE_AI_MODEL_DEPLOYMENT_NAME\": deployment_name\n",
"}.items() if not v]\n",
"\n",
"if missing:\n",
" raise ValueError(\n",
" f\"Missing required environment variables: {', '.join(missing)}. \"\n",
" \"Please set them as environment variables (e.g., in your .env file or shell environment).\"\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Create the Microsoft Foundry client\n",
"client = FoundryChatClient(\n",
" project_endpoint=endpoint,\n",
" model=deployment_name,\n",
" credential=DefaultAzureCredential()\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## What is the A2A Protocol?\n",
"\n",
"The **Agent-to-Agent (A2A) protocol** is an open standard that enables AI agents to communicate,\n",
"discover each other, and collaborate — even when they are built on different frameworks or hosted\n",
"by different services.\n",
"\n",
"Key concepts:\n",
"\n",
"- **Discovery** Agents publish an *Agent Card* that describes their capabilities, making it\n",
" easy for other agents (or orchestrators) to find the right specialist for a task.\n",
"- **Message Passing** Agents exchange structured messages through a common protocol, so a\n",
" request from one agent can be understood and fulfilled by another regardless of its internal\n",
" implementation.\n",
"- **Task Lifecycle** A2A defines states such as *submitted*, *working*, *completed*, and\n",
" *failed*, giving the orchestrator full visibility into how a delegated task is progressing.\n",
"\n",
"In this lesson we simulate A2A-style collaboration by wiring three specialized travel agents\n",
"into a workflow where each agent contributes its expertise and passes results to the next."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Creating Specialized Travel Agents"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"currency_agent = client.as_agent(\n",
" name=\"CurrencyExchangeAgent\",\n",
" instructions=\"\"\"You are a currency exchange specialist. You help travelers understand:\n",
"- Current exchange rates between currencies\n",
"- Best times to exchange money\n",
"- Tips for getting the best rates\n",
"When asked about a destination, provide relevant currency information.\"\"\",\n",
")\n",
"\n",
"activity_agent = client.as_agent(\n",
" name=\"ActivityPlannerAgent\",\n",
" instructions=\"\"\"You are a local activities specialist. You recommend:\n",
"- Must-see attractions and hidden gems\n",
"- Local experiences and cultural activities\n",
"- Restaurant and dining recommendations\n",
"Tailor suggestions to the traveler's interests.\"\"\",\n",
")\n",
"\n",
"travel_manager = client.as_agent(\n",
" name=\"TravelManagerAgent\",\n",
" instructions=\"\"\"You are a travel manager who coordinates between specialist agents.\n",
"When planning a trip:\n",
"1. Gather currency information from the currency specialist\n",
"2. Get activity recommendations from the activity planner\n",
"3. Synthesize everything into a cohesive travel brief\n",
"Present the final plan in an organized, easy-to-read format.\"\"\",\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Multi-Agent Collaboration via Workflow\n",
"\n",
"We connect the three agents into a sequential workflow that mirrors A2A message passing:\n",
"\n",
"1. **CurrencyExchangeAgent** receives the user request and produces currency guidance.\n",
"2. **ActivityPlannerAgent** receives the enriched context and adds activity recommendations.\n",
"3. **TravelManagerAgent** synthesizes both inputs into a final travel brief."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"workflow = WorkflowBuilder(start_executor=currency_agent) \\\n",
" .add_edge(currency_agent, activity_agent) \\\n",
" .add_edge(activity_agent, travel_manager) \\\n",
" .build()\n",
"\n",
"last_author = None\n",
"events = workflow.run(\n",
" \"Plan a week-long trip to Tokyo. I love food, temples, and technology.\",\n",
" stream=True,\n",
")\n",
"async for event in events:\n",
" if event.type == \"output\" and isinstance(event.data, AgentResponseUpdate):\n",
" update = event.data\n",
" author = update.author_name\n",
" if author != last_author:\n",
" if last_author is not None:\n",
" print()\n",
" print(f\"\\n{'='*50}\")\n",
" print(f\"🤖 {author}:\")\n",
" print(f\"{'='*50}\")\n",
" last_author = author\n",
" print(update.text, end=\"\", flush=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Understanding A2A in Production\n",
"\n",
"In a production environment the A2A protocol unlocks powerful cross-service scenarios:\n",
"\n",
"| Capability | Description |\n",
"|---|---|\n",
"| **Cross-framework interop** | An agent built with one framework can delegate tasks to an agent built with any other A2A-compliant framework, enabling true cross-organization interoperability. |\n",
"| **Service boundaries** | Agents can live in separate microservices, cloud regions, or even different organisations while still collaborating seamlessly. |\n",
"| **Dynamic discovery** | An orchestrator can query an Agent Card registry at runtime to find the best-suited specialist for a given sub-task. |\n",
"| **Streaming & push notifications** | A2A supports Server-Sent Events (SSE) for real-time progress updates and push notifications for long-running tasks. |\n",
"\n",
"The workflow we built above is a simplified, in-process version of this pattern. In a real\n",
"deployment each agent would expose an HTTP endpoint, publish an Agent Card, and communicate\n",
"via the A2A JSON-RPC protocol."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"In this lesson you learned:\n",
"\n",
"1. **What the A2A protocol is** — an open standard for agent-to-agent discovery, messaging,\n",
" and task management.\n",
"2. **How to create specialized agents** — a Currency Exchange agent, an Activity Planner agent,\n",
" and a Travel Manager orchestrator.\n",
"3. **How to wire agents into a workflow** — using `WorkflowBuilder` to model sequential\n",
" message passing between agents.\n",
"4. **How A2A works in production** — enabling cross-framework, cross-service collaboration\n",
" with dynamic discovery and streaming updates."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.13"
}
},
"nbformat": 4,
"nbformat_minor": 2
}