关于 aws-step-functions
面向编写和验证 AWS Step Functions 状态机的 Agent 技能,适用于构建分布式应用、自动化流程及数据或机器学习管道。内容涵盖 ASL、JSONata、错误处理、服务集成和测试,并提供从 JSONPath 迁移的指导。
主要功能
- 01ASL 状态机结构与状态类型
- 02JSONata 数据处理与变量
- 03错误处理和服务集成模式
- 04JSONPath 迁移指导
- 05验证及隔离状态测试
- 06架构模式与安全建议
适用场景
- 01编写含重试和回退的状态机
- 02将状态机从 JSONPath 迁移到 JSONata
- 03使用 TestState 模拟并测试单个状态
MCP 相关
建议使用 AWS MCP 服务进行沙盒执行和审计记录,但并非必需;所有步骤也可通过 AWS CLI 完成。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ aws/ agent-toolkit-for-aws --skill aws-step-functions安装后在 Claude Code 中输入/aws-step-functions确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/compensation-saga-pattern.asl.jsonexpress-standard-handoff.asl.jsonhuman-in-the-loop-with-timeout-escalation.asl.jsonnested-map-parallel-structures.asl.jsonpolling-loop-wait-check-choice.asl.jsonscatter-gather-with-partial-results.asl.jsonsemaphore-concurrency-lock.asl.jsonreferences/architecture-patterns.mdasl-state-types.mderror-handling.mdmigrating-from-jsonpath-to-jsonata.mdprocessing-state-inputs-and-outputs.mdservice-integrations.mdtransforming-data.mdvalidation-and-testing.md详细介绍
AWS Step Functions
概述
AWS Step Functions 使用 Amazon States Language(ASL)以 JSON 定义状态机。借助 AWS Step Functions,你可以创建工作流(也称为状态机),用于构建分布式应用程序、自动化流程、编排微服务,以及创建数据和机器学习管道。
此技能提供编写 ASL 状态机的全面指南,涵盖:
- ASL 结构和 JSONata 表达式语法
- 八种可用工作流状态的详细信息
$states保留变量- 使用
Assign管理工作流变量 - 错误处理
- AWS 服务集成模式
- 数据转换和架构示例代码
- 状态机的验证和测试
- 如何从 JSONPath 迁移到 JSONata
使用此技能时,建议使用 AWS MCP 服务执行沙箱化操作并进行审计日志记录,但所有步骤都使用 AWS CLI 语法,无需它也能正常运行。
何时加载参考文件
根据用户正在处理的内容加载相应的参考文件:
- ASL 结构、状态类型、Task、Pass、Choice、Wait、Succeed、Fail、Parallel、Map → 参见
references/asl-state-types.md - 错误处理、故障排除、Retry、Catch、回退、错误代码、States.Timeout、States.ALL → 参见
references/error-handling.md - 服务集成、Lambda 调用、DynamoDB、SNS、SQS、SDK 集成、Resource ARN、同步、异步 → 参见
references/service-integrations.md - 从 JSONPath 迁移到 JSONata、迁移、JSONPath 到 JSONata、InputPath、Parameters、ResultSelector、ResultPath、OutputPath、内置函数、Iterator、负载模板 → 参见
references/migrating-from-jsonpath-to-jsonata.md - 验证、Lint、测试、TestState、测试状态、模拟、模拟测试、单元测试、检查级别、DEBUG、TRACE、验证状态、隔离测试 → 参见
references/validation-and-testing.md - 架构模式、示例、轮询、Saga、补偿、分散-汇总、信号量、锁、人在回路中、升级处理、Express 迁移到 Standard → 参见
references/architecture-patterns.md - 数据转换、JSONata 表达式、筛选、聚合、字符串操作、$reduce、$lookup、$toMillis、$partition、$parse、$hash、$uuid → 参见
references/transforming-data.md - 状态输入/输出、$states、Assign、Output、Arguments、变量作用域、变量限制、求值顺序、状态间传递数据 → 参见
references/processing-state-inputs-and-outputs.md
快速参考
Standard 与 Express 工作流
| Standard | Express | |
|---|---|---|
| 最长持续时间 | 1 年 | 5 分钟 |
| 执行语义 | 恰好一次 | 至少一次(异步)/至多一次(同步) |
| 执行历史记录 | 保留 90 天,可通过 API 查询 | 仅 CloudWatch Logs |
| 最大吞吐量 | 2,000 次执行/秒 | 100,000 次执行/秒 |
| 定价模式 | 按状态转换次数 | 按执行次数 + 持续时间 |
.sync / .waitForTaskToken | 支持 | 不支持 |
| 适用场景 | 可审计、非幂等操作 | 高吞吐量、幂等的事件处理 |
选择 Standard,适用于:支付处理、订单履行、合规工作流,以及任何绝不能重复执行的操作。
选择 Express,适用于:IoT 数据摄取、流式转换、移动后端,以及高吞吐量的短时处理。
推荐 Express 时,必须始终说明的一项限制——即使对于即发即弃/高吞吐量管道也是如此——就是 Express 不支持
.sync或.waitForTaskToken(不支持回调、嵌套.sync等待、人工审批等待或作业完成等待)。还要说明:最长持续时间为 5 分钟、没有可查询的执行历史记录(仅 CloudWatch Logs),且执行语义为至少一次(异步)/至多一次(同步)——因此非幂等工作可能会运行两次。如果这些因素中有任何一项很重要,请选择 Standard(恰好一次,最长可达 1 年,提供完整历史记录)。
设置状态机查询语言
JSONata 是在 ASL 中引用和转换数据的首选方式。它用两个字段取代五个 JSONPath I/O 字段(InputPath、Parameters、ResultSelector、ResultPath、OutputPath):Arguments(输入)和 Output。
在顶层启用,以应用于所有状态:
{ "QueryLanguage": "JSONata", "StartAt": "...", "States": {...} }
也可以按状态启用,以便逐步从 JSONPath 迁移:
{ "Type": "Task", "QueryLanguage": "JSONata", ... }
支持 JSONPath,如果省略 QueryLanguage,则默认使用 JSONPath——现有状态机无需迁移。
字段映射(JSONPath → JSONata):
| JSONPath 字段 | JSONata 对应项 |
|---|---|
Parameters(键使用 key.$) | Arguments——去掉 .$ 后缀,并将每个值用 {% %} 括起来 |
ResultSelector 和 OutputPath | Output(通过 $states.result 引用原始结果) |
ResultPath | Assign(首选)或 Output |
InputPath | 不需要——直接引用 $states.input |
一个状态只能使用一种查询语言,不能同时使用两种。 不要在同一状态中混用 JSONPath 字段(
InputPath/Parameters/ResultSelector/ResultPath/OutputPath)和 JSONata 字段(Arguments/Output)——这是最常见的迁移错误。完整详情请参阅references/migrating-from-jsonpath-to-jsonata.md。
Assign 和 Output 如何评估(并行,而非顺序)
在同一个状态中,Assign 和 Output 同时并行评估,且都会读取相同的数据(状态输入加任务结果)。它们不会依次评估。由于二者同时运行,在该状态的 Output 中无法看到你在 Assign 中设置的变量:不存在一种执行顺序,能让 Output 观察到刚赋值的内容。赋值后的值只有在后续状态中才可用。
因此,如果你在 Assign 中设置变量,并在同一状态的 Output 中引用它,得到的会是旧值或未定义值——这并不是因为 Output 在 Assign“之前”运行,而是因为二者基于同一快照并发评估。若要立即使用该值,请在下一个状态中引用它(变量会在状态间保留);若要根据任务结果构造当前状态的输出,请在 Output 中直接使用 $states.result。
使用 TestState 对状态进行单元测试
使用 TestState API(aws stepfunctions test-state)和 --mock,即可无需部署状态机或调用实际服务,单独测试一个状态。完整答案需涵盖以下四点:
- 精确模拟服务响应——
--mock的result必须与目标 AWS 服务的 API 响应架构完全一致(字段名称区分大小写)。对于 LambdainvokeTask,应包含StatusCode和Payload:--mock '{"result":"{\"StatusCode\":200,\"Payload\":{...}}"}'。 - 三个检查级别(
--inspection-level):INFO(默认值——output、status、nextState)、DEBUG(增加数据流信息:afterArguments、result、variables——用于调试 JSONata/数据流)、TRACE(增加原始 HTTPrequest/response,用于 HTTP Task)。 .sync和.waitForTaskToken集成仍需模拟响应——对于.sync,模拟轮询 API(例如DescribeExecution,而非初始调用);对于.waitForTaskToken,还需传入--context '{"Task":{"Token":"..."}}'。- 无需部署或实际调用——可以独立测试该状态。
有关各服务的模拟结构以及错误/重试/Map/Parallel 测试,请参阅 references/validation-and-testing.md。
最佳实践
- 除非用户想使用 JSONPath,否则新建状态机时应在顶层设置
"QueryLanguage": "JSONata" - 精简
Output——只包含当前状态之后的状态立即需要的内容 - 使用
Assign存储后续状态所需的变量,而不是通过 Output 层层传递 - 使用
$states.input引用原始状态输入 Assign和Output基于状态进入时的数据并行评估,而非顺序评估——因此,在Assign中设置的变量在同一状态的Output中不可见(此时仍会读取赋值前的值);新值仅在下一个状态中生效。- 所有 JSONata 表达式都必须产生已定义的值——
$data.nonExistentField会抛出States.QueryEvaluationError - 使用
$states.context.Execution.Input从任意状态访问原始工作流输入 - 在控制台之外操作时,使用
.asl.json扩展名保存状态机定义 - 优先使用优化版 Lambda 集成(
arn:aws:states:::lambda:invoke),而非 SDK 集成
故障排除
常见错误
States.QueryEvaluationError——JSONata 表达式求值失败。请检查类型错误、未定义字段或超出范围的值。- 在同一状态中混用 JSONPath 字段和 JSONata 字段。
- 在 JSONata 表达式顶层使用
$或$$——请改用$states.input。 - 忘记在 JSONata 表达式两侧使用
{% %}分隔符——该字符串会被视为字面值。 - 在
Assign中赋值后,期望在同一状态的Output中使用这些变量——新值仅在下一个状态中生效。 - 有关详细的故障排除信息,请参阅 references/validation-and-testing.md 和 references/error-handling.md。
安全注意事项
- 最小权限执行角色。 将状态机的 IAM 角色权限范围限定为其调用的特定资源和操作(特定的 Lambda、DynamoDB、SQS 和 SNS ARN)。避免使用
*FullAccess策略和service:*通配符。 - 加密。 建议对工作流涉及的每个数据存储进行静态和传输中加密:使用 KMS 加密 DynamoDB 表,为 SQS 队列和 SNS 主题启用服务器端加密(
KmsMasterKeyId),并为 HTTP Tasks 使用 TLS。 - 任务令牌和消息正文属于敏感信息。
.waitForTaskToken令牌是一种凭证,应作为机密信息处理。不要在 SQS/SNS 消息正文或通知中放入个人身份信息、财务数据或机密信息;应传递引用 ID,并让接收方通过授权渠道查询详细信息。 - 验证输入并尽早失败。 在工作流开始处使用 Choice(或 Pass)状态,通过
$exists()和$type()验证必填字段,并将无效输入路由到 Fail 状态,避免格式错误的数据到达下游状态。通过在 Map 状态中设置MaxConcurrency并限制上游速率(StartExecution 速率限制或 EventBridge),保护下游服务免受突发流量影响。 - 跨账户访问。 使用
Credentials字段担任其他账户中的角色时,应在目标角色的信任策略中加入aws:SourceArn或aws:SourceAccount等条件键,以防止意外担任角色。 - 外部机密信息。 对于调用第三方 API 的 HTTP Tasks,应将 API 密钥和令牌存储在 AWS Secrets Manager 中(通过 EventBridge 连接引用),切勿将其直接嵌入状态机定义。
- 可观测性。 为执行启用 CloudWatch Logs(日志级别设为
ALL或ERROR;Express 工作流必须启用此功能,因为它们没有可查询的执行历史),启用 CloudTrail 以审计 Step Functions API 调用,并针对执行失败设置 CloudWatch Alarms。始终使用客户管理的 KMS 密钥加密执行日志组,因为状态输入和输出通常会流经执行日志。