AI Agent 上生产前,先把可观测性、权限与预算做成三道闸门
把 AI Agent 接入真实业务时,最危险的配置通常不是模型参数,而是让模型直接拥有一把没有边界的生产钥匙。一个代理可以读数据库、调用内部 API、修改工单,甚至触发部署。如果团队只验证回答是否看起来正确,却没有记录它调用过什么、为什么调用、花了多少钱,系统上线后就很难解释一次异常究竟来自模型、工具还是权限设计。
TechCrunch 在 2026 年 1 月 2 日的年度观察中把 AI 的方向概括为从炒作走向务实,重点包括更小的模型、边缘部署和嵌入真实工作流。8 月 27 日,TechCrunch Disrupt 2026 的企业 AI 安全议程又把可观测性、治理和安全架构放在一起讨论。开发者工具的新闻也在向同一个方向靠拢,Developer Tech 在 9 月 3 日报道 Cursor 让企业把云端编程代理工作负载放到自己的基础设施上,9 月 2 日报道 Cycode 增加 Agentic Code Scanning,用来控制代理化代码扫描带来的模型消耗。
这说明问题已经从"要不要用 Agent"转成"怎样让 Agent 在边界内工作"。生产环境至少要先装好三道闸门:可观测性负责看清路径,权限负责拦住越界,预算负责阻止失控成本。三道闸门应该相互独立,不能把拦截责任交给模型自己的回答。
可观测性要记录完整行动链
传统服务监控只要回答存活、延迟和错误率。Agent 还需要回答四个问题:它调用了哪些工具,工具拿到了什么范围的数据,调用顺序是否符合任务,最终结果是否通过了质量检查。只记录最终回复,就像只看账单总额而不看每一笔消费,事后很难定位问题。
生产日志应该由网关、工具适配层和策略引擎共同生成,而不是由 Agent 在回答中自述。每次会话先生成 session_id,每次模型请求和工具请求再生成 trace_id 与 span_id。父子关系要覆盖主 Agent、子 Agent、模型和外部工具,这样才能把一条复杂任务还原成时间线。
| 字段类别 | 建议字段 | 用途 |
|---|---|---|
| 会话 | session_id、user_id、agent_id、tenant_id | 关联用户、代理和租户边界 |
| 调用链 | trace_id、span_id、parent_span_id、step_number | 还原代理的完整行动顺序 |
| 模型 | model_name、prompt_tokens、completion_tokens、latency_ms | 分析延迟、用量和成本 |
| 工具 | tool_name、resource、input_hash、result_status | 审计访问对象并避免日志泄露原文 |
| 策略 | policy_version、decision、approval_id | 确认哪个规则放行或拒绝了动作 |
| 质量 | score、evaluator、passed、failure_reason | 判断结果是否值得交付 |
字段要分层保存。用户输入和工具返回可能含有个人信息,不应为了方便调试而原样写入普通业务日志。可以保存脱敏摘要、哈希和对象存储引用,把原始内容放进更严格的审计区域。OpenTelemetry 社区正在为生成式 AI 场景整理语义约定,接入时应优先采用标准字段,而不是每个团队自造一套名称。
一个最小的追踪配置可以先做到下面这样。示例中的端点来自部署环境,代码不承担密钥管理职责。
yaml
observability:
exporter:
type: otlp
endpoint: OTEL_EXPORTER_OTLP_ENDPOINT
trace:
sample_rate: 1.0
attributes:
- gen_ai.agent.id
- gen_ai.conversation.id
- gen_ai.request.model
metrics:
- llm.token.usage
- llm.request.duration
- tool.invocation.count
- agent.step.count
audit:
include_policy_decision: true
include_approval_id: true
上线前做一次故障演练:给代理一个会触发工具调用的任务,然后只拿 trace_id,要求值班人员在三十秒内找出模型请求、工具入参摘要、策略决定和最终状态。如果只能在多台机器上翻日志,这道闸门还没有装好。
权限控制不能靠提示词维持
"不要删库""不要把数据发出去"可以写在系统提示中,却不能替代安全策略。提示词属于模型上下文,策略应该在模型之外执行。模型可以提出动作,网关决定动作是否有资格执行,工具适配层再验证参数,生产写操作还要经过人工确认。
权限设计从工具粒度开始,不从一个过大的角色开始。一个客服 Agent 可能只需要读取指定客户的工单和写入回复草稿,不需要读取整张客户表,更不需要执行任意 SQL。一个发布 Agent 可能需要创建预发布构建,却不应默认拥有生产部署权限。
| 控制层 | 默认策略 | 失败时的动作 |
|---|---|---|
| 身份 | 每个代理使用独立身份,不复用个人令牌 | 拒绝请求并记录身份来源 |
| 环境 | 开发、预发布、生产使用不同连接和账户 | 生产资源默认不可见 |
| 工具 | 按读、写、执行拆分,禁止通配符权限 | 返回明确拒绝原因 |
| 资源 | 限制租户、项目、表和时间窗口 | 缩小范围后重试或转人工 |
| 高风险动作 | 删除、批量更新、发送外部消息需要审批 | 冻结当前步骤,保留待审请求 |
| 审计 | 网关独立记录动作与策略版本 | 禁止只相信代理口头说明 |
策略判断至少要同时看身份、环境、动作、资源和上下文。只判断动作名称不够,因为读取内部数据后再写入外发邮件,两个动作分别看似合理,组合起来可能已经造成数据外流。风险策略应识别连续动作、敏感资源和异常频率。
下面是一段简化的策略伪代码。重点不是语法,而是让默认结果为拒绝,并把高风险动作放进独立审批路径。
rego
package agent.policy
default allow = false
allow {
input.environment == "staging"
input.action.type == "read"
input.resource.scope == "project"
}
allow {
input.environment == "prod"
input.action.type == "read"
input.resource.classification == "public"
}
allow {
input.environment == "prod"
input.action.type == "write"
input.resource.scope == "approved_table"
input.human_approval == true
input.session.verified == true
}
deny_reason = "production write requires human approval" {
input.environment == "prod"
input.action.type == "write"
input.human_approval != true
}
策略上线后要测试绕过路径。让代理尝试修改提示词、改变工具参数、调用同一工具的别名,再检查网关是否仍然拒绝。策略日志必须与 Agent 的回答分开保存,不能因为 Agent 说"已获批准"就把它当成 approval_id。
预算上限要在循环外生效
Agent 的成本不只来自一次模型请求。循环调用、失败重试、子 Agent 扩散、超长工具返回都会把成本快速放大。预算控制如果只在任务结束后统计,发现超支时已经晚了。正确位置是模型网关和工具网关,每次调用前检查剩余额度,每次调用后写入实际消耗。
预算应该至少有会话、租户、团队和全局四个层级。会话预算防止单个任务失控,租户预算防止一个客户拖垮共享资源,全局预算保护月度账单。阈值不是越高越好,留出降级和人工接管的时间比追求预算利用率更重要。
| 阈值 | 建议动作 | 允许继续的范围 |
|---|---|---|
| 50% | 记录预警并通知负责人 | 正常执行,开始观察循环长度 |
| 75% | 标记高风险会话 | 限制并发,优先使用缓存结果 |
| 85% | 进入节俭模式 | 禁止启动新的子 Agent |
| 90% | 软终止 | 只允许当前步骤收尾,不再新增工具调用 |
| 95% | 硬终止 | 立即中断会话,保存现场并转人工 |
预算计量不能只看 Token。还要把外部搜索、代码执行、向量检索、图片处理和第三方 API 纳入同一张成本表。每个工具定义单位价格或固定权重,工具返回过大时先截断或分页,不让一次调用把完整数据库内容塞回上下文。
循环还需要硬性次数限制。可以设置单会话最大步骤数、同一工具连续失败次数、同一资源重复访问次数和子 Agent 总数。达到上限后不应继续让模型"想办法",而应返回可解释的终止状态。降级方案也要提前写好,例如从高成本模型切换到轻量模型,只读不写,或者直接进入人工队列。
三道闸门怎样串成最小架构
最小架构不需要一开始就采购复杂平台,但必须把职责分开。请求进入代理编排层后,先由身份层确认谁在发起任务,再由模型生成候选动作。候选动作不能直接触碰业务系统,而要经过策略网关和工具适配层。工具适配层负责参数校验、资源范围、超时和重试。所有节点把追踪和审计事件写入独立出口,预算服务在模型调用前后更新余额。
一次动作的顺序可以固定为:生成计划、检查预算、执行策略、必要时请求审批、调用工具、记录结果、更新质量状态。任何一个环节失败,都返回结构化状态,不让模型自行猜测"可能已经成功"。
| 组件 | 必须回答的问题 | 不应该承担的责任 |
|---|---|---|
| 编排层 | 下一步候选动作是什么 | 决定生产权限是否放行 |
| 策略网关 | 动作是否符合身份和规则 | 修改模型输出内容 |
| 工具适配层 | 参数和资源是否在允许范围 | 自行扩大权限范围 |
| 追踪系统 | 这次动作经过了哪些节点 | 决定是否允许动作执行 |
| 预算服务 | 本次调用还剩多少额度 | 仅在月底统计费用 |
| 人工审批 | 高风险动作是否可以执行 | 替代全部自动化流程 |
这个拆分还有一个好处:更换模型不会改变安全边界。模型可以升级,提示词可以调整,策略版本和审计字段仍然保持稳定。企业把云端编程代理放到自己的基础设施上时,真正要迁移的也不只是推理服务,而是身份、日志、密钥、网络出口和回滚机制。
上线前用故障演练验收
不要用"演示成功"作为生产标准。至少准备五类故障:工具返回超时,模型重复调用,策略拒绝,预算达到软阈值,人工审批迟迟没有回应。每类故障都要有可观察的事件、明确的终止状态和恢复动作。
上线检查可以按下面的顺序执行。
- 用测试身份运行只读任务,确认每个模型和工具调用都有 trace_id。
- 让工具返回超时,确认重试次数有上限,重复动作不会绕过预算检查。
- 让代理请求生产写操作,确认默认拒绝,审批前不会发出真实请求。
- 让任务连续触发工具循环,确认达到步骤或费用上限后自动终止。
- 检查审计日志是否能独立还原动作、资源、策略版本和审批结果。
- 故意升级一条策略版本,确认旧会话仍能追溯到当时使用的规则。
- 关闭一个非关键工具,确认 Agent 会转入降级或人工队列,而不是反复重试。
出现告警时,处置顺序也要固定。先通过 trace_id 拉取完整调用链,再核对 Token、步骤数和工具重试;接着查看策略审计,确认是否发生越权;如果动作仍在进行,立即终止会话并冻结相关凭据;保留追踪、审批和预算现场,修复策略或工具后再重新放行。不要先删除日志,也不要让原 Agent 自己总结事故。
把边界装好,再谈能力上限
AI Agent 的价值来自它能跨系统行动,风险也来自同一个能力。可观测性让团队看见行动链,权限控制让越界动作在真正执行前被拦住,预算上限让循环和重试有明确终点。三者缺一不可:没有可观测性,事故无法定位;没有权限,日志只能记录已经发生的越界;没有预算,系统可能在发现异常之前就把共享额度耗尽。
TechCrunch 所说的务实阶段,不是把模型换成更小的版本就结束,而是把智能能力嵌入可管理的工作流。先给 Agent 一个狭窄的工具集合,再用独立策略、结构化追踪和分层预算把边界固定下来。等故障演练证明系统能够拒绝、终止、转人工并留下证据,再逐步增加工具和自动化范围。生产级 Agent 的第一项能力,不是会做更多事,而是在不该做事时能停下来。