自学教程

Claude Agent SDK 多租户设计

简介

多租户(Multi-tenancy)指一套服务实例,同时为多个独立客户(租户)提供 Claude Agent 能力,租户之间数据、会话、资源互相隔离。

租户:可以是企业客户、独立项目、终端用户分组。
核心目标:共享服务代码,降低运维成本;同时严格隔离租户数据、控制各租户 API 配额,防止跨租户信息泄露。

三种多租户架构对比

方案隔离级别开发成本适用场景
共享数据库,共享表(行级隔离)低(代码隔离)低SaaS 中小客户,绝大多数场景
共享数据库,独立租户表中中中型客户,需要单独数据归档
独立数据库(一租户一库)高高大型企业、强合规、数据必须物理隔离

推荐方案:共享库 + 共享表,通过 tenant_id 行级隔离,平衡成本与安全性,也是 Claude Agent SDK SaaS 最常用方案。

前置准备

  1. Python3.10+ / Node.js18+
  2. SDK:anthropic / @anthropic-ai/sdk
  3. 数据库:MySQL / PostgreSQL,Redis(配额、缓存)
  4. 基础:会话持久化、错误重试、并发控制(前面章节内容)

核心架构设计

核心租户维度

  1. tenant_id:租户唯一标识(UUID),所有业务表必须携带 tenant_id
  2. user_id:租户下的子用户,一个租户可多个用户
  3. API Key 策略:两种模式
    • 平台统一持有 Anthropic API Key,平台侧做配额分发(推荐)
    • 租户自行填入自己的 Anthropic API Key,平台仅做代理转发(适合企业客户自带密钥)

数据流

  1. 租户用户发起请求,请求头携带 tenant_id
  2. 服务校验租户状态、额度、权限
  3. 读取该租户的会话历史(带 tenant_id 过滤)
  4. 调用 Claude SDK 执行Agent任务(工具调用/子代理/流式)
  5. 保存消息、token消耗、日志,所有记录写入时自动带上 tenant_id
  6. 返回结果,禁止读取其他租户任何数据

数据库表设计(共享库共享表,MySQL)

租户表 tenant

CREATE TABLE tenant (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  tenant_id VARCHAR(64) NOT NULL UNIQUE COMMENT '租户唯一UUID',
  tenant_name VARCHAR(128),
  status TINYINT NOT NULL DEFAULT 1 COMMENT '0禁用,1正常',
  max_rpm INT DEFAULT 10 COMMENT '租户最大请求并发RPM',
  max_token_month BIGINT DEFAULT 1000000 COMMENT '月度token限额',
  self_api_key TEXT NULL COMMENT '租户自备Anthropic Key,可为空',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

租户会话表 agent_session(重点,增加tenant_id)

CREATE TABLE agent_session (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  session_id VARCHAR(64) NOT NULL,
  tenant_id VARCHAR(64) NOT NULL,
  user_id VARCHAR(64),
  messages JSON NOT NULL,
  total_input_tokens INT DEFAULT 0,
  total_output_tokens INT DEFAULT 0,
  status TINYINT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_tenant_session (tenant_id, session_id)
);

租户用量统计表 tenant_usage

CREATE TABLE tenant_usage (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  tenant_id VARCHAR(64) NOT NULL,
  stat_date DATE NOT NULL,
  input_tokens BIGINT DEFAULT 0,
  output_tokens BIGINT DEFAULT 0,
  request_count INT DEFAULT 0,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_tenant_date (tenant_id, stat_date)
);

关键:查询会话时,必须同时带上 tenant_id + session_id,不能只用 session_id 查询,防止越权读取其他租户会话。

租户API密钥两种模式代码示例(Python)

模式1:平台统一API Key(平台管控配额)

所有租户共用平台的 Anthropic Key,平台内部按租户做限流与计费

import os
from anthropic import Anthropic# 全局平台客户端
platform_client = Anthropic(api_key=os.getenv("PLATFORM_ANTHROPIC_KEY"), timeout=20)
def get_tenant_agent_client(tenant_id: str):
# 平台统一密钥,直接返回全局client
return platform_client

模式2:租户自带API Key(企业客户Bring your own key)

每个租户使用自己的 Anthropic API Key,平台不接触租户模型计费

from anthropic import Anthropic
# 伪代码:从数据库读取租户密钥
def get_tenant_agent_client(tenant_id: str):
    tenant_api_key = get_tenant_api_key_from_db(tenant_id)
    if not tenant_api_key:
        raise Exception("租户未配置API Key")
    return Anthropic(api_key=tenant_api_key, timeout=20)

租户资源隔离与限流(Redis实现)

多租户最容易踩坑:A租户高并发请求,占用全部API配额,影响B租户。
需要租户级独立限流:

  1. 全局总RPM限制(Anthropic API Key 总限额)
  2. 每个租户单独RPM上限(在tenant表配置max_rpm)
  3. 月度token消耗上限,超过直接拒绝请求

Redis 限流伪代码:

# 校验租户是否超出RPM限额
def check_tenant_rpm(tenant_id: str, max_rpm: int) -> bool:
    key = f"tenant:rpm:{tenant_id}"
    # 计数器+1,过期60秒
    count = redis.incr(key)
    if count == 1:
        redis.expire(key, 60)
    return count <= max_rpm

工具调用的租户隔离要点

工具(文件读写、数据库查询、MCP调用)是多租户高危点!

  1. 租户文件目录隔离:每个租户独立工作目录,路径强制前缀绑定tenant_id,禁止跨目录访问,防止路径穿越读取其他租户文件
  2. 自定义工具入参校验:所有路径参数做白名单校验,强制限定租户根目录
  3. MCP服务隔离:
    • 轻量场景:MCP实例按租户会话隔离
    • 成本优化:共享MCP服务,但工具操作上下文必须带上tenant_id做权限校验

示例:租户文件根目录

./tenant_workspace/{tenant_id}/

工具收到文件路径,自动拼接租户根目录,不允许 ../ 向上跳转。

租户子代理隔离

子代理并行开发章节中,子代理会话同样必须绑定 tenant_id,持久化存入 agent_session 表:

  • 子代理生成的消息、tool_use/tool_result 全部归属租户
  • 子代理的并发额度占用租户自身RPM配额
  • 禁止子代理读取其他租户会话、文件、数据

安全与权限规范(重点)

  1. 永远不要省略 tenant_id 条件:所有SQL查询、更新、删除必须带上 tenant_id,否则会出现越权漏洞
  2. 租户API Key加密存储:租户自备的Anthropic Key,数据库中AES加密存储,禁止明文保存
  3. 提示词隔离:租户自定义系统提示词、CLAUDE.md风格规则,单独存在租户配置,互不干扰
  4. 审计日志:每一条请求记录 tenant_id、session_id、token消耗、工具调用记录,方便溯源
  5. 软删除:租户注销不直接删除数据,先标记禁用,满足合规备份要求

租户计量与计费

  1. 每次SDK调用完成,提取 usage 里面 input_tokens、output_tokens
  2. 写入 tenant_usage 按天聚合统计
  3. 可配置:按token计费、包月度额度套餐
  4. 告警:租户token用量达到阈值(例如80%)发送预警;达到上限直接拦截新请求

获取token消耗示例 Python

resp = client.messages.create(...)
input_tokens = resp.usage.input_tokens
output_tokens = resp.usage.output_tokens
# 写入租户用量统计
save_tenant_token_usage(tenant_id, input_tokens, output_tokens)

多租户常见坑

  1. ❌ 只使用session_id查询会话,不带tenant_id,越权漏洞
  2. ❌ 租户文件目录不隔离,路径穿越读取他人文件
  3. ❌ 全局统一限流,没有租户独立配额,大租户挤占小租户资源
  4. ❌ 租户API Key明文存储,密钥泄露风险
  5. ❌ 子代理、工具调用不记录tenant_id,审计日志无法区分租户

最佳实践

  1. 优先采用「共享数据库,行级租户隔离」架构,快速落地SaaS。大客户单独提供独立数据库方案。
  2. 分层限流:全局API Key总限额 + 租户独立RPM + 租户月度token上限三重防护。
  3. 所有租户资源(会话、文件、配置、用量)都绑定 tenant_id。
  4. 区分两种密钥模式:平台密钥用于标准SaaS;租户自带密钥用于企业私有化客户。
  5. 增加租户开关,可一键禁用租户,紧急情况下关停租户请求。

小结

Claude Agent SDK多租户设计核心:tenant_id行级隔离 + 租户独立配额管控 + 工具层资源隔离。
共享库行隔离是首选方案,同时做好token用量统计、密钥加密、审计日志。工具调用和文件操作是多租户安全高危区,必须严格做路径与权限隔离。

0 条笔记