Claude Managed Agents 数据驻留怎么配:用 model.inference_geo 固定推理地域
【免费下载链接】claude-cookbooksA collection of notebooks/recipes showcasing some fun and effective ways of using Claude.项目地址: https://gitcode.com/GitHub_Trending/an/claude-cookbooks
如果一个 agent 会接触受监管的数据,上线前必须先回答一个问题:它的模型请求在哪里运行。写在代理层或 runbook 里的保证,落在系统之外;model.inference_geo把这个答案直接放在 agent 定义上,让约束随 agent 一起走,甚至在 agent 发布之后政策变更仍然生效。本文基于 CMA_pin_inference_geo.ipynb 走一遍完整操作:把一个 agent 固定到us推理、在 session 上验证 pin、理解它与 workspace 驻留策略的交互,以及更新 agent 时 pin 被清空的坑。
准备条件
inference_geo走标准的managed-agents-2026-04-01beta 头,且需要anthropic>=0.121.0才有对应的类型化字段。按 managed_agents/README.md 的说明,先设置ANTHROPIC_API_KEY环境变量,然后在 Jupyter 中打开 notebook 从上到下运行;依赖由 notebook 自己安装:
%%capture %pip install -qU "anthropic>=0.121.0" python-dotenv初始化客户端。MODEL从环境变量COOKBOOK_MODEL读取,未设置时默认claude-sonnet-5:
import os import anthropic from dotenv import load_dotenv load_dotenv() BETAS = ["managed-agents-2026-04-01"] MODEL = os.environ.get("COOKBOOK_MODEL", "claude-sonnet-5") client = anthropic.Anthropic()后文所有 API 调用都带betas=BETAS,这一点不能漏。
在 agent 定义上固定推理地域
inference_geo位于model配置块内,与effort、speed同级,接受的值是"global"和"us"。两个行为差异决定了要不要设这个字段:
- 不设:每次模型请求在服务时刻解析到 workspace 当前的
default_inference_geo,之后修改 workspace 默认值会波及已经在运行的 session。 - 设置:pin 固定在这个 agent 上,不随 workspace 默认值变化。
创建一个固定到us的 agent:
researcher = client.beta.agents.create( name="us_records_analyst", description="Answers questions about internal records, pinned to US inference.", model={"id": MODEL, "inference_geo": "us"}, system="You answer questions about the records you are given, concisely.", tools=[{"type": "agent_toolset_20260401"}], betas=BETAS, ) print(f"{researcher.name}: {researcher.id} v{researcher.version}") print("inference_geo:", researcher.model.inference_geo)如果 workspace 的allowed_inference_geos不允许"us",这一步在保存时直接返回 400,后面"workspace 策略"一节会展开。
在 session 上确认 pin 是否生效
session 在创建时会对 agent 配置做一次快照,所以 pin 可以在session.agent.model上读回。这个读回检查能确认这个 session 的每一轮都绑定在us上,独立于 workspace 默认值今天是什么。先建一个anthropic_cloud类型的 sandbox 环境,再创建带初始消息的 session,然后流式读取直到 idle:
env = client.beta.environments.create( name="residency-demo", config={"type": "anthropic_cloud", "networking": {"type": "unrestricted"}}, betas=BETAS, ) session = client.beta.sessions.create( agent=researcher.id, environment_id=env.id, title="Records question, US-pinned", initial_events=[ { "type": "user.message", "content": [ {"type": "text", "text": "In one sentence: what is a data residency policy?"} ], } ], betas=BETAS, ) print("session pin:", session.agent.model.inference_geo) with client.beta.sessions.events.stream(session.id, betas=BETAS) as stream: for ev in stream: if ev.type == "agent.message": print("".join(b.text for b in ev.content if b.type == "text"), end="") elif ev.type == "session.status_idle": print(f"\n[idle] stop_reason={ev.stop_reason.type}") break验证方式是看session pin:这行输出是否为us(agent 回答的具体文本是模型输出,因运行而异),以及流在session.status_idle事件处退出。
workspace 策略决定 pin 能指向哪里
workspace 的驻留策略位于 Admin API 的 workspacedata_residency块中,包含两个字段:
allowed_inference_geos:地域列表,或字面值"unrestricted";default_inference_geo:未设 pin 的 agent 实际使用的地域。
agent 的inference_geo必须是allowed_inference_geos的成员(除非该字段为"unrestricted"),否则保存时返回 400。
pin 会被校验三次:agent 保存时、从它创建 session 时、以及 session 服务的每一轮上。它是严格强制而非祖父条款:如果管理员事后收窄allowed_inference_geos,一个"不再被允许"的 agent 的新 session 会被拒绝,而已经在运行的 session 会拒绝它的下一轮。这个严格性正是它能当驻留控制用的原因——pin 对会话中途发生的政策变更同样成立。多 agent 名册(roster)还有一条额外约束:coordinator 和每个 roster 成员要么全部设为同一个 geo,要么全部不设。
agents.update 时 pin 会被清空的一个坑
agents.update对model是整体替换而不是合并,所以只发model而不带inference_geo会清掉 pin。要改模型 id 同时保留地域,必须重新声明 pin:
cleared = client.beta.agents.update(researcher.id, model={"id": MODEL}, betas=BETAS) print("after model update without geo:", cleared.model.inference_geo) researcher = client.beta.agents.update( researcher.id, model={"id": MODEL, "inference_geo": "us"}, # restate the pin betas=BETAS, ) print("restated:", researcher.model.inference_geo)这段示例演示了两种调用方式的对比:第一次 update 不带inference_geo,第二次重新带上。如果日常用agents.update改过模型配置,检查返回对象的model.inference_geo是防止 pin 被静默清掉的手段。
用 agent_with_overrides 覆盖单个会话的地域
agent 上的 pin 是从它创建的每个 session 的默认值。如果只想让一个 session 跑在另一个地域、又不想改动共享的 agent,在sessions.create里传一个agent_with_overrides对象并覆盖model即可。覆盖只对该 session 的模型配置生效,agent 资源不受影响;同样的成员规则适用——覆盖目标 geo 必须在 workspace 允许范围内,roster 成员仍需一致:
override = client.beta.sessions.create( agent={ "type": "agent_with_overrides", "id": researcher.id, "model": {"id": MODEL, "inference_geo": "global"}, # this session only }, environment_id=env.id, title="One-off, global geography", betas=BETAS, ) print("override session pin:", override.agent.model.inference_geo) print( "agent still pinned to:", client.beta.agents.retrieve(researcher.id, betas=BETAS).model.inference_geo, )最后两行输出分别给出验证点:override session 读到global,而原 agent 经agents.retrieve读回仍是us,说明共享 agent 未被改动。
收尾:归档 demo 资源
以下清理操作会归档本次演示创建的 session、agent 和 environment(archive 是 Managed Agents 的资源生命周期动词,见 CMA_operate_in_production.ipynb 中资源生命周期部分的介绍)。归档前先等待 session 状态变为idle:session.status_idleSSE 事件可能早于sessions.retrieve报告status == "idle",紧接着的archive()会 400 报 "cannot be archived while its status is running",utilities.py 的wait_for_idle_status用短轮询吸收这个竞态:
from utilities import wait_for_idle_status wait_for_idle_status(client, session.id) for s in (session, override): client.beta.sessions.archive(s.id, betas=BETAS) client.beta.agents.archive(researcher.id, betas=BETAS) client.beta.environments.archive(env.id, betas=BETAS) print("archived")这个from utilities import ...要求 Jupyter 的工作根目录设在managed_agents/,这样与 notebook 同目录的 utilities.py 才能被导入。
pin 管什么、不管什么
inference_geo是驻留与合规控制,只说明 token 在哪里被处理,与 agent 能读什么、数据存储在哪里无关。存储地域是另一个独立的、不可变的 workspace 设置workspace_geo;两者合起来才回答合规审查会问的问题。
由于 pin 是在每一轮上强制而不是只在创建时,当保证必须活过 agent 发布之后的变更时它是正确的控制手段。对一个 agent 车队,文档给出的做法是:把 workspace 的default_inference_geo设好,让未 pin 的 agent 继承正确地域;把 per-agent pin 留给那些驻留绝不允许依赖默认值的 agent。生产环境中的完整上下文(MCP 工具集、vault、webhook 模式)在 CMA_operate_in_production.ipynb 中有一节专门讨论inference_geopinning,与本文的字段和取值说明一致。
【免费下载链接】claude-cookbooksA collection of notebooks/recipes showcasing some fun and effective ways of using Claude.项目地址: https://gitcode.com/GitHub_Trending/an/claude-cookbooks
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考