PluginsHooks
Guard
详细说明 guard 的阻断语义、执行顺序,以及它为什么不应该拿来改值
Guard
guard 的核心语义很简单:
- 通过,什么都不返回
- 不通过,直接抛错
它的职责不是改值
很多人第一次写 guard,会忍不住在里面顺手改输入。
但 guard 最稳的职责其实只有一个:
- 判断当前流程能不能继续
所以如果你的主要目标是“改一下输入”,那就应该去写 pipeline。
一个最小例子
await agent.plugins.guard("review.require_checked", {
reviewed: true,
});plugin 里可以这样定义:
hooks: {
guard: {
"review.require_checked": [
async ({ value }) => {
const body = value as { reviewed?: unknown };
if (body.reviewed !== true) {
throw new Error("review is required before continuing");
}
},
],
},
}多个 guard handler 怎么跑
如果同一个点上有多个 guard:
- 会按注册顺序依次执行
- 只要其中一个抛错,后面的就不再跑
所以它像一串安检门。
适合的典型场景
权限判断
例如:
- 当前用户有没有角色
- 当前请求有没有权限
前置条件判断
例如:
- 某个字段是不是必填
- 某个状态是否已经准备好
安全边界
例如:
- 某类请求是不是必须显式确认
- 某类输入是不是要先过审
不适合的场景
想继续执行但顺手记一条日志
记录日志应该拆到 effect。
想根据条件补默认值
补默认值应该拆到 pipeline。
想给最终决策答案
那是 resolve。
disabled plugin 时会怎样
如果某个 guard plugin 当前 disabled:
- 它的 handler 会被跳过
- 其他 active guard 仍然会继续执行
所以 guard 的语义是:
- active 的 guard 参与检查
- disabled 的 guard 不参与
最稳的实践
- 让错误信息直接说明为什么被拦住
- 不要在 guard 里偷偷写很多副作用
- 不要把“改值”和“拦截”混成一件事