跳到主要内容

Agent 运行

Vibe Coding 平台的核心流程是:用户说一句话 → Agent 循环调用 LLM 和工具 → 产出一个可部署的应用。要让这个流程可靠运行,平台在 Agent 运行层面临以下核心挑战:

  • 安全边界:Agent 需要操作云资源(数据库、部署等),但 LLM 输出不可预测,密钥不能暴露给 LLM 或其生成的代码
  • Agent 调度与会话连续性:Agent Loop 需要编排 Prompt、路由工具调用、管理会话状态,用户对话可能跨越多轮多天,上下文和沙盒工作区都需要持久化
  • 代码执行环境与弹性:LLM 生成的代码(npm install、build、运行用户逻辑)需要一个安全隔离的环境,不能直接跑在生产服务器上,同时沙盒实例需要按需创建/销毁,空闲时不应占用资源
  • 模型灵活性:不同任务适合不同模型(代码生成用强推理模型、简单问答用轻量模型),平台需要灵活切换

CloudBase 针对以上挑战提供对应的解决方案:

挑战CloudBase 方案
安全边界受控信任边界 — Agent Loop 作为唯一凭证持有者,LLM 和 Sandbox 均不感知密钥
Agent 调度与会话连续性Agent Loop — 部署在云函数中,驱动循环控制、会话管理(CloudBase 数据库持久化)、凭证管理
代码执行环境与弹性Sandbox 沙盒 — 隔离的容器/microVM,按需创建/回收,工作区通过 COS/CFS 跨对话持久化
模型灵活性MaaS 模型服务 — 多模型统一接入,按任务类型动态切换

下面先从核心架构看整体全貌,然后逐一展开每个组件的设计。


核心架构


受控信任边界

整个运行时架构的核心设计原则是受控信任边界——将不可预测的部分约束在明确的安全边界内,所有跨边界操作都必须经过 Agent Loop 这个受信任的中间层。

按信任等级划分为三层:

信任层组件信任等级凭证说明
受信任层Agent Loop✅ 受信任持有全部凭证平台方编写的确定性代码,行为可控、可审计
不受信任层 — 推理LLM❌ 不受信任输出不可预测,可能被 prompt 注入或产生幻觉
不受信任层 — 执行Sandbox❌ 不受信任仅终端用户的环境级密钥(MCP 用)执行 LLM 生成的任意代码,属于隔离的运行沙盒

为什么 LLM 和 Sandbox 不能处于信任边界内?

  • LLM:模型输出不可预测。如果 LLM 感知到密钥,恶意 prompt 注入可能诱导模型在生成代码中嵌入密钥外传逻辑
  • Sandbox:执行的代码由 LLM 生成,内容不可控。如果 Sandbox 持有平台级密钥,恶意代码可通过 curl 外传密钥、直接调用管理面 API 删除数据、或攻击其他用户环境

因此,Agent Loop 作为唯一的受信任中间层,承担所有跨信任边界的操作:LLM 只能"请求"操作,Sandbox 只能在受限范围内"执行"操作,真正的决策权和凭证始终由 Agent Loop 掌控。


请求生命周期

一个完整的 Vibe Coding 请求从用户发起到应用上线,经过以下阶段:


Agent Loop

Agent Loop 是部署在 CloudBase 云函数中的业务代码,负责驱动整个请求生命周期。

循环控制

Agent Loop 的核心是一个"调用 LLM → 执行工具 → 反馈结果"的循环:

  1. 将用户输入 + 会话上下文 + 工具定义组装为 Prompt,发送给 LLM
  2. 解析 LLM 返回的 Tool Calls,路由到对应的工具(Sandbox SDK 或 MCP Client)
  3. 将工具执行结果拼回 Prompt,继续下一轮循环
  4. 当 LLM 返回最终文本(非工具调用)时,结束循环,返回用户

会话管理

会话状态持久化到 CloudBase 数据库,包括:

  • 对话历史:完整的 message 列表(user / assistant / tool)
  • 上下文元数据:当前 Sandbox 实例 ID、工作区快照 ID、用户环境 ID 等
  • 状态机:当前请求所处的阶段(编码中 / 构建中 / 部署中 / 已完成)

凭证管理

Agent Loop 通过云函数环境变量持有以下凭证,任何凭证均不会传递给 LLM 或暴露在 Sandbox 工作区中:

凭证用途
LLM API Key调用大模型推理接口
用户 CloudBase 环境密钥(SecretId / SecretKey)签发环境级临时密钥,注入 Sandbox 供 MCP 使用
业务密钥按需持有,如 GitHub Token(拉取代码仓库)、NPM Token(访问私有包)、第三方 API Key 等

Sandbox 沙盒

Sandbox 是 Agent 的编程工具层,基于 CloudBase Sandbox 提供隔离的完整 OS 环境。

能力概览

能力说明
文件系统可读写的工作区目录,支持 read / write / list / remove / stat / mkdir
Shell 执行执行任意 Shell 命令,返回 stdout / stderr / exitCode
CloudBase MCP在 Sandbox 内运行 CloudBase MCP Server,通过 stdio 提供云资源操作能力
生命周期管理支持 create / pause / resume / destroy,以及 Snapshot 快照
工作区持久化通过 COS(Checkpoint)或 CFS(挂载)将工作区持久化,确保跨对话、跨实例保留
隔离性每个用户的 Sandbox 互相隔离,无平台级管理凭证
低延迟工具调用响应 < 500ms
资源配额磁盘 ≥ 512MB,命令超时可配置(≥ 5 分钟)

Agent 接入沙箱

Agent 需要将 LLM 的工具调用(bash、文件读写)转发到 Sandbox 中执行。根据平台架构不同,有两种接入方式:

方式原理适用场景
Sandbox SDK在 Agent 代码中直接调用 SDK 操作沙箱自建 Agent Loop
改写内置工具用自定义工具覆盖 Agent 内置的 bash/read/write基于开源 Agent(如 OpenCode)构建

方式一:通过 Sandbox SDK 直接编程

适用于自建 Agent Loop 的场景——在 Agent 服务代码中直接使用 Sandbox SDK 创建/操作沙箱。

注:@cloudbase/sandbox-sdk 目前为灰度测试阶段,API 兼容 E2B SDK。如需接入请联系产品团队获取。

import { Sandbox } from '@cloudbase/sandbox-sdk';

// 1. 创建沙盒,注入用户级别的凭据
const sandbox = await Sandbox.create({
envVars: {
CLOUDBASE_ENV_ID: userEnvId,
TENCENTCLOUD_SECRETID: credentials.secretId,
TENCENTCLOUD_SECRETKEY: credentials.secretKey,
GITHUB_TOKEN: user.githubToken,
NPM_TOKEN: user.npmToken,
}
});

// 2. 文件系统操作(封装为 Agent Tools 供 LLM 调用)
await sandbox.files.write('/app/index.js', code);
const content = await sandbox.files.read('/app/index.js');
const entries = await sandbox.files.list('/app');

// 3. Shell 命令执行
const result = await sandbox.commands.run('npm install && npm run build');
// result: { stdout, stderr, exitCode }

// 4. 销毁沙箱
await sandbox.kill();

方式二:改写 Agent 内置工具(以 OpenCode 为例)

适用于基于开源 AI Coding Agent 构建的场景——不修改 Agent 核心代码,通过覆盖内置工具将本地执行透明替换为远端沙箱。

OpenCode 支持用同名自定义工具覆盖内置工具。创建以下文件,即可将 bashreadwrite 全部转发到远端 CloudBase Sandbox:

OpenCode 内置工具 自定义工具覆盖(同名优先)
┌──────────┐ ┌──────────────────────────┐
│ bash │ ──替换为──▶ │ bash.ts │
│ read │ ──替换为──▶ │ read.ts │
│ write │ ──替换为──▶ │ write.ts │
└──────────┘ │ ↓调用 Sandbox SDK │
│ ↓ 远端 CloudBase Sandbox │
└──────────────────────────┘

1. 初始化 Sandbox 连接

注:@cloudbase/sandbox-sdk 目前为灰度测试阶段,API 兼容 E2B SDK。如需接入请联系产品团队获取。

// .opencode/tools/sandbox-client.ts
import { Sandbox } from '@cloudbase/sandbox-sdk';

let sandbox: Sandbox | null = null;

export async function getSandbox() {
if (sandbox) return sandbox;
sandbox = await Sandbox.create({
envVars: {
CLOUDBASE_ENV_ID: process.env.CLOUDBASE_ENV_ID!,
TENCENTCLOUD_SECRETID: process.env.TENCENTCLOUD_SECRETID!,
TENCENTCLOUD_SECRETKEY: process.env.TENCENTCLOUD_SECRETKEY!,
}
});
return sandbox;
}

2. 覆盖内置 bash 工具

// .opencode/tools/bash.ts
import { tool } from '@opencode-ai/plugin';
import { getSandbox } from './sandbox-client';

export default tool({
description: 'Execute a shell command in the remote CloudBase Sandbox',
args: {
command: tool.schema.string().describe('Shell command to execute'),
timeout: tool.schema.number().optional().describe('Timeout in ms'),
},
async execute(args) {
const sandbox = await getSandbox();
const result = await sandbox.commands.run(args.command, {
timeout: args.timeout || 300000,
});
return [
`Exit code: ${result.exitCode}`,
result.stdout ? `stdout:\n${result.stdout}` : '',
result.stderr ? `stderr:\n${result.stderr}` : '',
].filter(Boolean).join('\n');
},
});

3. 覆盖内置 read / write 工具

// .opencode/tools/read.ts
import { tool } from '@opencode-ai/plugin';
import { getSandbox } from './sandbox-client';

export default tool({
description: 'Read a file from the remote CloudBase Sandbox',
args: {
path: tool.schema.string().describe('Absolute file path in sandbox'),
},
async execute(args) {
const sandbox = await getSandbox();
return await sandbox.files.read(args.path);
},
});
// .opencode/tools/write.ts
import { tool } from '@opencode-ai/plugin';
import { getSandbox } from './sandbox-client';

export default tool({
description: 'Write content to a file in the remote CloudBase Sandbox',
args: {
path: tool.schema.string().describe('Absolute file path in sandbox'),
content: tool.schema.string().describe('File content to write'),
},
async execute(args) {
const sandbox = await getSandbox();
await sandbox.files.write(args.path, args.content);
return `Written to ${args.path}`;
},
});

4. 配置环境变量并启动

export CLOUDBASE_ENV_ID=your-env-id
export TENCENTCLOUD_SECRETID=your-secret-id
export TENCENTCLOUD_SECRETKEY=your-secret-key

opencode

启动后,OpenCode 中所有的 bash 命令执行、文件读写都会透明转发到远端 CloudBase Sandbox,用户侧体验与本地开发完全一致。

此方案也适用于其他支持自定义工具覆盖的开源 AI Coding Agent,核心思路相同。

Agent 接入 CloudBase

Agent 需要操作用户的 CloudBase 环境资源(建表、部署云函数、上传文件等)。有两种方式:

方式原理适用场景
在沙箱内运行 CloudBase MCP ServerSandbox 内启动 MCP Server,Agent Loop 通过 stdio 连接自建 Agent Loop,需要在沙箱内统一管理编程工具和云资源操作
Agent 直接连接 CloudBase MCPAgent 通过 HTTP SSE 直接连接远程 CloudBase MCP Server使用 OpenCode / Cursor / Claude Code 等支持 MCP 的工具

方式一:在沙箱内运行 CloudBase MCP Server

基于上文已创建的 sandbox 实例,通过 mcporter(MCP 客户端 CLI)调用 CloudBase MCP Server:

// 1. 在沙箱内安装 mcporter
await sandbox.commands.run('npm install -g mcporter');

// 2. 通过 mcporter 调用 CloudBase MCP 工具
// 查询 NoSQL 数据库结构
await sandbox.commands.run('mcporter call cloudbase.readNoSqlDatabaseStructure');

// 创建数据库集合
await sandbox.commands.run('mcporter call cloudbase.writeNoSqlDatabaseStructure name:todos');

// 部署云函数
await sandbox.commands.run('mcporter call cloudbase.manageFunctions action:create name:addTodo');

沙盒启动时已注入用户的环境级密钥(见上文 envVars),mcporter 使用该密钥调用管理面 API,仅能操作该用户自己的 CloudBase 环境,权限范围受限。

方式二:Agent 直接连接 CloudBase MCP

适用于 OpenCode、Cursor、Claude Code、Cline 等支持 MCP 协议的工具。在工具的 MCP 配置中添加 CloudBase MCP Server 即可:

{
"mcpServers": {
"cloudbase": {
"command": "npx",
"args": ["-y", "@cloudbase/cloudbase-mcp@latest"],
"env": {
"CLOUDBASE_ENV_ID": "your-env-id",
"TENCENTCLOUD_SECRETID": "your-secret-id",
"TENCENTCLOUD_SECRETKEY": "your-secret-key"
}
}
}
}

详细配置指南参考 CloudBase MCP 接入文档

工作区持久化

Sandbox 实例本身是临时的,但工作区需要跨对话保留。推荐方案:

方案I/O 性能一致性成本
挂载 CFS接近本地磁盘强一致较高
Checkpoint 到 COS恢复后等同本地最终一致

Vibe Coding 的核心负载是高频小文件读写(npm install 产生数万小文件),对 I/O 极敏感。

以 Checkpoint 方案为例,工作区持久化需要在以下三个时机触发:

注:@cloudbase/sandbox-sdk 目前为灰度测试阶段,API 兼容 E2B SDK。如需接入请联系产品团队获取。

import { Sandbox } from '@cloudbase/sandbox-sdk';

// ═══════════ 1. 每轮对话结束后触发保存 ═══════════

async function handleUserMessage(sandbox, sessionId, userMessage) {
const response = await agentLoop(sandbox, userMessage);
await sandbox.checkpoint(sessionId);
return response;
}

async function resumeSession(sessionId) {
const sandbox = await Sandbox.create();
await sandbox.restore(sessionId);
return sandbox;
}


// ═══════════ 2. 定时触发保存(长任务防丢失) ═══════════

function startPeriodicCheckpoint(sandbox, sessionId, intervalMs = 60_000) {
const timer = setInterval(async () => {
try {
await sandbox.checkpoint(sessionId);
} catch (err) {
console.error('Periodic checkpoint failed:', err);
}
}, intervalMs);
return () => clearInterval(timer);
}

const stopCheckpoint = startPeriodicCheckpoint(sandbox, sessionId, 60_000);


// ═══════════ 3. 沙箱销毁前触发保存 ═══════════

async function destroySandbox(sandbox, sessionId, stopCheckpoint) {
stopCheckpoint();
await sandbox.checkpoint(sessionId);
await sandbox.kill();
}

checkpoint() 将沙箱工作区的完整文件系统持久化到 COS,restore() 从 COS 还原到新的沙箱实例。对于长时间运行的编码任务(如大型 npm install),建议将定时保存间隔设为 30–60 秒,平衡数据安全与 I/O 开销。


MaaS 模型服务

CloudBase 提供大模型统一接入方案,平台方可灵活选择和切换模型。

  • 多模型接入:支持主流大模型(DeepSeek、混元、GLM、MiniMax、Kimi 等)的统一接入
  • 动态切换:平台方可根据任务类型动态选择模型(如代码生成用强推理模型,简单对话用轻量模型)
  • 统一计费:模型调用统一计费,成本可控
  • 灵活部署:支持公有云模型 API(成本低、免运维)和私有化部署(数据不出内网,适合高安全要求场景)