My agent’s prompt says “do not skip steps.” AWS just made that a state machine’s job
There’s a line in the driver prompt for the agent that writes the first draft of these posts that I’m not proud of. It says, in so many words, that the notify step “must actually run, not just be narrated.” I wrote it after a run where the agent cheerfully described sending me a notification instead of sending one. Above that line there’s a numbered list of nine steps and a polite request not to skip any of them.
That’s the whole control plane. A markdown file and good manners.
So when AWS announced this week that Step Functions workflows can now be exposed as tools for AI agents through Bedrock AgentCore Gateway, I read it with more personal interest than most “now available” posts get from me. The pitch from the announcement is one sentence: “Your agent decides when to run a workflow and what input to pass, and Step Functions runs each step exactly as you defined it.” That’s precisely the split I’ve been trying to fake with capital letters.
I didn’t wire this up hands-on. My blog agent runs on my laptop with no cloud credentials at all, on purpose, so this one is from the docs and the tutorial rather than a console session. But the docs are unusually specific, and a few details changed how I think about it.
The first surprise is that there’s no glue code. A workflow becomes a tool through a built-in connector target on the gateway, with a connector ID of states. You don’t write a Lambda, you don’t write an MCP server, and you don’t hand-write tool schemas. The core of the target configuration from the tutorial looks like this:
"connector": {
"source": { "connectorId": "states" },
"configurations": [
{
"name": "StartExecution",
"parameterValues": {
"stateMachineArn": "arn:aws:states:{{region}}:123456789012:stateMachine:AgentHelloWorld"
}
},
{ "name": "DescribeExecution" }
]
}
The interesting part is parameterValues. That’s pinning. The state machine ARN is fixed when the target is created, it’s stripped out of the schema the agent sees, and if the agent tries to pass one anyway the gateway rejects the call with cannot set parameter(s): [/stateMachineArn]. So the agent for StartExecution gets exactly one knob, input, a JSON string. It can’t go shopping for other state machines in the account. If you want to expose three workflows, you create three targets, and the tools come out namespaced like orders___StartExecution.
That’s the bit I actually wanted. My agent can call any python -m scripts.<whatever> it can spell, and the only thing stopping it is an allowlist I maintain by hand and keep getting slightly wrong. Pinning at the tool boundary is the same idea, enforced by something that isn’t the model.
The second thing worth knowing is the Express vs Standard split, because it decides what the agent can even see. The connector exposes ten operations, but they don’t all work on both workflow types. StartSyncExecution only works on Express, and it’s the nice one: status and output come back in the same tool call. Standard workflows go async, so the agent calls StartExecution, gets an execution ARN back, then polls DescribeExecution until the status stops being RUNNING. Going the other way, ListExecutions, DescribeExecution, GetExecutionHistory and StopExecution only work against Standard executions and throw InvalidArn on Express ones. You can mix the two in one target, with sync pinned to an Express machine and the rest pinned to a Standard one, which feels like the setup most people will end up with.
The third thing is human-in-the-loop, and it comes with a real gotcha. Standard workflows can pause on a .waitForTaskToken task, hand the token to your app, and wait for SendTaskSuccess or SendTaskFailure. The announcement’s example is a refund flow with a manager approval step in the middle, which is exactly where you want a human. But IAM can’t scope the task-token operations to specific executions, so the gateway role gets states:SendTaskSuccess on "*". The docs are blunt about it: any agent holding a valid token can complete that task, so treat task tokens as secrets. If your token is delivered somewhere the agent can read, your approval step is an approval step in name only.
Two more limits I’d flag before anyone gets excited. Every target on a gateway shares that gateway’s service role, so AWS’s own tutorial suggests one gateway per IAM boundary. And the docs don’t say what happens when a tool call outlives the agent’s patience, which is why polling is the documented pattern rather than one long blocking call.
Where this leaves me is fairly clear. Most of what makes my little pipeline reliable has nothing to do with the model being clever. It comes from deterministic steps with boring exit codes. The weak spot is that the order, the “must actually run,” and the “don’t skip” all live in prose that the same model is reading and executing. This feature moves the order into something that physically can’t reorder itself, and leaves the model in charge of the one thing it’s good at: deciding whether now is the moment.
I’m not moving a hobby blog pipeline into AgentCore Gateway to save myself a sentence in a prompt. But it has me eyeing the driver, and wondering whether the agent should just pick the topic and write the words, with a dumb script owning the sequence after that. The moment you catch yourself writing “please actually do this” to a model, that step probably shouldn’t be the model’s to skip.
Happy building, D
