Selecting how each step runs¶
Every state the runner visits gets a strategy that supplies its result. You assign
strategies per state via mock_mapping={state_name: strategy}. A state with no mapping is
handled by the default StandardFlowStrategy (see Control flow).
This is the core idea: the same workflow can run with each step backed by a different “means” — AWS-evaluated, mocked, your own function, a local container, or a real AWS call — and you can change a step’s means without touching the ASL.
Strategy catalog¶
Strategy |
The “means” |
Use it when |
|---|---|---|
(no mapping) → |
|
Pass/Choice/Wait/Succeed/Fail and any state whose logic the API can run. |
|
A fixed JSON string |
You just need a step to “return X” so the flow proceeds. |
|
Your Python function, in-process |
Compute a result from the input without a container. |
|
A local subprocess (no Docker) |
Run the step’s code directly in your terminal. |
|
A local Docker container |
Actually run a Batch/ |
|
A real AWS Batch submission |
Exercise the step remotely in AWS. |
|
A real AWS AppConfig fetch |
The step reads live AppConfig. |
|
Custom Map item selection |
A Map state’s items come from a non-obvious place in the input. |
Static mock¶
from aws_stepfunctions_toolkit import StaticMockResponseStrategy
# Lambda steps wrap their result in a Payload:
StaticMockResponseStrategy('{"Payload": {"statusCode": 200, "body": {"ok": true}}}')
Your own function (the simplest custom handler)¶
from aws_stepfunctions_toolkit import CallableStrategy
# Return a dict/list (json-encoded for you) or a pre-serialized JSON string.
CallableStrategy(lambda input_data: {**input_data, "decorated": True})
For full control, subclass StateExecutionStrategy:
import json
from aws_stepfunctions_toolkit import StateExecutionStrategy
class MyStrategy(StateExecutionStrategy):
def execute(self, state_name, state_def, input_data, orchestrator, context=None, parent_path=""):
result = my_logic(input_data) # do anything
return {"mock": {"result": json.dumps(result)}, "context": context}
Run the step locally as a subprocess (no Docker)¶
from aws_stepfunctions_toolkit import LocalExecutionStrategy
# Resolves the step's Command/Environment from the ASL, prepends `entrypoint`
# (the local equivalent of the image's ENTRYPOINT), injects OUTPUT_PATH, runs it,
# and reads the JSON the process writes to that path.
LocalExecutionStrategy(
entrypoint=["python", "jobs/process_data/main.py"],
cwd=".", # optional working directory
extra_env={"LOG_LEVEL": "DEBUG"}, # optional extra env vars
)
The same job code runs unchanged here or in a container — both honor the OUTPUT_PATH contract
(see Container-side handler). Use this for a fast, Docker-free inner loop;
switch the step to DockerBatchStrategy when you want the real image.
Run the step’s container locally¶
from aws_stepfunctions_toolkit import DockerBatchStrategy, DockerfileImage
DockerBatchStrategy(
s3_bucket="my-bucket",
image_source=DockerfileImage(context="./jobs/process_data"),
volumes=[("/host/data", "/data")], # optional bind mounts
variables={"workfolder": "/data"}, # optional, for resolving the step's overrides
gpus="all", # optional
)
DockerBatchStrategy resolves the step’s Command + Environment from the ASL (via
test_state), runs the container, and reads its output. The container must write its result
JSON to /tmp/output.json; the toolkit mounts a writable temp dir at /tmp and injects
OUTPUT_PATH and S3_OUTPUT_PATH. See Container-side handler for the
in-container contract and BatchJobInterface.
Submit a real AWS Batch job¶
from aws_stepfunctions_toolkit import BatchJobResponseStrategy
BatchJobResponseStrategy(
job_queue="arn:aws:batch:<region>:<account>:job-queue/my-queue",
job_definition="arn:aws:batch:<region>:<account>:job-definition/my-jd:1",
)
Image sources¶
DockerBatchStrategy gets its image from a pluggable ImageSource. A bake file is not
required — a plain Dockerfile is the easy default.
Image source |
Build/obtain by |
|---|---|
|
|
|
Run an existing local image or pull one (set |
|
|
Write your own by implementing ensure_image():
from aws_stepfunctions_toolkit import ImageSource
class MyImage(ImageSource):
def ensure_image(self) -> str:
# build / pull however you like
return "my-image:latest" # return a locally-runnable image ref
Helpers login_to_ecr(region=None) and get_codeartifact_token(domain, domain_owner, region=None)
are exported for custom sources.
Targeting a specific occurrence of a step¶
If the same state name appears in more than one place (e.g. inside two subflows or a Map), use a
hierarchical key "ParentPath/StateName" in mock_mapping to target one occurrence; a plain
"StateName" key matches it anywhere. See Control flow.