[A2A协议与实现-02]Agent发现机制和两种响应方式

[A2A协议与实现-02]Agent发现机制和两种响应方式 要使用A2A协议进行协作Agent首先需要相互发现并了解彼此的功能。在A2A协议中当服务端接收到来自客户端针对Agent的调用请求时它可以以两种基本方式进行响应一是响应承载结果的消息二是响应异步执行的任务。Agent的发现机制和响应方式是这篇文章关注的两个主题。1. Agent发现机制A2A通过AgentCard对Agent的自我描述进行标准化。。AgentCard定义了Agent提供的功能。客户端Agent可以通过多种策略发现这些AgentCard。客户Agent使用AgentCard来确定目标Agent的资质、构建请求结构并确保安全沟通它可以采用如下的几种策略来发现AgentCard。1.1 知名URIWell-Known URI在这种策略下A2A服务器通过在其域内使用标准化的、众所周知的URI托管AgentCard使其易于被发现。标准路径为https://{agent-server-domain}/.well-known/agent-card.json遵循RFC 8615的原则。具体流程如下客户端Agent知道或通过编程方式发现潜在的A2A服务器的域名例如smart-thermostat.example.com客户端向https://smart-thermostat.example.com/.well-known/agent-card.json发送HTTP GET请求如果AgentCard存在且可访问服务器将以JSON响应的形式返回该AgentCard这种发现策略的优点是易于实施符合标准且有助于自动发现。1.2 精选注册表/目录服务Curated Registries/Catalog-Based Discovery这种方法常用于企业环境或公共市场其中AgentCard通常由中央注册机构管理。该注册机构充当中央存储库允许客户根据技能或标签等标准查询和发现经纪人。在这种策略中注册中心维护着一个AgentCard集合。客户通过查询该注册中心根据各种标准例如提供的技能、标签、提供商名称、能力查找Agent具体流程如下A2A服务器将其AgentCard发布到注册表;客户端Agent通过注册表的API进行查询并按特定技能等条件进行搜索注册表返回匹配的AgentCard或推荐信息这种策略的优点是集中式管理和治理基于能力的发现例如按技能支持访问控制和信任框架适用于私有和公共市场如果采用这种Agent发现策略需要部署和维护注册表服务目前A2A规范尚未对这种策略提供标准化的API定义。1.3 直接配置/私有发现 Direct Configuration/Private Discovery这种方法适用于紧密耦合的系统、私有Agent或开发用途其中客户端直接配置AgentCard信息或 URL。客户端应用程序利用硬编码的详细信息、配置文件、环境变量或专有API进行发现。这种方法简单直接适用于在已知的静态关系中建立联系但需要考虑如下的因素对于动态发现场景而言这种方式不够灵活AgentCard信息的更改需要重新配置客户端基于专有 API 的发现机制也缺乏标准化2. 两种响应方式在A2A协议中当服务端接收到来自客户端针对Agent的调用请求时它可以以两种基本方式进行响应响应承载结果的消息这种类型的响应通常用于无需进一步状态管理即可立即完成的、独立的交互响应异步执行的任务如果响应是一个任务Agent将按照定义的生命周期处理该任务根据需要传递进度信息并要求输入直到任务达到中断状态例如需要输入、需要身份验证或终止状态completed,canceled,rejected和failed2.1 多个消息/任务的关联context_id是一个关键标识符它在逻辑上将多个Task和Message对象分组从而确保交互的连续性当客户端首次发送消息时Agent会响应一个新的context_id。 如果发起了一个任务该任务还会有一个task_id客户端可以发送后续消息并包含相同的context_id以表明它们正在同一上下文中继续之前的交互客户端还可以选择将task_id附加到后续消息中以表明该消息将继续执行该特定任务context_id支持跨多个可能并发的任务进行协作以实现共同目标或共享上下文会话。在内部A2A Agent使用context_id来管理其内部对话状态或其LLM上下文。可以将context_id视为一个会话ID, 相当于LangChain中的thread_id。2.2 返回Message还是Task选择以Message还是Task进行响应取决于交互的性质和Agent的能力。Message适用于不需要长时间处理或复杂状态管理的事务性交互而Task适用于需要持续跟踪、状态管理或用户输入的更复杂的交互。具体实现可以采用如下几种模式Message-Only始终以消息对象进行响应。它们通常不管理复杂的状态或长时间运行的执行并使用context_id将消息关联起来。这些Agent可以直接封装LLM调用和简单的工具;Task-Only始终以Task对象作为响应即使是回复也一样这些响应随后会被建模为已完成的任务。任务创建后Agent只会返回Task对象来响应发送的消息。任务完成后将无法再发送任何消息。这种方法避免了在Task和Message之间进行选择即使是简单的交互也会创建已完成的任务对象;Mixed: 生成消息对象和任务对象。这类Agent使用消息来协商Agent的功能和任务范围然后发送一个任务对象来跟踪执行情况并管理诸如需要输入或错误处理等状态。任务创建后Agent只会响应发送的消息而返回任务对象任务完成后将无法再发送任何消息。混合Agent使用消息来协商任务范围然后生成一个任务来跟踪其执行情况;2.3 Task的定义我们已经介绍A2A规范针对Message的定义接下来我们看看如下这个定义Task的Protobuf消息类型。 Task是A2A协议中的最核心逻辑单元。它不仅仅是一个简单的指令而是一个具有生命周期的会话容器。在Multi-Agent协作中一个任务可能涉及多次往返对话、状态切换以及最终产出。Task将这些信息全部整合在了一起message Task { string id 1 [(google.api.field_behavior) REQUIRED]; string context_id 2; TaskStatus status 3 [(google.api.field_behavior) REQUIRED]; repeated Artifact artifacts 4; repeated Message history 5; google.protobuf.Struct metadata 6; }消息成员说明如下id每个Task的唯一标识符通常由创建它的Agent生成。它对于跟踪、引用和管理任务非常重要context_id与Task相关联的上下文标识符。这允许多个任务共享相同的上下文信息促进协作和状态管理statusTask的当前状态定义了任务的生命周期阶段pending,in_progress,completed,canceled,rejected,failed。状态的变化可以触发不同的行为或通知artifacts与Task相关的产出物列表。这些Artifact代表了任务执行过程中生成的结果或中间成果可以是文本、图像、结构化数据等多种形式history与Task相关的消息历史记录。这些消息记录了任务执行过程中所有的交互包括客户端和Agent之间的通信。这对于调试、审计和理解任务执行过程非常有用metadata一个结构化的键值对集合用于携带与这个Task相关的上下文信息。这些信息可以用于分类、搜索、调试等目的中文将Status和State都翻译成状态了所以对于如下两个分别命名为TaskStatus和TaskState的消息类型我们不能简单地称它们为任务状态。这两个消息类型定义了A2A协议中任务的生命周期管理机制。它不仅记录了任务进行到哪一步还提供了处理异常和交互的标准化流程。message TaskStatus { TaskState state 1 [(google.api.field_behavior) REQUIRED]; Message message 2; google.protobuf.Timestamp timestamp 3; } enum TaskState { TASK_STATE_UNSPECIFIED 0; TASK_STATE_SUBMITTED 1; TASK_STATE_WORKING 2; TASK_STATE_COMPLETED 3; TASK_STATE_FAILED 4; TASK_STATE_CANCELED 5; TASK_STATE_INPUT_REQUIRED 6; TASK_STATE_REJECTED 7; TASK_STATE_AUTH_REQUIRED 8; }TaskStatus状态容器这是对任务某一时刻情况的快照除了具有一个TaskState类型的state字段外还关联中一个Message。当TaskState为FAILED时这里存放错误详情当TaskState为INPUT_REQUIRED时这里存放Agent向用户提出的问题。TaskState是一个枚举表明任务当前所处的生命周期阶段。