cd /news/artificial-intelligence/asynchronous-patterns-for-calling-am… · home topics artificial-intelligence article
[ARTICLE · art-103600] src=aws.amazon.com ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

Asynchronous patterns for calling Amazon Bedrock AgentCore agents in serverless pipelines

Amazon Web Services (AWS) introduced three asynchronous invocation patterns for Amazon Bedrock AgentCore agents in serverless pipelines to eliminate idle compute costs, where a blocking caller such as an AWS Lambda function is billed for the entire agent processing time. The patterns—task-token callback, direct service integration, and durable function—release the caller's compute during the wait, contrasting with the blocking anti-pattern. The example pipeline validates documents for real-estate financing, with the agent reading property records or loan contracts and returning a verdict.

read12 min views1 publishedAug 19, 2026
Asynchronous patterns for calling Amazon Bedrock AgentCore agents in serverless pipelines
Image: AWS ML Blog

Artificial Intelligence

Asynchronous invocation patterns for Amazon Bedrock AgentCore agents in serverless pipelines remove idle compute costs while your AI agent processes requests. A common example is document validation: in a real-estate financing back office, an agent can read a property record or loan contract, reason about whether the information is complete and consistent, and return a verdict that downstream steps act on. Amazon Bedrock AgentCore provides a platform to build, connect, and optimize agents at scale, with any framework or model.

These agents introduce a characteristic that traditional pipeline steps do not have: they think for a while before they answer. How long depends on the prompt, the model, and the document, but it’s rarely instant, and that latency changes how you should call it. The most common first implementation is a compute service, such as an AWS Lambda function, that invokes the agent and waits for the response. While that function waits, it does nothing, but it is still running, and you are billed for every second of it.

It helps to see where the cost actually lands, because the two sides of the call are billed differently. Amazon Bedrock AgentCore runtime, a capability of Amazon Bedrock AgentCore, has a consumption-based model that doesn’t charge for CPU while the agent is idle. For instance, while it waits on a large language model to generate a response, or on a tool or Model Context Protocol (MCP) call to return, you are billed for memory during that time, but not for CPU. The compute service that called the agent has no such behavior. A Lambda function, container, or Amazon Elastic Compute Cloud (Amazon EC2) instance that issues a synchronous call sits blocked. It holds (and pays for) its full compute allocation until the agent responds. So the waste is not on the agent side. It’s the caller, idling on an open connection.

That makes the caller’s cost track the agent’s runtime. A function that blocks on the agent is billed for essentially the entire processing time, whereas a function that starts the agent and returns is billed only for the brief dispatch. The fix is to release the caller’s compute during the wait and resume the pipeline only when the agent has a result. In this post, we show three patterns that do this (task-token callback, direct service integration, and durable function) and contrast them with the blocking anti-pattern.

An example pipeline #

To compare the patterns on equal footing, we run each one through the same pipeline and change only the step that calls the agent. The pipeline is a deliberately simple, made-up scenario (validating documents for real-estate financing) chosen to keep the orchestration clear. It’s not the point of the post. It stands in for any workflow that calls an agent (or another slow service) and then acts on the result, so picture your own use case in its place.

The pipeline has five stages:

Extract: An AWS Lambda function performs optical character recognition (OCR) and text extraction on the document. (Extraction is simulated, so the scenario runs without real documents.)Identify: A Lambda function classifies the document and sets routing flags (shouldOrganize

,shouldValidate

).Route: A Choice state directs the flow based on those flags.** Organize and Validate**: A Parallel state organizes the document while, in a separate branch, the Amazon Bedrock AgentCore agent validates it. This Validate branch is the only part that changes between patterns.Result: A Lambda function processes the agent’s verdict and decides the next action (approve, or return for correction).

The following diagram shows the pipeline. It stays the same in every case. Only the Validate branch is swapped to demonstrate each invocation pattern.

A single Amazon Bedrock AgentCore agent serves all four cases. The agent inspects each invocation and chooses how to respond: if it receives an AWS Step Functions task token, it wakes that execution when done. If it receives a durable-function callback ID, it wakes the durable function. If it receives neither, it returns the verdict directly in the response. This means you can change the orchestration pattern without changing or redeploying the agent.

How the agent returns control without blocking the caller #

The mechanism is a return-of-control action in the agent’s action group. When the agent finishes reasoning, it calls a Lambda that posts the result and the task token back to Step Functions. (Pattern 2, described later, eliminates this Lambda entirely by having Step Functions integrate directly with AgentCore.)

The following code shows the core of that Lambda:

The entrypoint decides whether to run in the background or synchronously based on the same signals:

With the agent in place, the rest of the post focuses on the four ways to call it.

Calling the agent: Four approaches #

We start with the blocking anti-pattern to establish the baseline cost, then show the three patterns that avoid it. The code and infrastructure definitions throughout are excerpts from the sample, included to illustrate each pattern.

The blocking anti-pattern

The most direct implementation calls the agent and waits for the answer in the same Lambda function. It works, and it is straightforward to implement, which is why it’s so common, but the function stays alive for the entire time the agent is thinking.

The function’s billed duration ends up approximately equal to the agent’s processing time. The next three patterns eliminate this idle cost, each making a different trade-off. In particular, Pattern 2 uses the Step Functions optimized integration for AgentCore Harness (InvokeHarness), removing the Lambda entirely.

Pattern 1: Task-token callback with a dispatcher function

This pattern keeps a Lambda function in the path for custom logic but removes the idle cost. Step Functions invokes the function with the waitForTaskToken

integration, which passes a task token and then s the execution. The function uses the token to start the agent, then returns in a few seconds. The execution stays d, billing nothing for compute, until the agent calls SendTaskSuccess

with that token to resume it.

The corresponding state passes the token from context and sets a timeout and heartbeat as a safety net, so a silent agent fails the execution cleanly rather than leaving it d indefinitely:

Cost. A Lambda function runs, but only long enough to start the agent and return: a few seconds, regardless of how long the agent then takes. You pay for that brief dispatch, not for the wait, because the function has already shut down while the agent works. The wait is held by the d Step Functions execution, which doesn’t bill for idle compute. This is the key difference from the blocking version, where the function’s billed time tracks the agent’s processing time.

Pattern 2: Direct service integration

When you don’t need custom code around the agent call, you can remove the dispatcher function and take Lambda out of the path entirely. Step Functions can call Amazon Bedrock AgentCore directly through its AWS SDK service integration, so the agent’s response flows straight into the next state. The Validate branch then becomes a single Task state:

Cost. There’s no Lambda function in the path, so there is no idle Lambda compute to pay for. Step Functions holds the wait, and a Standard workflow bills per state transition rather than for the duration of the wait, so the meaningful cost during processing is the agent itself.

Pattern 3: Lambda durable function

If you would rather express the orchestration as code in one place instead of a state machine, a Lambda durable function gives you the same cost behavior. With the @aws/durable-execution-sdk-js

SDK, the pipeline stages become context.step

calls, the parallel work becomes context.parallel

, and the wait for the agent becomes context.waitForCallback

. During that wait the function suspends and is not billed for compute. The agent resumes it with SendDurableExecutionCallbackSuccess

.

Cost. A single function holds the whole pipeline, but it doesn’t bill for compute while it is suspended waiting for the agent. You pay for the short bursts of execution between suspensions, the same economics as the task-token pattern, rather than for the wait.

Measuring the difference #

The point isn’t any particular number. The agent’s runtime varies with the prompt, the model, and the document. What matters is the relationship between two values in the task-token pattern: how long the Validate state was active, versus how long the dispatcher function was actually billed. A single run from our testing makes the relationship visible:

Step Functions, ValidateDispatch state
   Returned (TaskSubmitted): 14:08:19   <- the function returned and shut down
   Resumed  (TaskSucceeded): 14:08:34   <- the agent woke the execution
   State active ........ 19.6s

Lambda, dispatcher function (CloudWatch REPORT)
   Billed duration ..... 4.8s

Result: the state was active for 19.6s, but the function was billed for 4.8s.
The ~14.8s in between is wait time with no Lambda function running.

You can see the same thing in the Step Functions event history: with the task-token pattern, a TaskSubmitted

event (the function returned) is separated from TaskSucceeded

(the agent resumed the flow) by the agent’s processing time. A synchronous invocation has no such gap.

The following table summarizes how the Validate branch (highlighted in the preceding diagram) is implemented in each pattern:

Blocking (anti-pattern) | Pattern 1: Task token | Pattern 2: Direct integration | Pattern 3: Durable function | | | Orchestrator | Step Functions | Step Functions | Step Functions | Lambda (code) | | Lambda function in the path | yes, alive and billed | yes, but it returns early | none | the durable function (suspends) | | Idle Lambda compute during the wait | pays the full wait | none | none | none | | Custom code around the agent call | yes | yes | limited (state transformations) | yes | | Decouples the caller from the agent | no | yes | no | yes | | Relative complexity | lowest | higher (token and callback IAM) | lowest | medium (checkpoint/replay) |

One caveat on reading this: the total pipeline duration isn’t a useful comparison metric, because it’s dominated by the agent’s own reasoning time, which varies from run to run and is essentially the same in every scenario. The meaningful difference is how much compute you pay for during that wait, captured by the table and the billed-duration reading. The dispatcher’s billed time stays flat while the agent’s runtime grows. The preceding numbers come from a single run. Treat them as an illustration of the relationship, not a benchmark, and measure your own workload.

Choosing a pattern #

The following table summarizes the trade-offs to help you choose a pattern:

Blocking (anti-pattern) | Pattern 1: Task-token | Pattern 2: Direct integration | Pattern 3: Durable function | | Caller cost | Full agent processing time | Seconds (dispatch only) | Zero (no Lambda) | Seconds (dispatch only) | Integration effort | Low | Medium-high (IAM, heartbeat, timeout) | Low (single Task state) | Medium (checkpoint-and-replay model) | Business logic location | In Lambda (before + after) | In Lambda (before + after) | In Amazon States Language (ASL) only (intrinsic functions) | In Lambda (sequential code) | Best for | Prototypes, short agents | Custom pre/post-processing logic | Pure orchestration, no custom code | Complex async workflows in one function |

Best practices #

Guard against an agent that never answers. Set TimeoutSeconds

on every waitForTaskToken

state so the execution fails with States.Timeout

instead of hanging indefinitely. If your agent sends heartbeats, also set HeartbeatSeconds

for faster dead-agent detection. Catch the error and route to a failure or human-review path.

Use a stable session ID across retries. Set sessionId

to a value derived from the execution context (such as the Step Functions execution name) so that retries resume the same agent session rather than starting fresh. In the task-token pattern, set it in the dispatcher. In the direct-integration pattern, set it in the Task state parameters.

Turn on AWS X-Ray. Enable Tracing: Active

in your Step Functions and Lambda configurations. X-Ray shows exactly how long the agent spent thinking versus how long the caller spent waiting, confirming that your pattern actually released compute during the gap.

Size the dispatcher function for speed, not for the agent’s workload. The dispatcher only serializes a request and invokes an endpoint. 256 MB of memory and a 30-second timeout are usually sufficient. The heavy work happens on the agent side.

Costs #

These patterns incur charges for Lambda compute, Step Functions state transitions, durable-function execution storage, and, common to every approach, Amazon Bedrock AgentCore runtime and Amazon Bedrock model inference. The agent and model cost is the same in all four cases. The architecture changes only the orchestration overhead and, in the blocking anti-pattern, the wasted idle Lambda compute. For current pricing, see the pricing pages for each service.

Conclusion #

Putting an AI agent in a pipeline is the straightforward part. Calling it economically is what separates a prototype from a production design. A Lambda function that blocks on the agent is straightforward to implement but quietly expensive, spending most of its billed time waiting. In this post, we showed three ways to avoid that: a task-token callback when you need a Lambda function in the path, a direct service integration for the simplest case, and a durable function when you prefer orchestration as code. All three are driven by the same Amazon Bedrock AgentCore agent, which adapts its response to however it is called.

The full sample, including the complete agent, the state machine definitions, and the durable function, is available in the sample-bedrock-agentcore-async-stepfunctions repository on GitHub. To go deeper, review the Amazon Bedrock AgentCore documentation on asynchronous task processing.

For production deployments, use Amazon Bedrock Guardrails to enforce responsible-AI controls on agent inputs and outputs.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @amazon web services 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/asynchronous-pattern…] indexed:0 read:12min 2026-08-19 ·