多租户与请求上下文
租户信息从哪来、跟着请求走到哪:部署记录带 user_id / space_id,每个请求带统一信封和请求上下文,审计自动带上是谁。
依据 agent-runtime develop@0a47a523(2026-11-12)核实
租户是谁
企业里同一套平台通常要服务多个团队、多个用户。Runtime 用两个字段标识租户:
| 字段 | 含义 |
|---|---|
user_id | 哪个用户 |
space_id | 哪个空间(团队、项目、业务线) |
部署时把它们写进部署记录,查询时按它们过滤:
await manager.deploy_agent(DeployAgentParams(
name="promise_agent", version="1.0.0",
user_id="u-001", space_id="sales",
))
mine = await manager.list_deployments(ListDeploymentsParams(space_id="sales"))
示意代码,参数名取自 DeployAgentParams 和 list_deployments;本站没有运行它。
README 提到"租户中间件"在 server/ 目录,本站核实的基线版本里没有这个目录。能核实的隔离是:部署记录带租户字段、查询按租户过滤。谁能用哪个 space_id,需要上层的身份和权限来保证(见第 5 关"管理面与身份中心")。
每个请求都装在一个信封里
部署起来的智能体应用,基于 service/ 的服务框架。框架只认一种入口消息:Envelope。
Envelope
├─ type 路由键,同时是 REST 路径段
├─ metadata 请求元数据
│ ├─ request_id 必填:幂等键 + 链路追踪键
│ ├─ user_id、session_id、chat_id、bot_id、channel
│ ├─ trace_id、instance_id、timestamp
│ └─ extra 可扩展字段,不破坏结构
└─ rawdata 业务数据
源码Metadataagent-runtime/service/openjiuwen_runtime/service/envelope.py:22@0a47a523
字段名和其他消息格式对齐,所以从别的协议转换过来很轻。request_id 必填这件事很关键:重复投递的请求可以靠它去重,一次请求的日志、审计、链路都能靠它串起来。
两级上下文
服务框架把资源分成两级:
| 层级 | 类型 | 职责 |
|---|---|---|
| 进程级 | SystemContext | 持有数据库、Redis、缓存、锁、审计等共享资源,负责启停和就绪检查 |
| 请求级 | RequestContext | 绑定这次请求的信封、元数据、截止时间、日志字段、鉴权主体和清理回调 |
业务代码只跟 RequestContext 打交道:ctx.db_* 读写数据库、ctx.kv / ctx.idempotency 用 Redis、ctx.lock(...) 拿分布式锁、ctx.audit(...) 写审计。日志自动带上 request_id 和 trace_id。
审计自动知道"是谁"
await ctx.audit("create_order", resource="order", details={"order_id": "SO-001"})
示意代码,方法签名取自 RequestContext.audit;本站没有运行它。
这条审计事件会自动带上:actor(优先取鉴权主体,没有就用 user_id)、request_id、trace_id、session_id、消息类型、实例 ID。业务代码不用自己拼这些字段,也就不容易漏。
小结
- 租户用
user_id+space_id标识,部署记录带上、查询按它过滤。 - 每个请求都是一个
Envelope,request_id必填,是幂等和追踪的依据。 - 业务代码通过
RequestContext使用数据库、缓存、锁和审计,身份和链路字段由框架自动带上。 - 租户能访问什么,最终要靠身份与权限来约束,不能只靠调用方自报的字段。
源码出处
- agent-runtime/README.md多租户隔离的定位
- agent-runtime/management/openjiuwen_runtime/management/models/deployment_params.py:25
class DeployAgentParams部署参数里的 user_id / space_id - agent-runtime/management/openjiuwen_runtime/management/manager.py:223
async def list_deployments按租户过滤部署列表 - agent-runtime/service/openjiuwen_runtime/service/envelope.py:22
class Metadata请求元数据 - agent-runtime/service/openjiuwen_runtime/service/envelope.py:67
class Envelope统一消息信封 - agent-runtime/service/openjiuwen_runtime/service/context/request_context.py:76
class RequestContext请求级上下文 - agent-runtime/service/openjiuwen_runtime/service/context/request_context.py:471
async def audit审计事件自动带上身份和链路 - agent-runtime/service/openjiuwen_runtime/service/context/DESIGN.md服务上下文的设计说明
链接指向固定提交,仓库后续更新不影响这里的行号。
过关测验
1. Envelope 的 Metadata 里,哪个字段是必填的?
2. 业务代码调用 ctx.audit("create_order") 时,审计记录里的 actor 从哪来?
3. list_deployments 传了 space_id,返回什么?