首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >ooderAgent:什么才算「真 Agent」

ooderAgent:什么才算「真 Agent」

原创
作者头像
OneCode
发布2026-09-12 12:45:32
发布2026-09-12 12:45:32
1370
举报
文章被收录于专栏:ooderAgentooderAgent

本文只谈两件事:概念的边界与实现的方式。所有代码均取自 ooderAgent 仓库当前实现。

一、先给「Agent」划一条不能退让的线

「Agent」在学术上是有精确定义的,而且条件相当苛刻。把四个权威来源放在一起,边界就清楚了。

来源

定义要点

AIMARussell & Norvig, 1995

“An agent is anything that can be viewed as perceiving its environment through sensors and acting upon that environment through actuators.”更关键的是理性智能体与PEAS规范:Performance measure(性能度量)、Environment(环境)、Actuators(执行器)、Sensors(感知器)——没有显式目标与性能度量的,只是“会运行的程序”,不是理性智能体。

Wooldridge & Jennings1995

“A computer system that is situated in some environment, and that is capable of autonomous action in this environment in order to meet its design objectives.”并给出四属性:autonomy(自主)/reactivity(反应)/pro-activeness(主动)/social ability(社会能力),且要求同时具备。

Ferber1995

智能体不孤立存在:它处在有其他智能体活动的环境中,并且属于某个组织。

OECD2026

AI Agent:具备一定自主性、感知环境并行动、必要时使用工具、适应变化;Agentic AI进一步要求:多智能体协调、任务分解与委派、跨时间持续运行、最少人类监督。

Anthropic

以控制权归属划界:Workflow 由代码预定义路径,Agent 由模型动态决定路径与工具调用;Agent 设计收敛为三要素——Environment / Tools / System prompt。

A2A Protocolv1.0.0

用Agent Card(身份、能力、技能、服务端点、鉴权)描述智能体;用Task 生命周期(submitted → working → input-required → completed/failed/canceled)管理协作;产出Artifact;通信要求不共享内部状态、记忆与工具。

把这些约束合起来,可以得出一组可判定的「真 Agent 六判据」:

判据

内容

学术出处

A1 身份

有稳定、可寻址、可授权的标识

A2A Agent Card;Wooldridge autonomy

A2 感知-行动闭环

能感知环境并施加动作改变环境

AIMA(sensors / actuators)

A3 自主与主动

不被逐条指令驱动;目标驱动时可自行发起

Wooldridge autonomy + pro-activeness

A4 社会能力

能与其它智能体(人或软件)按某种通信语言交互

Wooldridge social ability

A5 生命周期与持续存在

可独立启停/升级;跨时间持续运行

OECD 持续运行;A2A Task lifecycle

A6 组织归属

处在组织之中(多个智能体共享环境)

Ferber;OECD 协调 / 委派

一句话:Agent 不是“能聊天的模型”,而是“有身份、有目标、有环境、有同伴、有时间”的执行体。

二、ooderAgent 的「真 Agent」定义

ooderAgent 把上述判据落成五特征 + 一个差异化

编号

特征

判定问题

对应判据

R-A1

独立身份

有稳定agentId(可寻址、可授权)?

A1

R-A2

独立入口

有自己的入口(独立页 / 独立端点),不借他人入口?

A2

R-A3

独立生命周期

可独立启动/停机/升级,状态可观测?

A5

R-A4

独立场景范围

归属某个 scene 作为范围边界?

A6

R-A5

永久在线

常驻(含定时/事件驱动),而非“人一发起才存在”?

A5 / A3

差异化

它是场景的 owner

知识库、LLM 配置、技能、参与者模型、workflow全部继承自内置场景;Agent 唯一多出来的东西是“拥有这个场景,并对该场景的产出负责”

Ferber 组织维度 + Anthropic 三要素的组织化封装

两条反例判据同样是定义的一部分:

  • 只是被调用的工具/技能、没有自有场景范围与持续在线诉求 → 它是能力(skill),不是 Agent;
  • 只做通道与数据对接(如外部 ERP / IM 平台)→ 它是适配器,不是 Agent。

声明者规则(谁声明 Agent)

编号

规则

R-D1

由业务拆分后的阶段性任务声明(不是技术组件)

R-D2

必须继承内置场景特性(知识、LLM、技能、参与者模型、workflow)

R-D3

必须同时给出身份与对方地址(触达),否则不可被 A2A 寻址

R-D3 与 A2A 的 Agent Card 同构:身份 + 技能 + 端点,缺一不可。

三、A2A 底座:四层独立支撑

A2A 底座不寄生于任何一个业务模块,而是四层各司其职。

L1 传输层:只暴露端口,不暴露实现

传输对上层而言必须是一个端口(port)。消息队列、Topic 约定、断线重连都属于这一层,协议层只依赖它的契约:

代码语言:javascript
复制
/** L1 传输端口:所有方法不得抛异常,失败一律返回 false 或记日志,由上层决定降级 */
public interface MqttTransportPort {
    boolean connect(String brokerUrl, String clientId, String user, String pwd);
    boolean publish(String topic, String payload);
    boolean subscribe(String topicFilter);
    void addHandler(BiConsumer<String, String> handler);
    void disconnect();
}

契约里“不得抛异常”是设计的一部分:传输不可用时,协议栈应降级而不能雪崩。

L2 协议层:消息模型 + 寻址 + 执行端

消息模型保留协作所需的最小字段,并把“谁干”与“发给哪个节点”彻底分开:

代码语言:javascript
复制
public class A2AMessage {
    private String messageId;        // 幂等键
    private String conversationId;   // 归属会话
    private String sceneGroupId;     // 组播分组
    private String fromAgentId;
    private String toAgentId;        // 执行体:谁干
    private String targetNodeId;     // 目标节点:发给谁(与 toAgentId 语义分离)
    private A2AMessageType messageType;  // TASK_REQUEST / TASK_RESPONSE / DATA_REQUEST ...
    private Object payload;
    private Map<String, Object> headers; // headers.requestId 用于请求-响应关联
}

寻址由“节点收件箱”与“场景组播”两套 Topic 承担:

代码语言:javascript
复制
// 定向:只投递到目标节点的收件箱
mqttTransport.subscribe(MqttEventTransport.targetedTopic(localNodeId));   // ooder/node/{nodeId}/inbox
// 组播:按场景组广播
mqttTransport.publish("ooder/event/A2A/" + group, wrapPayload(message));   // ooder/event/A2A/{group}

定向投递前必须解析出节点,解析不到就不发布并告警,语义上等于“绝不静默丢弃”:

代码语言:javascript
复制
String targetNodeId = resolveTargetNodeId(message);   // 显式 targetNodeId → 目录 nodeId
if (targetNodeId == null || targetNodeId.isEmpty()) {
    log.warn("[A2A-MQTT] 定向投递跳过:无法解析目标节点(agent={})", message.getToAgentId());
    return false;
}

执行端注册是“感知-行动闭环”的落点:按目录为每个执行体注册消费者;未注册的执行体在消息到达时按目录惰性注册。

代码语言:javascript
复制
@Override
public void registerHandler(String agentId, A2AMessageHandler handler) {
    if (agentId == null || agentId.isEmpty() || handler == null) return;
    handlers.put(agentId, handler);
    if (routeAgent != null) {
        try { routeAgent.registerAgent(agentId, null, handler); }
        catch (Exception e) { log.warn("[A2A] 路由登记失败(handler 已注册,非致命)", e); }
    }
}

装配时序同样属于协议设计:目录驱动的批量注册必须在所有启动 Runner 之后再做一次,否则名册尚未恢复。

代码语言:javascript
复制
@Bean
public ApplicationListener<ApplicationReadyEvent> a2aReadyRefresh(
        ObjectProvider<A2AProtocolService> ps, ObjectProvider<AgentDirectoryPort> dir,
        A2AMessageRouter router) {
    return evt -> {
        A2AProtocolService svc = ps.getIfAvailable();
        if (svc != null) svc.refreshHandlersFromDirectory();          // 注册执行端
        AgentDirectoryPort d = dir.getIfAvailable();
        if (d != null) d.listAgents().forEach(router::registerAgent); // 填充 capability/role 索引
    };
}

L3 执行体目录层:Agent Card 的最小实现

目录回答“有哪些执行体、谁在线、能力与角色是什么、在哪个节点”,字段集与 A2A Agent Card 同构:

代码语言:javascript
复制
public class AgentDescriptor {
    private String agentId;      // 身份(Agent Card: identity)
    private String name;
    private String role;         // 角色路由
    private String sceneGroupId; // 场景范围(组织归属)
    private String nodeId;       // 触达地址(Agent Card: endpoint 的最小形态)
    private boolean online;      // 生命周期 / 在线
    private List<String> capabilities;  // Agent Card: skills / capabilities
}

协议层只依赖端口,不依赖任何具体目录实现:

代码语言:javascript
复制
public interface AgentDirectoryPort {
    List<AgentDescriptor> listAgents();
    AgentDescriptor find(String agentId);
    boolean isOnline(String agentId);
}

L4 接入层:把能力变成可操作的面

接入层提供执行体的注册、列举、注销与派发诊断,使“身份 + 触达”可被真实配置与核验:

代码语言:javascript
复制
@PostMapping("/agents")               // 注册:agentId + 场景 + 角色 + 能力 + nodeId
@GetMapping("/agents")                // 列举:同时返回“协议层视角”(目录端口)与场景目录计数
@DeleteMapping("/agents/{agentId}")   // 注销:目录 + 协议栈 handler + 名册 三者同步
@PostMapping("/dispatch")             // 派发:toAgentId / targetNodeId / messageType / payload

点名注销时三者同步,语义才闭合:

代码语言:javascript
复制
acm.unregisterAgent(agentId);
a2aProtocolService.unregisterHandler(agentId);  // 停止消费
rosterStore.remove(agentId);                    // 移出持久化名册

四、A2A 的三条触发通道与四类语义

A2A 交互由三种方式触发,语义收敛为四类。

通道

入口

触发者

①LLM 工具

执行体的函数调用工具面

模型自主判断

②交互面板

HUMAN 节点操作栏

场景内参与者(人)

③预定义埋线

流程定义(operations/timeoutPolicy/a2aRules/ 事件订阅)

设计期埋点,运行期自动

四类语义:委派/指定中断/等待结束转交请求-响应回数

②通道由统一的 HumanOperation 枚举承载,委派类操作需要 DESIGNER 显式声明,形成“可委托范围”的硬边界:

代码语言:javascript
复制
public enum HumanOperation {
    DELEGATE_H2H("DELEGATE_H2H", "委托他人", true, "ri-user-shared-line"),
    DELEGATE_H2A("DELEGATE_H2A", "委托Agent", true, "ri-robot-line"),
    DELEGATE_H2T("DELEGATE_H2T", "委托Task",  true, "ri-task-line"),
    INTERVENE_EXCEPTION("INTERVENE_EXCEPTION", "例外介入", false, "ri-error-warning-line");
    // 第三个参数 = 是否要求 DESIGNER 定义(不在 operations 白名单内即拒绝执行)
}

提交统一走一个端点,响应把“派发结果”作为一等数据返回,使“人把活交给 Agent”成为可观测事件:

代码语言:javascript
复制
// POST /api/studio/chat/human-op
// {operation:"DELEGATE_H2A", activityId, processInstId, delegateContext:{targetId}}
{
  "h2aDispatch": {
    "dispatched": true,
    "agentId": "fin.voucher",
    "executor": "UnifiedCollaborationService.createCollaborationTask(AGENT)",
    "todoId": "todo-...-58c5",
    "remoteTaskId": "A2A-561f476bf5a8409b"
  }
}

③通道的“等待/升级”由超时策略承担,红线节点超时不放行,而是升级人工:

代码语言:javascript
复制
switch (effective) {
    case ESCALATE_HUMAN:                       // 不放行 + 发布升级人工信号
        log.warn("[BuildConfirmManager] 用户交互超时({}s),升级人工(不放行)", timeoutSeconds);
        signalEscalation(entry, "confirm_timeout");
        return false;
    case AUTO_CONFIRM: return true;            // 显式列举,新增枚举值不会被静默当作放行
    default:           return true;
}

五、融合交互面板:一个面板承载四象限

协作的两条轴是发起方执行方,三条触发通道回答的是谁触发——两者正交,因此可以用一个面板承载全部象限。

象限

发起 → 执行

是否 A2A

面板形态

P2P

人 → 人

委托弹窗(选人)+ 委托回执(im_delegation)

P2A

人 → Agent

是(②通道特例)

执行体选择器(人 / Agent 分栏)+ 派发回执(todoId/remoteTaskId)

A2P

Agent → 人

否(执行体内部确认)

确认卡(红线原因 + 超时策略说明 + 决策留痕)

A2A

Agent → Agent

消息流(from → to、类型、状态、失败原因)

面板的三条实现契约:

1)操作按象限分组渲染——面板只订阅节点声明的 operations 白名单,再按“人际 / 人-Agent / Agent-人 / Agent-Agent”归组,避免把不同责任面的按钮平铺在同一行:

代码语言:javascript
复制
// 面板依据流程定义声明的操作白名单渲染,未声明即不出现(责任边界由 DESIGNER 决定)
const opOrder = ['DELEGATE_H2H', 'DELEGATE_H2A', 'DELEGATE_H2T'];
const visible = declaredOperations.filter(
  op => opOrder.includes(op) || baseOps.includes(op)
);

2)执行体选择器与目录同源——“选谁”直接读执行体目录,人 / Agent 只是目录条目的两种类型,不需要第二套数据源:

代码语言:javascript
复制
// GET /api/studio/a2a/agents
{
  "viaDirectoryPort": [
    { "agentId": "fin.voucher", "name": "凭证导入 Agent", "role": "voucher",
      "sceneGroupId": "voucher-fill-scene", "nodeId": "studio-8104",
      "online": true, "capabilities": ["voucher.import", "voucher.fill"] }
  ],
  "viaDirectoryPortCount": 1,
  "sceneDirectoryCount": 1
}

3)回执必须结构化——派发不是“提交即结束”,h2aDispatch / todoId / remoteTaskId / 失败原因都要回流到面板,使面板能显示“谁在执行、执行到哪、为什么失败”。

六、可核验的落地清单

能力

入口 / 观测点

注册执行体(身份 + 触达)

POST /api/studio/a2a/agents,日志[A2A-OPS] Agent 已注册

目录双视角核验

GET /api/studio/a2a/agents(viaDirectoryPort与sceneDirectoryCount)

启动期恢复名册

日志[A2A-Roster] 启动期已从持久化名单恢复 N / M 个执行体

执行端就绪

日志[A2A] CoordinatorAgent 已注册为 TASK_REQUEST 消费者/A2A handler registered

定向派发与寻址

POST /api/studio/a2a/dispatch;订阅ooder/node/{nodeId}/inbox

本地执行端消费

日志[A2A-Local] 执行体消费任务: agentId=...

不可达不静默

日志[A2A-MQTT] 定向投递跳过:无法解析目标节点

自环不重复执行

自环消息不进入本地分发

人 → Agent 委派

POST /api/studio/chat/human-op(DELEGATE_H2A),响应h2aDispatch

超时升级人工

日志红线节点超时保护生效/升级人工(不放行)


结语

真 Agent = 有身份 + 有目标 + 有环境 + 有同伴 + 有时间。

ooderAgent 的落点是把它拆成可实现的四件事:A2A 底座给出独立四层(传输、协议、目录、接入),让 Agent 拥有可寻址的身份与触达方式;执行体目录与 Agent Card 同构,让“能力可被发现”;三条触发通道让 LLM、人、预定义埋线都能发起协作;融合交互面板把四象限收敛为一个操作面,让“委派、指定、等待、转交”在同一处完成并被记录。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、先给「Agent」划一条不能退让的线
  • 二、ooderAgent 的「真 Agent」定义
  • 声明者规则(谁声明 Agent)
  • 三、A2A 底座:四层独立支撑
  • L1 传输层:只暴露端口,不暴露实现
  • L2 协议层:消息模型 + 寻址 + 执行端
  • L3 执行体目录层:Agent Card 的最小实现
  • L4 接入层:把能力变成可操作的面
  • 四、A2A 的三条触发通道与四类语义
  • 五、融合交互面板:一个面板承载四象限
  • 六、可核验的落地清单
  • 结语
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档