news 2026/10/15 11:43:48

PAP协议解析:从工具调用到身份握手,Agent如何证明自己代表谁

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PAP协议解析:从工具调用到身份握手,Agent如何证明自己代表谁

1. 从“工具调用”到“身份握手”:PAP协议到底想解决什么问题

第一次看到“Person Agent Protocol”这个全称的时候,我下意识把它归类成了又一个“让大模型调用外部工具”的接口规范。毕竟这两年各种Agent协议、函数调用标准、插件描述格式已经多到让人麻木,光是把它们列个表就能占满一屏。但真正把PAP的设计动机和几个核心概念过了一遍之后,我发现它想干的事情跟之前那些协议根本不在一个层面上——它要解决的不是“Agent怎么调用工具”,而是“Agent怎么证明自己代表谁”。

这个区别听起来有点抽象,我举个生活化的例子你就明白了。以前的工具调用协议,本质上像是一个没有门禁的公共图书馆:任何人走进来,报一个书名,管理员就把书递给你。管理员不关心你是谁,也不关心你拿书去干什么,他只关心“你要的书我有没有”。而PAP想做的,是给这个图书馆加上一套身份核验机制:你进门要刷卡,卡上写着你是谁、你能进哪些区域、你能借几本书、借了之后要承担什么责任。管理员在递书之前,会先看一眼你的卡,确认你有权限,然后才把书给你。

这个类比里,“卡”就是PAP里的Person Agent概念,“刷卡”就是身份握手,“管理员看卡”就是权限校验。整套协议的核心,就是把“Agent代表谁执行操作”这件事,从一个隐含假设变成一个显式声明,并且让这个声明可以被验证、被追溯、被约束。

为什么这件事突然变得重要了?因为Agent的自主性在快速提升。早期的Agent基本是“你问一句它答一句”,所有的操作都在用户的直接指令下完成,出了问题用户自己兜着。但现在越来越多的Agent开始具备长链条任务执行能力——它可以自己规划步骤、自己决定调用哪些工具、自己判断什么时候该停下来。当一个Agent能自主完成“查资料→写报告→发邮件”这一整条链路的时候,“它到底代表谁”就不再是一个可以含糊过去的问题了。

我试过用一个很简单的场景来理解这个痛点:假设你有一个Agent帮你管理日程,它需要读取你的邮件、访问你的日历、可能还要代表你给其他人发会议邀请。在传统模式下,你只能给它一个“全权授权”,它拿着你的凭证去操作所有事情。一旦它判断失误,比如把一个不该发的会议邀请发给了错误的人,你很难说清楚这到底是你的责任还是Agent的责任,因为从系统角度看,所有操作都是用你的身份完成的。PAP想做的,就是把这个“全权授权”拆解成一个个具体的、有边界的、可追溯的授权单元,让每一次操作都能对应到一个明确的身份声明上。

注意:PAP目前还处于早期讨论阶段,不同实现方对细节的理解可能存在差异。下面我讲的内容,一部分来自公开的设计讨论,一部分是我基于常见Agent架构做的合理推演,你在实际落地时需要以你所用平台的最新文档为准。

2. 拆开PAP的三个核心概念:Person、Agent、Protocol

要理解PAP,得先把这三个词拆开看。很多人一上来就盯着“Protocol”研究通信格式,结果越看越糊涂,因为协议本身只是一层壳,真正决定它行为的是前面两个词的定义。

2.1 Person不是“人”,而是“责任主体”

在PAP的语境里,Person指的不是生物学意义上的人,而是一个责任主体。它可以是一个自然人,也可以是一个组织、一个部门、甚至另一个系统。关键在于,这个主体具备两个能力:第一,它能做出授权决策;第二,它能承担授权带来的后果。

这个定义听起来有点绕,我换个说法你就懂了。当你用个人账号登录一个服务的时候,你的账号背后对应的是一个Person,因为这个账号的授权行为(比如同意某个App访问你的数据)是由你做出的,出了问题也是你负责。但如果你在公司里用一个共享的服务账号去调用某个API,这个账号背后对应的可能是一个部门而不是具体某个人,那这个部门就是Person。

PAP要求每个Agent在行动之前,必须明确声明自己代表的Person是谁。这个声明不是随便写个字符串就完事了,它需要满足几个条件:可验证(别人能确认这个声明是真的)、可追溯(出了问题能找到对应的Person)、可撤销(Person能随时收回授权)。这三个条件缺一不可,少了任何一个,整套协议就退化成了一张废纸。

2.2 Agent是“被授权的执行者”,不是“自主决策者”

这是最容易产生误解的地方。很多人看到“Agent”这个词,脑子里浮现的是一个能自己思考、自己决策的智能体。但在PAP的框架下,Agent的角色被严格限定为执行者——它可以在授权范围内自主选择执行路径,但不能自主扩大授权范围。

我用一个实际场景来说明这个边界。假设你授权一个Agent帮你处理报销流程,授权范围是“读取发票信息、填写报销单、提交审批”。在这个范围内,Agent可以自己决定先读哪张发票、怎么分类、用什么格式填写,这些都属于执行层面的自主性。但如果它在执行过程中发现某张发票金额超标,需要额外审批,它不能自己决定“那我先提交了再说”,而是必须停下来,向Person请求扩大授权或者请求人工介入。

这个边界的设计逻辑很清晰:Agent的自主性应该体现在“怎么做”上,而不是“能不能做”上。前者是效率问题,后者是安全问题。PAP通过把授权决策权牢牢锁在Person手里,确保Agent无论多智能,都不会越过那条线。

2.3 Protocol是“握手规则”,不是“通信格式”

最后说Protocol。很多人一看到这个词就开始研究消息格式、字段定义、传输层选型,这其实是本末倒置了。PAP的Protocol部分,核心不是定义“消息长什么样”,而是定义“握手怎么发生”。

什么叫握手?就是Agent和Person之间建立授权关系的过程。这个过程需要解决几个问题:Agent怎么向Person证明自己的身份?Person怎么确认Agent的请求范围?双方怎么达成一个双方都认可的授权条款?授权条款怎么被记录下来供后续验证?这些问题解决了,消息格式反而是最简单的一部分——你用什么JSON schema、用什么传输协议,都是实现细节。

我个人的理解是,PAP的Protocol部分更像是一套授权契约的协商流程,而不是一套数据传输规范。这个定位上的差异,决定了你在实现PAP的时候,重点应该放在授权流程的设计上,而不是消息格式的打磨上。

3. 一次完整的PAP握手长什么样:从请求到授权的全流程拆解

光讲概念容易飘,我直接用一个模拟场景把整个流程走一遍。假设你有一个日程管理Agent,它需要代表你去读取某个外部系统的日历数据,然后根据你的空闲时间自动安排会议。这个场景涉及跨系统访问,正好能体现PAP的价值。

3.1 第一步:Agent发起身份声明

Agent在请求访问日历数据之前,首先要向目标系统发起一个身份声明。这个声明里包含几个关键信息:Agent自己的标识、它代表的Person标识、它请求的权限范围、以及这个请求的有效期。

这里有个细节值得注意:Agent的标识和Person的标识是分开的。Agent标识用来区分“是哪个Agent在操作”,Person标识用来区分“这个Agent代表谁”。为什么要分开?因为同一个Person可能授权多个Agent,同一个Agent也可能代表多个Person。如果把它们混在一起,后续的授权管理和审计就会变得非常混乱。

{ "agent_id": "calendar-assistant-v2", "person_id": "user-12345", "requested_scope": ["calendar.read", "calendar.write"], "valid_until": "2025-06-30T23:59:59Z", "nonce": "a1b2c3d4e5" }

这个声明本身不包含任何敏感信息,它只是一个“我要代表谁做什么”的意图表达。真正的授权决策发生在下一步。

3.2 第二步:Person侧进行授权决策

目标系统收到Agent的声明后,不会直接信任它,而是要把这个声明转发给Person侧进行确认。Person侧可能是一个授权服务,也可能是一个人工确认界面,取决于具体的实现。

在这个环节,Person侧需要做几件事:验证Agent的身份是否合法、检查请求的权限范围是否在Person的授权能力之内、确认这个请求是否符合Person的当前意图。最后一项特别重要——Person可能之前授权过这个Agent读取日历,但现在不想让它继续读了,那Person侧就应该拒绝这个请求。

我试过用一个简单的规则引擎来模拟这个决策过程:如果Agent在Person的白名单里,且请求的权限在Person的授权范围内,且当前时间在有效期内,就通过;否则就拒绝或者转人工。这个规则引擎不需要很复杂,但必须存在,否则PAP就退化成了“Agent说什么就是什么”。

3.3 第三步:生成授权凭证

如果Person侧批准了请求,就会生成一个授权凭证返回给Agent。这个凭证是Agent后续访问目标系统的“通行证”,它需要满足几个条件:不可伪造(通常用签名保证)、不可篡改(通常用哈希保证)、可验证(目标系统能独立验证)、可撤销(Person能随时让它失效)。

{ "grant_id": "grant-67890", "agent_id": "calendar-assistant-v2", "person_id": "user-12345", "granted_scope": ["calendar.read"], "issued_at": "2025-06-01T10:00:00Z", "expires_at": "2025-06-30T23:59:59Z", "signature": "base64-encoded-signature" }

注意这里granted_scope和之前requested_scope的差异:Agent请求了读和写两个权限,但Person只批准了读。这个差异是正常的,也是PAP设计里很重要的一点——Person有权缩小授权范围,Agent不能因为请求被部分拒绝就拒绝执行。

3.4 第四步:Agent携带凭证访问目标系统

Agent拿到授权凭证后,就可以带着它去访问目标系统了。目标系统在放行之前,会先验证凭证的有效性:签名对不对、有没有过期、权限范围是否覆盖当前操作。验证通过后,才执行实际的数据读取操作。

这个环节的关键在于,目标系统不需要直接和Person侧通信,它只需要验证凭证本身。这大大降低了系统的耦合度——Person侧只需要在授权时参与一次,后续的每次访问都是Agent和目标系统之间的事。

3.5 第五步:操作记录与审计

每次Agent使用凭证访问目标系统,都应该产生一条操作记录。这条记录里包含Agent标识、Person标识、授权凭证标识、操作类型、操作时间、操作结果。这些记录汇总起来,就形成了一条完整的审计链路。

审计链路的价值在于,当出现问题时,你可以沿着这条链路一路回溯:这个操作是哪个Agent做的?它代表谁?它用的是哪个授权凭证?这个凭证是谁批准的?批准时的权限范围是什么?这些问题都能找到答案,责任归属就清晰了。

提示:审计记录的存储和查询本身就是一个不小的工程。如果你的Agent数量不多,可以先从简单的日志文件开始;如果Agent数量上来了,建议尽早考虑结构化的审计存储方案,不然后期排查问题会非常痛苦。

4. 落地PAP时最容易踩的五个坑

概念和流程讲完了,接下来聊点实在的。我在模拟实现PAP的过程中踩了不少坑,有些是设计层面的,有些是实现层面的,这里挑五个最有代表性的分享出来。

4.1 坑一:把Agent标识和Person标识混用

这是最常见也最致命的一个坑。很多人在实现的时候图省事,直接用Person的标识作为Agent的标识,觉得反正都是同一个用户在操作,没必要区分。结果就是审计日志里全是Person标识,根本看不出是哪个Agent在操作,出了问题连排查方向都没有。

正确的做法是严格区分两个标识,并且在所有日志和凭证里都同时记录。Agent标识用来定位具体的执行者,Person标识用来定位责任主体。两者缺一不可。

4.2 坑二:授权范围定义得太粗

另一个常见问题是授权范围定义得太粗,比如直接给一个“calendar.*”的全权限,而不是细分成“calendar.read”和“calendar.write”。粗粒度的授权看起来省事,但实际上埋了大雷:Agent一旦被攻破或者出现逻辑错误,它能造成的破坏范围会大得多。

我的建议是,授权范围的定义粒度应该和你的审计能力匹配。如果你能精确审计到每一次读写操作,那授权范围就可以细到读写级别;如果你的审计只能到模块级别,那授权范围最好也控制在模块级别。审计能力和授权粒度不匹配,是很多安全问题的根源。

4.3 坑三:忘记处理授权撤销

授权撤销是PAP设计里很重要的一环,但在实现时经常被忽略。很多人只实现了“授权”流程,没实现“撤销”流程,结果就是Person一旦授权出去,就收不回来了。

撤销的实现有两种常见思路:一种是短有效期+频繁续期,每次续期都是一次重新授权,Person不续期就自动失效;另一种是维护一个撤销列表,目标系统在验证凭证时额外检查这个列表。两种思路各有优劣,短有效期实现简单但会增加授权频率,撤销列表实时性好但需要额外的存储和查询开销。

我个人的偏好是短有效期为主、撤销列表为辅。大部分场景下短有效期就够了,只有对实时性要求特别高的场景才需要引入撤销列表。

4.4 坑四:凭证验证逻辑写得太松

凭证验证是安全链条上的最后一环,也是最容易被攻破的一环。我见过不少实现只验证了签名,没验证有效期;或者只验证了有效期,没验证权限范围。任何一个验证环节缺失,都会让整个PAP的安全保证打折扣。

一个完整的凭证验证至少应该包含这几项:签名验证、有效期验证、权限范围验证、Agent标识验证、Person标识验证。这五项缺一不可,而且验证顺序也有讲究——先验证签名(防止伪造),再验证有效期(防止过期),最后验证权限范围(防止越权)。

4.5 坑五:审计日志只记不查

最后一个坑是审计日志只记录不查询。很多人把审计日志当成一个“合规摆设”,记录是记录了,但从来不查。结果就是出了问题之后,面对海量的日志无从下手,排查效率极低。

审计日志的价值在于查询,不在于记录。你需要在设计阶段就想清楚:出了问题之后,我会怎么查?我会按什么维度过滤?我会关注哪些字段?把这些想清楚了,日志的字段设计和索引设计就有了方向,后续排查才能快起来。

5. PAP和其他Agent协议的对比:什么时候该用它

聊到这里,你可能会问:市面上已经有那么多Agent协议了,PAP到底有什么不同?我什么时候该用它,什么时候不该用?我整理了一个对比表格,从几个关键维度把PAP和常见的工具调用协议做了区分。

对比维度传统工具调用协议PAP
核心目标让Agent能调用外部工具让Agent能证明自己代表谁
身份处理隐含在凭证里,不显式声明显式声明Person和Agent两个身份
授权粒度通常是全权授权细粒度、有边界、可撤销
审计能力依赖底层系统的日志协议层面要求审计链路
适用场景单用户、低风险操作多用户、跨系统、高风险操作
实现复杂度低中到高

从表格里能看出来,PAP不是要取代传统的工具调用协议,而是在它之上加了一层身份和授权管理。如果你的Agent只在单用户环境下运行,操作的风险也不高,那传统协议完全够用,没必要上PAP。但如果你的Agent需要跨系统操作、需要代表多个不同的Person、或者操作本身涉及敏感数据,那PAP的价值就体现出来了。

我个人的判断标准是:当“这个操作代表谁”这个问题变得重要的时候,就是该考虑PAP的时候。如果这个问题从来没人问过,那说明你的场景还没复杂到需要PAP的程度。

6. 一个最小可用的PAP实现思路

最后聊点实操的。如果你想在自己的项目里试试PAP,我建议从一个最小可用的实现开始,不要一上来就追求完整。下面是我梳理的一个最小实现思路,你可以直接参考。

6.1 定义三个核心数据结构

第一个是身份声明,包含agent_id、person_id、requested_scope、valid_until、nonce五个字段。第二个是授权凭证,包含grant_id、agent_id、person_id、granted_scope、issued_at、expires_at、signature七个字段。第三个是审计记录,包含record_id、grant_id、agent_id、person_id、operation、timestamp、result七个字段。

这三个结构不需要很复杂,但字段要齐全。特别是审计记录,字段设计的时候要想清楚后续怎么查,不然后期改起来很麻烦。

6.2 实现两个核心接口

第一个是授权接口,接收身份声明,返回授权凭证。这个接口的内部逻辑是:验证Agent身份、检查请求范围、生成凭证、签名、返回。第二个是验证接口,接收授权凭证和操作请求,返回验证结果。这个接口的内部逻辑是:验证签名、验证有效期、验证权限范围、返回结果。

这两个接口是整个PAP的核心,其他都是辅助。先把这两个接口跑通,再考虑扩展。

6.3 用签名保证凭证不可伪造

凭证的签名可以用常见的非对称加密算法实现,比如Ed25519或者RSA。Person侧持有私钥,用私钥对凭证内容签名;目标系统持有公钥,用公钥验证签名。这样即使凭证在传输过程中被截获,攻击者也无法伪造一个新的凭证,因为他没有私钥。

import nacl.signing # Person侧生成密钥对 signing_key = nacl.signing.SigningKey.generate() verify_key = signing_key.verify_key # 对凭证内容签名 credential_bytes = b'{"grant_id":"grant-67890",...}' signed = signing_key.sign(credential_bytes) signature = signed.signature # 目标系统验证签名 try: verify_key.verify(credential_bytes, signature) print("签名验证通过") except nacl.exceptions.BadSignatureError: print("签名验证失败")

这段代码只是一个示意,实际实现时你还需要考虑凭证的序列化格式、签名的编码方式、密钥的管理和轮换等问题。但核心思路就是:私钥签名、公钥验证、签名绑定内容。

6.4 用短有效期降低撤销复杂度

前面提到过,授权撤销是一个容易被忽略的环节。在最小实现里,我建议先用短有效期来替代复杂的撤销机制。比如把凭证的有效期设成1小时,Agent每次访问前先检查凭证是否过期,过期了就重新走一遍授权流程。

这个方案的优点是实现简单,不需要维护额外的撤销列表。缺点是授权频率会比较高,如果Agent的访问很频繁,可能会对Person侧造成压力。但在最小实现阶段,这个缺点是可以接受的,等后续有需要了再引入更复杂的撤销机制。

提示:短有效期的具体时长需要根据你的场景来定。如果Agent的操作是突发性的、间隔很长的,有效期可以设长一点;如果Agent的操作是持续的、高频的,有效期就要设短一点,同时考虑引入缓存机制来减少授权请求。

6.5 从单Person单Agent开始验证

最小实现的最后一步,是先用一个最简单的场景来验证整套流程。比如一个Person授权一个Agent读取一个数据源,Agent读取后返回结果。这个场景足够简单,能让你快速跑通整个链路,发现设计上的问题。

等这个场景跑通了,再逐步增加复杂度:多个Agent、多个Person、多种权限范围、跨系统访问。每增加一个维度,都重新验证一遍,确保新增的复杂度没有破坏原有的安全保证。

我个人在实际操作中的体会是,PAP这类协议的价值不在于它的技术有多复杂,而在于它把一些原本隐含的假设显式化了。在实现的过程中,你会被迫去思考很多以前没想过的问题:这个Agent到底代表谁?它的权限边界在哪里?出了问题怎么追溯?这些问题想清楚了,即使你不用PAP,你的Agent系统也会变得更健壮。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 11:43:36

CANOpen源码实战:从对象字典绑定到PDO同步调试

简介:本资源为开源CANOpen协议栈完整实现源码,面向嵌入式开发工程师、工业自动化系统集成人员及学习现场总线通信协议的高校师生,解决CAN网络中高层协议栈移植、定制与教学实践难题。压缩包共437个文件,以113个头文件(…

作者头像 李华
网站建设 2026/10/15 11:42:40

一文看懂防火墙与网闸:逻辑隔离和物理隔离差距究竟有多大?

很多网络建设项目中,不少技术人员容易混淆防火墙与网闸,甚至直接用防火墙替代网闸做高等级跨网隔离,埋下严重安全隐患。随着 NGFW 下一代防火墙、新一代信创网闸、AI 威胁检测技术普及,二者的技术边界、防护定位差异愈发清晰。防火…

作者头像 李华
网站建设 2026/10/15 11:42:36

用Go构建协同计算任务调度系统:DAG依赖编排与实战复盘

做分布式计算的人,多少都遇到过这种哭笑不得的局面:任务列表里有几十个作业,看上去谁都能跑,实际上彼此之间有严格的先后顺序和依赖关系——上游要产出中间数据,下游才能开工;左边三个模型必须全部就绪&…

作者头像 李华
网站建设 2026/10/15 11:41:46

解密279模式:用户生命周期管理的核心指标与实践

1. 解密279模式的底层逻辑 这个数字组合最近频繁出现在各类商业分析报告中——从初创公司的增长策略到上市企业的财报解读,279模式似乎成了一种现象级的商业方法论。我第一次注意到它是在研究某头部电商平台的季度运营报告时,发现其用户留存曲线与行业平…

作者头像 李华
网站建设 2026/10/15 11:40:52

无可挑剔不是天赋:标准、流程与反馈闭环打造的零瑕疵交付

“impeccable”,这个词我第一次认真琢磨它,是在一次项目复盘会上。当时甲方头儿用这个词评价了我们交付的一套东西,我心里咯噔一下——不是因为被夸了高兴,而是我清楚地记得,就在交付前夜,我们还在为一个按…

作者头像 李华
网站建设 2026/10/15 11:40:51

深入理解context-mode:请求上下文的设计原理与工程实战

1. 先对齐共识:context-mode 到底在解决什么问题我印象最深的一次线上事故,不是因为算法写错,也不是数据库被击穿,而是因为一个看起来人畜无害的全局变量。用户A登录后看到的却是用户B的购物车数据,后台没有报任何错误…

作者头像 李华