Featured image of post 同样一次 Git Push,为什么 Agent 有时该放行、有时必须拦住?

同样一次 Git Push,为什么 Agent 有时该放行、有时必须拦住?

同样是 GitHub push、邮件发送或文件写入,风险常常取决于 Agent 在此前的会话里读过什么、试过什么、花了多少预算。以 Databricks Omnigent 为例,拆解一种会随任务历史变化的权限策略。

同样一次 Git Push,为什么 Agent 有时该放行、有时必须拦住?

假设你让一个 Agent 帮忙整理客户反馈,最后它准备把一份总结推到 GitHub。单看这一步,很多系统只能给出两个选择:允许,或者不允许。

可问题不在这个 push 本身。它刚才读的是一份公开的 issue 列表,还是一份带客户报价和联系人信息的内部文档?它是在用户指定的仓库里改一个 README,还是先浏览了来路不明的网页,接着突然要把结果提交到另一个仓库?它在过去十分钟里调用了两次工具,还是已经连续重试几十次、花掉了一大笔模型预算?

同一个动作,放进不同的会话历史,含义完全不同。可大多数 Agent 权限系统,仍然在按“这一刻的工具调用”做判断。

Databricks 在 7 月介绍开源 meta-harness Omnigent 时,提出了一个更贴近这类问题的做法:策略不只看当前事件,还保存这次会话里已经发生的关键事情。它把这种机制称为 contextual policies(上下文策略)。策略可以记住 Agent 读过什么、调用过几次工具、累计了多少风险或花了多少钱,再决定下一个动作该 ALLOWASK 还是 DENY

换句话说,权限不应只绑定某个进程或某个工具,还应绑定一段有来龙去脉的任务。

为什么一条 git push 规则不够用

传统权限系统擅长管理稳定对象:服务账号能读哪个 bucket,CI 能部署到哪个环境,应用能不能访问摄像头。因为这些对象、目标和动作通常不会频繁变化。

Agent 的工作方式恰好相反。它会拆任务、读文件、搜网页、产生中间结果,再根据结果换一种工具或调整步骤。提前把它会用到的每个工具列成清单不现实;只看进程名,也解释不了一项操作为什么此刻合理、换个上下文又变得可疑。

例如,给 git push 做一个简单规则:允许,开发流程会更顺;禁止,安全边界更清楚。但两种做法都太粗。

一个正常的场景是,开发者让 Agent 修复测试。Agent 只在当前项目里读代码、改文件、跑测试,最后向同一个受控仓库提交变更。这次 push 的可解释性很强。

另一个场景是,Agent 先从外部网页复制了长段内容,又读取了本机的机密配置,随后要把一个新建文件推送到外部仓库。即使最后的 API 调用仍然只是 git push,它的风险已经变了。

如果策略只认识“是否允许 git push”,就不得不在便利和安全之间二选一。实际工作里,真正需要判断的是:这个 push 出现在怎样的执行路径里?

这也是为什么企业碰到 Agent 告警后,往往会走向两个极端:要么给整个 Agent 进程加白名单,后面的操作都跟着变成“可信”;要么每次工具调用都弹窗,用户最后只是机械地点“允许”。

上下文策略的目标没那么宏大:让常规路径少被打断,把确认和拦截留给那些已经出现异常信号的会话。

一次会话里,策略该保留哪些线索

要让策略“看见上下文”,不需要把 Agent 的每一条日志都丢进判断器。那会让成本和维护难度一起上升。先把会话历史压缩成少数会影响决策的状态,通常已经足够。

Agent 权限策略需要保留的四类会话线索

1. 最初的任务是什么

第一条状态是用户最开始交代的目标。

假如用户说“更新这份 Slides”,那么 Agent 读取、修改这份演示文稿通常是合理的;它突然调用 GitHub 工具,或者准备向外部邮箱发附件,就应该被重新审视。Omnigent 将这种思路称为 intent-based authorization(基于意图的授权):策略保存初始任务意图,再检查每个后续工具调用是否还在这个边界内。

这比单纯的工具 allow-list 更细。你不必永远禁用 GitHub,也不必给每次 GitHub 操作人工确认;只需要在“更新 Slides”的任务里,把无关的 GitHub 操作升格为 ASK

当然,初始意图不是万能的自然语言护身符。它需要和工作目录、项目、数据源等可验证的上下文绑定。否则“帮我整理项目资料”仍然可能被解释得过宽。它的价值在于给权限系统一个起点:知道 Agent 原本是为了什么被授权的。

2. 它已经读过哪些数据

第二条状态是数据接触记录。

很多泄露事故并不是由“读取机密文件”单独造成的,而是由读取之后的写入或外发造成的。Agent 在同一会话里先打开了机密文档,之后再把摘要写入一个它刚创建的普通文档,或者发给外部收件人,风险才真正出现。

Databricks 给出的 Google Drive 例子很直观:默认情况下,Agent 可以自由编辑本次会话中自己创建的文档;可一旦它打开了被标记为机密的文件,策略就收紧,写入被限制在机密集合内,避免把内容“向下写”到不受保护的位置。

这里的关键不是给“写文档”工具贴上危险标签,而是记录数据流向。一个本来无害的写操作,可能因为之前读取了敏感内容而变得不合适。

对本地 Agent 来说,这个状态可以很朴素:是否读取过 .env、凭据目录、受限工作区或标记为机密的知识库;后续的上传、邮件、外部 Git push 就以此作为额外条件。先把最容易造成影响的几类数据源标出来,比试图自动给所有文件分级更现实。

3. 风险是怎么累积的

第三条状态是会话风险分数。

单次网页搜索未必有问题。单次读取一个文件也未必有问题。可如果一个 Agent 连续访问外部内容、读取敏感数据、尝试执行系统命令、反复更换下载方式,安全团队通常会比看第一步时更谨慎。

上下文策略可以把这类信号累积成一个分数。低分时,常规工具调用直接放行;分数超过阈值后,外发、删除、权限提升等动作切换成 ASK;再高一些,就直接 DENY

这种设计的好处是,Agent 不必每迈一步都停下来问人。它只有在会话确实开始偏离普通路径时才需要人工介入。

分数也不该被理解成神秘的“AI 风险判定”。早期规则完全可以是显式的:读取受限目录加多少分,访问外部网页加多少分,尝试写启动项或上传文件加多少分;这些分值可以随着告警和误报复盘慢慢调整。可解释性比一开始追求精确更重要。

4. 预算和重试有没有失控

安全和成本常常被分成两个系统管理,但对长期运行的 Agent,它们都属于会话状态。

一个 Agent 在预算内完成一项资料整理,和它卡在错误路径上不断重试、反复调用昂贵模型,本质上都需要一个“该不该继续”的判断。Omnigent 的成本策略会记录单次会话的模型花费:越过软阈值时询问用户,达到硬上限后阻止继续调用昂贵模型,并允许切换到更便宜的模型。

同样的逻辑也能用于工具重试。连续换参数、换下载工具、换凭据来源,不应该无限发生。次数达到阈值后暂停,既能防止费用失控,也能避免一个配置错误的 Agent 在错误边界上越跑越远。

这不是要把每一次失败当作攻击。对 Agent 来说,重试本来就是解决问题的方式。限制的目标是把“合理的第二次尝试”和“持续扩散的异常路径”区分开来,并且留下人能读懂的原因。

把规则写成会话状态,而不是更长的白名单

如果把上下文策略落到实现层面,可以把它想成一个小型状态机,而不是一张越来越长的规则表。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
用户发起任务
记录:任务意图、工作目录、允许的数据源与目标
每次工具调用更新状态
    ├─ 读取敏感数据 → 标记数据范围、提高风险分
    ├─ 外部网页内容进入上下文 → 提高风险分
    ├─ 连续失败/重试 → 记录次数
    └─ 模型或外部 API 调用 → 累计成本
判断下一步
    ├─ 低风险且任务相关 → ALLOW
    ├─ 超过阈值或目标不匹配 → ASK
    └─ 违反硬边界 → DENY

从任务开始到放行、确认或拦截的权限状态机

真正值得花时间的,不是把这张图画得多复杂,而是先确定哪些状态值得记录,哪些动作值得触发状态变化。

一套最小版本可以只覆盖四种情况:

  • Agent 是否离开了用户指定的工作目录或项目;
  • Agent 是否读过标记为敏感的数据;
  • Agent 是否准备向外部目标发送内容;
  • Agent 的重试次数与会话花费是否超出预算。

有了这些状态,再把高影响动作放到 ASKDENY 分支:向外部仓库推送、发送邮件、上传附件、修改权限、删除大量文件。其余常规动作仍然保持流畅。

这比“一律先弹窗”更能减少无意义确认。用户看到的确认框不再只是“是否允许调用某工具”,而可以明确说明:“这个会话已读取机密目录,向外部仓库推送需要你再次确认。” 有了原因,人才能做判断。

先让人看懂规则,再让 Agent 执行

上下文策略也有一个明显风险:如果所有判断都藏在一套难以解释的评分模型里,用户和安全团队只会得到另一种“为什么被拦了”的困惑。

因此,第一版应该坚持几个朴素原则。

状态要能查看。 用户和管理员至少应知道 Agent 当前的任务边界、已访问的敏感区域、风险分变化和已用预算。不是要把完整思维链暴露出来,而是要显示与权限决策有关的事实。

规则要能回放。 一次 ASKDENY 应该能回到触发它的状态变化:读了哪个受限目录、访问了哪个外部来源、是哪几次重试让风险分超过阈值。否则团队无法调规则,只会选择关闭规则。

边界要能撤销。 一项授权不该因为用户点过一次确认就永久扩大。任务结束后,会话状态应当归档或失效;下一次新任务重新建立最小权限。对高风险变更,保留快照和回滚点,比事后在日志里追原因更有用。

不要把所有风险都丢给用户。 人工确认应该是升级路径,不是默认交互。若一个动作无论如何都不允许,例如把机密数据上传到未批准目标,系统应该直接拒绝;若风险很低,就应该让 Agent 顺畅执行。

最终要管理的是任务,不是某个按钮

过去我们常把 Agent 权限理解为一组“能不能用这个工具”的开关。这个视角在工具较少、任务较短时还说得过去;当 Agent 开始跨文件、浏览器、代码仓库和外部服务执行长任务,开关很快就会失效。

Agent 的工作是沿着目标调用工具、处理失败、调整步骤。策略的工作不是替它规划每一步,而是记住它已经穿过哪些边界:最初领到了什么任务,碰过哪些数据,风险是否正在累积,预算是否已经接近上限。

两者分工清楚,自动化才不必在“完全放行”和“每步打断”之间摇摆。Agent 可以继续执行,策略则在它跨到下一条边界前给出证据、要求确认,或者踩下刹车。

这或许才是下一代 Agent 权限系统真正需要的变化:不再孤立地审判一个动作,而是把它放回一段完整、可追溯的任务历史里。


参考来源

以上来源用于说明 Omnigent 的公开设计与 Agent 权限治理思路。具体策略阈值、数据分级和审批流程仍需结合组织的资产范围、合规要求与实际告警数据制定。

RSS Feed 使用 Hugo 构建
主题 StackJimmy 设计