任务:设计一个"批量图片处理"工作流,输入是 50 张图片,需要:(1) 调整大小到 800x600,(2) 添加水印,(3) 转换为 WebP 格式。
Level 1: 设计一个简单工作流要求:
- 画出流程图(用文字描述也可以,如 A → B → C)
- 说明哪些步骤用函数、哪些用 Agent
- 说明哪里可以并行执行
- 写出伪代码的核心部分(循环和分支)
学习目标:
- 掌握工作流的四个核心构建块
- 理解步骤间的依赖关系和数据传递
- 学会设计工作流的执行流程图
前置要求:第 1 课:从单次对话到工作流 | 下一课 第 3 课 >>
上一课我们看到工作流可以协调数十个代理完成复杂任务。但如果你打开一个工作流脚本,会发现它只是普通的代码:函数、循环、条件判断。
工作流的威力来自四个简单构建块的组合:
理解这四个构建块,你就能设计任何复杂度的工作流。1
**步骤是工作流的原子操作。**每个步骤要么是一个 Agent 调用,要么是一个确定性函数。2
什么时候用 Agent 步骤:
什么时候用函数步骤:
最佳实践: Agent 步骤做推理,函数步骤做计算。不要让 LLM 做简单的数组过滤或数字求和,这既慢又贵还不稳定。2
每个步骤应该有清晰的输入输出契约:
**清晰的契约让工作流易于理解和调试。**当第 5 步出错,你能立即看出是因为第 4 步的输出格式不对。3
**状态是步骤间共享的数据。**它像工作流的内存,保存中间结果和执行进度。4
工作流状态(Workflow State):
会话状态(Session State):
模式 1:脚本变量(适合短工作流)
模式 2:状态对象(适合中等复杂度)
模式 3:外部存储(适合长时间运行的工作流)
检查点(Checkpointing): 在关键步骤后保存状态,这样工作流可以从失败点恢复,而不是从头开始。5
分支根据条件选择不同的执行路径。6
**循环让你对多个相似对象执行相同操作。**这是工作流威力的核心来源。6
这里的 limit = 5 就是并发限制:一次最多同时跑 5 个,而不是一口气 Promise.all 全部 100 个,避免打开太多连接或文件句柄。
让我们组合这四个构建块,设计一个"微服务健康检查"工作流:
对应的脚本:
这个工作流用到了所有四个构建块:
listServices、checkServiceHealth、agent() 调用state 对象保存总数、健康/不健康列表map 并行循环、for 顺序循环从终点倒推:
识别并行机会:
明确依赖关系:
下一课: 第 3 课:如何拆解复杂任务 — 学习将复杂任务系统化拆解为工作流步骤的策略
MindStudio:Claude Code 五大工作流模式 — https://www.mindstudio.ai/blog/claude-code-agentic-workflow-patterns ↩
Mae Capozzi:构建多代理编排器 — https://maecapozzi.com/blog/building-a-multi-agent-orchestrator ↩ ↩2
AWS Marketplace:代理编排 — https://aws.amazon.com/marketplace/build-learn/ai-agent-learning-series/agent-orchestration ↩
MindStudio:工作流状态 vs 会话状态 — https://www.mindstudio.ai/blog/workflow-state-vs-session-state-ai-agents ↩ ↩2
MachineLearningMastery:AI 代理中的持久化内存和状态的 5 种架构模式 — https://machinelearningmastery.com/5-architectural-patterns-for-persistent-memory-and-state-in-ai-agents/ ↩
Alex Op:Claude Code 工作流确定性多代理编排 — https://alexop.dev/posts/claude-code-workflows-deterministic-orchestration/ ↩ ↩2
要求:
问题:
// Agent 步骤:让 LLM 做需要推理的工作
const summary = await agent({
task: '总结代码审查发现',
prompt: '从这些审查结果中提取关键问题,按严重性排序',
context: reviews
});
// 函数步骤:确定性转换,不需要 LLM
const filtered = reviews.filter(r => r.severity === 'high');
const count = filtered.length;
// 好的步骤:输入输出明确
async function analyzeFile(filePath) {
// 输入:文件路径(字符串)
const result = await agent({
task: `分析 ${filePath}`,
prompt: '返回 JSON: { complexity: number, issues: string[] }'
});
// 输出:{ complexity, issues }
return JSON.parse(result);
}
// 不好的步骤:输入输出模糊
async function doStuff(data) {
// data 是什么格式?返回什么?不清楚
return await agent({ task: '处理数据', context: data });
}
// 工作流状态示例
const workflowState = {
phase: 'analysis', // 当前阶段
filesAnalyzed: 47, // 进度
issues: [], // 累积的结果
nextAction: 'generate-plan' // 下一步
};
async function shortWorkflow() {
// 状态就是普通变量
let files = await listFiles();
let analysis = await analyzeFiles(files);
let report = await generateReport(analysis);
return report;
}
async function mediumWorkflow() {
const state = {
input: await getInput(),
processed: [],
errors: []
};
for (const item of state.input) {
try {
const result = await processItem(item);
state.processed.push(result);
} catch (err) {
state.errors.push({ item, error: err });
}
}
return state;
}
async function longWorkflow(taskId) {
// 状态存在数据库,随时可恢复
let state = await db.loadState(taskId);
if (state.phase === 'completed') return state.result;
// 从上次中断的地方继续
if (state.phase === 'analysis') {
state.analysisResult = await runAnalysis();
state.phase = 'planning';
await db.saveState(taskId, state);
}
if (state.phase === 'planning') {
state.plan = await generatePlan(state.analysisResult);
state.phase = 'execution';
await db.saveState(taskId, state);
}
// ...
}
const fileCount = files.length;
if (fileCount < 10) {
// 文件少,顺序处理
for (const file of files) {
await processFile(file);
}
} else {
// 文件多,并行处理
await Promise.all(files.map(f => processFile(f)));
}
// Agent 评估复杂性
const assessment = await agent({
task: '评估重构复杂度',
prompt: '返回 JSON: { complexity: "low" | "medium" | "high" }'
});
const parsed = JSON.parse(assessment);
if (parsed.complexity === 'low') {
// 自动重构
await autoRefactor();
} else if (parsed.complexity === 'medium') {
// 生成方案,等待人工确认
const plan = await generatePlan();
await waitForApproval(plan);
await executeRefactor(plan);
} else {
// 复杂度高,仅生成建议
await generateRecommendations();
}
for (const service of services) {
try {
await deployService(service);
} catch (error) {
if (error.type === 'transient') {
// 瞬态错误,重试
await retry(() => deployService(service));
} else {
// 永久错误,回滚
await rollback(service);
throw error;
}
}
}
// 一个接一个处理
for (const pr of pullRequests) {
const review = await reviewPR(pr);
await postComment(pr, review);
}
// 同时处理所有
const reviews = await Promise.all(
pullRequests.map(pr => reviewPR(pr))
);
// 并行但限制并发数(避免过载)
const limit = 5;
for (let i = 0; i < pullRequests.length; i += limit) {
const batch = pullRequests.slice(i, i + limit);
await Promise.all(batch.map(pr => reviewPR(pr)));
}
let totalIssues = 0;
const reports = [];
for (const file of files) {
const analysis = await analyzeFile(file);
totalIssues += analysis.issueCount;
reports.push({
file: file.path,
issues: analysis.issues
});
}
console.log(`总共发现 ${totalIssues} 个问题`);
let attempts = 0;
let success = false;
while (!success && attempts < 3) {
try {
await runTests();
success = true;
} catch (error) {
attempts++;
console.log(`测试失败,重试 ${attempts}/3`);
await wait(1000 * attempts); // 指数退避
}
}
if (!success) throw new Error('测试 3 次均失败');
async function healthCheckWorkflow() {
// 步骤 1: 获取服务列表(函数步骤)
const services = await listServices();
// 状态:保存结果
const state = {
total: services.length,
healthy: [],
unhealthy: []
};
// 分支:根据数量选择策略
let results;
if (services.length > 10) {
// 并行循环
results = await Promise.all(
services.map(s => checkServiceHealth(s))
);
} else {
// 顺序循环
results = [];
for (const service of services) {
results.push(await checkServiceHealth(service));
}
}
// 函数步骤:分类结果
for (const result of results) {
if (result.healthy) {
state.healthy.push(result);
} else {
state.unhealthy.push(result);
}
}
// 分支:根据结果生成不同报告
if (state.unhealthy.length > 0) {
// Agent 步骤:生成告警
const alert = await agent({
task: '生成告警报告',
prompt: `${state.unhealthy.length} 个服务不健康,
生成详细的故障报告和建议的修复步骤`,
context: state.unhealthy
});
await sendAlert(alert);
} else {
// Agent 步骤:生成健康报告
const report = await agent({
task: '生成健康报告',
prompt: `所有 ${state.total} 个服务健康,
生成简洁的状态总结`
});
await logReport(report);
}
return state;
}
// 依赖关系示例
const files = await readFiles(); // 步骤 1
const analysis = await analyze(files); // 步骤 2 依赖步骤 1
const plan = await makePlan(analysis); // 步骤 3 依赖步骤 2
// 可以并行(无依赖)
const [files, config, users] = await Promise.all([
readFiles(),
loadConfig(),
fetchUsers()
]);