Skip to content

New serverless pattern - lambda-durable-agentcore-springai-sam-java - #3264

Open
parasjain01 wants to merge 1 commit into
aws-samples:mainfrom
parasjain01:jainpar-feature-lambda-durable-agentcore-springai-java
Open

New serverless pattern - lambda-durable-agentcore-springai-sam-java#3264
parasjain01 wants to merge 1 commit into
aws-samples:mainfrom
parasjain01:jainpar-feature-lambda-durable-agentcore-springai-java

Conversation

@parasjain01

@parasjain01 parasjain01 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Description

Human-in-the-loop AI review with AWS Lambda durable functions and Amazon Bedrock AgentCore, in Java.

A Lambda durable function orchestrates a Spring AI agent hosted on AgentCore Runtime. The agent drafts a summary of a submitted document and flags what a reviewer should verify. The workflow then suspends at a callback until a human approves or rejects, and on approval asks the agent for a final version that folds in the reviewer's comments. No compute is billed while suspended, and the completed analyze step is served from its checkpoint on resume rather than re-invoking the model.

Two AWS services: Lambda and Amazon Bedrock AgentCore.

Workflow state — step results, the pending callback, and the handler's return value — is checkpointed by the durable execution service and read back with get-durable-execution and get-durable-execution-history, so the pattern provisions no database. Submission and approval are both driven from the AWS CLI.

Why this is useful

Agentic workflows tend to need a human somewhere in the loop, and that turns out to be awkward to build: the workflow has to wait an unbounded amount of time for a person, without holding an execution open or paying for idle compute, and without re-running the expensive model call every time it wakes up. This pattern shows the whole shape end to end, so a reader can take three specific things from it:

  • How to pause a workflow for a person, in Java. waitForCallback suspends the execution and resumes it when a decision arrives. The pattern shows the Java API for it, including details that are easy to get wrong - operation names are mandatory and must be stable across deployments, WaitForCallbackConfig nests a CallbackConfig rather than taking a timeout directly, and the execution timeout has to exceed the callback timeout or the workflow expires while still waiting.

  • How to avoid paying twice for an agent call. Because the callback resumes into a fresh invocation that replays the handler from the top, a naive implementation re-invokes the model on every resume. The pattern shows what makes replay skip completed work, and the unit tests assert it rather than just describing it.

  • How to run a Java agent on AgentCore, and call it from Lambda. AgentCore hosts source code directly only for Python and Node, so a Java agent has to be an ARM64 container - the pattern includes the build script and the CloudFormation for it. It also covers two things the SDK does not make obvious: InvokeAgentRuntimeResponse has no payload() accessor because the body is streamed, and reusing one runtimeSessionId across both calls is what lets the agent keep its earlier turn in context across the approval gate.

For readers weighing modelling choices, it also takes a position on two that caused real bugs while building it: approve and reject are both callback successes carrying the verdict as data, with failure reserved for "no decision could be obtained"; and the result keeps outcome separate from decision so "the reviewer said no" is never confused with "nobody answered".

It sits alongside lambda-durable-bedrock-agentcore-async, which pairs durable functions with AgentCore but uses waitForCallback as a machine-to-machine rendezvous with no human step. The two are complementary: that one shows an async agent callback, this one a synchronous agent step behind a human gate.

A note on dependencies

The agent uses spring-ai-agentcore-runtime-starter, which auto-configures the POST /invocations and GET /ping endpoints AgentCore requires. It is a Spring AI Community project under org.springaicommunity, published to Maven Central and Apache-2.0 licensed - not an official Spring AI or AWS module - and it requires Spring Boot 4.1 or later. Flagging it in case that matters for inclusion. The README says the same, and documents how to write the two endpoints by hand instead if a reader would rather not take the dependency.

Testing

  • mvn test in orchestrator/ runs 4 unit tests against the durable execution SDK's in-memory runner, covering the approve, reject and timeout paths, and asserting that replay skips completed steps rather than calling the agent again. No AWS account required.
  • Verified end to end on AWS: the AgentCore runtime reaches READY, both agent calls succeed against Bedrock, and analyze-document records exactly one StepStarted across two InvocationCompleted events. Approve and reject paths both confirmed, including that finalize-document is skipped on rejection.
  • sam validate --lint, sam build and the repo's scripts/validate.js schema validator all pass.

Checklist

  • One pattern directory only
  • README.md, example-pattern.json and template.yaml present, based on _pattern-model
  • SAM policy templates and scoped IAM used where possible
  • No architecture diagram image (per PUBLISHING.md, the website team creates it)
  • Branch named {username}-feature-{description}

The ServerlessLand URL placeholder in the README is left as << Add the live URL here >> pending publication.

Human-in-the-loop AI review with AWS Lambda durable functions and Amazon Bedrock
AgentCore, in Java.

A Lambda durable function orchestrates a Spring AI agent hosted on AgentCore
Runtime. The agent drafts a summary of a submitted document, the workflow
suspends at a callback until a human approves or rejects it, then resumes and
asks the agent for a final version if approved. No compute is billed while
suspended, and the completed analyze step is served from its checkpoint on
resume rather than re-invoking the model.

Two services: Lambda and AgentCore. Workflow state - step results, the pending
callback and the handler's return value - is checkpointed by the durable
execution service and read back with get-durable-execution and
get-durable-execution-history, so there is no table to provision. Submission and
approval are both driven from the AWS CLI.

The agent ships as an ARM64 container image because AgentCore hosts source code
directly only for Python and Node runtimes; scripts/build-agent-image.sh builds
and pushes it. The spring-ai-agentcore-runtime-starter auto-configures the
POST /invocations and GET /ping endpoints AgentCore requires, so the agent is a
single method annotated with @AgentCoreInvocation.

Includes unit tests using the durable execution SDK's in-memory runner covering
the approve, reject and timeout paths, and asserting that replay skips completed
steps instead of calling the agent again.

Verified end to end on AWS: the AgentCore runtime reaches READY, both agent calls
succeed against Bedrock, and analyze-document records exactly one StepStarted
across two InvocationCompleted events.
@parasjain01

Copy link
Copy Markdown
Contributor Author

Submission issue: #3265

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants