Three Async Patterns Cut Lambda Idle Cost in Bedrock AgentCore Pipelines
In this article
Amazon Bedrock AgentCore agents take time to reason — time measured in seconds that varies with the prompt, the model, and the document under inspection. That latency is fine on the agent side: AgentCore's consumption-based runtime stops billing CPU while the model generates tokens or a tool call returns. The problem sits in the caller. A Lambda function that issues a synchronous invoke and blocks holds its full compute allocation until the agent responds, billing for every second of the wait. An AWS Machine Learning blog post published 19 August 2026 by Daniel Abib and Alexandre Farber documents three production patterns — task-token callback, direct service integration, and durable function — that release the caller's compute during the wait, and contrasts them with the blocking anti-pattern.
The piece is practically significant for any team running agentic pipelines in production: the orchestration pattern determines whether you pay for a few seconds of dispatch or for the entire agent reasoning cycle.
The Shared Pipeline and Agent
All four approaches drive a single AgentCore agent through the same five-stage Step Functions pipeline: Extract (OCR via Lambda), Identify (document classification via Lambda), Route (a Choice state on shouldOrganize and shouldValidate flags), a Parallel state running Organize alongside a Validate branch, and a Result Lambda. Only the Validate branch changes between patterns.
The agent inspects each invocation for two signals: a Step Functions task token and a durable-function callback ID. If it finds a task token, its conclude_validation tool calls sfn.send_task_success(taskToken=task_token, output=json.dumps(verdict)). If it finds a callback ID, it calls lambda_client.send_durable_execution_callback_success(CallbackId=callback_id, ...). If it finds neither, it returns the verdict inline. The same deployed agent serves all four invocation modes without modification or redeployment.
The entrypoint uses an @app.async_task decorated coroutine for background work and an @app.entrypoint handler that checks for taskToken or callbackId in the event: if either is present, it fires asyncio.create_task(validate_document_async(...)) and returns {"status": "accepted"} immediately; otherwise it awaits the agent inline.
The Three Async Patterns
Pattern 1 — Task-token callback. The Step Functions state uses arn:aws:states:::lambda:invoke.waitForTaskToken, injecting $$.Task.Token into the Lambda payload. The dispatcher passes the token to AgentCore via InvokeAgentRuntimeCommand, then returns { dispatched: true } in a few seconds. The execution pauses — billing no compute — until the agent calls SendTaskSuccess. The state sets TimeoutSeconds: 120 and HeartbeatSeconds: 60 so a silent agent fails the execution cleanly. A single test run makes the economics concrete: the ValidateDispatch state was active for 19.6 seconds (from TaskSubmitted at 14:08:19 to TaskSucceeded at 14:08:34), but the dispatcher Lambda's CloudWatch REPORT showed a billed duration of 4.8 seconds. The ~14.8 seconds in between carried zero Lambda compute cost.
Pattern 2 — Direct service integration. When no custom code is required, the dispatcher Lambda disappears entirely. A single Task state calls AgentCore via arn:aws:states:::aws-sdk:bedrockagentcore:invokeAgentRuntime, setting AgentRuntimeArn, a RuntimeSessionId derived from States.Hash($$.Execution.Id, 'SHA-256'), and a Payload constructed with States.JsonToString. A ResultSelector extracts $.Response, and TimeoutSeconds: 120 provides the safety net. A Standard workflow bills per state transition rather than per wait duration, so the meaningful cost during processing is purely the agent runtime and model inference.
Pattern 3 — Lambda durable function. Using the @aws/durable-execution-sdk-js SDK, the pipeline is expressed as sequential context.step calls and a context.parallel block. The agent wait becomes ctx.waitForCallback("validate-agentcore", async (callbackId) => dispatchAgentCore(callbackId, ...), { timeout: { seconds: 120 } }). During the callback wait the durable function suspends and is not billed for compute; the agent resumes it with SendDurableExecutionCallbackSuccess. Cost behaviour matches Pattern 1 — you pay for short execution bursts between suspensions, not for the wait.
Pattern Comparison
| Dimension | Blocking (anti-pattern) | Pattern 1: Task-token | Pattern 2: Direct integration | Pattern 3: Durable function |
|---|---|---|---|---|
| Caller cost during agent wait | Full agent processing time billed | Seconds (dispatch only; 4.8 s in test run) | Zero — no Lambda in path | Seconds (dispatch only) |
| Lambda in path | Yes, alive and billed throughout | Yes, returns early | None | Durable function (suspends) |
| Custom code around agent call | Yes | Yes | Limited to ASL intrinsic functions | Yes |
| Decouples caller from agent | No | Yes | No | Yes |
| Integration effort | Lowest | Medium-high (IAM, heartbeat, timeout) | Low (single Task state) | Medium (checkpoint-and-replay model) |
| Best for | Prototypes, short agents | Custom pre/post-processing logic | Pure orchestration, no custom code | Complex async workflows in one function |
Operational Guardrails
The post names four production practices that apply across all patterns. Set TimeoutSeconds on every waitForTaskToken state so a silent agent triggers States.Timeout rather than an indefinitely paused execution; pair it with HeartbeatSeconds when the agent emits heartbeats. Derive sessionId from the Step Functions execution name so retries resume the same agent session. Enable Tracing: Active on both Step Functions and Lambda configurations so X-Ray can confirm the gap between dispatch and resume contains no running Lambda. Size the dispatcher for speed: the authors recommend 256 MB of memory and a 30-second timeout, since its only job is serializing a request and invoking the endpoint.
These patterns illustrate a broader architectural pressure reshaping how teams wire AI components into existing systems: as reasoning latency grows, the control layer between orchestrator and agent becomes a meaningful cost and reliability surface. The 4.8-second billed duration against 19.6 seconds of state activity is illustrative of the relationship, not a benchmark — measure your own workload's figures before generalising.