Most of what people call an agent is a fixed sequence of steps with one or two model calls in the middle. The control flow is knowable in advance, but teams hand it to the model anyway, then spend weeks making a non-deterministic loop behave. When the shape of the work is known, the orchestrator should be deterministic, and AWS Step Functions is a better fit for that job than a hand-rolled agent loop. It already solves retries, timeouts, error handling, parallelism, and human approval, the exact things an agent framework asks you to reimplement.

The reframing worth internalizing: let the model make decisions, not the plumbing. Use the model for the steps that genuinely need judgment, extract, classify, draft, and let a state machine decide what runs, in what order, and what happens when a step fails. You do not need an LLM to know that step three follows step two.

Deterministic orchestration is a feature, not a limitation

A rolled-your-own agent loop puts the model in charge of control flow: it decides which tool to call, reads the result, decides the next tool, and so on until it thinks it is done. That is the right design when the path is genuinely unknown at author time. It is the wrong design when the path is a workflow you could draw on a whiteboard, because now every run can take a different route, retries are ad hoc, and a failure halfway through leaves state you have to reconstruct.

Step Functions inverts that. You declare the states and transitions. Each state that needs judgment invokes Bedrock (directly or through a Lambda); each state that does not is plain logic. The run is reproducible, every transition is logged, and the execution history is a built-in audit trail. For a workflow with a known shape, determinism is exactly what you want.

Retries and error handling you do not write

The unglamorous majority of agent-reliability work is retry policy. A model call throttles, a tool times out, a downstream API returns a transient 500. In a hand-rolled loop you write backoff, jitter, and per-error handling by hand, and you usually get it subtly wrong.

Step Functions makes this declarative. Each state carries its own retry and catch behavior:

"InvokeModel": {
  "Type": "Task",
  "Resource": "arn:aws:states:::bedrock:invokeModel",
  "Retry": [{
    "ErrorEquals": ["Bedrock.ThrottlingException"],
    "IntervalSeconds": 2,
    "BackoffRate": 2.0,
    "MaxAttempts": 5
  }],
  "Catch": [{
    "ErrorEquals": ["States.ALL"],
    "Next": "HandleFailure"
  }]
}

Throttling gets exponential backoff, anything else routes to a failure state you control. No retry code, no lost exceptions, and the behavior is visible in the definition instead of buried in a loop.

Human-in-the-loop is a first-class state

The place hand-rolled agents hurt most is pausing for a human. An agent that can spend money, send email, or change production should stop and wait for approval, and doing that in a long-running process means holding state somewhere while a person takes hours or days to respond.

Step Functions has this built in through the callback pattern. A task started with .waitForTaskToken pauses the execution, emits a token, and does nothing until something calls SendTaskSuccess or SendTaskFailure with that token. The workflow can sit paused for as long as the approval takes without a process running, then resume exactly where it left off. You get a durable, auditable human gate without building a queue, a state store, and a resume mechanism yourself.

When you still want a real agent loop

This is not an argument against agent loops, it is an argument for using them where they earn their keep. Reach for a model-driven loop when the path is genuinely open-ended: the model has to decide, at runtime, which of many tools to use and in what order, and no fixed graph captures it. Open-ended research, freeform debugging, and tasks where the next step depends on what the last step returned in ways you cannot enumerate are the real home of the agent loop.

The trap is using that pattern for a five-step pipeline with one branch. If you can draw the flowchart, encode the flowchart. Save the non-deterministic loop for the work that is actually non-deterministic.

The takeaway

A large share of production agent work is deterministic orchestration wearing an agent costume. For that work, Step Functions gives you retries, error routing, parallelism, and a durable human-approval state that you would otherwise build and maintain by hand, plus an execution history that doubles as an audit log. Let the model make the calls that need judgment, and let a state machine own the control flow. The most reliable agent is often the one where the model decides the least.

Read this next

For the infrastructure and platform reading of the same pattern, including approval gates on high-risk operations, the cloud field notes live at ercan.cloud, and the hub is at ercanermis.com.