用途
Stackbone Guardrails 用于给已经在运行的 Stackbone 智能体或工作流加上限制:拦截违反规则的消息轮次、遮蔽个人数据、或将轮次挂起等待人工处理。它同时说明如何排查一条规则为何没有触发。
该技能本身不保存检查项目录,也不保存字段列表:检查项及其设置从运行该智能体的机器上实时读取,其余内容都在文档中。
事实来源
文档通过 MCP 以 stackbone-docs 服务器提供(https://docs.stackbone.ai/mcp,公开,工具为 search_docs、get_doc、list_docs)。stackbone docs 会打印连接信息。
先调用 list_docs。Guardrails(Home › Features)是面向运维人员的页面,Guardrails(SDK › Humans)是面向开发者的页面。从列表中取得它们的路径再 get_doc。不要凭记忆输入路径:页面会移动,标题不变。
检查项目录不在文档里,而在机器上。写规则前先读取它。它与 Studio 表单生成所用的、以及运行时校验所用的都是同一套 schema,因此目录接受的设置就是会实际运行的设置。从页面上抄来的检查项列表会在新检查项发布当天过时。
会话中没有 stackbone-docs 工具?获取 https://docs.stackbone.ai/llms.txt:同样的索引,每页一行,含标题、描述和指向原始 markdown 的链接。按标题选页并获取该链接。https://docs.stackbone.ai/llms-full.txt 是所有页面合并为一个文件(约 700 KB)。
代码中无需编写任何内容
护栏不是函数,SDK 中也没有 stackbone.guardrails。它是机器自身数据库中的一行记录,在需要它的那一轮被读取,因此编辑会在下一轮生效,无需重新构建、无需重启。
也没有对应的 CLI 命令。CLI 中与护栏最接近的只有操作收件箱的 stackbone hitl,它决定一个被挂起的轮次,而不触碰规则。其余操作都在 Studio 或机器自身的 API 中完成。
将客户端指向机器一次:
claude mcp add --transport http my-box http://127.0.0.1:4242/mcp # a local box under `stackbone dev`
已部署的机器使用它自己的地址,客户端自行协商登录。MCP(Home › Features)中有已部署和自托管两种变体。然后按名称操作,不要做全量扫描:list_operations 有上限,超过会返回 catalog_too_large,因此传入 tag: "guardrails",读取返回的 id,再对想要的那个调用 describe_operation。读取通过 call_read_operation,写入通过 call_write_operation。
五个名词
规则(rule)是存储的那行记录:名称、检查项、侧、动作、其设置、开关和 fail-open 开关。名称是拒绝时回给用户的内容,所以要写给陌生人看。
检查项(check)是谓词。有些是纯本地的;有些会询问模型。检查项返回 pass、violation 或“无法运行”,它从不决定接下来发生什么。
侧(side)是 input 或 output:进入的消息,或发出的回复。检查项只能守护它声明的侧,机器会拒绝把它指向另一侧的保存。
动作(action)是机器对违规的处理方式。Block 结束该轮。Redact 重写内容并继续,重写后的文本就是模型读到的、也是运行记录下来的内容。Hold 把该轮留给人工处理,它是存储值与名称不一致的那个:机器称它为 require_approval。
挂载(attachment)是规则生效的位置:一个智能体、一个工作流,或整个工作区。智能体和工作流是不同类型,即使同名。
从零到一条会触发的规则
- 确定单位和侧。输出规则会缓冲整个回复直到判定完成,因此该智能体会失去逐 token 流式输出。只给需要的智能体加输出规则。
- 读取机器的目录,从那里选择检查项及其设置。不要凭记忆输入设置名称。
- 如果检查项会询问模型,确保机器有模型提供方。检查用的模型本身可选:不设置则回退到平台默认,真正出问题的是提供方——或你指定的检查模型该提供方不提供。无法运行的检查默认 fail closed,因此每个受守护的轮次都会阻止,且拒绝信息会指明检查项而非你的内容。
- 如果动作是 hold,聊天必须携带持久会话。没有线程就没有可重放的内容,机器会结束该轮而不是挂起它。
- 创建规则,在运行该智能体的机器上——规则是该机器自己的行,因此针对你笔记本写的规则不会改变生产环境。用 Studio 的表单,或对机器写入。需要能写配置的席位,owner、admin 和 member 都有。approver 和 viewer 得到只读界面而非报错。发送到机器且没有挂载的创建会落到整个工作区,从下一轮起生效:Studio 表单要求你选择位置,API 则替你选择。
- 如果创建时没有限定范围,就挂载它。这是所有人都会跳过的一步,未挂载到任何位置的规则不起作用——列表会显示它不适用于任何位置。
- 在 Playground 中观察它触发。被阻止的轮次结束时不报错:流正常关闭,原因作为回复到达。
规则为何不触发
以下每种情况都是静默的。按顺序排查。
- 它没有挂载到任何位置。这是最常见的原因。
- 它被关闭了。
- 类型不匹配:挂载到智能体的规则不会在同名工作流上触发。
- 侧不匹配:它守护消息,而你在看回复。
- 该调用是平台发起的(文档摄取、触发器的映射器、评估标准)。豁免跟随调用,而非名称。
- 机器无法读取自己的策略。此时该轮在完全没有规则的情况下运行,只有机器日志中的一条警告说明这一点。这是 fail-open 之上的一层,fail-open 对此没有发言权。
会咬人的规则
- 遮蔽总是在判定之前运行。因此审核检查项读到的是模型实际会收到的文本,而非原始消息。两条遮蔽规则会组合而非冲突。
- 第一个违规获胜,其顺序不取决于操作者选的是 block 还是 hold。因此“哪条规则拦住了我”是稳定的。
- Fail open 只覆盖一种情况:检查项无法运行。真正的违规仍会阻止。在决策上读取失败原因,以区分“你的内容违反了规则”和“检查模型挂了”。
- 只有个人数据检查项能脱敏。机器在保存时拒绝在其他任何检查项上使用 redact 动作。
- 工作流不能 hold。没有线程也没有人在等,因此工作流上的 hold 变成普通拒绝。
- 编辑会在你写入的那台机器的下一轮生效,在其他机器上几秒内生效。不要等更久才认为别的地方出了问题。
- 删除和取消挂载都会先通过 MCP 询问你。机器自身的 API 两者都不做:原始调用直接通过。它们是两个阻止某物被拦截的操作。取消挂载缩小规则适用范围;删除则连同规则及其所有位置一起移除。
挂起是同一个收件箱,不是第四套系统
被挂起的轮次在同一张审批表中写入一行,并出现在同一个收件箱中,与工作流的 requestApproval() 和智能体的受门控工具一样。它们通过行上的标记区分,收件箱会给护栏的那些加上徽标。
不同之处在于恢复的含义。批准被挂起的轮次会逐字重放消息且不再判定,因为人已经同意了。拒绝则结束该轮,回复中指明规则。
之后在哪里看到它
- 运行追踪:在模型和工具调用旁边有一个护栏步骤,含动作、原因和规则。任何地方都没有触发列表:被阻止的轮次是正常完成,因此你逐次运行查看。
- 活动日志:只有发生过的写入:created、updated、deleted、attached、detached。
- HITL 收件箱:被挂起的轮次,带徽标,含被挂起的消息和规则自己的句子。
- 目录屏幕:反方向:打开一个智能体,看到治理它的每条规则。
脱敏会记录它遮蔽的种类,从不记录值,因为该行对任何有追踪访问权限的人可读。
该告诉用户什么
在创建或挂载任何东西之前,用两三句话说明,绝不要把操作 id 或原始负载粘贴回给他们。
- 规则会做什么,用他们的话说:它读什么、阻止什么、触发时另一端的人看到什么。
- 他们会在哪里看到它:规则本身在 Settings → Guardrails,被它阻止的轮次在运行追踪,你刚做的更改在活动日志。
- 只有他们能决定的一件事:它适用多广,以及无法运行的检查应该阻止还是放行。
之后用一行说明:什么在生效、适用于哪里、哪个屏幕显示它,以及取消挂载会缩小范围而删除会移除它。
本技能不涵盖的内容
输入校验,那是 schema 的职责而非护栏的。速率限制和支出上限。模型选择,除了挑选执行检查的那个。
其他技能
- stackbone:工作区内的代码,包括 requestApproval() 和受门控工具,它们是轮次等待人工的另外两种方式。
- stackbone-cli:CLI 的其余部分,包括用于决定被挂起轮次的 hitl。
- stackbone-evals:衡量智能体而非限制它。被规则阻止的用例算作已阻止,而非失败。
- stackbone-debug:不是智能体违反规则的失败。