Exam Room · Advanced GenAI

When to Orchestrate With Step Functions Instead of an Agent

July 31, 2026 · 31 min read

Generative AI Development · part of The Exam Room

The situation

An overnight job takes a batch of a few thousand supplier documents, extracts structured fields from each with a foundation model, validates the extraction against a schema, writes the clean records to a data store, and, when a document fails validation twice, routes it to a human reviewer before carrying on. Some of those steps are a model call. Most of them are not. The whole thing has to run to completion even when a single model invocation throttles, a Lambda times out, or a reviewer takes two days to respond, and the operations team wants to be able to open a run afterwards and see exactly which documents took which path.

The first instinct is to reach for a Bedrock agent, because the model is doing the interesting work. That instinct is worth questioning. The model is one participant in a workflow that is mostly known in advance, mostly deterministic, and mostly about moving data reliably between AWS services with retries and a human pause in the middle.

The choice sits between three orchestration engines: a model-driven Bedrock agent, a visually-defined Bedrock Flow, and an AWS Step Functions state machine. Each puts the decision about what happens next in a different place, and that placement is the whole question.

What actually matters

The first thing to name is where the control flow is decided. In a Bedrock agent the foundation model decides the sequence at run time: it reads the request, picks an Action groupThe bundle of API operations a Bedrock agent is allowed to call, described by a schema so the model knows what each one does. or a knowledge base, observes the result, and chooses the next step, looping until it is done. That is the right tool when the path genuinely cannot be known in advance. It is also precisely what you do not want when the path is known, because model-chosen control flow is nondeterministic, harder to test, and spends an extra model call every time the model stops to decide what to do next. A Bedrock Flow and a Step Functions state machine both invert this: a person draws the sequence, and the runtime walks the graph. The model still does the work inside a node, but it does not choose the order.

The second is durability and failure handling. A batch that runs for hours across thousands of documents will hit throttling, transient errors, and slow dependencies. Step Functions Standard workflows are durable: an execution can run for up to a year, each state can carry its own retry policy with backoff and its own catch handler for specific errors, and the service persists execution state so a long-running run survives without you holding it open in your own process. A Bedrock agent has no equivalent durable-execution model; if you want a retried, resumable, auditable long-running process, you are rebuilding a workflow engine around it.

The third is reach across AWS services and shape of the work. The document job is mostly not model calls: it is reads and writes to a data store, schema validation, fan-out across many records, and a human approval pause. Step Functions integrates directly with a large number of AWS services and can fan work out with its Map state, run branches in parallel, wait on a callback token for a human decision, and invoke Bedrock as an optimised integration for the steps that are model calls. When the GenAI work is one step inside a larger business process, the orchestrator that speaks fluently to the rest of AWS wins.

The fourth is auditability. When a run has to be defensible, which document was refunded, which was escalated, which field was overwritten, model-chosen control flow is a liability because it is hard to prove the model always took the required step. A Step Functions execution gives you a full execution history you can inspect state by state, and a Flow gives you a fixed graph you can trace node by node. The more the outcome has to be provable, the more the drawn sequence is worth.

Underneath all of it: reach for the model-driven agent only when the value it adds, discovering a path you could not draw, outweighs what it costs in determinism and operational control. For a workflow whose steps you already know, the agent is the expensive answer to a question you were not asking.

What we’ll filter on

  1. Who decides the control flow, the model at run time or a designer ahead of time?
  2. Does the run need durable, long-running, resumable execution with per-step retries and error handling?
  3. How much does the job reach beyond the model into other AWS services, fan-out, parallelism, and human-approval waits?
  4. How provable and auditable does each run need to be?
  5. Is the GenAI work the whole job, or one step inside a larger process?

The orchestration landscape

  1. A Bedrock agent. One agent, an instruction prompt, one or more action groups (each backed by a Lambda function or an API schema), and optional knowledge bases. The foundation model runs the reason-act-observe loop and chooses each step. Good when the path varies request to request and cannot be drawn in advance, and when the whole job is essentially reasoning with tools. Its ceiling is that the control flow is nondeterministic, every decision point is another model call, and there is no built-in durable execution, retry policy, or human-pause primitive; you would build those yourself around it. The sibling piece on orchestrating multiple Bedrock agents covers the multi-agent supervisor extension of this shape.

  2. A Bedrock Flow. A visual builder and runtime for a mostly-deterministic pipeline. You place nodes, prompt nodes, knowledge-base nodes, agent nodes, Lambda nodes, condition nodes, iterators, input and output, and wire the data between them. The graph is fixed; the model runs inside nodes but never chooses the order. Good when the sequence is known, stays close to Bedrock-native building blocks (prompts, knowledge bases, agents), and you want predictability and traceability with low assembly effort. A Flow can still drop in an agent node for one open-ended step. Its limits are that it is oriented around Bedrock primitives rather than the whole AWS surface, and it is not the tool for hours-long durable runs, large fan-out, or human-approval waits.

  3. An AWS Step Functions state machine. A general-purpose, durable workflow orchestrator. You define states in a state machine: task states that call a service or a Lambda or Bedrock, choice states that branch, parallel states, a Map state that fans out across a collection, wait states, and success or failure states. Standard workflows run up to a year with exactly-once execution and full history; Express workflows run up to five minutes for high-volume, short-lived work. Each state can carry retry and catch policies, and the callback pattern lets a run pause on a task token until a human or external system responds. It integrates directly with a large range of AWS services and invokes Bedrock as one step among many. It is the right home when durability, retries, fan-out, cross-service reach, or human pauses dominate, and the model is a participant rather than the conductor. The cost is that you design and maintain the state machine, and for a job that is purely model reasoning it is more scaffolding than you need.

You can also combine them rather than choosing once. A Step Functions state machine can invoke a Bedrock model, a Bedrock agent, or a Flow as a single task state, so a durable, auditable outer workflow can wrap a model-driven inner step exactly where run-time flexibility earns its place. The engines are layers, not rivals.

Side by side

Property Bedrock agent Bedrock Flow Step Functions
Control flow decided by Model, at run time Designer, ahead of time Designer, ahead of time
Deterministic / testable
Durable long-running execution ✓ (up to 1 year, Standard)
Built-in per-step retry and catch Limited
Fan-out and parallelism Iterator over a set ✓ (Map, Parallel)
Human-approval pause Build it yourself ✓ (callback task token)
Reach across AWS services Via action-group Lambdas Bedrock-centric plus Lambda ✓ (broad direct integrations)
Auditable per-run trace Trace of model reasoning Node-by-node graph ✓ (full execution history)
Best when Path must be discovered at run time Known Bedrock-native pipeline Durable cross-service process, model as one step

Reading it for the document job: the sequence is known, so the model-driven agent is the wrong axis; the run is long, retry-heavy, fans out over thousands of records, and pauses for a human, which is more than a Flow is built to carry; the state machine is the fit.

How to route it

Multi-step GenAI workflow Control flow known in advance? no Bedrock agent model decides at run time yes Durable retries, fan-out, human waits, broad AWS reach? yes Step Functions state machine, model as one step no Bedrock Flow mostly Bedrock-native pipeline, designer draws it can invoke a model, agent, or Flow as a step
First ask who decides the order. If the model must, use an agent. If a designer can, the durability, fan-out, and cross-service reach decide between Step Functions and a Flow.

The picks in depth

A Bedrock agent. The right shape when the sequence cannot be drawn ahead of time and the whole job is reasoning with tools. The model handles branching for free: it looks up a record, decides it needs a schedule, fetches it, and answers, without you specifying that path. Keep it here while the value of run-time flexibility is real. The moment the workflow is actually a known sequence that mostly moves data between services, needs to survive throttling and slow dependencies for hours, or has to pause for a human, you are asking an agent to be a durable workflow engine, and it is not one. Building retries, resumability, and audit trails around an agent is rebuilding Step Functions by hand. Reach for the agent for genuine path discovery, not for a pipeline you already understand.

A Bedrock Flow. The right shape when the sequence is known, the building blocks are Bedrock-native, and you want a predictable graph with little assembly. Draw it: take the input, retrieve from a knowledge base, run a condition on whether a policy resolves cleanly, branch to a prompt node that drafts a reply or to a Lambda that files a ticket, emit the result. The order is fixed, so any run traces node by node. A Flow is not all-or-nothing about flexibility; an agent node drops one model-driven step into an otherwise deterministic pipeline. Where a Flow runs out of road is scale and durability: long-running runs measured in hours, large fan-out across thousands of records, parallel branches with independent retry policies, and human-approval waits are the state machine’s territory, not the Flow’s.

AWS Step Functions. The right shape when the workflow is durable, cross-service, and mostly not model calls. Model the document job as a state machine: a Map state fans out across the batch, and for each document a task state invokes Bedrock to extract fields, a choice state checks the validation result, a retry policy on the extraction state handles throttling with exponential backoff, a catch handler routes a repeat failure to a wait-for-callback task that pauses on a task token until a reviewer decides, and success and failure states close each item out. Standard workflows give durable execution up to a year with a full history you can inspect state by state; Express workflows suit short, high-volume runs instead. The model is one task among many, and everything around it, retries, parallelism, the human pause, the writes to other services, is a first-class primitive rather than something you code and operate yourself. The cost is that you design and maintain the state machine, which is effort you do not want to spend on a job that is purely model reasoning.

Combining them. The three engines layer. A Step Functions state machine can invoke a Bedrock model, an agent, or a Flow as a single task state, so a durable, auditable outer workflow can wrap a model-driven inner step precisely where run-time judgement is worth its nondeterminism. When most of the job is a fixed, retryable, cross-service process but one step needs the model to choose its own path, the honest answer is both: the state machine for the spine, an agent for the one step that has to think.

A worked example: the overnight extraction batch, three framings

The job: a few thousand supplier documents, extract fields, validate, store, escalate two-time failures to a human.

Framed as an agent. One agent per document reads the file, calls an extract tool, checks the schema, and on a second failure calls a tool that notifies a reviewer. It works for a single document in isolation, but the batch has no home: nothing durably tracks three thousand in-flight runs, nothing retries a throttled model call with backoff for you, and nothing pauses cleanly for a two-day human response. You would wrap the agent in your own queue, retry logic, and state store, which is a workflow engine you are now maintaining.

Framed as a Flow. A Flow expresses the per-document happy path well: input, extract via a prompt or agent node, condition on validity, branch to store or to a notify Lambda. It falls short on the batch shape. Fanning out over thousands of records with independent retry policies, running branches in parallel, and pausing days for a reviewer are past what the Flow runtime is meant to carry.

Framed as a state machine. A Map state iterates the batch. Per document: a task state invokes Bedrock to extract, with a retry policy for throttling and a catch for hard errors; a choice state branches on the validation outcome; a failed document goes to a wait-for-callback state that holds on a task token until a reviewer resolves it, then rejoins; a clean document writes to the store. The run is durable across the whole night, every document has an inspectable history, and the model call is one state among many. This is the framing the job was asking for; the other two were trying to be a workflow engine that already exists.

What’s worth remembering

  1. The first question is who decides the control flow: the model at run time (an agent) or a designer ahead of time (a Flow or a state machine). A known sequence does not want a model choosing its order.
  2. A Bedrock agent has no built-in durable execution, retry policy, or human-pause primitive. Wanting those around an agent is a sign the job is really a workflow.
  3. Step Functions Standard workflows run durably for up to a year with exactly-once execution and a full, inspectable history; Express workflows suit short, high-volume runs up to five minutes.
  4. Per-state retry with backoff and per-state catch handlers are first-class in Step Functions, which is what a long, throttling-prone, cross-service run needs.
  5. Map and Parallel states give fan-out and parallelism; the callback task-token pattern gives a durable human-approval pause. None of these is native to an agent.
  6. Step Functions integrates directly with a broad range of AWS services and invokes Bedrock as one step, so it fits when the GenAI work is part of a larger process rather than the whole of it.
  7. Bedrock Flows are the middle ground: a known, mostly Bedrock-native pipeline you draw and trace node by node, with an agent node available for one open-ended step.
  8. Flows run out of road on hours-long durability, large fan-out, independent per-branch retries, and human waits; that is the state machine’s territory.
  9. The engines combine. A Step Functions state machine can invoke a model, an agent, or a Flow as a task, so a durable outer workflow can wrap a model-driven inner step where flexibility earns its keep.
  10. Match the engine to the job: path the model must discover, an agent; known Bedrock-native pipeline, a Flow; durable, retryable, cross-service process with the model as one step, a state machine.

These posts are LLM-aided. Backbone, original writing, and structure by Craig. Research and editing by Craig + LLM. Proof-reading by Craig.