Claude Code

Agent SDK 生产部署

Claude Agent SDK 生产部署指南: 会话模式、隔离、观测、成本、结构化输出、tool search、缓存 TTL,以及 TypeScript/Python 配置片段。

Agent SDK 适合把 Claude Code 的 agent loop 嵌入服务、后台任务、CI 或多租户产品。生产部署时要先接受一个核心事实: query() 不是一次纯无状态 API 调用,而是启动并监管一个 claude Claude Code CLI 子进程,SDK 通过 stdio 和它通信。

每个运行中的 agent session 都有自己的进程树、工作目录和本地 transcript。你需要像部署有状态 worker 一样规划文件系统、隔离、观测和成本控制。

如果你要先理解 SDK 权限评估、Hooks、MCP、SessionStore 和成本字段,看 Agent SDK 能力矩阵。TypeScript/Python API、session API 和迁移差异见 Agent SDK API 参考速查。Agent loop、settingSources、skills、subagents、todo tracking 和 checkpointing 见 Agent SDK Agent 能力。Custom tools、system prompt、streaming、structured output、tool search、用户审批和 SDK slash commands 的运行时设计见 Agent SDK 运行时模式。本页聚焦部署拓扑、多租户隔离和运行时运维。

#运行模型

项目生产含义
query()启动 Claude Code CLI 子进程,不是直接把 prompt 发给无状态 API wrapper
子进程拥有 shell、工具调用、当前工作目录和本地 session 文件
并发N 个并发 session 通常意味着 N 个子进程,需要按 CPU、内存、磁盘和 API 限额规划
cwd默认继承宿主应用工作目录;多 session 或多租户必须显式传入
本地状态容器重启、扩缩容、迁移节点时会丢失,除非你单独持久化

本地默认状态主要有三类:

状态默认位置生产处理
Session transcripts~/.claude/projectsCLAUDE_CONFIG_DIR 下的 projects/需要跨主机恢复时用 SessionStore 镜像
Memory files用户层 ~/.claude/CLAUDE.md,项目层工作目录内 CLAUDE.md不会被 SessionStore 替代,需要独立卷、对象存储或禁用策略
工作产物session 的 cwd用每租户/每任务目录、卷或对象存储同步

#会话模式

模式适合场景关键设计
Ephemeral一次性修复、分析、转换、CI job每个任务一个容器或 sandbox,结束即销毁;只保留你显式导出的结果
Long-runningSlack bot、邮件 agent、持续站点构建器容器长期运行,HTTP/WebSocket 入口把同一 session 路由到同一 worker
Hybrid + SessionStore用户间歇回来继续的研究、项目管理、客服工单空闲时释放容器,下次用 session ID 加 SessionStore 恢复 transcript
Multi-agent container多 agent 协作或仿真同容器内多个 SDK 子进程,每个 agent 单独 cwd、配置目录和权限边界

SessionStore 只镜像 transcript,不是本地状态的替代品。Claude Code 子进程仍然先写本地 transcript,SDK 再把批次转发到 store。CLAUDE.md、auto memory、文件 checkpoint blob 和工作目录产物都不由 SessionStore 接管。

如果 SessionStore.append() 失败,SDK 会重试有限次数,最终失败时继续运行并在消息流中发出 mirror_error。生产环境要监控 { type: "system", subtype: "mirror_error" },否则外部存储可能悄悄缺 transcript 批次。

#多租户隔离

默认 SDK 会读取本机的 user、project、local settings 和 memory。共享容器里如果不隔离,一个租户的 CLAUDE.md、MCP、命令或 auto memory 可能进入另一个租户的上下文。

隔离点TypeScriptPython目的
禁用文件系统 settingssettingSources: []setting_sources=[]不加载 user/project/local settings
禁用 auto memoryCLAUDE_CODE_DISABLE_AUTO_MEMORY=1CLAUDE_CODE_DISABLE_AUTO_MEMORY=1避免 ~/.claude/projects/<project>/memory/ 注入系统提示
每租户配置目录CLAUDE_CONFIG_DIR=/srv/claude-config/<tenant>同左隔离 ~/.claude.json、transcripts 和缓存状态
明确工作目录cwd: tenantDircwd=tenant_dir隔离文件读写、命令执行和产物
租户 egress/proxy在网关或网络层配置同左独立 outbound IP、凭据注入、domain allowlist 和审计

Python SDK 旧版本曾把 setting_sources=[] 当作未设置处理。依赖空列表隔离时,先升级到当前版本再上线。

#观测与成本

Agent 是长生命周期进程,一次用户任务可能跨多轮 API、工具调用、MCP 请求和子代理。生产环境至少要导出 OpenTelemetry,并从 result message 记录 token 与成本字段。

CLAUDE_CODE_ENABLE_TELEMETRY=1
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp
OTEL_LOGS_EXPORTER=otlp
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_ENDPOINT=http://collector.example.com:4318
OTEL_RESOURCE_ATTRIBUTES=service.name=agent-runtime,team=platform

默认不要记录 prompt 原文、工具输入输出或 raw API body。只有在隔离排障环境短期开启这些高敏字段。

字段含义用途
message.total_cost_usdSDK 汇总的客户端成本估算计入每 session/租户账单和预算告警
message.usage.input_tokens本轮标准输入 token判断上下文膨胀
message.usage.output_tokens本轮输出 token判断回复和工具规划成本
message.usage.cache_creation_input_tokens写入 prompt cache 的 token缓存写入成本,通常高于标准输入
message.usage.cache_read_input_tokens从 prompt cache 读取的 token缓存命中收益,通常按较低输入价计费

成功和失败的 result message 都可能带 usagetotal_cost_usd。不要只在 success 分支记录成本。

#结构化输出与工具规模

结构化输出适合把 agent 结果写入数据库、任务系统或 UI。配置 outputFormat / output_format 后,最终 result message 会带 structured_output;SDK 会按 JSON Schema 校验,不匹配时重试,最终失败则返回错误结果。

Custom tools 和 MCP 是生产 agent 的主要扩展方式:

能力用法
Custom tools用 SDK 的 in-process MCP server 包装应用内函数、数据库访问或内部 API
Remote MCP连接 HTTP/SSE/stdio MCP server,把 Slack、GitHub、DB、工单系统接入 agent
allowedTools / allowed_tools预批准明确工具或 mcp__server__* 通配符
Tool search工具很多时延迟加载定义,避免每轮都把全部工具 schema 放进上下文

ENABLE_TOOL_SEARCH 常用值:

行为
未设置默认启用;在 Vertex AI 或非一方 ANTHROPIC_BASE_URL 下可能回退到 upfront 工具定义
true强制启用,代理或模型不支持 tool_reference 时请求可能失败
auto工具定义超过上下文窗口 10% 时启用
auto:5工具定义超过 5% 时启用,更早进入搜索模式
false禁用 tool search,每轮加载全部工具定义

工具少于约 10 个时,全部 upfront 加载通常更简单。工具库达到几十、几百甚至上千个时,tool search 通常能显著降低上下文占用并改善工具选择。

#Prompt cache TTL

Agent SDK 会自动使用 prompt caching。你通常不需要手写 cache 控制,但要知道 5 分钟和 1 小时 TTL 的成本差异。

规则说明
默认 API key / Bedrock / Vertex / Foundry缓存写入通常是 5 分钟 TTL
ENABLE_PROMPT_CACHING_1H=1可选请求 1 小时 TTL,适合短会话反复加载相同系统提示和上下文
Claude subscription计划额度内通常自动使用 1 小时 TTL
1 小时写入写入价格更高,适合能换来更多 cache read 的工作负载
Cache hit命中会刷新 TTL;TTL 是闲置过期时间,不是总寿命
前缀变化换模型、换 effort、工具定义变化、MCP 连接变化、/compact 等都可能降低命中

cache_creation_input_tokenscache_read_input_tokens 分开看。creation 每轮都很高,通常说明 prompt 前缀在变;read 持续升高,说明同一前缀被复用。

#TypeScript 配置片段

import path from "node:path";
import { query, type SessionStore } from "@anthropic-ai/claude-agent-sdk";

declare const prompt: string;
declare const sessionId: string | undefined;
declare const sessionStore: SessionStore;

const tenantId = "tenant_123";
const tenantDir = path.join("/srv/agent-work", tenantId);
const configDir = path.join("/srv/claude-config", tenantId);

for await (const message of query({
  prompt,
  options: {
    cwd: tenantDir,
    resume: sessionId,
    sessionStore,
    maxTurns: 30,
    maxBudgetUsd: 5,
    permissionMode: "dontAsk",
    settingSources: [],
    allowedTools: ["Read", "Grep", "Glob", "mcp__enterprise-tools__*"],
    mcpServers: {
      "enterprise-tools": {
        type: "http",
        url: "https://tools.example.com/mcp"
      }
    },
    outputFormat: {
      type: "json_schema",
      schema: {
        type: "object",
        properties: {
          summary: { type: "string" },
          actions: {
            type: "array",
            items: { type: "string" }
          }
        },
        required: ["summary"]
      }
    },
    env: {
      ...process.env,
      CLAUDE_CONFIG_DIR: configDir,
      CLAUDE_CODE_DISABLE_AUTO_MEMORY: "1",
      CLAUDE_CODE_ENABLE_TELEMETRY: "1",
      CLAUDE_CODE_ENHANCED_TELEMETRY_BETA: "1",
      OTEL_TRACES_EXPORTER: "otlp",
      OTEL_METRICS_EXPORTER: "otlp",
      OTEL_LOGS_EXPORTER: "otlp",
      OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf",
      OTEL_EXPORTER_OTLP_ENDPOINT: "http://collector.example.com:4318",
      ENABLE_TOOL_SEARCH: "auto:5"
    }
  }
})) {
  if (message.type === "system" && message.subtype === "mirror_error") {
    console.error("SessionStore mirror failed", message);
  }

  if (message.type === "result") {
    console.log({
      subtype: message.subtype,
      cost: message.total_cost_usd,
      usage: message.usage,
      structured: message.structured_output
    });
  }
}

TypeScript 的 env 会替换子进程环境,不是 merge。生产代码里通常要展开 ...process.env,否则 PATHANTHROPIC_API_KEY 或 provider 变量可能丢失。

#Python 配置片段

import asyncio
from pathlib import Path

from claude_agent_sdk import ClaudeAgentOptions, query

session_store = ...


async def run_agent(prompt: str, session_id: str | None = None) -> None:
    tenant_id = "tenant_123"
    tenant_dir = Path("/srv/agent-work") / tenant_id
    config_dir = Path("/srv/claude-config") / tenant_id

    options = ClaudeAgentOptions(
        cwd=tenant_dir,
        resume=session_id,
        session_store=session_store,
        max_turns=30,
        max_budget_usd=5,
        permission_mode="dontAsk",
        setting_sources=[],
        allowed_tools=["Read", "Grep", "Glob", "mcp__enterprise-tools__*"],
        mcp_servers={
            "enterprise-tools": {
                "type": "http",
                "url": "https://tools.example.com/mcp",
            }
        },
        output_format={
            "type": "json_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "summary": {"type": "string"},
                    "actions": {
                        "type": "array",
                        "items": {"type": "string"},
                    },
                },
                "required": ["summary"],
            },
        },
        env={
            "CLAUDE_CONFIG_DIR": str(config_dir),
            "CLAUDE_CODE_DISABLE_AUTO_MEMORY": "1",
            "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
            "CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1",
            "OTEL_TRACES_EXPORTER": "otlp",
            "OTEL_METRICS_EXPORTER": "otlp",
            "OTEL_LOGS_EXPORTER": "otlp",
            "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
            "OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector.example.com:4318",
            "ENABLE_TOOL_SEARCH": "auto:5",
        },
    )

    async for message in query(prompt=prompt, options=options):
        if getattr(message, "type", None) == "system" and getattr(message, "subtype", None) == "mirror_error":
            print("SessionStore mirror failed", message)

        if getattr(message, "type", None) == "result":
            print(
                {
                    "subtype": getattr(message, "subtype", None),
                    "cost": getattr(message, "total_cost_usd", None),
                    "usage": getattr(message, "usage", None),
                    "structured": getattr(message, "structured_output", None),
                }
            )


asyncio.run(run_agent("分析这个租户工作区并返回结构化摘要"))

Python 的 env 会叠加到继承环境上,但仍建议把认证和代理变量交给容器 secret 或网关统一注入。

#上线检查

检查项通过标准
子进程边界每个 session 有明确 cwd、资源上限、最大轮数和预算
Session 恢复需要跨主机恢复的 session 已配置 SessionStore,并监控 mirror_error
状态持久化memory files、工作目录产物和 transcript 分别有清楚的保留策略
租户隔离settingSources: [] / setting_sources=[]CLAUDE_CODE_DISABLE_AUTO_MEMORY=1、每租户 CLAUDE_CONFIG_DIR 和 egress policy 都已落地
观测OTEL traces/metrics/logs 进 collector,敏感日志默认关闭
成本result message 的 total_cost_usd、usage 和 cache read/write tokens 都按租户归档
工具custom tools/MCP 有权限白名单,大工具集启用或评估 tool search
缓存已根据会话间隔选择默认 5m 或 ENABLE_PROMPT_CACHING_1H=1

#官方参考

Support / 支持

Need help? / 需要帮助?

接入、计费与模型异常可邮件联系;服务可用性以状态页为准。For setup, billing, or model issues, email us. Check the status page for uptime.

也可使用右下角微信 / QQ 客服 · WeChat / QQ support is available at the bottom right