我们在写伪代码吗?
有时候在写 prompt 的时候,感觉有点像在写伪代码
- “先 xxx,再 xxx” → 对应代码的执行顺序
- “如果 xxx,就 xxx” →
if逻辑 - “一直执行直到 xxx” →
while循环
既然如此,我们能不能直接把一段“伪代码”丢给 AI 呢?
kimi-k2 执行效果:
看起来还可以!
给它加一点限制,让它从 1+…+ 到 n,同时排除所有位数之和加起来为 5 的倍数的数字,不能调用脚本:
let count = Tool.AskUserQuestion(`please input a number`);
let sum = 0;
for (let i = 1; i <= count; i++) {
if (Prompt(`${i} 的每个位数加起来之和为 5 的倍数`)) {
} else {
sum += i;
}
}
Prompt(`最终计算结果为 ${sum}`)
好吧,这下原型毕露了,比如 86 这个完全不应该排除的数字,被它直接排除掉了。
而且它是先计算的所有值的和,再减去需要排除的值,其实没有严格按照我们的逻辑来执行。
其实好好想一想上面的过程,我们把一个伪代码丢给大模型来执行,期望于就像把代码丢给编译器来执行一样,但是 AI 有着很多的幻觉,这个“编译器”很不稳定。
在一些复杂任务的实测里,它会跳过逻辑胡乱执行,比如没按照预期调用 tool,或者直接在半路上认为自己已经成功了,特别是一些笨蛋 AI,每次执行过程和结果可能都不一样。
可以用代码驱动 AI 吗?
为了解决这种不稳定性,我们需要一种能强约束执行流程的工具。
在 Claude Code 或类似的 Agent 框架中,AI 可以根据 Tool 的返回决定下一步。那么,我们能不能反过来?由一段真实的代码来驱动 AI,AI 只负责完成其中的“自然语言函数”部分?
这正是 agent-workflow-mcp-tool 的核心思路:利用 MCP 协议,通过 TypeScript 的 Generator 函数,将 AI 变成流程中的一个执行单元。
下面的代码是可以真实执行的代码而非伪代码:
async function* Workflow() {
const count = yield* ClaudeCodeTools.AskUserQuestion(
`please input a number`,
z.number()
);
let sum = 0;
for (let i = 1; i <= count; i++) {
sum = yield* Prompt(`calculate ${sum} + ${i}`, z.number());
}
return sum;
}github 地址:https://github.com/voderl/agent-workflow-mcp-tool
它有哪些优势呢:
- 用代码控制流程。 Agent lies, code not
- 使用 zod 强校验,避免模型幻觉
- 完善的 typescript 支持
- 支持 async await throw catch 等语法
- 对比其他工具特别轻量,完全基于 mcp 协议
- 配合 claude code 和 kimi-k2 & deepseek 工作良好
比如用我们再举上面的例子,如果用该工具去处理上面的问题,让 AI 从 1+…+n,同时排除所有位数之和加起来为 5 的倍数的数字,那么完整的写法如下:
import { ClaudeCodeTools, registerWorkflowTool, Prompt, z } from "agent-workflow-mcp-tool";
const server = new McpServer({
name: "agent-workflow",
version: "0.0.1",
});
registerWorkflowTool(
server,
"workflow",
{
title: "workflow",
description: `workflow control`,
},
async function* Workflow() {
const count = yield* ClaudeCodeTools.AskUserQuestion(
`please input a number`,
z.number()
);
let sum = 0;
for (let i = 1; i <= count; i++) {
if (
yield* Prompt(
`计算 "${i}" 的所有位数加起来之和是否为 5 的倍数`,
z.boolean()
)
) {
} else {
sum += i;
}
}
return sum;
}
);这时你让 Claude Code 直接执行该 mcp
Ask: use mcp "agent-workflow" tool "workflow" directly执行结果见下图:
kimi-k2 真的严格按照代码给定的流程,从 1 + 2 + 直到加到 87,对每一个数字判断其所有数字加起来之和是否为 5 的倍数,调用了 87 次 mcp tool,最终得出了正确的结果。
可以在图中看出,在大模型每次调用 mcp 时,mcp 会给出当前的任务,如果大模型执行成功,大模型需要在下次调用时带上上次任务的执行结果。
每一步都有完善的 zod 类型校验,如果传参不对会给大模型提示,避免大模型的传参幻觉。
基于这样的 workflow,我们也可以把“对每一个数字判断其所有数字加起来之和是否为 5 的倍数”这一步可能会有大模型幻觉产生的步骤,改为使用代码来执行保证。
async function* Workflow() {
const count = yield* ClaudeCodeTools.AskUserQuestion(
`please input a number`,
z.number()
);
let sum = 0;
for (let i = 1; i <= count; i++) {
if (sumDigits(i) % 5 === 0) {
} else {
sum = yield* Prompt(`calculate ${sum} + ${i}`, z.number())
}
}
return sum;
}更多复杂场景
基于该工具,我们可以实现更复杂的逻辑,比如自动生成 commit 信息并在用户确认后提交代码:
registerWorkflowTool(
server,
"auto-commit",
{
title: "auto commit",
description: `auto commit`,
},
async function* Workflow() {
const filesChangeList = yield* Prompt(
`获取当前变更文件列表`,
z.array(z.string())
);
if (filesChangeList.length === 0) {
return `没有任何代码更改`;
}
const commitMessage = yield* Prompt(
`根据当前变更内容生成对应的 commit message,格式需满足:
(fix|feat|chore): 单行简洁的提示
多行详细变更内容`,
z.string()
);
const { is_confirm } = yield* ClaudeCodeTools.AskUserQuestion(
`commit message 为 ${commitMessage},是否确认继续`,
z.object({
is_confirm: z.boolean(),
})
);
if (!is_confirm) return `已取消`;
yield* Prompt(`将当前变更代码提交,commit message 为 ${commitMessage}`);
}
);自动提交确认效果:
还可以基于上面的流程,在 commit 前获取所有变更文件,挨个给每一个文件都使用 AI review 一遍,可以试试看~
使用
npm install agent-workflow-mcp-toolimport { registerWorkflowTool, Prompt, ClaudeCodeTools, z } from 'agent-workflow-mcp-tool';欢迎使用和反馈~
感谢看到这里~