Claude code云端部署 & 魔改sdk实现http流式调用保姆级教程

简介: 本文介绍将Claude Code本地CLI改造为云端HTTP流式服务的完整方案:通过离线打包部署、FastAPI+SSE封装SDK、Docker镜像构建及“一用户一沙箱+文件版本化”隔离架构,实现多用户安全、可伸缩、状态持久的Agent服务能力。

一、背景

在 OpenClaw、Claude Code 等产品出现之前,开发同学实现一个 Agent 的基本思路是:基于 LLM 实现一个 Loop 调用,配合 MCP 或代码层面自定义的工具来完成 ReactAgent;或者利用 Spring AI、LangGraph 等框架,配置工具、设计提示词,就可以实现一个能完成基本检索类任务的助理。我们之前也是这么做的,甚至将 Loop 处理逻辑和上下文处理做成了通用性调用——对这个 Loop 赋予不同的提示词和工具,就能产出不同的垂域助理。



但随着 Harness Engineering 概念的提出,对一个稳定好用的 Agent 的设计要求明显变高了。如果是自行开发的 ReactAgent 架构,还需要补充更多的约束层工具、任务完成的 Evaluation 机制、上下文切换到干净的子 Agent 等设计。而利用 Spring AI、LangGraph 等框架则更难去适配最新的 Agent 设计理念。



因此,当下最快实现一个 Harness Engineering 工程的路径是:部署现有的产品 → 提供调用能力 → 在应用层和端上做封装及扩展。



本文将围绕以 Claude Code 作为通用助理底层能力的实践过程,就以下几个核心问题展开:

1.

如何将一个本地化的闭源产品部署到云端——且由于网络限制,有些服务器或沙箱中并不支持 brew install 等在线安装方式。

2.

云端部署后以什么方式对外提供服务——CLI 方式显然不可取:一是非流式的,用户等待时间较长;二是 Claude Code 的 CLI 命令产出的是终端图形化界面,并非可供程序消费的结构化结果。

3.

多用户场景下的隔离问题——Claude Code 是一个单实例、记忆与配置长期文件化的系统,云上部署后不同用户的提问、记忆、配置可能相互串扰,如何解决?

实现效果

1.云端部署且隔离好(沙箱)claude code

 

2.提供出http接口可远程调用云上的claude code实例

 

3.同时可查看魔改后的claude code提供出的所有远程http接口:quer、session、hook、多agent等等配置也都支持

 

 


二、整体方案思路

针对上述三个问题,我们设计的整体方案如下图所示:

┌───────────────────────────────────────────────────────────────────┐
│                        Application Layer                         │
│              (Web UI / Bot / API Gateway / ...)                  │
└──────────────────────────┬────────────────────────────────────────┘
                           │  HTTP + SSE
┌───────────────────────────────────────────────────────────────────┐
│                     Sandbox Control Plane                         │
│         (路由分发 / 沙箱生命周期管理 / 用户实例映射)                   │
└──────┬───────────────┬───────────────┬────────────────────────────┘
       │               │               │
       ▼               ▼               ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│  Sandbox A  │ │  Sandbox B  │ │  Sandbox C  │   ← 每个用户独占一个沙箱实例/文件版本
│ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │
│ │ Claude  │ │ │ │ Claude  │ │ │ │ Claude  │ │
│ │ Code CLI│ │ │ │ Code CLI│ │ │ │ Code CLI│ │
│ └────┬────┘ │ │ └────┬────┘ │ │ └────┬────┘ │
│      │      │ │      │      │ │      │      │
│ ┌────▼────┐ │ │ ┌────▼────┐ │ │ ┌────▼────┐ │
│ │ HTTP    │ │ │ │ HTTP    │ │ │ │ HTTP    │ │
│ │ Service │ │ │ │ Service │ │ │ │ Service │ │
│ │ :8765   │ │ │ │ :8765   │ │ │ │ :8765   │ │
│ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │
│  ~/.claude/ │ │  ~/.claude/ │ │  ~/.claude/ │   ← 独立记忆 & 配置
└─────────────┘ └─────────────┘ └─────────────┘

整条链路分为四层:

第一层:云端离线部署。 通过 npm pack 将 Claude Code 打包为 tgz 离线包,在无外网的服务器上通过 npm install -g 完成安装,解决闭源产品无法在线安装的问题。

第二层:HTTP 流式服务化。 我们基于 Claude Code 官方的 Python SDK(claude-agent-sdk)+ FastAPI + SSE,将 SDK 的 query()ClaudeSDKClient 两种调用模式封装为 RESTful HTTP 接口,实现实时流式输出,替代不可用的 CLI 方式。

第三层:基础镜像构建。 将 Node.js 运行时、Claude Code CLI、Python 环境、HTTP 服务代码打包为一个 Docker 基础镜像,做到一次构建、处处部署。

第四层:沙箱多实例隔离。 通过沙箱平台的容器调度能力,为每个用户分配独立的沙箱实例。每个沙箱内部运行一套独立的 Claude Code + HTTP Service,天然实现记忆、配置、文件系统的完全隔离。且由于每个用户的配置其实都是各类文件,可以将用户的所有文件进行版本化存储,新启实例时,加载这个用户的所有文件,销毁实例时,保存这个用户此时的文件版本


三、claude code云端部署(离线方案)

Claude Code CLI 是一个基于 Node.js 的命令行工具,通过 npm 发布。在无外网的云端服务器上安装,核心要解决两个问题:Node.js 运行环境 和 Claude Code 包本身。

3.1 环境要求

首先确认目标服务器的环境:

node -v    # 需要 Node.js 18+
npm -v
uname -m   # 确认 CPU 架构: x86_64 or aarch64

如果服务器没有 Node.js,需要从 Node.js 官方发布页 下载对应架构的二进制包(推荐 LTS 版本),在本地下载后上传到服务器手动解压配置。

3.2 获取 Claude Code 离线包

推荐使用 npm pack 方式。在本地有外网的机器上执行:

npm pack @anthropic-ai/claude-code

会生成一个形如 anthropic-ai-claude-code-2.1.119.tgz 的文件,这就是要上传到服务器的核心包。

也可以使用整目录打包方式来避免潜在的依赖缺失问题:

# 本地全局安装
npm install -g @anthropic-ai/claude-code
# 找到全局安装路径并打包
cd $(npm root -g)
tar -czvf claude-code-full.tar.gz @anthropic-ai/claude-code

3.3 离线安装步骤

将 tgz 包上传到服务器后:

# 如果需要手动安装 Node.js
tar -xf node-v20.x.x-linux-x64.tar.xz
export PATH=$PWD/node-v20.x.x-linux-x64/bin:$PATH
# 离线安装 Claude Code
sudo npm install -g ./anthropic-ai-claude-code-2.1.119.tgz
# 验证安装
claude --version

3.4 注意事项

有几点需要特别注意。首先是 CPU 架构匹配,本地下载的 Node.js 二进制包必须与服务器架构一致(x64 / arm64),可以通过 uname -m 确认。其次,npm pack 只会打包主包本身不含依赖,如果安装时报缺依赖,需要改用整目录打包方案。最后,Claude Code 运行时仍然需要网络访问 Anthropic API,如果服务器完全无外网,需要配置内网 API 代理(例如通过设置 ANTHROPIC_BASE_URL 指向内部代理地址)。

四、基于FastApi重写claude-agent-sdk

这是整个方案中最核心的一层。Claude Code 支持两种调用模式:query() 单次查询和 ClaudeSDKClient 多轮会话。我们基于 FastAPI + SSE(Server-Sent Events)将这两种模式封装为 HTTP 接口,实现了从 CLI 到 HTTP 的完整转换。且该http服务还支持在query中传入harness工程所需的各类工具、插件、skills、hook等

实现的该http调用claude code的代码仓库:https://code.alibaba-inc.com/alsc-info-ilink-agent/Claude-code-http-service

4.1 技术选型

整个 HTTP 服务基于以下技术栈构建:

FastAPI:异步 Web 框架,天然支持 async/await,与 SDK 的异步迭代器完美配合。

sse-starlette:SSE 协议实现库,将异步生成器直接转换为标准 SSE 事件流。

claude-agent-sdk:Claude Code 官方 Python SDK,提供 query()ClaudeSDKClient 两种调用方式。

Pydantic:请求/响应模型定义与校验。

依赖配置(requirements.txt):

fastapi>=0.110.0
uvicorn[standard]>=0.29.0
sse-starlette>=2.0.0
pydantic>=2.6.0
claude-agent-sdk>=0.1.60
python-multipart>=0.0.9


4.2 项目结构

claude-code-scripts/
├── app/
│   ├── __init__.py
│   ├── main.py              # FastAPI 应用入口,环境变量配置
│   ├── models/
│   │   └── schemas.py       # Pydantic 请求/响应模型
│   ├── routers/
│   │   ├── health.py        # 健康检查
│   │   ├── query.py         # 单次查询路由(同步 + SSE 流式)
│   │   └── sessions.py      # 多轮会话管理路由
│   └── services/
│       ├── agent_service.py  # 核心:SDK 封装、SSE 事件序列化
│       └── session_service.py# 持久化会话查询
├── run.py                    # Uvicorn 启动入口
└── requirements.txt

4.3 核心设计:从 SDK 消息到 SSE 事件流

query() 是一个异步迭代器,每次 yield 出一条消息对象(SystemMessageAssistantMessageResultMessage)。我们的核心工作是将这些消息对象序列化为 JSON,通过 SSE 推送给客户端。

消息序列化层(agent_service.py,关键逻辑摘录):

def _serialize_message(message: Any) -> dict[str, Any]:
    """将 SDK 消息对象转换为 JSON 可序列化的 SSE 事件字典"""
    if isinstance(message, SystemMessage):
        return {
            "event": "system",
            "data": {
                "subtype": getattr(message, "subtype", None),
                "session_id": getattr(message, "session_id", None)
                    or (message.data.get("session_id") if hasattr(message, "data") else None),
                "details": message.data if hasattr(message, "data") else {},
            },
        }
    elif isinstance(message, AssistantMessage):
        blocks = []
        for block in message.content:
            if isinstance(block, TextBlock):
                blocks.append({"type": "text", "text": block.text})
            elif hasattr(block, "type") and block.type == "tool_use":
                blocks.append({
                    "type": "tool_use",
                    "name": block.name,
                    "id": getattr(block, "id", None),
                    "input": getattr(block, "input", {}),
                })
            else:
                blocks.append({"type": getattr(block, "type", "unknown"), "raw": str(block)})
        return {
            "event": "assistant",
            "data": {
                "content": blocks,
                "parent_tool_use_id": getattr(message, "parent_tool_use_id", None),
            },
        }
    elif isinstance(message, ResultMessage):
        return {
            "event": "result",

SSE 流式端点(query.py):

@router.post("/query/stream")
async def query_stream(req: QueryRequest):
    async def event_generator():
        async for event in run_query_stream(req):
            yield {
                "event": event.get("event", "message"),
                "data": json.dumps(event.get("data", {}), ensure_ascii=False),
            }
    return EventSourceResponse(event_generator())

客户端收到的 SSE 事件流形如:

event: system
data: {"subtype": "init", "session_id": "abc-123", ...}
event: assistant
data: {"content": [{"type": "text", "text": "我来分析一下当前目录..."}]}
event: assistant
data: {"content": [{"type": "tool_use", "name": "Glob", "input": {"pattern": "**/*.py"}}]}
event: result
data: {"subtype": "success", "result": "...", "total_cost_usd": 0.012}

4.4 两种调用模式

模式一:单次查询(Single-shot)

适用于一问一答的场景。客户端发送一个 prompt,服务端流式返回 Claude 的完整处理过程直至最终结果。

# SSE 流式
curl -N -X POST http://localhost:8765/v1/query/stream \
  -H 'Content-Type: application/json' \
  -d '{"prompt": "分析当前目录下的代码结构"}'
# 同步(等待完整结果)
curl -X POST http://localhost:8765/v1/query \
  -H 'Content-Type: application/json' \
  -d '{"prompt": "列出当前目录的文件"}'


模式二:多轮会话(Streaming-input Session)

适用于需要连续对话的场景。客户端先创建一个会话,然后在一个 SSE 连接上持续监听,同时向会话发送多条消息。

# 1. 创建会话
SESSION=$(curl -s -X POST http://localhost:8765/v1/sessions/create \
  -H 'Content-Type: application/json' \
  -d '{"allowedTools": ["Read", "Edit", "Glob"]}' | jq -r '.session_id')
# 2. 监听事件流(另一个终端)
curl -N http://localhost:8765/v1/sessions/$SESSION/events
# 3. 发送消息
curl -X POST http://localhost:8765/v1/sessions/$SESSION/send \
  -H 'Content-Type: application/json' \
  -d '{"message": "分析 auth 模块"}'
# 4. 继续对话
curl -X POST http://localhost:8765/v1/sessions/$SESSION/send \
  -H 'Content-Type: application/json' \
  -d '{"message": "用 JWT 重构它"}'


多轮会话在服务端的实现基于 StreamingSession 类,它内部维护一个消息队列和响应队列,通过后台异步循环驱动 ClaudeSDKClient。以下是核心设计的简化示意(完整实现还包含图片消息支持、关闭信号处理、异常恢复、心跳机制等):

class StreamingSession:
    def __init__(self, session_id: str, options: ClaudeAgentOptions):
        self.session_id = session_id
        self._client: Optional[ClaudeSDKClient] = None
        self._message_queue: asyncio.Queue = asyncio.Queue()   # 用户消息入队
        self._response_queue: asyncio.Queue = asyncio.Queue()   # Agent 响应出队
        self._running = False
    async def start(self):
        """初始化 SDK Client 并启动后台处理循环"""
        self._client = ClaudeSDKClient(options=self.options)
        await self._client.__aenter__()
        self._running = True
        self._task = asyncio.create_task(self._process_loop())
    async def _process_loop(self):
        """后台循环:从消息队列取用户输入 → 调用 SDK → 推送响应到响应队列"""
        while self._running:
            msg = await self._message_queue.get()
            if msg is None:  # 关闭信号
                break
            await self._client.query(msg["message"])
            async for response in self._client.receive_response():
                await self._response_queue.put(_serialize_message(response))
            await self._response_queue.put(
                {"event": "turn_complete", "data": {"session_id": self.session_id}}
            )
    async def receive_events(self) -> AsyncGenerator[dict, None]:
        """SSE 事件流输出,超时时发送心跳保活"""
        while self._running or not self._response_queue.empty():
            try:
                event = await asyncio.wait_for(self._response_queue.get(), timeout=120)
                yield event
            except asyncio.TimeoutError:
                yield {"event": "heartbeat", "data": {"session_id": self.session_id}}

4.5 高级功能支持

除了基础的查询和会话功能,HTTP 服务还完整支持了 SDK 的所有高级特性:

权限控制(Permission Mode): 支持 defaultdontAskacceptEditsbypassPermissionsplan 五种权限模式。默认设置为 bypassPermissions,使 Claude 能自由读写文件系统,避免在无人值守的云端环境中因权限确认而阻塞。

子代理(Subagents): 支持通过 API 定义专用子代理,指定其工具集、模型和提示词,实现任务分解:

{
  "prompt": "审查并优化代码",
  "agents": {
    "code-reviewer": {
      "description": "代码审查专家",
      "prompt": "关注安全性和最佳实践",
      "tools": ["Read", "Glob", "Grep"]
    }
  }
}

MCP 服务器集成: 支持连接外部 MCP 服务器(stdio/http/sse),将第三方工具能力接入 Claude:

{
  "prompt": "列出最近的 GitHub issues",
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {"GITHUB_TOKEN": "ghp_xxx"}
    }
  }
}

钩子(Hooks): 支持 PreToolUse / PostToolUse 等生命周期钩子,可实现工具调用审计、敏感操作拦截等:

{
  "hooks": {
    "PreToolUse": [
      {"matcher": "Write|Edit", "action": "deny", "reason": "禁止写入 .env 文件"}
    ],
    "PostToolUse": [
      {"action": "webhook", "webhook_url": "https://audit.example.com/log"}
    ]
  }
}

4.6 踩坑记录

在实际开发过程中,遇到了几个值得记录的问题:

1.

SDK 版本问题。 Claude Code 的文档中引用的 claude-agent-sdk>=0.2.111 在 PyPI 上并不存在(截至实践时最高版本为 0.1.66)。需将依赖约束改为 >=0.1.60 才能正常安装。

2.

权限拦截问题。 SDK 默认的权限模式会在 Claude 尝试读取 ~/.claude/CLAUDE.md 等文件时触发安全确认,导致无人值守场景下卡死。解决方案是在 _build_options() 中将未指定权限模式的请求默认设置为 bypassPermissions

3.

闭包变量绑定问题。 在 _build_hooks() 中动态生成钩子函数时,循环变量 event_name 在闭包内是延迟绑定的,导致所有钩子共享了最后一次循环的值。通过将循环变量作为默认参数捕获(_event_name=event_name)来修复。

4.

异步阻塞问题。 SDK 的部分 session 管理函数(list_sessionsget_session_info 等)是同步阻塞调用。在 FastAPI 的异步上下文中直接调用会阻塞事件循环。通过 asyncio.to_thread() 包装解决。

五、构建基础镜像

基础镜像的目标是将运行环境、Claude Code CLI、HTTP 服务代码一次性打包,做到沙箱实例开箱即用。以下是 Dockerfile 的核心模块解析:

# ============================================================
# 第一阶段:引入沙箱基础层
# ============================================================
FROM hub.docker.alibaba-inc.com/aone/sandbox:v0.0.1 as sandbox
FROM hub.docker.alibaba-inc.com/ali/ubuntu:22.04

# ============================================================
# 第二阶段:系统依赖 + Node.js + Python 3.11
# ============================================================
ENV PYPI_MIRROR http://mirrors.aliyun.com/pypi/simple
ENV PYPI_MIRROR_HOST mirrors.aliyun.com

# 系统依赖(编译工具链 + 浏览器运行时库)
RUN apt-get update && apt-get install -y \
    make gcc build-essential curl git wget ...

# Node.js 22.x(Claude Code 运行时依赖)
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \
    apt-get install -y nodejs

# Python 3.11(从源码编译,确保版本一致性)
RUN cd /opt/temp && \
    wget https://registry.npmmirror.com/-/binary/python/3.11.13/Python-3.11.13.tgz && \
    tar xvf Python-3.11.13.tgz && cd Python-3.11.13/ && \
    ./configure && make -j && make install

# ============================================================
# 第三阶段:安装 Claude Code CLI
# ============================================================
RUN npm pack @anthropic-ai/claude-code \
        --registry=https://registry.npmmirror.com && \
    npm install -g ./anthropic-ai-claude-code-*.tgz && \
    rm -f ./anthropic-ai-claude-code-*.tgz

# ============================================================
# 第四阶段:部署 HTTP 服务
# ============================================================
COPY --from=sandbox /codebox /codebox
USER admin

COPY claude-code-scripts /home/admin/claude-code-scripts
RUN pip3 install --no-cache-dir \
    -r /home/admin/claude-code-scripts/requirements.txt \
    -i $PYPI_MIRROR --trusted-host $PYPI_MIRROR_HOST

# API 配置(也在 Python 代码中硬编码,环境变量作为兜底)
ENV ANTHROPIC_BASE_URL=https://your-api-proxy.example.com/api/anthropic
ENV ANTHROPIC_API_KEY=your-api-key

WORKDIR /home/admin/claude-code-scripts

容器启动脚本(sandbox_start.sh)非常简洁——只需拉起 HTTP 服务:


6.4 用户文件版本化存储设计

这套版本化存储机制是整个隔离方案的基石。它要解决的核心问题是:沙箱实例是短暂的,但用户的记忆和工作成果必须是持久的。

需要持久化的文件范围:

Claude Code 的用户态文件主要分布在以下位置,全部需要纳入版本管理:

~/.claude/                    # Claude Code 全局记忆与配置
  ├── CLAUDE.md               # 用户级记忆文件(跨项目)
  ├── settings.json           # 全局设置(权限、模型偏好等)
  ├── credentials.json        # 认证信息
  ├── sessions/               # 会话历史索引
  │   ├── <session_id>.json
  │   └── ...
  └── projects/               # 项目级记忆
      └── <project_hash>/
          └── CLAUDE.md       # 项目级记忆文件

~/workspace/                  # 用户工作目录
  ├── .claude/                # 项目级 Claude 配置
  │   └── CLAUDE.md
  ├── src/                    # 用户的代码文件(Claude 可能读写)
  └── ...


版本化存储流程:

整个流程分为三个阶段——加载、运行、保存:

       ┌─────────────────────────┐
                    │    用户发起请求           │
                    └────────────┬────────────┘
                    ┌────────────▼────────────┐
                    │  Control Plane 查找      │
                    │  该用户是否有活跃沙箱?    │
                    └────────────┬────────────┘
                   ┌─────────────┴─────────────┐
                   │ 无                         │ 有
                   ▼                            ▼
        ┌────────────────────┐       ┌──────────────────┐
        │ ① 分配空闲沙箱实例  │       │  直接转发请求      │
        └─────────┬──────────┘       └──────────────────┘
        ┌─────────▼──────────┐
        │ ② 从 OSS 拉取该    │
        │ 用户的最新文件快照   │
        │                    │
        │ ossutil cp          │
        │ oss://snapshots/   │
        │ user_001/latest/   │
        │ → ~/.claude/       │
        │ → ~/workspace/     │
        └─────────┬──────────┘
        ┌─────────▼──────────┐
        │ ③ 启动 HTTP 服务    │
        │ 转发用户请求         │
        │                    │
        │ 用户正常使用 ...     │
        │ Claude 读写文件      │
        │ 记忆不断积累         │
        └─────────┬──────────┘
                  │  (闲置超时 / 主动销毁)
        ┌─────────▼──────────┐
        │ ④ 回写文件快照       │
        │                    │
        │ 对比文件变更          │
        │ (增量 diff)         │
        │ 上传至 OSS           │
        │ 记录新版本号          │
        └─────────┬──────────┘
        ┌─────────▼──────────┐
        │ ⑤ 释放沙箱实例       │
        │ 回归空闲池            │
        └────────────────────┘

增量同步策略:

为了避免每次加载和保存时都传输全量文件(用户的工作目录可能包含大量代码),我们采用增量同步策略。加载阶段在沙箱启动后,从对象存储拉取该用户的最新快照,解压到对应目录。首次加载是全量拉取,后续如果沙箱被复用(仅切换用户),则只需替换差异文件。保存阶段在沙箱即将回收时,计算当前文件系统与上一版本的差异(可以利用 rsync --dry-run 或文件 hash 对比),只上传发生变更的文件,并在数据库中记录一条新的版本记录。

版本管理数据模型:

-- 用户文件快照版本表
CREATE TABLE user_snapshots (
    id          BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id     VARCHAR(64) NOT NULL,
    version     INT NOT NULL,
    storage_key VARCHAR(256) NOT NULL,   -- OSS 路径,如 snapshots/user_001/v3.tar.gz
    file_count  INT,                      -- 文件数量
    total_size  BIGINT,                   -- 快照总大小(bytes)
    created_at  TIMESTAMP DEFAULT NOW(),
    INDEX idx_user_version (user_id, version DESC)
);

6.5 沙箱生命周期管理

结合文件版本化存储,沙箱实例的生命周期变得更加灵活——实例本身是无状态的、可随时替换的:

按需分配:用户首次请求时,从空闲沙箱池中取一个实例(而非每次新建),拉取用户文件快照后即可提供服务。如果池中无空闲实例,再触发新实例创建。

闲置回收:沙箱在无请求超过一定时间(如 30 分钟)后触发回收流程——先回写文件快照到持久存储,然后清理沙箱内的用户数据,实例回归空闲池等待下一个用户使用。

主动释放:用户可以通过 API 主动关闭自己的沙箱。关闭前同样会触发文件快照保存。

定期清理:超过一定时间(如 30 天)未使用的用户快照可以设置归档或清理策略,避免存储无限膨胀。

6.6 请求路由流程

一次完整的用户请求经历如下流程:

用户请求 (带 user_id)
  Control Plane 收到请求
        ├─ 查映射表:该 user_id 是否已有活跃沙箱?
        ├─ [有] ──→ 直接转发到 sandbox_ip:8765
        └─ [无] ──→ 从空闲池分配沙箱
                        ├─ 从 OSS 拉取该用户最新文件快照
                        ├─ 解压到 ~/.claude/ 和 ~/workspace/
                        ├─ 启动 HTTP 服务,等待 health check 通过
                        ├─ 记录 user_id → sandbox_ip 映射
                        └─ 转发请求


在应用层的调用代码可以非常简洁:

import httpx

async def query_claude(user_id: str, prompt: str) -> AsyncIterator[dict]:
    """通过 Control Plane 路由到用户专属沙箱"""
    sandbox_url = await control_plane.get_or_create_sandbox(user_id)

    async with httpx.AsyncClient() as client:
        async with client.stream(
            "POST",
            f"{sandbox_url}/v1/query/stream",
            json={"prompt": prompt},
        ) as response:
            async for line in response.aiter_lines():
                if line.startswith("data: "):
                    yield json.loads(line[6:])


6.7 方案优势

这套"一用户一沙箱 + 文件版本化"的组合设计带来了几个关键优势:

彻底的隔离性。 每个用户拥有独立的文件系统、进程空间和网络栈,完全不存在记忆串扰、配置冲突的可能。相比在应用层逐一识别并隔离 Claude Code 散布在各处的状态文件(~/.claude/.claude/ 项目配置、内存中的会话注册表等),容器级隔离一刀切地解决了所有问题,且不惧 SDK 升级引入新的状态点。



状态永不丢失。 用户的一切工作成果——Claude 积累的记忆、写过的代码、会话历史、个性化配置——都以文件快照的形式持久化在对象存储中。沙箱实例可以随时销毁、随时重建,用户无感知。



资源弹性伸缩。 沙箱实例不再与用户绑定,而是变成了可复用的无状态计算节点。活跃用户少时,少量实例即可服务;高峰期只需扩大沙箱池。闲置用户不占用任何计算资源,只占用廉价的对象存储空间。



天然的版本回溯能力。 由于每次回收都生成新版本,用户的文件天然具备了时间线。如果 Claude 在某次操作中写坏了代码或误删了文件,可以回滚到任意历史版本恢复——这实际上为 Claude Code 的工作成果提供了一层"安全网"。



七、总结

本文介绍了一套将 Claude Code 从本地 CLI 工具转变为云端 HTTP 流式服务的完整方案。回顾开篇提出的三个核心问题:



对于离线部署问题,我们通过 npm pack 打包 + Docker 基础镜像的方式,实现了无外网环境下的一键部署。

对于服务化输出问题,我们基于 claude-agent-sdk + FastAPI + SSE 构建了完整的 HTTP 服务层,支持单次查询和多轮会话两种模式,以及 Hooks、Subagents、MCP、Permission 等全部高级特性,解决了 CLI 方式非流式、非结构化的根本缺陷。

对于多用户隔离问题,我们采用"一用户一沙箱 + 用户文件版本化存储"的架构。容器级隔离解决了运行时串扰问题,文件版本化存储则让沙箱实例彻底无状态化——用户的记忆、配置、工作成果以快照形式持久化在对象存储中,沙箱可以随时创建和销毁而用户状态永不丢失。这套设计还附带了版本回溯能力,为 Claude Code 的自动化操作提供了一层额外的安全保障。



整套方案的设计原则是尽量不改造 Claude Code 本身,而是在外围做封装和调度。这样做的好处是,当 Claude Code 升级时(例如 SDK 新增 API、CLI 功能增强),我们只需要更新基础镜像中的 tgz 包,HTTP 服务层和沙箱调度层基本不需要改动。



八、个人感悟

Ai的合理利用真的对研发提效很大,这个项目,从  claude code部署调研->部署方案设计->重构sdk为FastApi项目->基础镜像构建->沙箱部署->本篇ata撰写   仅仅耗时1.5人日及1909 Credits

但:个人的工程设计能力 始终是借助ai高效产出的基础,合理的设计思路才能快速引导Ai构建高质量系统

借助ai做的一些具体事情如下:

ai分析离线部署方案:

 

基础镜像构建:

 


FastApi重构claude code



ata撰写

 


来源  |  阿里云开发者公众号

作者  |  奕寰

相关文章
|
3天前
|
API
阿里云微服务引擎 MSE 及 API 网关 2026 年 5 月产品动态
阿里云微服务引擎 MSE 及 API 网关 2026 年 5 月产品动态。
|
4天前
|
人工智能 安全 关系型数据库
RDS Agent可观测能力正式邀测!全面支持Qoder、Codex、Claude Code、OpenClaw等主流研发Agent
阿里云RDS Agent可观测平台正式发布!面向Qoder、Codex等多类AI Agent,提供统一接入、Token/成本归因、ROI分析、风险回溯与全链路Trace下钻能力,基于RDS MySQL+DuckDB列式分析底座,助力团队从“使用Agent”迈向“治理Agent”。
123 6
|
7天前
|
人工智能 自然语言处理 安全
阿里云Coding Plan和Token Plan团队版有啥区别?百炼ai大模型平台如何选择?
阿里云百炼提供Coding Plan(个人向,按次计费、限频次、仅文本模型)与Token Plan团队版(企业向,按Credits计费、无频次限制、支持文本+图像多模态),适配不同场景与安全合规需求。免费领取7000万tokens:https://t.aliyun.com/U/fPVHqY
155 6
|
7天前
|
人工智能 缓存 自然语言处理
阿里云Token Plan是什么?看这一篇就够了,Credits计费、百炼支持模型、收费价格及使用方法
阿里云百炼Token Plan团队版是面向企业/团队的AI大模型订阅服务,以Credits统一计费,支持Qwen、GLM、Kimi、DeepSeek等20+文本与图像模型(如qwen-image-2.0、wan2.7-image),兼容Cursor、OpenClaw等主流AI工具。提供标准(198元/月/席)、高级(698元)、尊享(1398元)三档坐席,含25K–250K Credits额度,并可购共享用量包(5000元/62.5万Credits)。包月预算可控、数据不用于训练、多租户不排队。免费领千万tokens:https://t.aliyun.com/U/fPVHqY
|
7天前
|
人工智能 自然语言处理 API
阿里云TokenPlan和CodingPlan有啥区别?选哪个调用ai模型更划算?
阿里云百炼两大订阅方案:Coding Plan(200元/月)面向个人开发者,按调用次数计费,仅支持文本模型,有频次限制;Token Plan团队版(198–1398元/坐席/月)面向企业团队,按Credits统一抵扣,支持文本+图像多模态模型,无频次限制、多租户隔离、数据不用于训练。开通阿里云百炼免费领取千问tokens:https://t.aliyun.com/U/fPVHqY
194 1
|
11天前
|
人工智能 安全 关系型数据库
RDS Agent可观测能力正式邀测!全面支持Qoder、Codex、Claude Code、OpenClaw等主流研发Agent
阿里云RDS Agent可观测平台正式发布!面向Qoder、Codex等AI Agent,基于RDS MySQL+DuckDB列式分析底座,提供多Agent一键接入、Token/成本归因、ROI投入产出分析、风险回溯至Trace/Session、全链路下钻能力,助力团队从“使用Agent”迈向“治理Agent”。
|
11天前
|
人工智能 自然语言处理 API
阿里云海外重磅发布 Qwen Cloud
Qwen Cloud,正是为AI Agent 而生的全新服务方式。
744 23
|
1天前
|
Web App开发 弹性计算 文字识别
Qwen3.7-Plus:想得深,看得懂,做得到
阿里发布Qwen3.7-Plus:全球前五、中国第一的多模态智能体模型,实现“看懂界面—生成代码—操作GUI—自主验证”闭环,11小时端到端开发APP,支持视觉编程、搜索增强问答与真实场景推理。
|
1天前
|
API 开发者
千问云上线Qwen3.7-Max,支持API与Token Plan调用!
Qwen3.7-Max是阿里云2026年发布的旗舰智能体大模型,全球评测排名第五、国产第一。支持百万级上下文与自主长程任务执行,API调用价12/36元(每百万Token),已接入千问云及Token Plan订阅服务。
|
1天前
|
人工智能 运维 安全
阿里云发布Qwen Cloud,加速AI出海!
阿里云在新加坡发布面向海外的AI战略升级:推出全新AI官网Qwen Cloud、Agent产品MuleRun、智能体编程平台Qoder及桌面智能体QoderWork,并完成云基础设施Agentic化改造,全面支持Agent原生开发与部署。