AWS Machine Learning Blog

Securing AI agents with temporal policies in Amazon Bedrock AgentCore

8.5内容质量
Securing AI agents with temporal policies in Amazon Bedrock AgentCore

TL;DR · AI 摘要

Amazon Bedrock AgentCore通过时间策略实现基于会话历史的动态授权,防止AI代理绕过安全控制。

核心要点

  • 时间策略在网关层运行,无法被代理代码绕过
  • 可防止数据篡改和金融风险暴露超过阈值
  • 自动收紧权限当检测到无人工参与操作

结构提纲

按章节快速跳转。

  1. 传统访问控制无法应对AI代理的动态行为,需引入时间策略

  2. 时间策略在网关层评估会话轨迹,实现状态感知授权

  3. 防止数据篡改、金融风险超限、重复保险理赔等场景

  4. 通过策略定义、轨迹分析、权限动态调整三阶段实现

  5. 策略无法被代理代码拦截或篡改,确保执行不可绕过

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • Amazon Bedrock AgentCore安全
    • 时间策略机制
      • 网关层执行
      • 轨迹分析
    • 应用场景
      • 防止数据篡改
      • 金融风险控制
      • 操作合法性验证

金句 / Highlights

值得收藏与分享的关键句。

#AWS#AI安全#AgentCore#时间策略#机器学习
打开原文

使用时间策略在Amazon Bedrock AgentCore中保护AI代理 | 人工智能

使用时间策略在Amazon Bedrock AgentCore中保护AI代理

在AI代理出现之前,访问控制通常只需将每个操作视为独立事件即可。应用程序依赖确定性的业务逻辑来确保操作是否按正确顺序执行或数据是否最新。AI代理的行为与传统应用程序有本质区别。它们在运行时决定调用哪些工具、使用哪些参数以及执行顺序。这种灵活性加上日益智能的模型,使代理既具备强大能力又难以控制。单独考虑时,一次工具调用可能被视为安全,但在前一次调用的上下文中可能造成危害,例如在读取不可信数据源之后。问题随之而来:如何制定授权规则,使代理无法规避地考虑其会话历史?

Amazon Bedrock AgentCore中的时间策略使您可以定义有状态的规则,通过评估当前请求在代理轨迹中先前事件的上下文,来确定对AgentCore网关目标的授权。由于这些策略在AgentCore网关外围运行,位于代理代码之外,因此代理无法拦截或篡改它们。

在本文中,您将了解时间策略是什么、它们如何工作,并通过示例进行演示。我们将向您展示如何使用时间策略强制执行工作流程顺序、防止工具调用之间的数据伪造、限制每会话的累计财务敞口,并要求对高价值操作进行人工批准。您还将看到如何在代理在没有人工参与的情况下运行时自动收紧权限。不过,首先我们将更详细地探讨有状态策略的需求和使用场景。

为什么代理需要有状态策略执行

AgentCore策略中的现有访问控制对每个请求执行无状态、确定性规则:谁可以调用哪个工具,在什么条件下。无状态控制是必要的,但通常不足以应对代理的需求。考虑以下现有无状态控制无法发现关键问题的场景:

  • 代理调用lookup_customer工具,编造与返回结果不同的账户号码,并将其传递给transfer_funds工具,导致资金转移到错误客户的账户。
  • 失控的代理在循环中执行数十笔交易,因为没有任何机制跟踪累计敞口已超过风险限额。
  • 代理在几秒钟内同时批准和拒绝同一份保险索赔。

在这些场景中,每个单独的工具调用都会通过无状态策略检查。只有在查看代理的轨迹——即会话中操作的有序序列时,问题才会显现。时间策略通过在AgentCore中添加这种轨迹感知的执行层,扩展了策略功能。时间策略在网关运行,位于代理代码之外,因此无论代理执行什么操作、如何被提示或代理代码中存在什么错误,都无法绕过这些策略。一些常见的时间策略使用场景包括:

  • 在链式工具中强制输出完整性。要求传递给当前工具调用的参数必须与先前工具调用的输出完全匹配,防止代理在步骤之间编造或替换值。
  • 强制执行工具调用顺序。要求在调用某个工具之前必须先调用另一个工具,以验证是否符合标准操作流程(SOP)。
  • 在执行特权操作前要求人工审批。在记录明确的人工审批事件之前,阻止执行破坏性或敏感的工具调用。
  • 强制数据新鲜性。要求在授权相关操作前,必须完成在指定时间范围内的数据查询,防止基于过时信息做出决策。时间策略是授权控制机制,用于回答“根据AgentCore网关观察到的最近轨迹,该特定请求是否被授权?”的问题。它们基于当前请求和近期轨迹(即会话内的事件)来判断网关路由的请求是否应被允许。它们不会转换请求、调用工具、执行分析或直接协调代理。

时间策略作用于通过AgentCore网关传输的流量。由于网关通过单一端点路由代理的模型上下文协议(MCP)工具调用、代理间调用和模型推理调用,因此当代理通过网关发出这些调用时,时间策略可以统一管理所有三种类型的调用。这为您提供了统一的视角来分析代理随时间推移的行为,无论代理执行的是哪种类型的调用。

时间策略的工作原理

时间策略基于现有的策略引擎,该引擎已用于无状态访问控制。它们引入了代理轨迹的概念,轨迹是由主体和会话ID标识的有界操作序列。代理永远无法看到策略逻辑,不会接触状态存储,也无法更改控制规则。与现有的AgentCore策略功能一样,时间策略默认拒绝,禁止权限优先于允许权限。

当网关接收到工具调用时,策略引擎会执行以下操作:

  • 查询与正在评估的策略相关的操作、输入和输出的轨迹状态。
  • 在历史范围(即客户定义轨迹中的先前事件)的上下文中,将每个时间策略与当前请求进行评估。
  • 返回确定性的允许(ALLOW)或拒绝(DENY)决策,并记录决策的完整上下文。

每个时间策略评估的请求都必须携带一个x-amzn-bedrock-agentcore-policy-session-id头,用于标识请求所属的会话。您决定会话的开始和结束条件。边界可以反映对您的应用程序有意义的任何工作单位,无论是单个用户对话、多步骤任务还是更长的运行工作流。由于每个会话最多只能有一个并发授权请求,我们建议尽可能缩小会话的范围。如果没有传递头信息,系统将为您生成一个。但请注意,新的会话ID意味着策略引擎将针对一个全新的、无历史记录的轨迹进行评估。

会话从不只由其ID单独定义。AgentCore将会话ID与终端用户的身份结合,生成唯一的会话,这意味着两个不同的身份可以使用相同的会话ID,但仍会被视为完全独立的会话。由于底层身份不同,策略会独立应用于每条轨迹。在活跃会话期间,代理轨迹携带的最大回溯窗口为24小时。超过该时间的轨迹事件会自动删除。会话与策略之间还有一个附加规则:每当策略引擎中的策略发生变更时,现有会话将被失效。这确保每个会话都基于当前策略集进行评估,并且每个相关轨迹事件都会以预期的模式记录。

将时间策略应用于私人银行投资组合代理

为了使这些概念更具体,我们将逐步说明时间策略如何保护一个假设的私人银行代理。该代理帮助金融服务公司的财富顾问管理客户投资组合。它会检索客户档案、加载投资组合持仓、获取实时市场价格、执行分析,并代表顾问执行交易。

在此场景中,以下MCP工具通过AgentCore网关暴露:

工具 | 描述 ---|--- get_client_profile | 获取客户的风险承受能力、投资政策、账户限制和相关投资组合ID load_portfolio | 获取客户的投资组合持仓和当前头寸 get_market_price | 获取证券的当前市场价格 execute_trade | 对投资组合执行买入或卖出订单 rebalance_portfolio | 调整投资组合在持仓间的配置

存在三种不同的顾问角色:初级顾问(有限交易权限)、高级顾问(完整交易权限)和合规官(只读监控权限)。在此示例中,我们将使用Amazon Cognito进行身份验证,并通过JWT向AgentCore网关传递入站认证。要了解AgentCore网关以及如何与网关设置认证,请阅读《AgentCore网关文档》。时间策略使用Dogwood,这是一种专为代理及其工具设计的新开源治理语言。Dogwood支持评估现有的Cedar策略,并启用时间条件的支持。由于Dogwood与现有Cedar策略兼容,客户无需迁移即可继续使用当前的Cedar策略。有关Dogwood及其语义的更多细节,可以阅读语言文档或这篇博客文章。

合规团队要求在代理投入生产前实施以下时间控制措施:

  • 代理必须先获取客户档案,然后加载投资组合,之后才能执行任何交易。
  • 交易中使用的portfolio_id必须与get_client_profile的输出完全匹配。
  • 市场价格必须在交易执行后1分钟内获取。
  • 任何单个会话的总交易价值不得超过60,000美元。
  • 任何单笔超过25,000美元的交易都需要顾问批准,每笔交易需要一次批准。
  • 代理不能在同一轨迹中先买入再以亏损价格卖出同一证券。
  • 在顾问15分钟无操作后,代理将失去写操作权限。

请求通过网关和策略的流程

图1:请求通过AgentCore网关和策略的流程

该图示展示了请求如何通过AgentCore网关被策略拦截和评估。当投资组合代理发起工具调用时,将发生以下步骤:

  • 请求到达AgentCore网关。顾问已通过AgentCore身份验证。请求携带当前会话的轨迹ID。
  • 策略引擎检索轨迹的累积状态。
  • 每个时间策略会将当前请求与历史记录进行比对。
  • 如果所有策略都允许,请求将传递给MCP工具。如果任何策略禁止,请求将被拒绝并记录拒绝信息。
  • 成功执行后,操作及其结果将被追加到轨迹状态中,供未来评估使用。

实现时间策略

如果您已有处于ENFORCE模式的策略引擎,可以将其实施模式更新为LOG_ONLY,或者更改单个策略的实施模式。不建议将现有策略或策略引擎切换为LOG_ONLY模式用于生产工作负载,因为策略将不再执行这些安全规则。

先决条件

在实施此解决方案之前,请确认您已满足以下先决条件:

  • 启用Amazon Bedrock AgentCore的活动AWS账户。
  • 配置了至少一个MCP目标的AgentCore网关。
  • 附加到网关的策略引擎。
  • 创建和管理策略资源的适当身份和访问管理(IAM)权限(参见文档)。

策略1:工作流序列(多跳链)

合规团队要求代理必须按顺序执行get_client_profile、load_portfolio和rebalance_portfolio。没有客户档案时,代理将无法获得系统验证的上下文信息,包括哪些投资组合属于该客户、客户的风险承受能力或适用的账户限制。

code
permit (principal, action == AgentCore::Action::"FinTarget___load_portfolio", resource == AgentCore::Gateway::<GATEWAY_ARN>)
when temporal {
    formerly within 5m (AgentCore::Action::"FinTarget___get_client_profile"::response{eventResource: resource})
};

permit (principal, action == AgentCore::Action::"FinTarget___rebalance_portfolio", resource == AgentCore::Gateway::<GATEWAY_ARN>)
when temporal {
    formerly within 5m (AgentCore::Action::"FinTarget___load_portfolio"::response{eventResource: resource})
};

该策略禁止在未按正确顺序完成get_client_profile和load_portfolio的情况下执行rebalance_portfolio。即使代理接收到相关指令,若跳过加载档案步骤直接进行再平衡操作,请求将被拒绝。

轨迹状态 | 尝试的操作 | 预期结果 ---|---|--- 空 | rebalance_portfolio (portfolio_id: "8821", amount: 15000) | 拒绝 get_client_profile已完成 | get_client_profile然后load_portfolio已完成 | rebalance_portfolio(portfolio_id: "8821", amount: 15000) | 允许

策略2:输出到输入的完整性

传递给execute_trade的portfolio_id必须与get_client_profile返回的其中一个投资组合ID完全匹配。代理不能伪造或替换不同的投资组合ID。

code
permit (
    principal,
    action == AgentCore::Action::"execute_trade",
    resource
)
when temporal {
    formerly within 24h (
        AgentCore::Action::"get_client_profile"::response{
            input.profile_id: context.input.profile_id,
            eventResource: resource
        }
    )
};

此策略可防止攻击者利用提示注入诱导代理人为其他客户的账户执行交易。攻击者可能说服语言模型使用伪造的ID,但该策略会将值与CRM系统实际返回的结果进行验证。

get_client_profile 返回

execute_trade 账户ID

端口-8821

端口-3347

策略3:数据新鲜度

在授权 execute_trade 之前,必须在最近30秒内完成 get_market_price 调用。代理不能基于过时的报价进行操作。

code
permit (
    principal,
    action == AgentCore::Action::"execute_trade",
    resource
)
when temporal {
    formerly within 30s (
        AgentCore::Action::"get_market_price"::response{eventResource: resource}
    )
};

在波动性市场中,即使60秒前的报价也可能出现显著的价格偏离。此策略强制代理在每次交易前刷新市场数据,确保决策基于最新信息。

自 get_market_price 调用以来的时间

操作

4秒前

买入股票A

2分钟前

从未调用

策略4:每轨迹累计预算上限

单个策略会话(或轨迹)内的总交易价值不得超过60,000美元。这可限制失控代理或成功攻击造成的潜在影响范围。

code
permit (
    principal,
    action == AgentCore::Action::"execute_trade",
    resource
)
when temporal {
    exists (total: Long). ((sum amount for (amount: Long), (t: Timepoint). where (formerly within 24h (
        AgentCore::Action::"get_market_price"::request{input.cost: amount, eventResource: resource} && tp(t)))) == total && total < 60000
    )
};

被攻破的代理执行数十笔看似正常的小额交易,仍可能导致灾难性风险累积。当累计达到60,000美元后,所有交易将被拒绝,直到开始新的轨迹。

先前累计交易

当前交易金额

总计

0美元

15,000美元

22,000美元

37,000美元

30,000美元

67,000美元

策略5:大额交易的人工审批(一次性消耗)

任何超过25,000美元的交易都需要顾问的明确批准。每个批准仅对应单笔交易。第二次大额交易需要新的批准。

code
permit (
    principal,
    action == AgentCore::Action::"execute_trade",
    resource
)
when {
    context.input.cost < 25000 || temporal {
        !(
            AgentCore::Action::"execute_trade"::response{eventResource: resource}
        )
        since within 24h (
            AgentCore::Action::"approve_trade"::response{ input.status: "approved", eventResource: resource}
        )
    }
};

这可防止代理将单次批准误解为对多次大额交易的通用授权。每个批准仅对应一次执行。

交易金额

轨迹中的审批状态

允许(低于阈值)

已批准(未消耗)

30,000美元(第二次交易)

仅存在已消耗的先前批准

策略6:互斥操作

如果代理在同一轨迹中以亏损价格卖出同一证券,则不能先买入再卖出。

code
permit (
    principal,
    action == AgentCore::Action::"execute_sell",
    resource
)
unless {
    context.input.profit < 0 && temporal {
        formerly within 24h (
            AgentCore::Action::"execute_buy"{
                stock_symbol: context.input.stock_symbol, eventResource: resource}
        )
    }
}
};

如果代理在两分钟前卖出AAPL,现在尝试买入AAPL,该请求将被拒绝。这种矛盾本身就是一个信号,表明出现了问题,需要重新审查会话。

先前操作

当前操作

时间间隔

卖出股票A

2分钟

7分钟

买入股票B

允许(不同证券)

策略7:渐进信任衰减

在15分钟内没有顾问交互后,代理将失去对写操作(execute_trade、rebalance_portfolio)的访问权限。顾问可以在任何时候重新介入以恢复完整权限。

code
permit (
    principal,
    action in [
        AgentCore::Action::"execute_trade",
        AgentCore::Action::"rebalance_portfolio"
    ],
    resource == AgentCore::Gateway::"<arn>"
)
unless temporal {
    formerly within 15m AgentCore::Action::"interact_advisor"::response{eventResource: resource}
};

当顾问离开时,代理会自然地收敛到只读行为。这确保了长时间的自主操作不会积累未受控的风险。

自上次顾问交互以来的时间

3分钟

20分钟

允许(只读)

成本考量

您只需为代理执行期间发生的授权请求付费。每次代理通过AgentCore网关调用工具时,策略都会将操作与您的规则进行比对,以确定是否允许或拒绝。您在每个策略引擎中的前100个临时策略包含在现有每授权请求的价格中(详见AgentCore定价页面)。

清理

为避免持续收费,请删除本操作指南中创建的资源。按顺序删除资源:首先从策略引擎中删除临时策略,然后将策略引擎从网关分离,最后删除策略引擎本身。只要策略引擎仍包含策略或仍连接到网关,就无法删除它。如果您创建了网关,并且仅用于本操作指南,请一并删除这些网关。请注意,删除或修改策略会使所有活动策略会话失效,因此请在测试会话完成后执行清理操作。

列出并删除策略引擎上的策略。对每个策略重复删除策略命令:

code
aws bedrock-agentcore-control list-policies $
  --policy-engine-id <POLICY_ENGINE_ID>

aws bedrock-agentcore-control delete-policy $
  --policy-engine-id <POLICY_ENGINE_ID> $
  --policy-id <POLICY_ID>

通过更新网关(不带策略引擎配置)将策略引擎从网关分离:

code
aws bedrock-agentcore-control create-gateway $
  --name my-gateway $
  --role-arn arn:aws:iam::123456789012:role/my-gateway-service-role $
  --protocol-type MCP $
  --authorizer-type CUSTOM_JWT $
  --authorizer-configuration '{
    "customJWTAuthorizer": {
      "discoveryUrl": "https://cognito-idp.us-west-2.amazonaws.com/some-user-pool/.well-known/openid-configuration",
      "allowedClients": ["clientId"]
    }
  }'

删除策略引擎:

code
aws bedrock-agentcore-control delete-policy-engine $
  --policy-engine-id <POLICY_ENGINE_ID>
code
aws bedrock-agentcore-control delete-gateway-target $
  --gateway-identifier <GATEWAY_ID> $
  --target-id <TARGET_ID>

aws bedrock-agentcore-control delete-gateway $
  --gateway-identifier <GATEWAY_ID>

结论

在本文中,你学习了时态策略如何为智能体AI系统带来有状态的、轨迹感知的授权能力。你将七种策略模式应用到一个假设的私人银行投资组合智能体上。这些模式涵盖了工作流顺序控制、输入输出完整性、数据新鲜度、累计预算上限、人机协同审批、互斥控制以及渐进信任衰减。这些模式可以推广到智能体在运行时与敏感工具交互的各个领域。由于执行发生在AgentCore网关边界,位于智能体自身推理循环之外,这些保护措施无论模型行为如何都保持不可篡改。这为你提供了一种声明式、可审计的方式来强制操作边界,同时不会限制使智能体有价值的那种灵活性。要开始使用,请查阅AgentCore文档。

作者简介

'"`