拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI Agent安全防线:Harness与AgentCore Gateway双闸门实现实时拦截

AI Agent安全防线:Harness与AgentCore Gateway双闸门实现实时拦截

刚把一个售后客服 Agent 从 demo 推到生产,第一周就差点出事故:有用户用一段精心构造的"系统指令"诱导 Agent 去调用订单数据库的导出接口,当时外网鉴权拦了一道,没有造成真正的数据泄露,但事后回溯整条链路才发现一个让人后怕的事实——模型层、应用层、工具层,没有任何一层对这个越权请求做了实时拦截。问题不在于模型不够聪明,而在于整个运行链路缺少"带闸门的调度层"。从那次之后,我把 Agent 的安全设计整个推翻重做,核心方案就是两个组件的组合:Harness 作为 Agent 运行时的管控框架,AWS AgentCore Gateway 作为统一流量入口的策略执行网关。这篇内容把这套组合架构的设计思路、核心实现、配置细节和踩坑记录完整过一遍,给正在做 AI Agent 生产落地的团队一份能直接参考的落地档案。

1. 为什么 AI Agent 需要一道"实时安全防线"

AI Agent 落地到今天,很多团队对安全的认知还停留在"API 网关 + 密钥管理"阶段。但实际上以 LLM 为决策核心的应用,威胁模型和传统服务完全不同。我们遇到的这次事件,追根溯源就是三个叠加的问题:提示词注入把恶意意图变成模型眼中的"合理指令";工具调用边界没有在运行时动态校验;审计日志只记录了结果没有记录推理过程。这三条每一条单拎出来都不算新鲜,但叠在同一个请求里,就成了能穿透传统防护的裂缝。

1.1 传统 API 网关解决不了的三个断点

先看传统网关注重什么:身份认证、传输加密、基础限流、把请求正确路由到后端服务。这些能力在静态接口时代是够用的,但放到 Agent 场景里会有三个明显断点。

断点一是请求的目标是变化的。传统网关在事前就知道客户端会调用哪个接口,可以针对每个路径配权限。但 Agent 是动态的,同一个用户的同一条消息,可能触发一个工具、两个顺序工具调用、甚至跨多个内部系统的编排流程。网关看到的还只是一个 HTTP 请求头,真正的风险发生在它看不见的下游工具调用链里。

断点二是没有"意图"维度的校验。举个例子,某客户想删除一条工单,但他输入"把上周所有投诉都清理掉"。如果工具层只认"删除工单"这个动作,就可能把整张表都删了。传统网关只能看到删除接口的调用关系,看不出这个调用背后的用户意图是违规的,需要对请求内容做语义层面的实时判定。

断点三是下游工具不受统一策略覆盖。真实生产环境里,一个 Agent 往往要同时对接内部文档库、CRM、工单系统甚至数据库直连。每个系统有自己的权限模型和审计方式,Agent 作为"超级调用方"一旦拿到令牌,就成了梭哈的入口。传统网关根本管不到这些散落在不同系统里的工具调用。所以你会发现,Agent 安全的核心场景其实不在入口,而在入口到工具之间的整条动态链路上。

1.2 "实时防线"的真正含义:从事后审计到前置熔断

回到标题里"实时安全防线"这个说法。很多人理解实时是"日志尽快能看到",这不完全对。我理解的实时防线包含两层:第一层是在每个决策点、每次工具调用发生之前做校验,不允许有延迟窗口;第二层是当防线判定存在风险时能立即熔断后续动作,而不是等数据都出去了再报警。

这两层里,第一层靠 Harness 的拦截器体系在运行时内实现,第二层靠 AgentCore Gateway 在边界上做统一策略执行。分层的好处是可以把"细粒度校验"和"统一管控"解耦:细粒度校验贴近模型和工具,能捕捉到语义层面的异常;统一管控贴近流量入口,能保证不管哪个 Agent 接入都过同一套安全基线。两者互为补充,缺一个都会有盲区。如果只做网关,拦不住下游动态工具调用;如果只做 Harness 拦截器,又挡不住入口处的批量扫描和流量突刺。

2. Harness 与 AWS AgentCore Gateway 的角色分工

开始之前先澄清一个容易混的概念。网上经常有人把"Harness"和"Agent"对立起来讨论,其实这两个不是一个维度的东西。Agent 是自主执行任务的主体,Harness 是约束、编排、保护这个主体的运行框架。打个比方,Agent 是一台高性能跑车,Harness 是安全带、刹车系统和限速器的集合——没有它车也能跑,但有了它才能在赛道上安全地跑完一圈。

2.1 Harness 是什么:给 Agent 戴上一套"缰绳"

实际工程里,Harness 的职责通常覆盖四块。第一块是上下文的注入与裁剪,决定哪些系统指令、用户历史、工具定义真正进入模型视野,防止"越权上下文"被读走。第二块是工具调用的拦截与校验,在模型输出 tool_call 之后、真正执行工具之前插入钩子,做权限、参数、语义三层校验。第三块是运行时的状态管理,记录每个步骤的输入输出、调用链、token 消耗,为审计和回滚提供依据。第四块是失败与重试策略,工具调用失败后不等于把原始错误抛回给用户,而是统一转换、有限重试、逐级降级。

我们团队在使用 Harness 之前是让 Agent 直接调工具函数,后来统一改为"模型 → 规划器 → Harness 拦截器 → 工具执行"的链路。改了之后最明显的变化是,任何工具调用都有了一个统一的"关卡"位置,想加策略不用去改每一个 Agent 的实现,只改 Harness 的拦截器配置就行。

另外多说一句,Harness 是模型无关的。不管底层接的是开源模型还是闭源 API,还是团队自己在私有环境部署的模型服务,Harness 只关心"模型输出中的意图和工具调用",不关心模型本身。这一点让我们后来做底座模型替换时几乎没有改动安全策略,这也是它作为运行时管控层的一个天然优势。

2.2 AgentCore Gateway 的定位:边界上的策略执行点

接着看 AWS AgentCore Gateway。它的定位是 Agent 流量的统一边界网关,所有进出 Agent 应用的流量都要经过这里。它管的是 Agent 应用与外界的入口出口,包括宿主应用进来的 HTTP 请求、Agent 要到外部系统去请求的 API、还有模型服务的调用流量。

实际落地上,网关承担四个核心职责。一是统一认证与身份注入,接收宿主应用传来的用户身份,转换成内部可识别的 principal,再连带 Agent 身份一起传给下游。二是协议转换与动态路由,不同 Agent 框架的上游协议可能不一样,网关负责在统一入口处做适配,把请求安全地路由到对应的 Harness 运行时。三是流量治理,在边界统一做并发限制、token 消耗控制、熔断和降级,防止单个 Agent 拖垮整个网关。四是审计汇聚,无论请求最终调用了几次工具,网关统一记录入口处的请求摘要、身份、策略评估结果,形成全链路的审计拼图。

AWS 生态下它天然能和 IAM、CloudTrail、KMS 等服务打通,加密、凭据管理和操作审计都能复用平台能力。但即使你不用 AWS 全家桶,这套"网关做边界统一 + Harness 做运行时细粒度管控"的分层模型同样成立,核心思路是可以迁移的。

2.3 双防线协同:一次请求在两个组件间的完整旅程

把整套架构串起来看。用户输入到达 AgentCore Gateway 后,网关先完成黑盒层面的检查:来源 IP 与身份、基础限流、请求体大小、是否命中等。通过网关的请求进入 Harness 运行时,Harness 对上下文进行重组,调用模型产出候选动作,然后每个 tool_call 都会先经过 Harness 的拦截器,在运行时层面做权限与语义校验。如果某个工具调用被判定为高风险,拦截器直接返回不允许执行的错误,并把这一事件标记为 potential risk 上报网关。

关键设计在于,网关的"黑盒检查"和 Harness 的"白盒校验"都不会单独放行任何一次工具调用。Gateway 管住的是"谁可以走到运行时",Harness 管住的是"运行时内什么动作可以真正发生",两道闸在同一请求链路里协同工作,任何一道拦截都会阻断整条链路。这种双保险在实际生产里非常有用,因为两边用的判定维度不同:网关看身份和流量特征,Harness 看意图和上下文语义,交叉验证时误报和漏报都明显低于单一方案。

3. 实时安全防线的核心实现:认证、鉴权、审计、限流

架构理清楚了,接着看真正落到项目里要做的部分。这四个能力是所有安全防线里最核心的,拆开逐一讲。

3.1 身份绑定:让每个工具调用都有"户主"

Agent 场景最头疼的问题之一就是身份传递。用户发起主请求,Agent 在内部可能拆成多个子调用,甚至某些场景下还会有多 Agent 协作。如果每一步都不知道当前的最终用户是谁,权限就无从谈起。

我们的做法是在 Harness 里维护一个身份上下文对象,里面包含 user_id、tenant_id、agent_id、session_id 和一组动态 scope。每一次工具调用执行前,拦截器都会从这个上下文取 principal,去 AgentCore Gateway 预下发的策略里查这个 principal 有没有对应权限。同时,Gateway 在入口处会把身份信息用 JWT 方式绑定到请求体上,强制内部所有服务不得自行覆盖身份字段。这个设计后来在排查泄漏类事故时帮了大忙,随便拉一个工具调用日志,都能定位到用户、会话和 Agent 实例。

注意:不要让模型自己决定身份。曾经有个 Agent 框架版本允许系统指令里指定"以管理员身份执行",这种写法在权限模型里必须彻底封禁。身份只能从可信的网关入口注入,任何从模型输出中解析出来的身份声明都不予采纳。

3.2 工具级 RBAC 鉴权:拒绝超范围的任何调用

单体应用时代我们习惯给服务配一个全局角色,但 Agent 的粒度不一样。同一个用户在这条会话里可能被允许读订单,却不允许删订单,这个判断必须细化到工具方法和参数上。

Harness 的拦截器里,我通常会配置一个 RBAC 策略表,结构大概是"主体、上下文条件、动作、资源路径、允许/拒绝"。当一个模型发出 delete_order 调用时,拦截器不仅会查主体有没有 delete_order 的权限,还会查资源路径是否匹配当前用户绑定的租户范围。跨租户删除、跨项目读取、关闭审计开关等高风险操作,在策略表里全部设为显式拒绝,任何情况下都不能被覆盖。

这块有个容易忽略的点:工具调用的参数也可能成为注入载体。我们在参数校验层面加了白名单规则,比如 update_user_profile 的 biography 字段不允许超过一定长度,不允许包含可执行的关键词模式。这样即使用户把恶意指令塞进参数里,也不会直接落到下游系统。

如果想加深对这套模型的理解,可以把 RBAC 规则想象成机场安检的"黑名单 + 白名单"双通道。白名单决定哪些人可以上飞机,黑名单决定哪些行为一旦出现就整体停飞。Agent 工具调用也一样,既要允许正常的读操作,也要把那些"危险但合法"的操作限制在特定条件下。

3.3 内容审计与提示注入检测

提示注入是 Agent 最经典的攻击方式。攻击者把恶意指令隐藏在输入文本中,让模型以为自己收到了更高优先级的系统指令。完全杜绝很难,但实时防线至少要做三件事。

第一,在 Gateway 层对入站请求做轻量级模式检测。关键词特征、Base64 编码特征、频繁出现"忽略之前指令""你是系统管理员"等典型模式的请求,直接降级为待审核状态或拦截。

第二,在 Harness 层对最终拼接进模型的上下文做"指令边界标记"。我们会把系统指令、用户指令、工具返回内容用不同类型的分隔标记包裹,并明确告诉模型:只有在 system 标记内的内容才具有指令效力,其他位置都只是数据。这个做法实测下来能明显减少"数据被当指令"的情况。

第三,对工具返回的文本做二次污染检测。已经发生过攻击者先诱导 Agent 调一次工具,再把污染文本通过工具结果塞进上下文去影响下一次决策。针对这种情况,Harness 在把工具结果写回上下文之前会跑一遍净化逻辑:剥离可执行性标记、截断异常超长内容、标记来源类型。虽然不能百分百防住对抗性注入,但能把攻击面压到很窄。

下面是一个简化的拦截器伪代码示意,展示了运行时层检测的思路。

# harness 运行时中的工具调用拦截器(示意代码) async def pre_tool_call(ctx, tool_name, args): # 1. 解析可信身份 principal = ctx.identity # 来自网关 JWT,不可被模型输出覆盖 if principal.is_internal_service(): raise PermissionDenied("internal principal cannot call external tools") # 2. 工具级 RBAC 判定 if not rbac_check(principal, f"tool:{tool_name}", args.get("resource")): metrics.counter("rbac_deny").inc() raise PermissionDenied(tool_name) # 3. 参数与内容净化 for key in ARG_BLACKLIST_PATTERNS: if re.search(key, json.dumps(args)): metrics.counter("arg_blocked").inc() raise ContentPolicyViolation(key) # 4. 超时与幂等校验 if requires_idempotency(tool_name): if ctx.client_request_id in recently_executed_cache: return previous_result(ctx.client_request_id)

流程看着简单,但顺序不能乱。身份解析必须放在最前面,任何权限判定、内容检测都基于可信身份展开;如果身份都不可信,后面所有的判定都没有意义。

3.4 Token 预算与三层并发控制(它怎么扛住高并发)

热搜里很多人问"ai agent 怎么扛并发"。我的回答是,Agent 并发不能按普通接口并发的思路来设计。普通接口把并发打高就行,Agent 每个请求都要消耗 LLM 算力、可能要串行调用多次工具、还要维护大上下文,直接在网关层简单堆并发会让后端直接雪崩。

推荐的做法是把并发控制拆成三层。

  • 入口层限流:AgentCore Gateway 按客户端维度限制每秒请求数。之所以放在网关而不是 Harness,是因为要在流量还没进内部时就挡住,避免消耗模型服务资源。
  • 运行时限流:Harness 内按 Agent 实例维度设置并发槽位,超过槽位的调用进入队列而不是直接拒绝,关键任务可以配置优先级。
  • 模型层预算:给每次会话分配 token 预算,Harness 在步骤累计消耗接近阈值时主动切换轻量模型或终止规划循环。

三层配合之后,我们对一个爆量场景做过压测:客户端并发从 200 涨到 2000 时,模型服务端的有效请求数始终被控制在设定值内,队列超时率稳定在 5% 以下。这个结果说明限流不是把请求挡掉就完事,而是要有一套"排队、降级、熔断"的组合逻辑。

有个很常见的误解是"token 预算不就是限制一次请求能用多少 token"。其实它更重要的是控制 Agent 的规划循环长度。如果模型陷入循环调用工具,token 消耗会指数增长,预算机制实际上是在给 Agent 的"思考"设置上限,让它在一个合理范围内收敛。

3.5 全链路审计与配置回滚

最后一个核心能力是审计。很多 Agent 框架自带简单的对话存档,但安全审计需要的是可完整回放的事件链。我们最终把审计事件分成三类:

事件类型记录内容保存位置
入口事件请求来源、身份、网关策略评估结果AgentCore Gateway 审计日志
决策事件模型输出、tool_call 参数、拦截器判定结果Harness 运行时日志
执行事件工具真实执行结果、耗时、错误码工具侧调用日志

三个事件通过 trace_id 关联,排查问题时只要拿一个 trace_id 就能把整条链路的日志拉齐。这套审计在"配置回滚"场景里尤其重要。我们上线过一个有问题的策略导致正常工具调用被大量误杀,当时立刻用 Harness 的配置版本控制把策略回滚到上一个稳定版本,同时用 trace_id 定位受影响的那段请求重放验证,全程没有重启服务。

4. 实操落地:从部署到策略配置的完整路径

讲完理论,把落地过程完整过一遍。我们当时从零到一搭这套架构,前后大约两周,下面是这过程中被验证有效的步骤。

4.1 部署 Harness 运行时的关键步骤

Harness 的部署方式我们用的是独立运行时 + 容器化。第一步是把它做成一个 sidecar 容器,和 Agent 应用部署在同一个 Pod 里,这样拦截器可以通过本机端口访问,不引入额外的网络路径。

第二步是配置运行时插件。Harness 本身支持插件化加载,我们把安全相关的拦截器做成了独立插件,通过配置文件声明加载顺序。加载顺序是我强烈建议重点关注的:先做身份解析,再做权限校验,再做内容审计,最后做 token 统计。顺序反了会导致一部分高危请求已经执行完才记了日志,起不到拦截作用。

第三步是接入配置中心的策略下发。策略不能写死在镜像里,因为安全策略的变更频率远高于应用发布频率。我们用配置中心管理一组 JSON 策略文件,运行时收到变更事件后热加载,不用重启 Agent 进程。热加载机制上线后,每次策略调整的平均生效时间从小时级降到了秒级,这对应急响应来说非常关键。

4.2 配置 AgentCore Gateway 路由与策略

网关侧的核心配置是路由和策略的绑定关系。下面这份是简化后的路由配置片段,基本结构是我们生产环境的真实模板。

gateways: - name: agentcore-gw-prod listen: 0.0.0.0:8443 routes: - path: /agent/v1/chat target: harness-runtime-svc:9001 policies: auth: mode: JWT issuer: https://id.internal.example rate_limit: per_client_rps: 50 burst: 100 body_inspect: max_bytes: 65536 block_patterns: ["system_role_override", "ignore_previous_instructions"] audit: mode: full sample_ratio: 1.0

这一段配置里最容易被误解的是body_inspect里的block_patterns。它不是在做语义分析,只是第一道文本特征过滤,要求超时时间极短,不影响正常请求。真正精细的语义判断永远在 Harness 层做。如果把这层做重了,网关反而会变成性能瓶颈。

4.3 策略配置示例与参数解读

再看 Harness 侧的策略文件。同样给出实际生产中简化过的版本。

{ "policies": { "default": { "identity": {"source": "gateway_jwt", "override": false}, "rbac": { "rules": [ { "principal": "{user_id}", "condition": "tenant:{tenant_id}", "action": "do:order:read", "resource": "order/{region}/{tenant_id}/*", "effect": "allow" }, { "principal": "*", "action": "admin:*", "effect": "deny" } ] }, "tool_intercept": { "enabled": true, "pre_check": true, "parameter_validation": { "strict": true, "max_depth": 4 } }, "token_budget": { "per_session": 20000, "per_step": 3000, "on_exceed": "downgrade_model" } } } }

几个参数值得细细说。"override": false是防止 Agent 内部代码自己改身份来源,前面讲身份绑定时说的封禁就是从这来的。resource里的{region}和{tenant_id}是动态占位符,系统在判定时用身份上下文里的值替换,这样同一套规则能服务不同租户,不需要为每个租户各写一份。token_budget的on_exceed我选了downgrade_model,意思是超预算的会话从高性能模型切到轻量模型继续跑,而不是直接中断。理由是客服场景里任务中断的体验伤害大于回答质量轻微下降。

5. 常见问题与排查技巧实录

5.1 身份传递断裂:子代理调用丢用户上下文

多 Agent 协作是身份链断裂的高发地。我们曾遇到这样的问题:主 Agent 把一个代码审查任务交给子 Agent,子 Agent 发起的工具调用被 Gateway 判为未授权。查日志发现子 Agent 拿到的是一个内部服务账号身份,用户身份在路上丢了,这是拼写错误导致的:代码里把x-user-id拼成了x-userid,网关识别不了。

排查并不难,把入口事件和决策事件对齐,对比principal字段就能看出来。抓到根因后我们在 Harness 的身份解析插件里加了一条校验:如果解析出的身份为空或者来自内部服务账号,则拒绝放行这个请求,不让它带着残缺身份继续往下走。这里想说的一点是,别过度相信框架默认的上下文透传,安全身份字段必须在每个边界点显式校验。

5.2 限流误伤:重试风暴比并发本身更可怕

一次线上压测,HTTP 400 的数量骤增,排查了很久发现是网关限流触发后,客户端 SDK 默认自动重试机制导致重试风暴。客户端 A 被限流,重试打进来,网关继续限流,客户端继续重试,最终把网关的连接池打满,受影响的不只是 A,连正常用户也一起被拖死。

解决方案在两端同时做。网关侧对限流响应加了Retry-After头,并区分"可重试错误"和"不可重试错误"的状态码;客户端侧的 SDK 则加上了指数退避和最大重试次数。之前只做一端的时候效果不好,这说明限流这类问题必须上下游一起约定协议,单靠一边很难彻底解决。

5.3 审计日志被刷爆:日志采样的取舍

上线审计全量记录后,日志系统的成本飙升了快三倍,每天新增的存储增量直接吓人。我们最初设置的是所有事件全量记录,结果发现大量价值极低的调试日志混在里面。

后来调整了策略:入口事件和决策事件按 100% 采样,执行事件只在工具调用出现异常或耗时超过阈值时记录。这套规则下存储量下降了 60%,但安全事件相关的关键信息基本没丢。想提一句的是,审计采样的取舍要根据自己业务的合规需求来,如果行业要求全量审计留痕,那就只能接受成本,我们当时是因为内部风险审计允许按风险分级采样才敢这么调。

5.4 工具超时与幂等设计

Agent 的实时安全防线里,工具超时是最容易被忽视的一环。我们踩过一次坑:某次工具调用超时,拦截器把它判定为失败并让模型重新规划,结果重复执行了一个非幂等的下单接口,客户被重复扣款。

从那以后,所有工具接入 Harness 前都必须做幂等改造:写操作带上 client_request_id,Harness 在重试前检查这个 ID 是否已经执行过。同时拦截器侧配置了超时分级:快速失败的接口给 3 秒,外部 API 给 10 秒,数据库长任务给 30 秒,超过时间统一按失败处理但不自动重试,交给模型走人工确认分支。这套改完,至少把重复执行的坑填平了。

6. 最后的几条个人体会

6.1 分层防线要避免的常见误区

抛开架构和代码,讲几句实际的体会。第一,AI Agent 的安全防线一定是分层设计而不是单点加固,网关层和运行时层缺一不可。我们初期只做了网关层,效果很差,因为真正的风险点在下游工具调用链;加上 Harness 运行时拦截后才真正管住了。第二,安全策略要预案先行,不要等出事再加规则。上线之前把提示注入特征、越权调用类型、重试风暴场景都先列成一个清单,哪怕不完整也先建框架,后面再补。第三,别让实时安全变成实时卡顿,在校验链路上严格控制检测逻辑的耗时,尽量把重计算放在异步审计里,同步链路上只保留轻量判定。

6.2 扩展方向与给不同规模团队的建议

如果团队规模不大、Agent 数量还少,可以先从 Harness 运行时拦截器入手,把工具调用链路的权限、内容检测、身份注入做好,网关层可以用相对轻量的方案代替。如果团队已经开始规模化接入多个 Agent、多个模型底座,那 AgentCore Gateway 这类统一边界就是必需品,它解决的不只是安全,还有流量治理和协议适配成本。

后续如果向多 Agent 协作场景扩展,还需要关注三件事:跨 Agent 的身份链传递、全局 token 预算的分配、以及统一的策略治理面。这三点我们目前还在持续打磨,但基于现有的"Harness 运行时 + 统一网关"骨架,扩展路径已经比较清晰。希望这篇内容能给正在做 Agent 生产落地的团队一些可参考的思路,少走我们走过的弯路。

返回列表