mcpField
S
stackbone

stackbone

github.com/stackboneAgent 工作流1105 次安装6 周前更新
代码仓库

关于 stackbone

stackbone 是面向在 Stackbone 工作区中工作的编码 Agent 的技能,说明如何用 SDK 构建深度 Agent 和持久化工作流、查询文档并在模拟器中验证更改。

主要功能

  1. 01工作区与代码布局约定
  2. 02深度 Agent 和工作流模式
  3. 03环境 SDK 客户端用法
  4. 04工作流步骤幂等性指导
  5. 05通过 MCP 查询文档
  6. 06通过模拟器验证

适用场景

  1. 01向 Stackbone 工作区添加 Agent
  2. 02构建带检查点的持久化工作流
  3. 03在工作流中调用 Agent
  4. 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(),也无需连接字符串。

如何开展工作

  1. 定位目标。 Agent 位于 deep-agents/<name>/index.ts;工作流位于 workflows/<name>.workflow.ts。如果目标不存在,请使用 stackbone add agent|workflow|workflow-agent <name> 创建框架(参见 stackbone-cli 技能)。不要手动编写文件布局或 package.json 中的固定版本。
  2. 先阅读,再编写。 对于更改涉及的每个接口,请阅读对应页面(如何找到页面)。请通读整个页面:你需要的选项通常在后半部分。
  3. 按下方的结构编写代码。 保持工具函数体或步骤简短;所有环境调用都放在其中。
  4. 在模拟器中验证。 运行 stackbone dev,然后与 Agent 聊天,或运行 stackbone workflows start <name> --input '…';接着运行 stackbone runs get <runId> 和 stackbone logs tail --run <runId>(参见 stackbone-cli 技能)。更改必须经由一次成功运行,才算完成。
  5. 遇到失败? 切换到 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:从一句话构想开始,通过访谈构建新功能,然后回到这里编写代码。

评论

支持 Markdown