This article is a machine translation of the contents of the following URL, which I wrote in Japanese:

【AWS】Step Functionsをエージェントのツールにしてみた:ピン・IAM・トークンの効き方を検証【AgentCore】 #MCP - Qiita

はじめに 2026年10月29日、AWS Step Functionsのワークフローを、AIエージェントのツールとして使えるようになりました。Amazon Bedrock AgentCore Gatewayの組み込みコネクタを経由します。 エージェントは「何をどの順で行う...

favicon qiita.com

Introduction

On October 29, 2026, AWS Step Functions workflows became available as a tool for AI agents. This is achieved through a built-in connector in the Amazon Bedrock AgentCore Gateway.

The strength of an agent lies in its ability to decide "what to do and in what order." However, there are tasks, such as refunds and onboarding, where "the same procedure must be followed every time, and a record of what was executed must be kept." This connector stores the procedure in a state machine, leaving the agent only responsible for "when to start and what inputs to use."

However, when passing execution-related APIs to an agent, the focus shifts from the functionality itself to "how far to allow it." There are three mechanisms for restricting the scope of what an agent can call—in other words, control—: pinning, IAM, and task tokens. This article uses the official documentation as primary source information to organize the 10 operations exposed by the connector and explains how to use these three controls, along with the results of testing on a real system.

The verification covered 8 items. The five connector-specific items are tools/list, denial of pinning, includedData, IAM denial of execution ARN, and the authorization flow via waitForTaskToken. Three additional items were added: Standard/Express constraints, tokens for non-public state machines, and how the caller appears in CloudTrail. The results are summarized in "Actual Verification Content and Results".

Premise: Where have the controls moved with the update?

Of the three controls, pinning involves pre-fixing the stateMachineArn of the operation in the gateway target settings. Pinned parameters disappear from the tool's input schema, and the agent cannot change their values.

The official documentation explains the advantage of this connector as "you don't need to write a Lambda function or MCP server, and you don't need to define the tools yourself" (Source: AWS Step Functions as Connector Target). MCP (Model Context Protocol) is a common agreement for agents to find and invoke tools. Conversely, before the update, it can be interpreted that Step Functions were being tooled by preparing Lambda functions or custom MCP servers (my interpretation). In that case, the controls that narrowed the scope allowed to agents were likely on the code and role side, as follows:

Controls Before Update (Tooling with Lambda or custom MCP server) (My interpretation) After Update (Connector)
Pinning the Target Write the state machine ARN in the code Specify in parameterValues of the target settings. The gateway rejects calls that pass different values.
IAM Narrow the scope of permission with roles you have prepared yourself, such as the Lambda execution role Narrow with the gateway's service role. Share between targets on the same gateway.
Task Token Handle in your own code. You can insert validation logic, etc. Expose SendTask* as is. IAM cannot be used for filtering; only tokens provide control.

The updated columns are also based on the same documentation.

In other words, the control previously written in code has been replaced by "target settings" and "service roles." While you no longer need to write code, you must understand for yourself whether the settings work as intended and where they don't. This article aims to verify the following three points:

Control What to verify Corresponding validation (number in the table below)
Pin If a different stateMachineArn is passed, is it denied as configured? What does the agent see? 1, 2
IAM Is referencing and stopping unauthorized executions denied by a policy filtered by the execution ARN? What is passed in includedData? 3, 4
Task Token Assuming filtering is not possible with IAM, how does the authorization flow work and what does the token control? 5

Conclusion

Issues Conclusion
What is now usable? With AgentCore Gateway's built-in connector (connectorId: "states"), existing Standard/Express state machines can be exposed as MCP tools without writing Lambda or custom MCP servers.
Division of Roles The agent decides "when and with what input to execute," and the state machine decides "which steps to execute and in what order." The agent cannot omit or rearrange steps.
Control is 3-tiered ① Pinning of the state machine, ② IAM policy of the gateway's service role, ③ Confidentiality of the task token. ① and ② are complementary, and ③ cannot be filtered with IAM.
Selection Criteria For tasks where you want to refer to and stop execution later, or where an audit trail is required, use Standard. If you only need the results synchronously, use Express (the author's interpretation derived from the verified constraints)
What was confirmed during verification Passing a pinned stateMachineArn is rejected, and the execution is not created. References and stops to unauthorized execution ARNs are rejected by IAM. Input and output are included in the response with includedData: ALL_DATA. Task tokens work with Resource: "*", and resending used tokens fails. Execution of state machines not exposed to the gateway can also be completed if a token is available. Standard/Express constraint errors occur as shown in the official table

The sources for "What is now available," "Roles and responsibilities," and "3-tier control" are the official documentation listed in the prerequisites section.

Verification Environment

Item Content
Region ap-northeast-1 (Tokyo)
Gateway AWS_IAM authorization. Main targets are hello and approval. Added express and wrongtype for Express verification
State Machine 4 Standard (AgentHelloWorld, AgentOtherWorkflow, ApprovalWorkflow, UnexposedApproval), 1 Express (AgentExpressWorkflow)
Caller awscurl (SigV4 signature. AWS request signing scheme). Sent the same MCP JSON-RPC request that the agent sends directly.
Tools AWS CLI 2.34.24 (updated to 2.39.3 during verification. See below), Python 3.12, awscurl 0.44

As a prerequisite, this assumes readers understand IAM roles, the basics of Step Functions, and JSON-RPC used for MCP communication (tools/list to get a list of tools and tools/call to call tools). It is based on the same configuration as the official tutorial. We added a state machine that is not exposed for checking IAM rejections, SQS and workflows for the authorization flow, and an Express state machine to verify the differences between Standard and Express.

Overall Structure

flowchart LR A["Agent<br/>(Strands / LangGraph, etc.)"] -- "MCP<br/>tools/list, tools/call" --> G["AgentCore Gateway<br/>Step Functions Connector"] G -- "Authenticate with Service Role<br/>Merge Fixed Parameters" --> S["Step Functions<br/>State Machine"]

According to the official documentation, the process flow is as follows:

# Content
1 Add a target with connectorId: "states" to the gateway and select the operations to be tooled. Pin the stateMachineArn to the corresponding ones. The gateway takes a snapshot of the tool schema.
2 When the agent calls tools/list, one tool is visible for each configured operation. Pinned parameters do not appear in the schema (e.g., StartExecution only has input).
3 When the agent calls tools/call, the gateway merges the pinned parameters and arguments and calls Step Functions in the service role.
4 The Step Functions API response is returned as a JSON string in content[].text. In case of an error, isError: true is returned, and the Step Functions error name is inserted (in verification, the error name was returned at the beginning of the body; see below).
5 The agent chains the tools. A typical example is StartExecution → DescribeExecution → GetExecutionHistory.

Source: AWS Step Functions as Connector Target

Calling tools/list returned the tools for the 6 configured operations in alphabetical order (not configuration order). The tool names are in the form of the target name followed by ___ (three underscores), such as hello___DescribeExecution. The input schema for hello___StartExecution was only input; stateMachineArn was not visible.

10 Operations Exposed by the Connector

According to the official documentation, the connector (version 1.0.0) exposes 10 operations. These are broadly divided into "4 that can be pinned to the state machine" and "6 that the agent passes identifiers to."

4 Pinnable Operations

Operation Role Fields Visible to Agents by Default Additional Fields That Can Be Exposed Corresponding Workflow
StartExecution Starts the state machine. The returned executionArn allows tracking the state later. input (JSON string) name, traceHeader Standard / Express
StartSyncExecution Starts Express, waits for completion, and returns the result in the same call. input name, traceHeader Express only
ListExecutions Returns a list of state machine executions. Filter by status statusFilter maxResults, nextToken Standard only
DescribeStateMachine Returns the state machine definition, role, and settings includedData None Standard / Express

Six identifiers the agent passes (not PINnable)

Operation Role Identifier to pass Default field Additional fields that can be exposed Corresponding workflow
DescribeExecution Returns the execution status (success, failure, etc.) and start/end times. ALL_DATA returns input and output as well executionArn executionArn, includedData None Standard execution only
StopExecution Stops execution in progress executionArn executionArn error, cause Standard execution only
GetExecutionHistory Returns execution event history (events at each step) executionArn executionArn includeExecutionData, maxResults, reverseOrder, nextToken Standard execution only
SendTaskSuccess Restarts a task awaiting approval as successful taskToken taskToken, output None Standard / Express
SendTaskFailure Terminates a task awaiting approval as failed taskToken taskToken, error, cause None Standard / Express
SendTaskHeartbeat Indicates a long task and prevents timeout taskToken taskToken None Standard / Express

To show additional fields, specify visible: true in parameterOverrides for that operation. Only stateMachineArn cannot be exposed via parameterOverrides and can only be specified via pinning.

includedData for DescribeExecution and DescribeStateMachine defaults to METADATA_ONLY. Specifying ALL_DATA includes the execution's input/output and state machine definition.

Testing revealed that the response with includedData omitted was identical to the response with METADATA_ONLY specified. When DescribeStateMachine is called with METADATA_ONLY, definition is returned as "{}" (empty), and ALL_DATA contains the entire definition.

Differences between Standard and Express (Pitfalls)

The following errors are limitations of Step Functions, not connector bugs.

Operation Usable Types Using Different Types
StartSyncExecution Express only Fails in Standard. Use polling with StartExecution and DescribeExecution.
ListExecutions Standard only StateMachineTypeNotSupported in Express.
DescribeExecution / GetExecutionHistory / StopExecution Standard execution only InvalidArn in Express execution ARN (because it cannot be handled by ARN after start).
StartExecution / DescribeStateMachine / SendTask* Both -
  • If you want both types to coexist in one target, fix StartSyncExecution to Express and other pinable operations to Standard.

  • The callback pattern (.waitForTaskToken) is only supported by Standard. Express does not support it.

  • These constraints are written in the tool descriptions returned by tools/list, allowing the agent to select the appropriate tool.

Source: AWS Step Functions as Connector Target

Looking at the descriptions in tools/list, four tools—DescribeExecution, GetExecutionHistory, ListExecutions, and StopExecution—state "Standard workflows only." ListExecutions also states that it will fail with StateMachineTypeNotSupported in Express. StartExecution and DescribeStateMachine have no listed constraints, corresponding to their usability with both types.

Furthermore, an Express state machine was prepared to actually generate the behavior shown in the table above.

Operation Result
StartSyncExecution on the Standard state machine StateMachineTypeNotSupported (This operation is not supported by this type of state machine)
StartSyncExecution on the Express state machine Success. The response contains status, output, and billingDetails.
ListExecutions on the Express state machine StateMachineTypeNotSupported
Pass the execution ARN obtained from Express's StartExecution to DescribeExecution, GetExecutionHistory, and StopExecution All three return InvalidArn (Resource type not valid in this context: express)
Create an Express state machine with a definition including .waitForTaskToken InvalidDefinition (Express state machine does not support '.waitForTaskToken' service integration)

This matches the official table. The official documentation only states that StartSyncExecution directed to Standard "fails," but the actual error name was StateMachineTypeNotSupported. Furthermore, the execution ARN for Express is returned as express:<state machine name>:..., a different resource type from Standard's execution:. In this case, we also allowed express:AgentExpressWorkflow:* via IAM and confirmed that Step Functions returned InvalidArn instead of IAM denial.

When Express is exposed, the agent cannot check its status, view its history, or stop after startup (as verified above, all three return InvalidArn). If the requirement is to "trace execution later," choosing Standard is the safer option (my interpretation).

Control Design: What to Allow the Agent

This is the core of this article. The official documentation explains controls in two layers: "pins" and "IAM." The two are complementary, not interchangeable (Source: AWS Step Functions as Connector Target).

Figure 1: How to restrict agent permissions (1: Pinning, 2: IAM for service roles, 3: Task tokens)

stepfunctions-agentcore-gateway-governance.png

Control Scope of Effect Notes
Pinning (stateMachineArn Pinning) StartExecution, StartSyncExecution, ListExecutions, DescribeStateMachine Agents cannot change this target. The gateway denies it.
Gateway Service Role IAM Policy Six Cannot-Pin DescribeExecution / StopExecution / GetExecutionHistory can be narrowed down to the execution ARN of the state machine to be exposed.
Task Token Concealment SendTaskSuccess / SendTaskFailure / SendTaskHeartbeat IAM does not have resource-level permissions and allows with "*". Any agent with a valid token can complete the task.

① Pinning

Pinned parameters are removed from the tool schema and enforced in all calls. When the agent passes stateMachineArn, it is rejected with the following error:

Invalid request parameters: cannot set parameter(s): [/stateMachineArn] 

I tried passing the ARN of a different state machine (AgentOtherWorkflow) as stateMachineArn. isError: true returned the following, and the execution was not created. The wording is the same as in the official documentation, but with the error name at the beginning.

IllegalArgumentException - Invalid request parameters: cannot set parameter(s): [/stateMachineArn] 

The error name is IllegalArgumentException, which differs in format from the IAM rejection (Step Functions error wrapped in DependencyFailedException) described later. The pin violation can be interpreted as the gateway rejecting the Step Functions before it is called (my interpretation).

The official documentation includes the following cautionary note:

  • Only one pin is allowed per operation. If you want to expose multiple state machines with the same operation, separate the targets.

  • Even if you forget to set parameterValues.stateMachineArn in the operation you want to pin, the target itself can still be created. However, the tool will fail every time because the state machine is not passed.

② Service Role IAM Policy

The three operations that cannot be pinned, such as DescribeExecution, operate on the execution ARN passed by the agent. The IAM policy for the service role is what restricts this.

Since the execution ARN is a different resource type from the state machine ARN, the policy in the official tutorial is divided into two statements (Source: Tutorial).

{ "Version": "2012-10-17", "Statement": [ { "Sid": "StateMachineOperations", "Effect": "Allow", "Action": [ "states:StartExecution", "states:ListExecutions", "states:DescribeStateMachine" ], "Resource": "arn:aws:states:<region>:<account-id>:stateMachine:AgentHelloWorld" }, { "Sid": "ExecutionOperations", "Effect": "Allow", "Action": [ "states:DescribeExecution", "states:GetExecutionHistory", "states:StopExecution" ], "Resource": "arn:aws:states:<region>:<account-id>:execution:AgentHelloWorld:*" } ] } 

The trust policy trusts bedrock-agentcore.amazonaws.com while filtering by aws:SourceAccount and aws:SourceArn (gateway/...).

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "bedrock-agentcore.amazonaws.com" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "aws:SourceAccount": "<account-id>" }, "ArnLike": { "aws:SourceArn": "arn:aws:bedrock-agentcore:<region>:<account-id>:gateway/step-functions-gateway-*" } } } ] } 

With the above policy (only allowing execution ARNs for AgentHelloWorld) applied, I passed execution ARNs for AgentOtherWorkflow, which are not permitted, to DescribeExecution, GetExecutionHistory, and StopExecution. All three were rejected. Execution of AgentHelloWorld, which is permitted, could be accessed. The rejection of DescribeExecution is as follows (account IDs, etc., have been omitted):

DependencyFailedException - {"errorType":"com.amazon.coral.service#AccessDeniedException","errorMessage":"User: arn:aws:sts::<account-id>:assumed-role/AgentCoreGatewayToStepFunctions/gateway-session-invocation is not authorized to perform: states:DescribeExecution on resource: arn:aws:states:<region>:<account-id>:execution:AgentOtherWorkflow:<execution-id> because no identity-based policy allows the states:DescribeExecution action","statusCode":400,"service":"states","operation":"DescribeExecution"} 

Two points can be inferred:

  • The denial is occurring during the Step Functions IAM evaluation ("service":"states"). The error name is wrapped in DependencyFailedException, so the agent needs to read the JSON inside.
  • The caller is the service role assumed-role/.../gateway-session-invocation. The session name is fixed, and it's not possible to tell from this message which agent or user made the call.

The next two screenshots are from after adding the approval workflow (ApprovalWorkflow) in Verification 5. Therefore, Resource contains both AgentHelloWorld and ApprovalWorkflow.

Figure 2: Inline Policy for Service Roles (StateMachineOperations: Allowed by State Machine ARN)

13_AllowedPolicy.png

Figure 3: Inline Policy for Service Roles (ExecutionOperations: Allowed by Execution ARN)
12_AllowedPolicy.png

Targets on the same gateway share the service role. If you want to change IAM boundaries for each workflow, separate the gateways.

③ Task Token

The three functions SendTaskSuccess, SendTaskFailure, and SendTaskHeartbeat cannot be restricted to specific executions via IAM (Source: AWS Step Functions as Connector Target). Therefore, the task token itself is the sole control. Treat the token as sensitive information and deliver it only to the agent that should process it.

When the service role was allowed states:SendTaskSuccess and two other states with Resource: "*" (see screenshot below), SendTaskSuccess via the gateway succeeded. Resending the token for a completed task failed with TaskTimedOut (Provided task does not exist anymore).

Figure 4: Service Role Inline Policy (TaskTokenOperations: Allow SendTask* with Resource: "*")

11_Allow Policy.png

Furthermore, I directly launched an execution from the CLI using a state machine (UnexposedApproval) that was not exposed to any gateway targets. Passing that token to SendTaskSuccess via the gateway resulted in SUCCEEDED. Random tokens were rejected with InvalidToken. Since it cannot be filtered by PIN or IAM, if you have the token, you can complete the execution even of a state machine not exposed to the gateway.

Figure 5: Graph view of a state machine not exposed to the gateway (UnexposedApproval) (after SendTaskSuccess via the gateway. All steps were successful)

15_StepFunctions.png

Figure 6: Event history of the same execution (from TaskSucceeded to ExecutionSucceeded)

16_StepFunctions.png

Summary of Control Design

Requirements Controls to be Used
Limit the workflows that can be launched Pinning
Limit the scope of executions that can be viewed and stopped IAM policy for service role (scoped by execution ARN)
Pass tasks that can be resumed later, such as manual approval Limit the destination of task token delivery (cannot be narrowed down with IAM)
Separate permission boundaries for each workflow Separate gateways (because the service role is shared)

Operational Perspective

Perspective Content
Recording the Caller Execution via the gateway results in the gateway's service role being the caller on CloudTrail (Source: Tutorial). In the actual event, the userIdentity of the StartExecution event was AssumedRole (assumed-role/AgentCoreGatewayToStepFunctions/gateway-session-invocation), and invokedBy was bedrock-agentcore.amazonaws.com.
Identifying Who Initiated It Since the caller is the gateway's role, it's not possible to distinguish "which agent/user initiated it" using CloudTrail alone. From what I could see, the session name was fixed as gateway-session-invocation, and there were no fields indicating the gateway ID or the calling agent/user. Also, requestParameters.input was replaced with HIDDEN_DUE_TO_SECURITY_REASONS, and the contents of the input were not recorded in CloudTrail. Therefore, even if you put a user ID in the execution's input, it cannot be tracked in CloudTrail. On the other hand, responseElements.executionArn is recorded, so you can identify the execution from the CloudTrail event and check the input in the Step Functions execution history.
Input/Output Exposure Allowing includedData: ALL_DATA means that the execution's input/output is passed to the agent (LLM context). Handle with caution in workflows that contain personal information. In my tests, executing an input of approximately 400 characters resulted in a response of 674 characters (default: METADATA_ONLY) to 1410 characters (ALL_DATA), with the input JSON (simulated data including customer ID and address) and output being included as is.

The StartExecution event via the gateway is as follows (account ID and other details have been masked):

{ "eventVersion": "1.11", "userIdentity": { "type": "AssumedRole", "principalId": "AROA****************:gateway-session-invocation", "arn": "arn:aws:sts::<account-id>:assumed-role/AgentCoreGatewayToStepFunctions/gateway-session-invocation", "accountId": "<account-id>", "accessKeyId": "ASIA****************", "sessionContext": { "sessionIssuer": { "type": "Role", "principalId": "AROA****************", "arn": "arn:aws:iam::<account-id>:role/AgentCoreGatewayToStepFunctions", "accountId": "<account-id>", "userName": "AgentCoreGatewayToStepFunctions" }, "attributes": { "creationDate": "2026-11-01T11:28:30Z", "mfaAuthenticated": "false" } }, "invokedBy": "bedrock-agentcore.amazonaws.com" }, "eventTime": "2026-11-01T11:28:30Z", "eventSource": "states.amazonaws.com", "eventName": "StartExecution", "awsRegion": "ap-northeast-1", "sourceIPAddress": "bedrock-agentcore.amazonaws.com", "userAgent": "bedrock-agentcore.amazonaws.com", "requestParameters": { "stateMachineArn": "arn:aws:states:ap-northeast-1:<account-id>:stateMachine:AgentHelloWorld", "input": "HIDDEN_DUE_TO_SECURITY_REASONS" }, "responseElements": { "executionArn": "arn:aws:states:ap-northeast-1:<account-id>:execution:AgentHelloWorld:<execution-id>", "startDate": "2026-11-01T11:28:30Z" }, "requestID": "<request-id>", "eventID": "<event-id>", "readOnly": false, "eventType": "AwsApiCall", "managementEvent": true, "recipientAccountId": "<account-id>", "eventCategory": "Management" } 

The userIdentity session name is fixed as gateway-session-invocation, and invokedBy is bedrock-agentcore.amazonaws.com. There are no fields in this event indicating which agent or user made the call.

Two Patterns of Agent and Workflow Collaboration

According to the official documentation, there are two ways for agents and workflows to collaborate (Source: AWS Step Functions as Connector Target).

Pattern A: Agent Starts and Monitors Workflow

StartExecution → DescribeExecution (polling) → GetExecutionHistory → (if necessary) StopExecution. If synchronous execution is acceptable, use StartSyncExecutionSource:https://dev.to/aws-builders/aws-using-step-functions-as-an-agent-tool-testing-how-pins-iam-and-tokens-work-agentcore-5a1o