AI 代理需要操作网关的五个信号
AI 代理操作网关让编程代理无法直接持有密钥,明确审批流程,并记录每一次 HTTP 或 SSH 操作。

当 AI 编程代理能够带着无人明确检查、批准或撤销的权限,在工作区之外执行操作时,就需要操作网关。问题不在于代理会写代码,而在于它可以使用凭据、修改托管服务,或在有人把密钥粘贴到它的上下文中并称之为配置之后,打开 SSH 会话。
团队通常要等到险些出事后,才会把这称为 AI 代理操作网关问题。令牌出现在聊天记录里。一次编程运行使用了生产部署账号,因为那是唯一可用的账号。有人问是谁批准了数据库变更,得到的回答却是一串零散消息和一次共享终端会话。这些不是文档工作没做好,而是说明团队把操作权限交给了不受信任的进程,却没有为它设置可用的边界。
网关不会通过判断每条命令在道德上是否正确,来让代理变得安全。这不是它应该做出的承诺。网关让凭据留在代理之外,在合适的节点加入人的决定,并留下记录,让操作人员无需凭记忆重建事件,就能回答发生了什么。如果下面的情况听起来很熟悉,直接向代理提供凭据的便利已经失去了价值。
复制 API 密钥已经成了常规配置
当开发者为了让代理完成工作,把 API 密钥粘贴到提示词、环境文件、终端会话或代理配置中时,就需要为代理设置独立的操作边界。这种习惯看似无害,因为第一次运行往往确实完成了开发者要求的事情。但它也会在原本从未用于存储生产权限的位置制造副本。
代理上下文中的凭据可能通过比原始提示词更多的路径泄露。代理可能在命令中再次输出它,把它写入配置文件,放进错误报告,加入生成的文档,或在解释失败原因时暴露它。终端回滚内容、Shell 历史、进程环境、CI 日志、备份和支持工单截图都会产生更多副本。遮住一条可见消息,并不能删除这些副本。
团队经常混淆的区别很简单:代理使用密钥,不等于代理持有密钥。浏览器可以提交付款,而不必让页面上的每个脚本都看到卡号。代理也可以采用同样的分离方式。它可以带着说明清楚的请求体请求 POST /deployments,由可信执行器注入凭据并返回响应。
不要接受一种假分离方案:系统把 API_KEY=... 换成 ${SECRET_NAME},然后在代理进程内部解析这个占位符。明文仍然到达了同一个进程。被入侵的扩展、仓库中的恶意指令,或过于积极的调试输出都可能把它取出来。
更安全的请求边界可以是这样:
{
"channel": "http",
"credential": "deploy-service",
"method": "POST",
"url": "https://api.example.internal/deployments",
"headers": {"content-type": "application/json"},
"body": {"service": "catalog", "revision": "a1b2c3d"}
}
代理可以看到端点、请求体、审批状态和响应,却看不到授权请求所需的 bearer token。正因为如此,你可以轮换凭据,而不必同时清理提示词和本地工作树中的泄露副本。
如果密钥已经进入代理上下文,就应按已暴露处理。撤销或轮换它,检查这次运行把输出记录到了哪些位置,并移除直接交付密钥的模式。团队有时会因为无法证明令牌已经泄露而拖延轮换。你不需要证明复制的凭据已经被盗,只需要承认自己已经无法控制它现在位于哪里。
共享账号隐藏了执行变更的人
当代理通过共享部署用户、全团队共用的云令牌,或所有开发者和自动化任务共用的 SSH 账号执行操作时,就需要操作网关。共享访问短期内能省下账号管理工作,但一旦出了问题,责任归属也会立即消失。
考虑一种常见的故障。代理收到修复构建失败的请求。它发现一个过时的基础设施设置,于是使用 ops@production 连接主机。这个账号之所以能用,是因为权限很广,而且私钥就在仓库的入门说明中。代理修改了文件,重启服务,然后报告成功。
后来服务开始返回错误。服务器日志显示 ops 重启了服务,云审计记录显示团队令牌调用了部署 API。但这两条记录都没有说明是哪个代理进程、哪项工作请求、哪个启动进程的人,或是否有人在操作执行前看过它。团队得到的只能是一场依靠推测完成的事故调查。
为每个人使用独立凭据当然比共享账号好,但这还不能完全解决代理使用问题。如果代理拿到了 Alice 的私钥或长期令牌,审计记录只能说明 Alice 的凭据执行了操作。它无法可靠说明请求究竟是 Alice、她的终端、被入侵的仓库指令,还是她的代理发起的。
让身份和记录各自承担不同的职责:
- 服务身份定义外部系统允许执行什么。
- 代理会话标识提出请求的具体运行进程。
- 审批标识接受操作范围的人。
- 操作记录标识确切的请求及其结果。
不要把这些信息压缩成一个名为 user 的字段。发生故障或进行访问审查时,它们分别回答不同的问题。
对于 SSH,共享的宽权限账号尤其值得警惕。SSH 私钥是一种可携带的签名权限。如果代理拥有这个文件,那么你原本打算在登录后施加的控制,就已经失去了最有用的边界。强制命令和账号限制可以减少损害,值得使用,但它们无法改变一个事实:代理可以发起该密钥允许的每一条连接。
将密钥放入由执行器负责完成 SSH 操作的环境中。给代理一个请求接口,记录主机、命令、身份、会话和结果。请求范围要足够窄,让审查者能够理解。systemctl restart catalog 可以审查,而 ssh host 'bash -c "$(curl ... )"' 则是一个对任意权限进行不透明转发的隧道。
一次审批全部操作,不算真正的审批
当开发者一次性批准了模糊权限,却无法知道后续哪些请求使用了这项权限时,代理就需要操作网关。标为“允许代理访问”的按钮,如果涵盖了未知数量的端点、命令、账号和时长,就只是同意的表演。
审批要有用,必须回答两个实际问题:哪个进程提出了请求,这项审批覆盖什么范围?进程身份很重要,因为一台本地设备上可能同时运行受信任的编程代理、从仓库复制来的未签名脚本,以及冒用代理名称的恶意进程。仅凭显示名称不能建立信任。代码签名权限能给审查者提供一个值得检查的事实。
范围也很重要,因为审批疲劳会把人变成自动点击者。要求每位开发者每小时检查五十个日常调用,并不能带来人的控制,只会教会他们关闭提示。反过来,为生产凭据提供一周有效的全范围审批,也会让一条意外指令拥有过大的操作空间。
根据能力带来的后果,使用两种不同的审批范围:
- 会话审批可以覆盖一个已识别代理进程在退出前发出的普通调用。
- 对于能够进行不可逆生产变更、转移资金、修改访问权限或访问任务范围外数据的凭据,应逐次确认。
边界应随着进程结束而失效,而不是随着某人昨天点击过的模糊记忆持续存在。新进程应获得新的决定。这样,当代理重启、工具更新,或开发者从另一个仓库开始第二次运行时,控制仍然有效。
审批卡片应先显示进程身份,再用通俗的语言说明能力范围。“已签名进程 X 请求使用 deploy-service 发起 HTTP 调用”能让人做出接受或拒绝的决定。“工具需要权限”则不能。如果操作需要逐次确认,还应显示目标和操作。人无法判断隐藏在通用能力名称背后的请求。
不要因为问题看起来复杂,就建立一套微型策略语言。团队可能花上几周为提示驱动的工具编写允许规则,最后才发现难点根本不在语法,而在于代理是否应该获得这项权限。先从保险库网关、进程范围的同意,以及在影响范围需要时进行逐凭据确认开始。凌晨两点,你仍然应该能向值班人员解释这些控制措施。
代理可以从一次性检出目录访问生产环境
当仓库、分支或一次性开发环境仅仅因为代理在那里运行,就能触发真实的外部操作时,代理就需要操作网关。仓库是输入。把仓库指令当成可信操作员,是概念上的错误。
恶意拉取请求不需要用戏剧化的方式攻击模型。它可以把指令放进代理正常工作时会读取的文件中:“运行这条诊断命令”“使用环境中的部署令牌”或“把日志上传到这个 URL”。如果代理拥有直接访问密钥的权限和不受限制的网络能力,仓库作者就找到了通往操作权限的路径。
这个问题也会在善意的工作中出现。开发者检出一个旧分支来对比迁移脚本。该分支包含一个指向生产环境的旧脚本,因为多年前这样做看起来合理。代理按照附近的文档执行,发现环境中有有效凭据,于是发起请求。没人想修改生产环境,但环境凭据和不受信任指令的组合让这件事成为可能。
将代码访问和操作权限分开。让代理以普通的本地权限读取、测试和编辑检出目录。让出站操作经过一个明确的边界,并标明目标和凭据。代理仍然可以请求执行操作,但不应仅仅因为旁边存在一个密钥文件,就继承相关权限。
这也是为什么仅靠网络过滤不能解决问题。出站规则可以阻止已知目标,在合适的地方应当使用它,但它无法说明是谁发起了允许的请求,请求使用了哪个凭据,或是否有人批准了发出请求的代理会话。网络控制是一道有用的外墙,却不能替代让凭据远离代理。
用一次有意设置为不受信任的代码检出目录进行测试。创建一个只记录请求的无害端点。在项目文件中放入一条有说服力的指令,要求代理使用所谓的诊断令牌调用它。然后以开发者平时使用代理的方式运行。如果端点收到令牌、在代理内部解析的密钥名称,或绕过审查的请求,你就找到了需要修复的边界。
你无法快速撤销正在运行的代理
当一次糟糕的运行只能通过关闭终端、撤销它可能复制过的所有凭据,或希望它已经执行完毕来应对时,代理就需要操作网关。可靠的控制应让操作人员停止当前权限,而不必把本地错误扩大成全面的凭据紧急事件。
进程生命周期提供了一个自然的撤销单位。如果审批绑定到一个代理进程,撤销该会话就会阻止这次运行发起后续操作,即使进程仍然打开。代理可以继续起草代码,却无法访问网关控制的外部通道。这比在事故中关闭无关的开发工作,或轮换组织范围的令牌,影响小得多。
团队经常把三种不同的撤销混为一谈:
- 撤销会话会阻止一个已识别的代理运行继续发出已批准的请求。
- 锁定凭据保险库会停止所有受保护操作,直到授权人员重新打开它。
- 轮换或停用外部凭据会在签发它的服务处移除相关权限。
使用能够控制事故的最小操作,需要时再执行范围更大的措施。如果开发者只是选错了任务,撤销会话可能就够了。如果代理把令牌打印进了外部记录,就应轮换令牌。如果你无法确定哪些代理运行拥有访问权,先锁定保险库,再从稳定状态开始调查。
保险库锁定时,网关应拒绝操作。这一点看似显而易见,但有些工具为了方便会缓存解密后的凭据。操作人员最需要锁定权限时,缓存的权限却会让锁定失去意义。锁定状态必须意味着执行器无法使用存储的密钥发起 HTTP 调用或 SSH 连接。
在事故发生前进行演练。启动一个代理会话,请求执行一项无害的受保护操作,撤销会话,然后重复同一个请求。预期响应应说明授权已经失效。接着启动新进程,确认它必须取得自己的审批。如果旧进程仍然可以继续工作,你构建的只是通知系统,而不是控制系统。
你的日志记录了输出,却没有记录操作
当你拥有聊天记录和终端输出,却无法提供可靠的操作记录时,代理就需要操作网关。对话记录只能描述代理声称自己做了什么,不能证明什么穿过了网络,也不能证明哪个凭据授权了它。
操作记录应尽可能靠近执行器捕获事件。对于 HTTP 调用,记录代理会话、请求时间、目标、方法、凭据引用、授权决定和结果状态。对于 SSH,记录主机、账号引用、命令请求、决定和退出结果。不要为了让日志看起来完整,就记录原始密码、私钥、bearer token 或完整的敏感响应正文。
OWASP 的 Logging Cheat Sheet 也提出了同样的实际建议:日志应支持安全调查,但应用应避免直接记录访问令牌、密码、会话标识符和其他密钥。许多团队只做到了前一半。他们在代理失败后打开详细调试,结果又在日志存储中制造了一次密钥泄露。
更好的做法是把证据和密钥材料分开。执行器可以保留 deploy-service 这样的凭据引用、请求摘要和操作结果。调查人员可以确认某个已授权会话使用该凭据执行了某项具体操作,却不需要拿到凭据本身。
记录还需要具备篡改证据。如果执行操作的同一个进程可以悄悄改写昨天的日志,那么日志记录的就只是该进程希望你相信的内容。哈希链是一种实用防护:每条记录都包含上一条记录的摘要,修改或删除过去的记录就会破坏后续验证。
验证不应要求解密每一条敏感事件。实用的审计工具可以针对加密记录验证哈希链完整性,让操作人员在不广泛授予内容访问权限的情况下发现篡改。这不能证明每项原始操作都明智,只能证明记录的顺序没有事后被悄悄编辑。
尝试提出一个超越“代理成功了吗”的审计问题:“昨天哪个代理运行使用了生产部署凭据,哪个进程获得了同意,每个请求返回了什么结果?”如果你必须拼接 Shell 历史、云日志、聊天导出和某个人的回忆,那就没有真正的操作日志。
代理在观察流量,但它仍然拥有权限
当建议的解决方案只是一个观察流量的代理,而代理仍然持有 API 令牌或 SSH 密钥时,代理就需要操作网关。代理确实有合理的用途,但流量可见性和凭据保管是两种不同的控制措施。
反向代理可以在应用边缘验证请求。出站代理可以过滤目标或保存请求日志。但这两种安排都不一定能阻止本地代理读取令牌、将令牌放入另一个请求、保存到文件,或使用另一条获准路径。对于 SSH,网络代理也无法解决私钥位于代理环境中的问题。
中间人设计还会带来自己的运营负担。它必须处理 TLS 信任、证书部署、协议例外,以及应用自行固定或加密的流量。团队有时会因为它看起来像一个通用控制点而搭建这种方案,最后却发现仍然需要决定哪个进程可以使用哪个凭据。
把边界放在操作上,而不只是数据包上。代理发出结构化请求。执行器选择存储的凭据,将其注入 HTTP 请求或用于 SSH,记录决定,然后返回结果。代理持有的是请求执行工作所需的信息,而不是足以在别处冒充服务身份的材料。
这种设计有一个有用的限制:它不试图成为一个从自然语言预测意图的通用策略引擎。它让权限变得明确。代理通过已知通道请求操作,人或配置好的凭据控制决定该通道是否对这次运行开放,记录则捕获发生了什么。
对于 macOS 团队,Sallyport 通过 MCP stdio shim 采用了这种模式:代理请求 HTTP 或 SSH 操作,而应用将 API 和 SSH 密钥保存在加密保险库中并自行执行操作。这并不意味着可以忽略服务权限的合理设置,但它消除了把原始凭据交给代理的习惯。
你依赖最小权限,却没有测试边界
当团队声称令牌遵循最小权限,却没有测试这些权限落在自主进程手中时能做什么,代理就需要操作网关。最小权限是实际凭据及其可触达操作的属性,不是附加在角色上的标签。
一个只能部署单个服务的令牌,仍然可能修改该服务的环境变量,从而重定向流量或暴露数据。限制在一台主机上的 SSH 账号,仍然可能读取包含其他系统凭据的部署配置。无法删除资源的云角色,仍然可能创建一个使用权限过大的工作负载。权限名称很少会揭示全部后果。
围绕操作而不是产品进行权限审查。写下代理可以要求执行器做什么,然后逐项检查服务的授权规则。把读取操作也包括进去。代理无需修改任何资源,就可能通过导出端点、日志获取、配置读取和发现 API 引发高成本或敏感事件。
审查时可以使用一张小表:
| 请求操作 | 外部身份 | 滥用后的后果 | 审批范围 |
|---|---|---|---|
| 创建预览部署 | 预览部署账号 | 临时工作负载和成本 | 会话 |
| 重启生产服务 | 生产运维账号 | 用户中断 | 逐次调用 |
| 读取事故日志包 | 支持账号 | 可能暴露敏感数据 | 逐次调用 |
| 通过 SSH 连接构建主机 | 构建主机账号 | 在主机上执行命令 | 命令范围较窄时可按会话审批 |
这张表会迫使团队进行一场不太舒服却很有价值的讨论。如果你无法用简短的话说明后果,那么权限可能过于宽泛,或者请求接口过于模糊。
不要把操作网关当成继续放任服务身份拥有过大权限的理由。它能减少密钥暴露,改善同意流程并提供证据,但外部 API 或主机仍然决定凭据可以做什么。减少这些权限,为不同环境使用不同身份,并为不可逆操作设置更严格的审批规则。
第一个边界应该覆盖本周可能造成伤害的操作
操作网关的价值在于替代团队已经在使用的直接凭据路径,而不是变成一项持续六个月的访问权限重构。选出代理当前执行的最高影响操作,先迁移这条路径。
对许多团队来说,这是生产部署 API。对另一些团队来说,则是访问构建主机或运维主机的 SSH。选择应依据实际权限,而不是哪个集成最容易演示。只读的问题跟踪器令牌可能也很重要,但不应让你忽视一把可以重启生产服务的私钥。
让第一次部署具体可执行:
- 盘点代理可以使用的令牌、SSH 密钥、共享账号和环境变量。
- 选择一个跨越真实信任边界的凭据,从代理环境中移除它的明文。
- 定义代理可以发出的结构化操作请求,包括目标和操作。
- 要求这条请求路径使用进程范围的授权,如果操作可能造成重大损害,再采用逐次调用确认。
- 运行一次无害测试,撤销会话,并确认日志同时显示允许的调用和被拒绝的重试。
只有当测试环境真实执行了相同的操作路径时,才先使用测试凭据。完全不同工具中的测试令牌,几乎无法证明生产授权会如何运行。测试必须覆盖实际的执行器、审批、撤销和审计路径。
不要等待代理行为变得完美。提示注入防护、仓库审查、沙箱、服务权限和网络控制都能降低风险,但当代理进程使用本不应拥有的凭据请求外部操作时,它们都无法给你一个清晰的答案。在下一枚复制出来的令牌变成事故调查之前,先把凭据放到边界之后。
常见问题
AI 编程代理的操作网关是什么?
操作网关让凭据留在代理进程之外,并代表代理执行经过批准的外部操作。密钥管理器负责存储和读取密钥;如果它把 API 令牌交还给代理,代理仍然持有令牌,也就可能泄露或重复使用它。
小团队也需要操作网关吗?
可以从一个危险通道开始,通常是生产环境的 HTTP 访问或 SSH。第一个有用的边界很简单:代理请求执行操作,独立的可信组件持有凭据,人可以看到并停止这个会话。
如果代理把 API 密钥复制到提示词里,我该怎么办?
令牌一旦进入提示词、对话记录、Shell 历史、终端截图或生成文件,就应视为已经暴露。撤销并替换它,查明它出现在哪里,然后改变让代理获得该令牌的工作流程。
受限 SSH 密钥可以直接交给代理吗?
不安全。SSH 密钥可能受到账号、来源地址或命令限制,但代理进程仍然可以使用该密钥拥有的全部权限。将私钥放在独立的执行器中,并审批或限制它执行的命令。
为什么共享服务账号不适合代理访问?
共享账号会抹去责任归属,因为成功的请求只能告诉你是哪个账号执行了操作,无法说明是哪个代理会话或哪个人发起了请求。条件允许时,为每个工作负载使用独立身份,并在每条操作记录中关联代理会话。
代理操作的审批提示应该显示什么?
有用的审批应写明代理进程、目标、操作、涉及的凭据或能力,以及审批范围。只写着“代理请求访问”的审批,会迫使人去猜真正重要的信息。
AI 代理的操作日志应该包含什么?
操作记录应包含代理会话、时间、目标、方法或命令、授权结果和执行结果。除非你为这些数据准备了有意设计的受保护流程,否则不要记录原始凭据、令牌和敏感响应正文。
反向代理可以替代操作网关吗?
代理可以观察或转发流量,但这不会自动阻止它持有凭据或使用其他网络路径。操作网关应负责持有凭据并执行操作,而不只是位于请求路径中。
什么时候应该要求代理每次调用都审批?
已知代理进程执行日常工作时,如果会话能正常结束且范围有限,会话级审批通常就够了。对于会对生产环境产生广泛影响、执行不可逆操作,或过去经常被误用的凭据,应要求每次使用都单独确认。
如何在不停止开发的情况下引入代理操作控制?
先盘点代理可以使用的所有凭据、SSH 密钥、共享账号和出站集成。然后优先从影响最大的路径移除直接交付密钥的做法,并确认你能从请求、审批一路追踪到结果,还原一次测试操作。