Amazon Bedrock Flows.
Every Bedrock resource covered in this series — Knowledge Bases, Guardrails, AgentCore agents — solves one piece of a problem. Amazon Bedrock Flows is the glue layer: a node-based workflow builder that chains those pieces into an end-to-end pipeline, versions it as an immutable snapshot, and exposes it as a single API endpoint your application can call. You design the graph; Bedrock handles the orchestration.
aws bedrock-agent create-flow --name "my-rag-flow" --execution-role-arn <role> --definition file://flow.json
01What Flows is — and the three-phase lifecycle
A flow is a directed graph: a collection of named nodes connected
by typed edges (connections). When you call InvokeFlow, the input
travels through the graph from the single required input node until it
reaches one or more output nodes; the response carries the final output.
Everything between — model calls, knowledge-base queries, Lambda invocations,
branching logic — is invisible to the caller.
The lifecycle has three phases:
- Draft (DRAFT) —
CreateFlowcreates a mutable working draft. CallUpdateFlowas many times as you like, thenPrepareFlowto compile the latest changes into a testable state.InvokeFlowon DRAFT is fine for testing. - Version —
CreateFlowVersiontakes a snapshot of the current DRAFT and assigns an immutable integer version number. Versions never change. - Alias —
CreateFlowAliascreates a named pointer (prod,blue,latest) that routes invocations to one or more versions via a weightedroutingConfiguration. Your application calls the alias; you do blue/green by updating alias routing — no code change on the caller side.
Flows uses the same draft → version → alias model as Bedrock Agents. If you've shipped an Agent, the deployment mental model is identical.
02The thirteen node types
Nodes fall into two families: logic nodes control the execution path; data nodes do the work.
Logic nodes
| Node | What it does |
|---|---|
| Input | Entry point. Validates the content from InvokeFlow and forwards it. Every flow has exactly one. |
| Output | Exit point. Extracts from the previous node and returns as flowOutputEvent.content. A flow with branches can have multiple output nodes — one per branch. |
| Condition | Evaluates relational + logical expressions (==, !=, >, >=, <, <=, and, or, not) and routes data to the matching branch. Conditions are evaluated in order; first match wins. A default condition is the fallback. |
| Iterator | Takes an Array and emits items serially (not in parallel). Each item produces a separate response. Outputs: arrayItem + arraySize. |
| Collector | Receives iterated items and re-assembles them into an Array. Pair with Iterator for fan-out / fan-in. |
| DoWhile | Runs a sub-graph repeatedly while a boolean condition remains true. Condition is evaluated after each pass (do-while semantics). maxIterations defaults to 10; always specify it explicitly. |
Data nodes
| Node | What it does |
|---|---|
| Prompt | Calls a foundation model. Prompt is inline (model ID + template + inference params) or referenced from Prompt Management by ARN. Inputs map to template variables; output is modelCompletion: String. Guardrails attach here. |
| Agent | Invokes a Bedrock Agent alias (agentAliasArn). Supports multi-turn: the agent can pause mid-flow, request user clarification, and resume. |
| KnowledgeBase | Queries a Knowledge Base. With modelId → RetrieveAndGenerate (returns outputText: String). Without modelId → Retrieve (returns retrievalResults: Array). Guardrails only work with RetrieveAndGenerate. |
| Storage (S3) | Writes content to an S3 bucket. Inputs: content + objectKey. Output: s3Uri. |
| Retrieval (S3) | Reads a UTF-8 string from an S3 object key. Output: s3Content. |
| LambdaFunction | Calls a Lambda function using a standard input event (messageVersion: "1.0", flow.*, node.inputs.*). Output is whatever the Lambda returns. Cross-account invocations are supported. |
| InlineCode (preview) | Executes Python 3 in an isolated, managed environment with no internet access. The last evaluated expression is returned as output. No separate Lambda required. |
03Connections and expressions
Every connection in a flow is one of two types. A data connection (solid gray line in the console) carries data from an upstream node output to a downstream node input. A conditional connection (dotted purple line) carries data from a condition node to a downstream node when that condition is true.
Every node input is configured with an expression — a JSONPath-like
selector that extracts the relevant slice of the whole input arriving
at that node. The simplest expression is $.data, which selects the
entire document. $.data.genre digs one level in;
$.data[1] takes the second array item. Amazon Bedrock validates the
extracted value against the declared type (String, Number,
Boolean, Object, Array) at runtime and
returns an error on mismatch.
04Versions, aliases, and blue/green deployments
The DRAFT version is the only mutable state. To lock down behavior for production:
import boto3
client = boto3.client("bedrock-agent", region_name="us-east-1")
# Snapshot → version
resp = client.create_flow_version(flowIdentifier=flow_id)
flow_version = resp["version"] # e.g. "1"
# Alias → stable invocation endpoint
client.create_flow_alias(
flowIdentifier=flow_id,
name="prod",
routingConfiguration=[{"flowVersion": flow_version}]
)
To run a canary rollout, update the alias routing to split traffic between versions:
client.update_flow_alias(
flowIdentifier=flow_id,
aliasIdentifier=alias_id,
routingConfiguration=[
{"flowVersion": "1", "flowVersionWeight": 0.9},
{"flowVersion": "2", "flowVersionWeight": 0.1},
]
)
Your application holds the alias ARN. Promoting v2 to 100% is a single
update_flow_alias call — no change to the caller's code.
05Sync vs async invocation
Synchronous — InvokeFlow
The call blocks until the flow completes or hits the 1-hour hard
timeout. Results stream back as server-sent events:
flowOutputEvent, flowCompletionEvent,
flowErrorEvent. Good for interactive, latency-sensitive workloads.
The client is bedrock-agent-runtime, not bedrock-agent.
Asynchronous — StartFlowExecution (preview)
Decouples invocation from execution. The response is an executionArn;
poll with GetFlowExecution to check status.
| Limit | Value |
|---|---|
| Per-node timeout | 5 minutes |
| Total flow runtime | 24 hours |
| Status values | Running, Succeeded, Failed, TimedOut, Aborted |
Use ListFlowExecutionEvents to debug: eventType=Node
returns per-node inputs and outputs across all intermediate nodes;
eventType=Flow returns only the entry/exit events. Amazon Bedrock
auto-captures a snapshot of the flow definition at execution
start (GetExecutionFlowSnapshot) — so updating the flow while an
execution is running doesn't affect that execution.
06Guardrails, Prompt Management, and pricing
Guardrails attach to Prompt nodes (scans both prompt and
response) and KnowledgeBase nodes (RetrieveAndGenerate only — bare
Retrieve is not guarded). Add the configuration block to the node:
"guardrailConfiguration": {
"guardrailIdentifier": "abc123",
"guardrailVersion": "1"
}
Prompt Management — a Prompt node can reference a versioned prompt by ARN instead of defining it inline. This separates prompt authoring from flow wiring: a prompt engineer owns the prompt; a platform team owns the graph. Neither blocks the other when iterating.
Pricing — Flows itself has no per-request charge. You pay for the underlying resources: model invocations on Prompt and Agent nodes, Knowledge Base queries, Lambda invocations, and S3 reads/writes.
07Limits worth knowing
InvokeFlowhard timeout is 1 hour. If your flow touches slow external APIs or chains many model calls, budget for latency or switch toStartFlowExecution.- Iterator is serial, not parallel. Items fan out one at a time. For high-volume array processing, use a Lambda node that does parallel work internally and returns an aggregated result.
- DoWhile
maxIterationsdefaults to 10. If you expect more iterations, set it explicitly — silent exit at the limit is easy to miss in testing. - S3 Retrieval requires UTF-8 strings. Binary files (PDFs, images) need pre-processing before a Retrieval node can consume them.
- Guardrails on KnowledgeBase are
RetrieveAndGenerateonly. If you useRetrieve(nomodelId) and want content filtering, add a downstream Prompt node with a guardrail. - InlineCode is Python 3 only and in preview. No internet access inside the execution environment. Stable behavior may differ at GA.
- Two distinct API clients. Build-time operations (
CreateFlow,PrepareFlow,CreateFlowVersion,CreateFlowAlias) use thebedrock-agentclient. Runtime operations (InvokeFlow,StartFlowExecution) usebedrock-agent-runtime. Using the wrong client is the most common early mistake.
08Try it in five minutes
The following creates a minimal end-to-end flow: input a topic, a Prompt node summarises it, the output is returned.
import boto3
client = boto3.client("bedrock-agent", region_name="us-east-1")
ROLE = "arn:aws:iam::123456789012:role/MyFlowsRole" # replace
# Define nodes
input_node = {
"type": "Input", "name": "FlowInput",
"outputs": [{"name": "document", "type": "Object"}]
}
prompt_node = {
"type": "Prompt", "name": "Summarise",
"configuration": {"prompt": {"sourceConfiguration": {"inline": {
"modelId": "amazon.nova-lite-v1:0",
"templateType": "TEXT",
"templateConfiguration": {"text": {
"text": "Write a 3-sentence summary of: {{topic}}"
}},
"inferenceConfiguration": {"text": {"temperature": 0.5}}
}}}},
"inputs": [{"name": "topic", "type": "String",
"expression": "$.data.topic"}],
"outputs": [{"name": "modelCompletion", "type": "String"}]
}
output_node = {
"type": "Output", "name": "FlowOutput",
"inputs": [{"name": "document", "type": "String",
"expression": "$.data"}]
}
# Wire connections
connections = [
{"name": "in_to_prompt", "source": "FlowInput",
"target": "Summarise", "type": "Data",
"configuration": {"data": {
"sourceOutput": "document", "targetInput": "topic"}}},
{"name": "prompt_to_out", "source": "Summarise",
"target": "FlowOutput", "type": "Data",
"configuration": {"data": {
"sourceOutput": "modelCompletion",
"targetInput": "document"}}},
]
# Create, prepare, version, alias
resp = client.create_flow(
name="TopicSummariser", executionRoleArn=ROLE,
definition={"nodes": [input_node, prompt_node, output_node],
"connections": connections}
)
flow_id = resp["id"]
client.prepare_flow(flowIdentifier=flow_id)
v = client.create_flow_version(flowIdentifier=flow_id)["version"]
alias = client.create_flow_alias(
flowIdentifier=flow_id, name="prod",
routingConfiguration=[{"flowVersion": v}]
)
# Invoke (note: bedrock-agent-runtime, not bedrock-agent)
rt = boto3.client("bedrock-agent-runtime", region_name="us-east-1")
response = rt.invoke_flow(
flowIdentifier=flow_id,
flowAliasIdentifier=alias["id"],
inputs=[{"nodeName": "FlowInput", "nodeOutputName": "document",
"content": {"document": {"topic": "quantum computing"}}}]
)
for event in response["responseStream"]:
if "flowOutputEvent" in event:
print(event["flowOutputEvent"]["content"]["document"])
Sources: Amazon Bedrock Flows overview, Key definitions, Node types, Code samples, Async flow executions.
If the docs change, this tip is a snapshot of that day — check the sources for current behaviour.
This page — research, writing, verification, and deployment — was built by Claude Cowork. No human touched the prose, the layout, or the upload pipeline. The tip was generated this morning, cross-checked against the official AWS docs by an independent verification pass, and published to Cloudflare R2 on a schedule.