A while loop in Lambda that calls Bedrock until “done” is a token incinerator without audit. Step Functions give you timeouts, maps, human approval via task tokens, and compensations finance will accept. Day 33 replaces infinite ReAct with an explicit graph.
⚡ TL;DR: Model turns as states: plan → toolChoice → tool/approve → evaluate → succeed|compensate. Cap iterations and token budget in state. Use Standard workflows for human-in-the-loop, Express for short chats.
Graph beats soup
Start → Plan → ToolChoice →
Choice:
needs_approval → WaitForTaskToken
safe_tool → InvokeTool → Evaluate →
(continue | succeed | fail_compensate)
for i in range(100):
out = converse(...)
if not out.tool_calls: break
run_tools(out.tool_calls)
Human approval with task tokens
{
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters": {
"FunctionName": "requestApproval",
"Payload": {
"taskToken.$": "$$.Task.Token",
"diff.$": "$.proposedPatch",
"sessionId.$": "$.sessionId"
}
},
"TimeoutSeconds": 86400,
"HeartbeatSeconds": 3600
}
Approval posts to Slack/Jira; Approve calls SendTaskSuccess. Heartbeats detect abandoned approvals.
Compensations and budgets
If create_resources succeeds and register_dns fails, a compensating state deletes resources. Track tokens_used and iteration in state; fail closed when budgets exceed — do not rely on the model to stop.
Production checklist
- [ ] Max iteration + token budget in state
- [ ] waitForTaskToken for mutating actions
- [ ] Compensating transitions on failure paths
- [ ] Execution history retained for replay
- [ ] Alarms on failure rate and stuck approvals
- [ ] Game-day: force compensate path once per quarter
Series navigation
Last updated September 11, 2026
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
