关于 stackbone
stackbone 是面向在 Stackbone 工作区中工作的编码 Agent 的技能,说明如何用 SDK 构建深度 Agent 和持久化工作流、查询文档并在模拟器中验证更改。
主要功能
- 01工作区与代码布局约定
- 02深度 Agent 和工作流模式
- 03环境 SDK 客户端用法
- 04工作流步骤幂等性指导
- 05通过 MCP 查询文档
- 06通过模拟器验证
适用场景
- 01向 Stackbone 工作区添加 Agent
- 02构建带检查点的持久化工作流
- 03在工作流中调用 Agent
- 04在模拟器中验证工作区更改
MCP 相关
该技能使用公开的 `stackbone-docs` MCP 服务,通过 `list_docs`、`get_doc` 和 `search_docs` 查找 SDK 文档。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ stackbone/ stackbone-skills --skill stackbone安装后在 Claude Code 中输入/stackbone确认已加载。
详细介绍
Stackbone SDK 技能
本技能介绍如何在 Stackbone 工作区中开展工作。它不包含 API 参考:所有签名、选项、错误代码和限制都以 Stackbone 文档为准,请从文档中查阅。
文档所在位置
文档通过 MCP 作为 stackbone-docs 服务提供(https://docs.stackbone.ai/mcp,公开,工具包括 search_docs、get_doc、list_docs)。CLI 会在执行 stackbone init / stackbone link 时将其接入你的编码 Agent;stackbone docs 会输出连接详情。
- 使用
list_docs开始会话。 它会返回目录:按区域和章节列出每个页面,并附上一行说明。下方的如何找到页面会说明任务需要查阅哪个页面;从列表中获取其路径,然后用get_doc获取页面。切勿凭记忆输入路径:页面会移动,标题不会变。 - 在本次会话中,如果你还没有阅读过某个接口对应的页面,请先阅读,再编写调用代码。
- 如果不知道某个方法、选项、错误代码或限制在哪个页面,请用通俗文字向
search_docs提问(知道区域时请传入area:sdk、cli、examples、faqs、home),然后用get_doc获取最相关的结果。 - 不要凭记忆编写签名。在
'use step'中,错误的签名可能编译通过,却在运行时失败。
会话中没有 stackbone-docs 工具? 获取 https://docs.stackbone.ai/llms.txt:其中是相同的索引,每个页面占一行,包含标题、说明和原始 Markdown 的链接。按标题选取页面并获取该链接。https://docs.stackbone.ai/llms-full.txt 是包含所有页面的单个文件(约 700 KB)。
心智模型
- 工作区按磁盘上的文件约定自动发现:每个
deep-agents/<name>/index.ts都是一个 Agent(文件夹名就是其名称,也是客户端选择的model);每个workflows/<name>.workflow.ts都是一个工作流(名称 = 文件基础名,导出项 =<camelCase(name)>Workflow)。无需编辑注册表。 - Deep Agent 只有一个文件:从
@stackbone/sdk/deep导入defineDeepAgent,并使用export default defineDeepAgent({ name, model, tools })。其指令不在该文件中,而是存放在 Box 目录中的提示词,由 Agent 按名称标识,在 Studio 中编写和发布。它在进程内运行,运行时通过标准的 OpenAI / Anthropic 聊天协议提供服务。无需编写 HTTP 代码。 - 工作流是一个标记为
'use workflow'的普通异步函数,其副作用位于标记为'use step'的辅助函数中。每个步骤都是一个持久检查点:运行一次后会被持久化,失败时会重试。 - 每个接口都通过环境客户端访问:在任何工具函数体或步骤中导入
stackbone:import { stackbone } from '@stackbone/sdk'。无需createClient(),也无需连接字符串。
如何开展工作
- 定位目标。 Agent 位于
deep-agents/<name>/index.ts;工作流位于workflows/<name>.workflow.ts。如果目标不存在,请使用stackbone add agent|workflow|workflow-agent <name>创建框架(参见 stackbone-cli 技能)。不要手动编写文件布局或package.json中的固定版本。 - 先阅读,再编写。 对于更改涉及的每个接口,请阅读对应页面(如何找到页面)。请通读整个页面:你需要的选项通常在后半部分。
- 按下方的结构编写代码。 保持工具函数体或步骤简短;所有环境调用都放在其中。
- 在模拟器中验证。 运行
stackbone dev,然后与 Agent 聊天,或运行stackbone workflows start <name> --input '…';接着运行stackbone runs get <runId>和stackbone logs tail --run <runId>(参见 stackbone-cli 技能)。更改必须经由一次成功运行,才算完成。 - 遇到失败? 切换到 stackbone-debug 技能查找原因,然后回到这里修复。
三种结构
Deep Agent:deep-agents/<name>/index.ts
import { tool } from '@langchain/core/tools';
import { z } from 'zod';
import { defineDeepAgent } from '@stackbone/sdk/deep';
import { stackbone } from '@stackbone/sdk';
const readTone = tool(
async () => {
const tone = await stackbone.config.get('tone'); // any ambient surface works here
return tone.error ? 'neutral' : String(tone.data);
},
{
name: 'read_tone',
description: "Return the agent's current tone setting.",
schema: z.object({}),
},
);
export default defineDeepAgent({
name: 'support', // must equal the folder name — it is who owns this agent's prompts
model: 'openai/gpt-4o-mini', // a bare id, resolved through the deployment's model provider
// No instruction here on purpose: it is a prompt keyed by this agent's name, written in
// Studio. Add `instructions: { key, variables }` to point at another key or feed it {{vars}}.
tools: [readTone],
// interruptOn: { send_mail: true }, // pause for a human before this tool runs
});
持久工作流:workflows/<name>.workflow.ts
import { z } from 'zod';
import { stackbone } from '@stackbone/sdk';
import { welcomes } from '../src/schema'; // your Drizzle tables live at src/schema.ts
export const inputSchema = z.object({ userId: z.string(), email: z.string().email() });
export const outputSchema = z.object({ userId: z.string(), welcomed: z.boolean() });
type OnboardingInput = z.infer<typeof inputSchema>;
export async function onboardingWorkflow(input: OnboardingInput) {
'use workflow'; // cheap, deterministic glue: it replays on resume
const valid = await validateSignup(input);
return await persistWelcome(valid.userId);
}
async function validateSignup(input: OnboardingInput) {
'use step';
if (!input.email.includes('@')) throw new Error(`Invalid email: ${input.email}`);
return { userId: input.userId };
}
async function persistWelcome(userId: string) {
'use step'; // runs once, persisted, retried: make it idempotent on userId
await stackbone.database.insert(welcomes).values({ userId }).onConflictDoNothing();
return { userId, welcomed: true };
}
调用 Agent 的工作流:一个步骤委派整个轮次
import { callDeepAgent } from '@stackbone/sdk/workflow';
async function askAgent(message: string) {
'use step'; // the whole agent turn is this one durable step
const { text } = await callDeepAgent('support', message);
return text;
}
streamDeepAgent(导入方式相同)是 workflow-agent 脚手架使用的流式版本:回复会流式输出到运行的聊天界面,Studio 会将工作流显示为聊天。
适用于所有场景的规则
- 解构
{ data, error }并处理两个分支。 每个环境提供的接口都会返回这个封装。抛出错误以使步骤失败,或针对需要处理的情况按error.code分支处理。绝不要吞掉error。 - 有三个接口会改为抛出错误。
stackbone.database使用原生 Drizzle(返回行数据,出错时抛出错误);callDeepAgent/streamDeepAgent会抛出错误并使所在步骤失败;stackbone.connection(id)会抛出ConnectorCallError,应通过err.code匹配,绝不要使用instanceof。 - 步骤必须幂等。
'use step'可能运行两次。编写步骤时,确保运行两次也安全。 - 通过触发工作流的连接器写入数据时,工作流需要使用
isOwnEcho。 此次写入会触发变更通知,导致运行再次启动;由于没有重复操作,因此无法通过去重来阻止。为写入操作指定echoPath,然后在步骤写入前进行保护:if (await isOwnEcho(connectorId, value)) return { … }(从@stackbone/sdk/workflow导入;提前返回时仍须为已声明的outputSchema提供值)。让value与触发器匹配。监视新对象的触发器:使用新对象的 ID。跟踪updatedAt等变更列的触发器:使用该列,因为 ID 不会改变,基于 ID 的保护会吞掉对该对象之后的每次人工编辑。绝不要使用事件 ID,因为每次循环都会生成新的事件 ID。选择前请阅读 Home 下的 Trigger events 页面,并使用触发器自身的注意事项中给出的确切路径。 - **
requestApproval()必须在工作流主体中运行,绝不能放在'use step'内,**并且应从@stackbone/sdk/workflow导入,而不是从主入口导入。仅当decision.status === 'approved'时才执行副作用。 - 代码中绝不包含指令。 指令是提示词目录中的提示词,由 Agent 持有并以其名称作为键,在 Studio 中编写和发布(或使用
stackbone prompts create)。instructions: { key, variables }指向另一个键,或向其传入{{vars}}——绝不会承载提示词文本。即使没有人编写提示词,Agent 仍会启动并回答。 - 模型必须是裸 ID(
'openai/gpt-4o-mini'),由部署通过模型提供方解析;也可以使用构建好的 LangChain 聊天模型实例。不要使用密钥构建客户端。 - 运行时依赖必须放在工作区根目录的
package.json中(deepagents、@langchain/*、workflow),每个进程只保留一份。不要为每个 Agent 单独创建package.json,也不要嵌套node_modules。 - 绝不要硬编码或索取注入的环境变量。
STACKBONE_POSTGRES_URL、MODEL_PROVIDER_API_KEY、MODEL_PROVIDER_BASE_URL、STACKBONE_INSTALLATION_ID和存储凭据由运行时注入。由运营人员管理的值应通过stackbone.secrets和stackbone.config获取。 - 将工作流契约声明为并列的
inputSchema/outputSchema导出项。 输入类型通过z.infer从inputSchema派生;输出类型必须显式声明,而不是推断得出。 - RAG 架构由平台提供。 自有数据表通过
src/schema.ts+stackbone db migrate create创建(使用 stackbone-cli 技能);绝不要手动编写 RAG 表。
如何查找页面
文档沿用代码中的名称,因此通常无需搜索:
- 每个环境 API 都有一个与之同名的页面,位于 SDK 下:
stackbone.database、stackbone.storage、stackbone.rag、stackbone.ai、stackbone.config、stackbone.secrets、stackbone.settings、stackbone.prompts、stackbone.connection。调用其中任一项之前,先对照list_docs中的路径,用get_doc获取该页面。有两项不符合此规则:stackbone.workflows的文档位于Background jobs & workflow triggers页面;requestApproval/ 审批 API 的文档位于Human-in-the-loop页面。 - 每种形态在其 SDK 分区下都有
Overview和Getting started页面(Agents、Workflows、Workflow + Agents)。在某次会话中首次编写该形态时,请同时阅读这两个页面;该分区的其他页面(Calling a sibling agent、Browser tools、Serial execution)也列在它们旁边。 - 没有独立页面的辅助函数或类型(
interruptOn、callDeepAgent、callConnector、connectorTool、defineWorkspace、Result<T>、错误代码):使用sdk区域,通过search_docs搜索标识符原文,并查看排名最高的结果。 - 完整示例:使用
list_docs,并指定examples区域。产品问题(Agent 还是工作流?使用哪个模型?):指定faqs区域。
其他技能
- stackbone-cli:搭建脚手架(
init、add)、运行(dev)、迁移(db migrate)、管理运行 / 审批 / 日志,以及发布(build、package、link)。 - stackbone-debug:查找错误、失败或卡住的运行,以及搁置审批的原因。
- stackbone-coder:从一句话构想开始,通过访谈构建新功能,然后回到这里编写代码。