首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >北向协议 · 5W 深度解构 智能体平台的"控制面契约":规范协议在企业级落地中的核心作用

北向协议 · 5W 深度解构 智能体平台的"控制面契约":规范协议在企业级落地中的核心作用

原创
作者头像
OneCode
发布于 2026-10-11 08:11:50
发布于 2026-10-11 08:11:50
1050
举报
文章被收录于专栏:ooderAgentooderAgent

0. 引言:协议是"被约束的通信"

通信学中有一个极简而有力的模型——拉斯韦尔(Harold Lasswell)的 5W:Who(谁)→ Says What(说了什么)→ In Which Channel(经何渠道)→ To Whom(对谁说)→ With What Effect(取得何效)。它揭示了一个事实:任何一次可靠的通信,都必须同时约束"主体、内容、通道、对象、效果"五件事;少约束任何一件,通信就会在工程上退化为"碰运气"。

协议,本质上是人类为"机器之间的通信"写下的这份约束。它不是一张接口清单——接口清单只回答"有哪些地址";协议要回答的是谁在什么时机、以什么结构、经哪条通道、把什么交给谁,并如何证明它被正确地交付了。

本文以 ooderAgent 的技能中枢(skillCenter)与其节点之间的 北向协议(Northbound Protocol) 为对象,从 5W 五个维度剖析其定义、架构、原理与边界,并重点论证:在企业级智能体平台中,一份被规范化、强类型化、可演进的北向协议,是"目录权威、统一寻址、生命周期治理、安全统一"得以成立的前提。

1. 前置:术语与概念基线

前置术语对齐边界约定

1.1 核心术语

术语

定义

北向 Northbound

节点 → 中心的控制面(注册/激活/登录/心跳/上报/查询/解析),走 HTTP,前缀 /api/sc/**

南向 Southbound

中心 → 节点的数据面(任务下发/事件投递),走 MQTT

三分层

按调用方划分的三组端点:nodeClient(写)/appClient(读)/adminClient(运维)

四角色

声明者 Declarer/执行者 Executor/提供者 Provider/解析者 Resolver

nodeId

节点主键,命名 <sysId>-<port>(如 studio-8104)

accountId / agentAccount

主体标识:节点级 accountId = nodeId;agent 级 agentAccount = agentId(拟人化主键)

sessionToken

登录签发的会话凭据(区别于静态管理令牌)

resolve

寻址解析:只回答"这次投给谁",不投递、不执行

bootstrap

自举参数(心跳/上报路径等),activate 与 clone 共用同一构造

目录层 / 驻留层

目录层 = 逻辑技能(COUNT(DISTINCT SKILL_ID));驻留层 = 可执行副本(COUNT(*))

墓碑 tombstone

软删标记,用于增量同步下发"删除事件"

热 / 冷数据

承载节点在线(经 ENDPOINT 检索)/离线(按登记路径静态直读)

fail-closed

校验不通过即拒绝的安全默认

1.2 三条不可逾越的边界

边界

规定

方向

北向不承载业务数据;南向不做寻址决策(寻址由中心 resolve 定,南向只按结论投递)

语义

/api/sc/** 是"节点向中心报到";/api/agent/** 是"节点对外提供服务",两者方向相反

权威

目录/地址/节点/会话以中心为准;agent 名册以 Studio roster 为单主,中心仅存只读镜像

2. What:北向协议是什么

What · 是什么 控制面契约 HTTP ⊥ MQTT

2.1 定义

北向协议 = 节点与技能中心之间的"控制面契约"。它管"台账、目录、寻址、鉴权",不管业务数据的搬运。

它由三部分构成:通道约定(走 HTTP 控制面,与 MQTT 数据面正交)、报文规范(端点、字段、信封、错误码)、序列化契约(类型/时间/可空性/长度/版本)。

图 1 南北向通道与三分层:控制面(HTTP)与数据面(MQTT)正交

2.2 三分层:按"调用方"而非"资源"划分

层

路径前缀

调用方

职责

鉴权

nodeClient(写)

/api/sc/node/**

各节点

register / activate / login / heartbeat / skills / kb / scene / roster / summary

register 免;其余需登录后的 sessionToken

appClient(读)

/api/sc/app/**

各服务消费方

查询节点/技能/知识/名册、resolve、clone

需 token,并经受信端口校验

adminClient(运维)

/api/sc/admin/**

管理统计台

统计与运维视图

X-Cluster-Admin-Token

SDK 兼容面

/api/v1/**

历史 SDK 客户端

技能市场式查询(不纳入三分层)

按 HTTP 方法分流

设计原则:三类调用方的信任级别、生命周期、变更节奏完全不同——写端跟随节点版本,读端跟随消费方版本,运维端跟随管理台。按调用方分层,使得任一方的演进都被局部化,不会牵动全局。

2.3 协议主线:五步

代码语言:javascript
复制
register  →  activate  →  login  →  heartbeat(周期)  →  report(技能/知识/场景/名册/摘要)
  • register:报到,返回"身份的引用" accountRef(不下发凭据);
  • activate:凭激活口令换取"正式身份" agentAccount(含 credential);
  • login:以 account 为主体登录,换 sessionToken;
  • heartbeat:周期存活信号(携带负载);
  • report:技能、知识、场景、名册、摘要的持续上报。

2.4 四角色:目录权威的职责切分

北向协议不执行任何技能,只回答四个问题:

角色

回答

权威载体

协议落点

声明者 Declarer

"定义的定义"是什么

代码(C1)/ 声明式(C2)

POST /node/skills/apply

执行者 Executor

谁能执行

进程内驻留代码

不上行(中心只存驻留摘要)

提供者 Provider

谁现在可达

节点上报的技能行

PUT /node/{id}/skills

解析者 Resolver

这次投给谁

中心

POST /app/resolve

2.5 序列化契约:协议的"地基"

若"说了什么"没有统一结构,字段表即为纸糊。北向协议将这一层单独立为序列化契约——一份唯一映射表:

逻辑类型

JSON

Java(DTO)

MySQL

字符串 / 枚举

string

String

VARCHAR(n)

长整型(时间戳 / REV)

number(int64)

Long

BIGINT

整型(计数 / 端口)

number(int32)

Integer

INTEGER

浮点(负载)

number(double)

Double

DOUBLE

布尔

boolean

Boolean

INTEGER(0/1)

对象

object

嵌套 DTO

*_JSON(TEXT)

数组

array

List<X>

*_JSON / 关联表

四条纪律:时间一律 epoch millis 且以 At 结尾;请求侧"缺失 ≡ null ≡ 不修改"(显式清空用 [] / "");长度上限与 DDL 逐字对齐、越界即拒;X-SC-Protocol 版本头协商。

3. 背景与技术架构:SkillCenter

背景 · 架构

四层 + 横切

部署结构

3.1 定位与职责

技能中枢(skillCenter) 是一个独立目录服务:它不执行任何技能,而是作为全平台技能事实的唯一权威,回答四个问题——

  1. 全平台有哪些技能?(目录权威)
  2. 谁能执行某个技能?(提供者集合)
  3. 某个执行体现在在哪?(名册镜像)
  4. 这一次调用该投给谁?(寻址解析)

3.2 服务端分层架构

服务端遵循 web → service → engine → repository 四层,横切关注点(序列化、鉴权、持久化)下沉为独立组件:

层

职责

代表组件

web

端点、边界校验、DTO 收发

ScNodeController(写)、ScNodeSkillController、ScReportController、ScAppController(读)、ScAdminController(运维)、SkillCatalogV1Controller(SDK 面)

service

用例编排 + 事务边界

SkillCenterService

engine

领域集成:注册/上报/克隆编排、VFS 接缝

NodeRegistrationEngine、ReportEngine、CloneEngine、VfsBridge / UplinkVfsBridge

repository

持久化与幂等 DDL

SkillCenterRepository、SchemaInitializer

横切·安全

分层鉴权、版本协商

ScTokenAuthFilter、JdsClusterAuthPort(JdsAuthAdapter / SharedTokenJdsAuthPort)、ProtocolVersionFilter

横切·序列化

fastjson2 统一编解码

FastJson2Config、ProtocolJson

图 2 SkillCenter 服务端分层架构(web → service → engine → repository + 横切)

3.3 数据模型(SC_* 表族)

中心以 MySQL 库 ooder_skillcenter 承载,表族按职责分组:

组

表

承载

节点与会话

SC_NODE · SC_SESSION

节点台账/负载、登录会话

技能

SC_SKILL · SC_SKILL_CAPABILITY

技能驻留摘要、能力面

名册镜像

SC_AGENT

Studio roster 的只读镜像(含 LLM 运行面)

知识三要素

SC_KB · SC_KB_BINDING · SC_KB_ADDRESS

目录、绑定关系、地址登记

场景与路由

SC_SCENE · SC_SCENE_PARTICIPANT · SC_SCENE_CAP_BINDING · SC_SCENE_KB_BINDING · SC_NODE_SCENE · SC_NODE_ROUTE

场景实体、参与方、能力/知识绑定、节点声明

摘要与配置

SC_SUMMARY · SC_CONFIG

上下文/任务摘要、实例级配置

两种口径:目录层(COUNT(DISTINCT SKILL_ID))回答"有哪些技能";驻留层(COUNT(*))等于"技能数 × 在线宿主数"。协议必须写明"每个统计数在回答哪个问题"。

3.4 客户端与消费方

侧

组件

职责

共享契约模块

ooder-cluster-client(net.ooder.cluster.dto)

协议契约单一真源:全部 DTO + ProtocolJson + SkillCenterNodeReporter

节点接入

SkillCenterNodeReporter

register / activate / login / heartbeat(全平台唯一实现)

中心查询

SkillCenterHttpClient

读端消费(skills / resolve / roster / clone …)

上行器

SkillCenterUplink / SkillCenterKbUplink / SkillCenterSceneUplink / SkillCenterSummaryUplink

技能/知识/场景/摘要上行

名册镜像

SkillCenterRosterMirror

Studio roster → 中心

3.5 部署结构

维度

内容

服务

skill-center,端口 8125,独立 Spring Boot 进程

存储

MySQL ooder_skillcenter(目录/地址/节点/会话);VFS 承载配置文件形态的原始文件

实体

LuceneServer 承载索引与文档(唯一实体),中心不存内容

节点侧

本地 SQLite 承载运行态,经上报通道入库中心

配置注入

systemd 单元 + drop-in(skill-center.service.d/{db,auth}.conf)注入 DB 连接与鉴权令牌

南北向通道

北向 HTTP(控制面);南向 MQTT(数据面,ooder/node/{nodeId}/inbox 定向、ooder/event/A2A/{sceneGroupId} 组播)

图 3 部署结构:控制面(HTTP)/ 数据面(MQTT)与三类存储的职责分工

4. Why:规范协议在企业级落地中的核心作用

Why · 核心作用

契约优先

承重结构

4.1 企业级落地的结构性难题

把 AI 推向生产的企业会先后撞上三堵墙:模型墙(底座半年一代,调用写死各处)、编排墙(一次请求经过哪些环节说不清)、技能墙(工具/能力/场景散落在不同宿主进程:有哪些技能?谁能执行?这次投给谁?下线了如何保证不再被调到?)。

前两堵墙归平台工程(Platform Engineering)与智能体运行时(Agent Runtime)解决;第三堵墙——技能的统一目录、寻址与治理——正是北向协议要回答的问题域。

4.2 无契约时的"失效模式"分类

当"说了什么"缺乏结构约束时,系统不会报错,而是以若干可分类的静默失效退化。这是"接口"与"协议"的分水岭:

失效模式

机理

后果

类型歧义

字段无统一类型映射

同义字段类型漂移(如端口 Integer vs String)

静默 null

以 Map 手写读写、字段名靠字符串

拼写错误不编译报错、运行时静默丢失

非原子写

多语句写未事务化

中途失败留"半覆盖"

并发丢更新

读-改-写非原子

版本号(REV)回退

值域失控

枚举未校验

任意字符串入库

静默空包

非法入参不报错

调用方误判"无数据"

边界失守

无长度校验

依赖 DB 截断/报错

语义缺失

删除无墓碑

无法表达"取消登记"

上述失效的共同点:它们都不"炸",只"沉默"。这正是 5W 中"Says What"失守后的典型症状。

4.3 标准协议必须回答的三个问题

#

问题

内容

P-1

序列化契约

统一数据类型、时间格式、可空性语义、长度上限、版本协商

P-2

报文规范集中

端点、信封、错误码集中为一张总表,杜绝"未纳管端点"

P-3

报文内容完整

每个报文字段集必须足以回答其对应的问题("有哪些技能"要答得完整)

规范协议即以这三问为纲:把"序列化契约"立为地基,把"报文规范"集中成总表,再以 4 张附录(枚举 / 必填 / 长度 / 错误码)收口。

4.4 核心作用:协议是企业级能力的"承重结构"

企业级能力

协议提供的支撑

目录权威

统一报文与去重口径,使"有哪些技能"可被确定地回答(目录层 vs 驻留层)

统一寻址

resolve 以 ONLINE/ACTIVE 为准,寻址决策与数据投递分离,避免路由散落

生命周期治理

注册→激活→登录→心跳→上报→注销的状态机 + 墓碑 + 增量游标

可替换 / 可演进

契约不变则底座/骨架可换;版本协商 + 双写期让"变化"成为契约的一部分

安全统一

三层客户端令牌策略统一收口(fail-closed),消除"哪条路径没校验"的黑洞

边界清晰

控制面/数据面正交,中心只登记目录与地址,实体归 LuceneServer,取数直达

4.5 理论依据

理论支点

出处

在协议中的投影

契约优先(Contract-First)

Design by Contract(Meyer, 1986)

先定协议与 DTO,再由双端实现反向驱动

控制面 / 数据面分离

SDN / Kubernetes / Service Mesh

北向(台账/寻址)与南向(投递/执行)正交

信息论

Shannon, 1948

版本协商、UTF-8 强制、错误码表 = 对抗"熵增"的冗余

幂等与 HTTP 语义

RFC 7231

register 按主键 upsert;heartbeat 幂等;DELETE 幂等且连带清理

制品供应链治理

SemVer / 制品库 / OpenSSF SLSA

版本分离、墓碑、增量游标

依赖倒置(DIP)

SOLID

中心不引重依赖(受信端口化、VFS 接缝),底座可替换

5. Who:谁参与、谁权威

Who · 谁

四角色

权威载体

5.1 参与方

参与方

位置

说什么

权威

节点 / 宿主

各进程

register / activate / login / heartbeat / 上报

自身运行态

技能中枢 skillCenter

:8125

下发身份、bootstrap、目录、寻址结论

✅ 目录 / 地址 / 节点 / 会话

Studio

桌面宿主

名册上行

✅ agent 名册(中心只读镜像)

消费方

各服务

查询 / resolve

—

管理台

运维面

统计 / 诊断

只读消费

5.2 单一实现原则

协议的可治理性建立在"同一职责只有一份实现"之上。全平台节点接入客户端 SkillCenterNodeReporter 收敛为唯一实现(置于轻量契约模块 ooder-cluster-client);集群接入实现同样收敛为单一 ClusterRegistrationClient,各方按配置委派而非各自实现。

原则:若允许多份实现并行演化,协议即名存实亡。收敛,是实现层对协议的履约。

5.3 权威载体与命名纪律

实体

权威载体

说明

Node

中心 SC_NODE

节点台账 + 负载

agentAccount

Studio roster(中心 SC_AGENT 只读镜像)

单主:Studio 说、中心记

Skill

中心 SC_SKILL

全量覆盖 或 行级 upsert

Session

中心 SC_SESSION

有效 + 未过期 + ACTIVE

KnowledgeBase

中心 SC_KB / SC_KB_ADDRESS

目录与地址,不是内容

命名纪律:nodeId = <sysId>-<port>(禁用 hostname);节点级 accountId = nodeId,agent 级 agentAccount = agentId,二者不同层。

6. When:何时发生、何时演进

When · 何时

生命周期

版本协商

6.1 节点接入生命周期

图 4 节点接入生命周期:register → activate → login → heartbeat → report → offline

6.2 状态机与"心跳语义"硬规则

代码语言:javascript
复制
          register           activate(校验口令)      heartbeat(存活)     TTL 超时
(无) ──────────▶ REGISTERED ──────────▶ ACTIVE ──────────▶ (保持 ACTIVE)
                     └── heartbeat ────┴──────────────────┴──▶ ONLINE ──▶ OFFLINE

硬规则:心跳是存活信号、不是状态断言——只允许 REGISTERED/OFFLINE → ONLINE,不得把 ACTIVE 降级;寻址 resolve 只接受 ONLINE 与 ACTIVE。

同一动作(心跳)在不同状态下含义不同:协议必须显式区分"存活"与"状态变更"。

6.3 版本协商与废弃策略

  • 请求头 X-SC-Protocol 必带、响应回显;不匹配 ⇒ 400 PROTOCOL_MISMATCH 并回 supported;
  • 字段废弃须经 ≥1 个大版本的双写期,废弃字段显式标注 @Deprecated;
  • 时间维度同理:未发生的时间字段"省略"而非 0(如未激活则无 activatedAt)。

6.4 鉴权开启的时序约束

分层鉴权有一条不可并行的前置:先完成客户端收敛,再开启鉴权。否则旧实现会"双重失效"(既打退役路径、又无 token)。动作的次序本身,就是协议的一部分。

↑ 回到目录

7. Where:协议边界与数据归属

Where · 边界

单前缀

取数直达

7.1 分层边界(单前缀)

归处

前缀

已退役旧路径

写

/api/sc/node/**

/api/sc/nodes/**、/api/sc/skills/**、/api/sc/roster/sync

读

/api/sc/app/**

/api/sc/kb、/api/sc/scene、/api/sc/clone

运维

/api/sc/admin/**

—

规范前缀是单前缀、不保留别名——"过渡别名"会让协议永远无法收敛。

7.2 上下行的不对称设计

上行报地址,下行克内容;两侧同源(同一 SC_* 表),不产生第二套账。

  • 上行 Report(节点 → 中心):报摘要 + 地址(不含内容);
  • 下行 Clone(中心 → 节点):克配置/数据(按 nodeId 全量事实 / 按 peerType 类型摘取)。

7.3 知识三要素与"取数直达"

代码语言:javascript
复制
技能层 skillId ──绑定 SC_KB_BINDING(SKILL)──▶ 目录层 kbId
目录层 kbId    ──地址登记 SC_KB_ADDRESS(nodeId+endpoint+indexPath)──▶ 地址层
地址层         ──取数直达──▶ 实体层 LuceneServer({base}/index/lucene/{kbId})

中心 MySQL · ooder_skillcenter目录(SC_KB)· 地址(SC_KB_ADDRESS)· 节点 · 会话取数直达(不经中心)LuceneServer · 索引与文档(唯一实体){base}/index/lucene/{kbId}VFS配置文件形态登记 vfsPath客户端 SQLite运行态数据经上报入库中心冷热地图:热 → 经 ENDPOINT 在线检索;冷 → 按 INDEX_PATH / VFS_PATH 静态直读

图 5 知识三要素:中心只登记目录与地址,实体归 LuceneServer,取数直达

要素

归谁

载体

目录层(kbId)

中心

SC_KB

地址层(在哪)

中心

SC_KB_ADDRESS

实体层(索引/文档)

LuceneServer

取数直达,不经中心

7.4 冷热数据地图

状态

判定

访问路径

热

承载节点 ONLINE/ACTIVE

经 ENDPOINT 在线检索

冷

承载节点 OFFLINE

按登记的 INDEX_PATH / VFS_PATH 静态直读

节点离线后若只有 nodeId,知识即不可达;唯有登记 indexPath,才支撑冷数据静态直读——这就是"上行报地址"的全部意义。

8. 结语:从"接口"到"秩序"

回到拉斯韦尔。一次通信的五问,在协议里被翻译成五条工程纪律:

5W

传输学之问

北向协议之答

Who

谁在说

四角色 + accountId=nodeId / agentAccount=agentId

What

说了什么

序列化契约 + 报文总表 + DTO 单一真源

Channel

经何渠道

北向 HTTP 控制面 ⊥ 南向 MQTT 数据面

Whom

对谁说

中心权威(目录)+ 解析者 resolve

Effect

取得何效

生命周期状态机 + 治理 + 可演进的契约

北向协议最终交付的,不是端点数量,而是三重企业级能力:

  1. 可替换——底座/骨架可换,只要契约不变(依赖倒置);
  2. 可治理——目录、地址、会话各有唯一权威,不产生第二套账;
  3. 可演进——版本协商 + 双写期 + 墓碑,让"变化"成为契约的一部分。

从"功能落地"到"秩序落地",中间隔着的,正是一份被认真对待的协议。

附:5W × 理论对照表

维度

理论锚点

出处

What

传播 5W 模型

Lasswell, The Structure and Function of Communication in Society, 1948

What

通信的数学理论

Shannon, A Mathematical Theory of Communication, 1948

Why

契约优先设计

Contract-First / Design by Contract(Meyer, 1986)

Why

控制面 / 数据面分离

SDN / Kubernetes / Service Mesh

Who

依赖倒置原则

Martin, DIP(SOLID)

When

并发一致性与乐观并发

原子自增 / REV 版本游标

Where

制品库与供应链分级

SemVer / Nexus·Artifactory / OpenSSF SLSA

Where

存储职责分离

目录(元数据) ⊥ 实体(索引/文档)

How

边界类型化与不可变契约

DTO + @JSONField 钉名 + validate()

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

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

目录
  • 0. 引言:协议是"被约束的通信"
  • 1. 前置:术语与概念基线
  • 1.1 核心术语
  • 1.2 三条不可逾越的边界
  • 2. What:北向协议是什么
  • 2.1 定义
  • 2.2 三分层:按"调用方"而非"资源"划分
  • 2.3 协议主线:五步
  • 2.4 四角色:目录权威的职责切分
  • 2.5 序列化契约:协议的"地基"
  • 3. 背景与技术架构:SkillCenter
  • 3.1 定位与职责
  • 3.2 服务端分层架构
  • 3.3 数据模型(SC_* 表族)
  • 3.4 客户端与消费方
  • 3.5 部署结构
  • 4. Why:规范协议在企业级落地中的核心作用
  • 4.1 企业级落地的结构性难题
  • 4.2 无契约时的"失效模式"分类
  • 4.3 标准协议必须回答的三个问题
  • 4.4 核心作用:协议是企业级能力的"承重结构"
  • 4.5 理论依据
  • 5. Who:谁参与、谁权威
  • 5.1 参与方
  • 5.2 单一实现原则
  • 5.3 权威载体与命名纪律
  • 6. When:何时发生、何时演进
  • 6.1 节点接入生命周期
  • 6.2 状态机与"心跳语义"硬规则
  • 6.3 版本协商与废弃策略
  • 6.4 鉴权开启的时序约束
  • 7. Where:协议边界与数据归属
  • 7.1 分层边界(单前缀)
  • 7.2 上下行的不对称设计
  • 7.3 知识三要素与"取数直达"
  • 7.4 冷热数据地图
  • 8. 结语:从"接口"到"秩序"
  • 附:5W × 理论对照表
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档