AWS Lambda · Step Functions · Lambda Durable Functions · AI Agents · Bedrock · Multi-Agent · Strands SDK · Architecture · Orchestration
Three Ways to Orchestrate AI Agents on AWS. Here's How We Pick.
By Ramesh Nori · April 24, 2026 · 8 min read
A fintech client asked us to build an AI-powered loan application pipeline. Incoming applications get scanned by Bedrock, flagged for risk, routed to an underwriter for review, and then a decision letter gets generated and emailed.
Simple enough on a whiteboard. But the first question was: how do we orchestrate this?
There are three ways to do this on AWS right now. We've used all three across different client projects. Here's how we think about the decision.
The examples below are simplified patterns from multiple engagements. No client code is shared here.
The Three Options
Step Functions is the established choice. Visual state machine, drag-and-drop workflow designer, deep integration with every AWS service. It's been around since 2016.
Lambda Durable Functions launched at re:Invent 2025. You write sequential code in a regular Lambda, and the runtime handles checkpointing, retries, and long pauses automatically. No state machine, no JSON workflow definitions.
Multi-agent orchestrators (Bedrock Agents, Strands SDK, LangGraph) let AI models decide the next step. Instead of you defining the workflow, the AI routes between specialized agents based on the input.
Three tools. Same problem. Very different trade-offs.
When the Workflow Is Predictable, Use Durable Functions
Our fintech client's pipeline had a fixed sequence: scan the application, flag risk factors, route to an underwriter, generate a decision letter. Every application follows the same path. The only variable is whether the underwriter approves or rejects.
This is where durable functions shine. The code reads like a script:
@step()
def scan_application(ctx, pdf_url):
response = bedrock.invoke_model(
modelId="anthropic.claude-sonnet-4-6-20250514-v1:0",
body={"prompt": f"Assess this loan application for risk factors: {pdf_url}"}
)
return response["risk_assessment"]
@step()
def flag_risk(ctx, assessment):
if assessment["risk_score"] > 0.7:
return {"needs_review": True, "assessment": assessment}
return {"needs_review": False, "assessment": assessment}
@callback()
def wait_for_approval(ctx, review_data):
# Pauses here. No compute charges. Resumes when underwriter responds.
return ctx.callback_result
@step()
def generate_decision_letter(ctx, approved_data):
letter = bedrock.invoke_model(
modelId="anthropic.claude-sonnet-4-6-20250514-v1:0",
body={"prompt": f"Generate a loan decision letter based on: {approved_data}"}
)
send_email(letter)
return letter
No state machine. No workflow JSON. Just code. If it fails at step 3, it picks up from step 3. If the underwriter takes a week to review, it waits for free.
The same thing in Step Functions would be 150+ lines of Amazon States Language JSON, plus separate Lambda functions for each step, plus an SQS queue for the callback.
When the AI Needs to Decide the Next Step, Use Multi-Agent
A different client needed something less predictable. Their customer support system handles tickets that could be billing questions, technical issues, account changes, or escalations. The right response depends entirely on what the customer wrote.
You can't hardcode that flow. The AI has to read the ticket and decide which specialist to call.
billing_agent = Agent(
model="anthropic.claude-sonnet-4-6-20250514-v1:0",
instructions="Handle billing inquiries. Access invoice and payment tools.",
tools=[lookup_invoice, process_refund]
)
technical_agent = Agent(
model="anthropic.claude-sonnet-4-6-20250514-v1:0",
instructions="Debug technical issues. Access logs and system status.",
tools=[search_logs, check_system_status]
)
orchestrator = Agent(
model="anthropic.claude-sonnet-4-6-20250514-v1:0",
instructions="Route customer tickets to the right specialist.",
agents=[billing_agent, technical_agent]
)
# The AI decides who handles this
result = orchestrator.invoke("My invoice shows a double charge and my dashboard is down")
The orchestrator reads the ticket, sees two problems (billing + technical), and routes to both agents. You didn't define that flow. The AI figured it out.
Try doing that with durable functions and you'd end up writing a giant if/else tree that breaks every time a new ticket type shows up.
Where Does Step Functions Fit?
Step Functions is still the right choice when you need heavy parallel execution, complex branching with multiple conditions, or deep integration with non-AI AWS services (ECS, Glue, EMR, CodeBuild).
For AI workflows specifically, we've been reaching for it less. The workflow definition language adds friction when you're iterating fast on prompts and agent behavior.
How We Decide
When a client asks us to build an AI workflow, we ask two questions:
1. Is the sequence fixed or does the AI need to choose the path?
Fixed sequence with known steps, waits, and approvals? Durable functions. The AI decides routing? Multi-agent.
2. How many AWS services are involved beyond Bedrock?
If the workflow orchestrates five AWS services with complex error handling and parallel branches, Step Functions still has the edge. If it's mostly Bedrock calls with some S3 and SES, durable functions keep it simpler.
| Durable Functions | Multi-Agent | Step Functions | |
|---|---|---|---|
| Best for | Predictable AI pipelines | Dynamic routing | Complex multi-service orchestration |
| Workflow definition | Sequential code | AI-decided | JSON state machine |
| Human-in-the-loop | Built-in callbacks | Custom implementation | Activity tasks |
| Cost while waiting | Free | N/A (doesn't wait) | Free (Standard) / No (Express) |
| Learning curve | Low (just code) | Medium (agent design) | High (ASL syntax) |
| When we use it | Document pipelines, approval flows | Support routing, research agents | Data pipelines, CI/CD orchestration |
The Bottom Line
Most AI workflows we build for clients today fall into one of two buckets: predictable pipelines or dynamic routing. Durable functions handle the first. Multi-agent frameworks handle the second. Step Functions is still there for everything else, but it's no longer our default.
The biggest mistake we see is teams reaching for a multi-agent framework when their workflow is actually a straight line. If you know the steps upfront, you don't need an AI to figure out what to do next. Write it as code. Let it checkpoint. Move on.
Written by Ramesh Nori. If this was useful or you have feedback, reach me at cloudbuckle@gmail.com.