A2A Python SDK 源码架构解读:一个请求是如何被处理的

本文是 A2A 协议学习系列的第三篇。前两篇分别介绍了协议全景规范细节,本文将走进 a2a-python SDK 的源码,看看这个 Python 库是如何把协议规范变成可运行的代码的。

为了让内容更好理解,本文会大量使用类比和流程图,尽量避免堆砌抽象概念。

一、SDK 是什么?一句话说清楚

a2a-python(pip 包名 a2a-sdk)是 A2A 协议的官方 Python 实现。

打个比方:如果 A2A 协议是"快递行业标准"(规定了包裹格式、运单格式、签收流程等),那么 a2a-sdk 就是一套"快递收发工具包"------它帮你打包、发送、接收、拆包,你只需要关心"包裹里装什么"。

具体来说,SDK 提供了两大能力:

  • 客户端:帮你向远程 Agent 发送请求、接收响应(相当于"寄快递")
  • 服务端:帮你搭建一个 A2A 服务,接收请求、执行任务、返回结果(相当于"开快递站")

1.1 技术栈一览

用途 技术选型 说明
数据模型 Pydantic v2 定义 Task、Message 等数据结构,自动校验和序列化
HTTP 客户端 httpx + httpx-sse 发送 HTTP 请求,接收 SSE 流式响应
HTTP 服务端 FastAPI / Starlette 搭建 Web 服务(可选,按需安装)
gRPC grpcio(可选) 高性能 RPC 通信
数据库 SQLAlchemy(可选) 任务持久化存储
可观测性 OpenTelemetry(可选) 分布式追踪

核心依赖只有 5 个包,其余都是可选的。最小安装只需 pip install a2a-sdk,需要什么能力再按需加装,比如 pip install "a2a-sdk[http-server]" 加装 FastAPI 服务端支持。

1.2 代码目录结构

先看一下 SDK 的代码是怎么组织的,后面会逐个讲解:

复制代码
a2a/
├── types.py              # 所有数据结构的定义(Task、Message、Part 等)
├── _base.py              # 数据结构的基类配置
│
├── client/               # 客户端(发送请求的一方)
│   ├── client.py          #   客户端接口定义
│   ├── client_factory.py  #   客户端工厂(自动选择通信方式)
│   ├── base_client.py     #   客户端核心实现
│   ├── transports/        #   通信方式的具体实现
│   │   ├── jsonrpc.py      #     JSON-RPC 方式
│   │   ├── rest.py         #     REST 方式
│   │   └── grpc.py         #     gRPC 方式
│   └── middleware.py      #   中间件(如自动加认证头)
│
├── server/               # 服务端(接收请求的一方)
│   ├── agent_execution/   #   Agent 执行引擎
│   │   ├── agent_executor.py  # 开发者实现的 Agent 逻辑
│   │   └── context.py         # 请求上下文信息
│   ├── request_handlers/  #   请求路由和处理
│   │   ├── default_request_handler.py  # 核心调度器
│   │   ├── jsonrpc_handler.py          # JSON-RPC 格式适配
│   │   └── rest_handler.py             # REST 格式适配
│   ├── apps/              #   Web 应用(FastAPI/Starlette)
│   ├── tasks/             #   任务管理
│   │   ├── task_store.py       # 任务存储接口
│   │   ├── task_manager.py     # 任务状态管理
│   │   └── task_updater.py     # Agent 更新任务的工具
│   └── events/            #   事件队列
│       └── event_queue.py      # Agent 和服务端之间的消息通道
│
├── grpc/                 # gRPC 相关的生成代码
└── utils/                # 工具函数

二、数据模型:SDK 怎么表示协议中的数据结构

2.1 为什么用 Pydantic 而不是 protobuf?

A2A 协议用 Protocol Buffers(proto 文件)定义数据结构。按理说,SDK 可以直接用 protobuf 自动生成的 Python 类。但 SDK 选择了 Pydantic v2 来重新定义这些数据结构。

为什么?因为 protobuf 生成的 Python 类用起来不太"Pythonic":

  • 没有类型提示,IDE 补全不友好
  • 没有运行时校验(传错类型不会报错)
  • 序列化控制不灵活

而 Pydantic 是 Python 生态中最流行的数据校验库,写出来的代码更自然:

python 复制代码
# protobuf 生成的类(不太好用)
task = a2a_pb2.Task()
task.id = "xxx"
task.context_id = "yyy"

# Pydantic 类(更 Pythonic)
task = Task(id="xxx", context_id="yyy")
# 自动校验:如果 id 不是字符串,立刻报错
# IDE 自动补全:输入 task. 就能看到所有字段

2.2 命名转换:Python 风格 ↔ JSON 风格

A2A 协议要求 JSON 中使用 camelCase(如 contextId),但 Python 习惯用 snake_case(如 context_id)。SDK 通过一个基类自动处理这个转换:

python 复制代码
class A2ABaseModel(BaseModel):
    model_config = ConfigDict(
        alias_generator=to_camel,    # 自动生成 camelCase 别名
        serialize_by_alias=True,     # 输出 JSON 时用 camelCase
        validate_by_name=True,       # 写代码时用 snake_case
    )

效果就是:

python 复制代码
# 写代码时用 Python 风格
task = Task(context_id="abc")

# 序列化为 JSON 时自动变成协议要求的格式
task.model_dump_json()
# → {"contextId": "abc"}

所有协议数据结构(Task、Message、Part、Artifact、AgentCard 等)都继承这个基类,开发者完全不需要操心命名转换。

2.3 核心类型速览

types.py 文件约 2000 行,定义了协议中的所有数据结构。几个最重要的:

python 复制代码
# 任务状态枚举
class TaskState(str, Enum):
    submitted = 'TASK_STATE_SUBMITTED'       # 已提交
    working = 'TASK_STATE_WORKING'           # 处理中
    completed = 'TASK_STATE_COMPLETED'       # 已完成
    failed = 'TASK_STATE_FAILED'             # 失败
    canceled = 'TASK_STATE_CANCELED'         # 已取消
    input_required = 'TASK_STATE_INPUT_REQUIRED'  # 需要用户输入
    rejected = 'TASK_STATE_REJECTED'         # 被拒绝
    auth_required = 'TASK_STATE_AUTH_REQUIRED'    # 需要认证

# 任务
class Task(A2ABaseModel):
    id: str                                  # 任务 ID
    context_id: str | None = None            # 会话 ID
    status: TaskStatus                       # 当前状态
    artifacts: list[Artifact] | None = None  # 产出物
    history: list[Message] | None = None     # 交互历史

# 消息内容(文本、文件、结构化数据三选一)
class Part(RootModel):
    root: TextPart | FilePart | DataPart

三、服务端架构:一个请求是怎么被处理的

服务端是 SDK 中最复杂也最核心的部分。为了让大家理解它的工作方式,这里用一个类比来说明。

3.1 餐厅类比:理解服务端的分层设计

想象一家餐厅:

复制代码
顾客点餐(HTTP 请求到达)
    ↓
前台服务员(FastAPI 应用层)------ 接待顾客,记录订单
    ↓
后厨调度(DefaultRequestHandler)------ 分配任务,协调流程
    ↓
厨师(AgentExecutor)------ 真正做菜的人(开发者实现)
    ↓
传菜窗口(EventQueue)------ 厨师做好一道菜就放到窗口
    ↓
服务员上菜(SSE 流式响应)------ 一道一道端给顾客

SDK 的服务端就是这样分层工作的:

复制代码
HTTP 请求到达
    ↓
[Web 应用层] FastAPI/Starlette ------ 接收 HTTP 请求
    ↓
[协议适配层] JSONRPCHandler ------ 拆开 JSON-RPC 信封,识别是什么操作
    ↓
[核心调度层] DefaultRequestHandler ------ 创建任务、启动 Agent、管理事件
    ↓
[Agent 执行层] AgentExecutor ------ 开发者写的业务逻辑
    ↓
[事件队列] EventQueue ------ Agent 产生的事件在这里排队
    ↓
[任务管理层] TaskManager + TaskStore ------ 把事件转化为任务状态并保存

每一层只做自己的事,互不干扰。下面逐层介绍。

3.2 AgentExecutor:开发者唯一需要写的代码

这是整个 SDK 中最重要的概念------开发者只需要实现一个类,就能创建一个 A2A Agent

python 复制代码
class AgentExecutor(ABC):
    async def execute(self, context, event_queue):
        """处理请求。从 context 读取用户输入,把结果放到 event_queue 里。"""

    async def cancel(self, context, event_queue):
        """取消任务。"""

就两个方法。SDK 把所有协议细节(HTTP 处理、JSON 序列化、任务状态管理、SSE 流式传输......)都封装好了,开发者只需要关心:

  1. context 里读取用户发了什么
  2. 执行自己的业务逻辑
  3. 把结果通过 event_queue 发出去

这就像餐厅里的厨师------你不需要知道前台怎么接单、服务员怎么上菜,你只管做菜就行。

3.3 RequestContext:Agent 能拿到什么信息

当 Agent 的 execute 方法被调用时,context 参数包含了所有需要的信息:

python 复制代码
context.message          # 用户发来的消息
context.task_id          # 任务 ID(SDK 自动生成)
context.context_id       # 会话 ID(SDK 自动生成)
context.current_task     # 如果是多轮对话,这里有之前的任务信息
context.get_user_input() # 便捷方法:直接拿到用户的文本输入

开发者不需要自己生成 ID、不需要自己管理会话,SDK 全部搞定。

3.4 EventQueue 和 TaskUpdater:Agent 怎么返回结果

Agent 通过 EventQueue(事件队列)返回结果。但直接操作队列比较底层,所以 SDK 提供了一个更好用的工具------TaskUpdater

python 复制代码
async def execute(self, context, event_queue):
    # 创建一个 TaskUpdater,它会帮你往 event_queue 里放事件
    updater = TaskUpdater(
        event_queue=event_queue,
        task_id=context.task_id,
        context_id=context.context_id,
    )

    # 告诉客户端:我开始干活了
    await updater.start_work()

    # 执行业务逻辑...
    result = do_something(context.get_user_input())

    # 把结果作为产出物返回
    await updater.add_artifact(parts=[TextPart(text=result)])

    # 告诉客户端:我干完了
    await updater.complete()

TaskUpdater 提供了一组直观的方法,对应任务的各种状态:

方法 含义 任务还能继续吗?
start_work() 开始处理
complete() 处理完成 不能,结束了
failed() 处理失败 不能,结束了
reject() 拒绝处理 不能,结束了
cancel() 已取消 不能,结束了
requires_input() 需要用户补充信息 能,等用户回复后继续
requires_auth() 需要用户授权 能,等用户授权后继续
add_artifact() 添加一个产出物

TaskUpdater 还有一个安全机制:一旦任务进入终态(完成/失败/取消/拒绝),就不能再更新了 。如果你不小心在 complete() 之后又调用了 start_work(),它会直接抛出异常,帮你发现 bug。

3.5 DefaultRequestHandler:幕后的调度中心

DefaultRequestHandler 是服务端的"大脑",负责协调所有组件。当一个请求到达时,它做的事情可以用一张流程图说清楚:

非流式请求(客户端等待最终结果):

复制代码
1. 收到客户端消息
2. 创建任务管理器(TaskManager)
3. 创建事件队列(EventQueue)
4. 在后台启动 AgentExecutor.execute()
5. 等待事件队列中的事件:
   ├── 收到状态更新 → 保存到 TaskStore
   ├── 收到产出物 → 追加到任务
   └── 收到终态事件 → 停止等待
6. 把最终的 Task 返回给客户端

流式请求(客户端实时接收进度):

复制代码
1. 收到客户端消息
2. 创建任务管理器 + 事件队列
3. 在后台启动 AgentExecutor.execute()
4. 每收到一个事件,立刻:
   ├── 保存到 TaskStore
   └── 通过 SSE 推送给客户端
5. 直到收到终态事件,关闭连接

两种模式的区别就像:

  • 非流式 = 你在餐厅点了外卖,等所有菜做好一起打包送来
  • 流式 = 你坐在餐厅里,厨师做好一道就上一道

3.6 EventQueue:Agent 和服务端之间的"传菜窗口"

EventQueue 是一个异步队列,Agent 往里放事件,服务端从里面取事件:

复制代码
AgentExecutor                    EventQueue                    DefaultRequestHandler
     │                              │                                │
     │  enqueue(开始工作)            │                                │
     │─────────────────────────────→│                                │
     │                              │  dequeue() → 开始工作           │
     │                              │───────────────────────────────→│ → 保存状态
     │                              │                                │
     │  enqueue(产出物)              │                                │
     │─────────────────────────────→│                                │
     │                              │  dequeue() → 产出物             │
     │                              │───────────────────────────────→│ → 保存 + 推送给客户端
     │                              │                                │
     │  enqueue(完成)                │                                │
     │─────────────────────────────→│                                │
     │                              │  dequeue() → 完成               │
     │                              │───────────────────────────────→│ → 保存 + 关闭连接

EventQueue 有一个巧妙的功能------tap()(分流)。它可以创建一个"子队列",父队列收到的所有事件会自动复制一份到子队列。这解决了一个实际问题:如果多个客户端同时订阅同一个任务的进度,每个客户端都能收到完整的事件流

复制代码
                    ┌─→ 子队列 1 → 客户端 A
EventQueue(父)────┤
                    └─→ 子队列 2 → 客户端 B

3.7 TaskManager 和 TaskStore:任务的保存和管理

TaskManager 负责把事件队列中的事件"翻译"成任务状态的变化:

  • 收到 TaskStatusUpdateEvent → 更新任务状态,把旧的状态消息存入历史
  • 收到 TaskArtifactUpdateEvent → 把产出物追加到任务
  • 收到 Task 对象 → 直接保存

TaskStore 是任务的存储后端,SDK 提供了两种实现:

实现 适用场景 特点
InMemoryTaskStore 开发和测试 数据存在内存里,重启就没了
DatabaseTaskStore 生产环境 支持 PostgreSQL/MySQL/SQLite

你也可以自己实现一个 TaskStore(比如基于 Redis),只需要实现三个方法:

python 复制代码
class TaskStore(ABC):
    async def save(self, task): ...    # 保存任务
    async def get(self, task_id): ...  # 读取任务
    async def delete(self, task_id): ... # 删除任务

3.8 协议适配层:同一套逻辑,多种协议格式

A2A 协议支持三种通信格式:JSON-RPC、REST、gRPC。SDK 通过"适配层"让同一套核心逻辑支持所有格式:

复制代码
JSON-RPC 请求 ──→ JSONRPCHandler ──→ ┐
                                      │
REST 请求 ─────→ RESTHandler ────────→├──→ DefaultRequestHandler(核心逻辑)
                                      │
gRPC 请求 ─────→ GRPCHandler ────────→┘

每个 Handler 做的事情很简单:

  • JSON-RPC Handler :拆开 JSON-RPC 的"信封"(提取 methodparams),调用核心逻辑,再把结果包回 JSON-RPC 格式
  • REST Handler:从 URL 路径和 HTTP 方法判断操作类型,调用核心逻辑,返回纯 JSON
  • gRPC Handler:从 protobuf 消息中提取参数,调用核心逻辑,返回 protobuf 响应

开发者不需要关心这些------选择哪种格式是在搭建服务时决定的,Agent 的业务逻辑完全不受影响。

3.9 Web 应用层:一行代码启动服务

SDK 提供了开箱即用的 FastAPI 和 Starlette 应用,自动注册所有需要的路由:

python 复制代码
# JSON-RPC 模式
from a2a.server.apps.jsonrpc import A2AFastAPIApplication

app = A2AFastAPIApplication(agent_card=card, http_handler=handler)
fastapi_app = app.build()
# 自动注册:
#   GET  /.well-known/agent-card.json  → 返回 Agent Card
#   POST /                             → 处理所有 A2A 请求
python 复制代码
# REST 模式
from a2a.server.apps.rest import A2ARESTFastAPIApplication

app = A2ARESTFastAPIApplication(agent_card=card, http_handler=handler)
fastapi_app = app.build()
# 自动注册:
#   GET  /.well-known/agent-card.json  → 返回 Agent Card
#   POST /v1/message:send              → 发送消息
#   POST /v1/message:stream            → 流式消息
#   GET  /v1/tasks/{id}                → 获取任务
#   POST /v1/tasks/{id}:cancel         → 取消任务
#   ...

四、客户端架构:怎么和远程 Agent 通信

4.1 三层设计:像打电话一样简单

客户端的设计目标是:不管远程 Agent 用的是 JSON-RPC、REST 还是 gRPC,调用方式都一样

复制代码
你的代码
    ↓ 调用 client.send_message()
Client(统一接口)
    ↓ 自动选择通信方式
ClientTransport(通信层)
    ↓ 具体的 HTTP/gRPC 调用
JsonRpcTransport / RestTransport / GrpcTransport

这就像打电话------你不需要知道对方用的是移动还是联通,你只管拨号就行,运营商的事情手机帮你处理了。

4.2 ClientFactory:自动选择最佳通信方式

ClientFactory 是创建客户端的推荐方式。它会读取 Agent Card 中声明的通信方式,自动选择一个双方都支持的:

python 复制代码
# 最简单的用法:给一个 URL,自动搞定一切
client = await ClientFactory.connect('https://agent.example.com')

# 也可以更精细地控制
client = await ClientFactory.connect(
    'https://agent.example.com',
    client_config=ClientConfig(
        streaming=True,                    # 我要用流式
        supported_transports=['JSONRPC'],  # 我只支持 JSON-RPC
    ),
)

connect 方法内部做了这些事:

  1. 访问 https://agent.example.com/.well-known/agent-card.json 获取 Agent Card
  2. 看 Agent Card 里声明支持哪些通信方式(JSON-RPC?REST?gRPC?)
  3. 和客户端配置对比,找到双方都支持的方式
  4. 创建对应的通信层实例
  5. 返回一个可以直接使用的 Client 对象

4.3 使用客户端:发送消息和接收响应

python 复制代码
# 发送消息
async for event in client.send_message(
    Message(role=Role.user, parts=[TextPart(text="今天天气怎么样?")])
):
    if isinstance(event, Message):
        # Agent 直接回复了一条消息(没有创建任务)
        print("Agent 说:", event.parts[0].root.text)
    else:
        # Agent 创建了一个任务
        task, update = event
        print(f"任务状态:{task.status.state}")
        if task.artifacts:
            print(f"产出物:{task.artifacts[0].parts[0].root.text}")

注意 send_message 返回的是一个异步迭代器(async for)。无论底层是流式还是非流式,上层代码的写法都一样。这是 SDK 的一个巧妙设计------统一了流式和非流式的编程模型

4.4 中间件:在每个请求上"加料"

客户端支持中间件(Interceptor),可以在每个请求发出前做一些处理,最常见的用途是自动添加认证信息:

python 复制代码
class MyAuthInterceptor(ClientCallInterceptor):
    async def intercept(self, method, payload, http_kwargs, card, context):
        # 在每个请求的 HTTP 头里加上 Token
        headers = http_kwargs.setdefault('headers', {})
        headers['Authorization'] = f'Bearer {my_token}'
        return payload, http_kwargs

# 创建客户端时传入中间件
client = await ClientFactory.connect(
    'https://agent.example.com',
    interceptors=[MyAuthInterceptor()],
)

五、完整示例:从零搭建一个 A2A Agent

把上面讲的串起来,看看搭建一个完整的 A2A Agent 需要写多少代码:

python 复制代码
from a2a.server.agent_execution import AgentExecutor, RequestContext
from a2a.server.events import EventQueue
from a2a.server.tasks import TaskUpdater, InMemoryTaskStore
from a2a.server.request_handlers import DefaultRequestHandler, JSONRPCHandler
from a2a.server.apps.jsonrpc import A2AFastAPIApplication
from a2a.types import (
    AgentCard, AgentCapabilities, AgentInterface, AgentSkill,
    TextPart,
)

# ========== 第一步:实现你的 Agent 逻辑 ==========
class EchoAgent(AgentExecutor):
    async def execute(self, context: RequestContext, event_queue: EventQueue):
        updater = TaskUpdater(
            event_queue=event_queue,
            task_id=context.task_id,
            context_id=context.context_id,
        )
        await updater.start_work()

        # 你的业务逻辑写在这里
        user_input = context.get_user_input()
        result = f"你说的是:{user_input}"

        await updater.add_artifact(parts=[TextPart(text=result)])
        await updater.complete()

    async def cancel(self, context: RequestContext, event_queue: EventQueue):
        updater = TaskUpdater(
            event_queue=event_queue,
            task_id=context.task_id,
            context_id=context.context_id,
        )
        await updater.cancel()

# ========== 第二步:定义 Agent Card(你的 Agent 的"名片")==========
card = AgentCard(
    name="Echo Agent",
    description="一个简单的回声 Agent,会把你说的话原样返回",
    version="1.0.0",
    supported_interfaces=[
        AgentInterface(
            url="http://localhost:8000",
            protocol_binding="JSONRPC",
            protocol_version="1.0",
        )
    ],
    capabilities=AgentCapabilities(streaming=True),
    default_input_modes=["text/plain"],
    default_output_modes=["text/plain"],
    skills=[
        AgentSkill(
            id="echo", name="Echo",
            description="回声服务", tags=["echo"],
        )
    ],
)

# ========== 第三步:组装并启动 ==========
handler = DefaultRequestHandler(
    agent_executor=EchoAgent(),
    task_store=InMemoryTaskStore(),
)
jsonrpc_handler = JSONRPCHandler(agent_card=card, request_handler=handler)
app = A2AFastAPIApplication(agent_card=card, http_handler=jsonrpc_handler)
fastapi_app = app.build()

# 启动命令:uvicorn main:fastapi_app --host 0.0.0.0 --port 8000

三步就搞定了:

  1. 写 Agent 逻辑(EchoAgent
  2. 填 Agent 名片(AgentCard
  3. 组装启动(把各个组件串起来)

其中真正需要动脑子的只有第一步------你的 Agent 要做什么。剩下的都是"填表"和"接线"。

六、SDK 的设计哲学:可插拔的组件

SDK 的一个核心设计原则是:几乎所有组件都可以替换。就像乐高积木,每个部件都有标准接口,你可以用默认的,也可以换成自己的。

组件 默认实现 你可以换成 什么时候需要换
Agent 逻辑 无(必须自己写) 任意实现 永远需要自己写
任务存储 内存存储 数据库存储、Redis 等 生产环境需要持久化时
通信方式 JSON-RPC REST、gRPC 根据性能需求或已有基础设施
ID 生成器 UUID 自定义格式 需要特殊 ID 格式时
推送通知 基础实现 自定义实现 需要特殊推送逻辑时

这种设计的好处是:

  • 入门简单:用默认组件,几行代码就能跑起来
  • 扩展灵活:需要定制时,只替换需要的部分,其他不动
  • 测试友好:可以用内存实现做单元测试,用数据库实现做集成测试

七、协议概念到 SDK 代码的对照表

如果你读过前两篇关于协议规范的文章,下面这张表可以帮你快速找到"协议里说的那个东西,在 SDK 里对应哪段代码":

协议里的概念 SDK 里的实现 说明
Task、Message、Part 等数据结构 types.py 中的 Pydantic 类 自动处理 camelCase 转换
Task 状态机 TaskState 枚举 + TaskUpdater TaskUpdater 自动防止非法状态转换
SendMessage 操作 客户端 client.send_message() / 服务端 handler.on_message_send() 流式和非流式统一接口
SSE 流式传输 EventQueue + FastAPI 的 EventSourceResponse Agent 往队列放事件,框架自动转成 SSE
Agent Card 发现 /.well-known/agent-card.json 路由自动注册 应用层 build() 时自动注册
多协议绑定 ClientFactory + 三种 Transport 自动协商,对开发者透明
推送通知 PushNotificationSender + PushNotificationConfigStore 可选功能,按需启用
任务持久化 TaskStore 接口 + 内存/数据库实现 协议没规定怎么存,SDK 提供了灵活方案
错误处理 utils/errors.py 中的异常类 9 种协议定义的错误类型都有对应

八、架构亮点总结

回顾整个 SDK 的设计,有几个特别值得学习的地方:

1. AgentExecutor 的极简接口

只有 executecancel 两个方法。所有协议复杂性都被封装在 SDK 内部,开发者的学习成本降到最低。这是"好的抽象"的典范------把复杂的东西藏起来,只暴露简单的接口。

2. EventQueue 的"分流"设计

tap() 方法让同一个任务的事件可以同时推送给多个客户端,不需要引入 Redis 或 Kafka 这样的外部消息队列。对于大多数场景来说,这个内置方案已经够用了。

3. Pydantic 的命名转换

一个基类配置就解决了 Python snake_case 和 JSON camelCase 之间的转换问题。开发者写代码时用 Python 风格,序列化时自动变成协议要求的格式,完全无感。

4. TaskUpdater 的安全保护

通过锁和状态标记,在运行时防止 Agent 在任务已经结束后继续发送事件。这种"防呆设计"能帮开发者在开发阶段就发现 bug,而不是等到生产环境才出问题。

5. 可选依赖的分层安装

核心包只有 5 个依赖,FastAPI、gRPC、数据库、OpenTelemetry 等都是可选的。这意味着如果你只需要客户端功能,安装包会非常轻量。

九、总结

a2a-python SDK 的核心思路可以用一句话概括:把协议的复杂性封装起来,让开发者只关注业务逻辑

对于想要构建 A2A Agent 的 Python 开发者来说:

  • 你只需要实现一个 AgentExecutor(写业务逻辑)
  • 填一个 AgentCard(描述你的 Agent 能做什么)
  • 用 SDK 提供的组件把它们串起来

协议处理、任务管理、事件分发、多协议支持、持久化------这些"脏活累活"全部由 SDK 代劳。


参考资料:

相关推荐
2401_851272992 小时前
实战:用Python分析某电商销售数据
jvm·数据库·python
IT_陈寒2 小时前
Redis缓存击穿:3个鲜为人知的防御策略,90%开发者都忽略了!
前端·人工智能·后端
vx_biyesheji00012 小时前
Python 全国城市租房洞察系统 Django框架 Requests爬虫 可视化 房子 房源 大数据 大模型 计算机毕业设计源码(建议收藏)✅
爬虫·python·机器学习·django·flask·课程设计·旅游
code 小楊2 小时前
yrb 1.5.0 正式发布:Python 极简国内下载加速与全景可视化终端体验!
开发语言·python
电商API&Tina2 小时前
【电商API接口】开发者一站式电商API接入说明
大数据·数据库·人工智能·云计算·json
2401_857918292 小时前
用Python和Twilio构建短信通知系统
jvm·数据库·python
樹JUMP2 小时前
使用Docker容器化你的Python应用
jvm·数据库·python
湘美书院--湘美谈教育2 小时前
湘美谈教育湘美书院网文研究:人工智能与微型小说选集
人工智能·深度学习·神经网络·机器学习·ai写作
uzong2 小时前
Harness Engineering 是什么?一场新的 AI 范式已经开始
人工智能·后端·架构