WhatsApp Ordering with Amazon Bedrock AgentCore: Persistent Memory, MCP Tools, and Safety

One WhatsApp number, three conversation modes, one persistent customer memory

Same customer: they text “What’s on the menu near 75201?” while commuting, and five minutes later they call to confirm pickup from the same device. The assistant recognizes them, restores the cart state, and the backend owns the totals.

Customer: What’s on the menu near 75201?
Agent: [tools: GeocodeAddress, GetNearestLocations, GetMenu]
Here’s what’s available at Amazing Burgers – Dallas:
– Burger Combo ($8.99)
– Chicken Tenders ($6.49)

Customer: A burger combo and a milkshake, please.
Agent: [tools: AddToCart, GetCart]
Added to your cart:
– 1x Burger Combo – $8.99
– 1x Milkshake – $3.49
Total: $12.48. Want me to place the order?

Customer: Yes.
Agent: [tools: PlaceOrder]
Your order is placed and is being prepared for pickup at Amazing Burgers – Dallas. I’ll let you know when it’s ready.

The blueprint behind that exchange connects Meta’s WhatsApp Cloud API to Amazon Bedrock AgentCore and the Nova models, exposes backend business logic as named tools (MCP), and preserves a single cross-channel memory so the customer is recognized across text, voice notes, and live calls. As the reference implementation notes, Orders are persisted in Amazon DynamoDB with channel = “whatsapp”.

Why this pattern matters for business

  • WhatsApp already reaches over two billion monthly users (per Meta), making it a high-value channel where customers expect conversational interactions.
  • Keeping authoritative business rules and pricing in backend tools reduces refunds and disputes, and prevents the model from inventing totals.
  • Privacy-first identity and fast webhook handling are operationally essential for reliability and compliance.

How the reference solution is built, the high-level pieces

  • Amazon Bedrock AgentCore (runtime, gateway, memory), runs per-conversation microVMs for isolation, exposes backend REST endpoints as discoverable MCP (Model Context Protocol) tools, and provides shared memory keyed by a customer identifier.
  • Amazon Nova models, the sample uses amazon.nova-2-lite-v1:0 for chat via the Bedrock Converse API and amazon.nova-2-sonic-v1:0 for speech-capable flows. Verify model IDs and region availability in Bedrock docs before deploying (model names and availability change over time).
  • Meta WhatsApp Cloud API, a single WhatsApp Business number handles messages, media, and calling. Meta-side setup (Developer App, WABA, phone number) is required outside the AWS deployment.
  • AWS integration layer, public webhook API Gateway + ingest Lambda, SQS (ingest queue with DLQ), an async worker Lambda, MCP-exposed business tools, DynamoDB (Customers, Orders, Menu, Carts, Locations), Amazon Location Service (geocoding/nearest store), Amazon Kinesis Video Streams (KVS) for WebRTC/TURN, a VPC for the voice runtime, ECR/CodeBuild to build container images, CloudWatch, and KMS for encryption.
  • Tooling pattern, GetMenu, AddToCart, PlaceOrder are exposed to agents as named MCP tools. Tools are authoritative: the agent asks, the tool computes and persists.

Side note on the TURN/voice path: in this sample KVS supplies managed TURN and signaling for WebRTC (required for real-time calls here). Alternatives include AWS Chime SDK or third-party TURN providers, so pick the option that matches your latency, compliance, and egress-cost requirements.

Why tools (MCP) matter, and how to avoid model-made money mistakes

Models handle conversation well, but they do not guarantee numbers. The defensive pattern is simple and repeatable:

  • Agent calls a tool (for example, PlaceOrder) and receives a canonical JSON invoice with prices, taxes, and an order ID.
  • Agent echoes that canonical invoice only after the tool confirms persistence. The UI shows the tool-supplied totals and order ID, and the model never invents a final price.

This prevents hallucinated totals and makes reconciliation straightforward if a customer later disputes a charge.

Customer identity without storing raw phone numbers

The sample avoids persisting raw E.164 phone numbers. The reference solution shows this formula verbatim:

“wa-” + sha256(E164 || Pepper)[:16]

That construction creates a pseudonymous customer key used across AgentCore memory and DynamoDB. A couple of important hardening notes you should apply before production:

  • Prefer HMAC over raw concatenation. Use HMAC-SHA256(key=pepper, message=E164) and hex/base64-encode the result. HMAC is resilient to subtle concatenation errors and reduces risks if E.164 normalization ever changes.
  • Avoid or be cautious about truncation. Truncating a SHA256 digest (or an HMAC) reduces entropy and increases collision risk. If you must shorten keys for storage, choose a length with tested uniqueness and implement collision detection on insert.
  • Normalize input first. Ensure E.164 normalization (country code, no formatting chars) before hashing; inconsistent normalization breaks lookups.
  • Pepper rotation options: (a) keep prior peppers for a transition window and re-hash during lookup, (b) encrypt and store raw E.164 under KMS to re-compute derived IDs on rotation, or (c) generate and persist a stable internal UUID the first time a customer is resolved and use that mapping thereafter. For low-latency lookups at scale, a small, access-controlled mapping table (option c) is pragmatic.

Shared memory and concurrency, what “one AgentCore memory” actually means

The shared AgentCore memory is an AgentCore-managed store (persisted, not ephemeral in-process RAM) that the three channel runtimes can read and update keyed by the pseudonymous customer ID. That cross-channel memory enables context continuity, but it also raises practical concerns:

  • Privacy trade-off: a single memory makes it easier to leak context across channels. Consider an explicit consent flag or a sensitive-data gating policy before syncing certain fields across channels.
  • Concurrency hazards: simultaneous messages from chat and a live call can race. Implement optimistic locking or version checks on updates, and surface merge conflicts to a human-in-the-loop escalation workflow when needed.

End-to-end request flow, the practical steps

  1. WhatsApp sends a webhook to API Gateway. The ingest Lambda validates the signature, enqueues the payload to SQS, and returns HTTP 200 quickly so Meta’s webhook timeout isn’t hit, aim for <200 ms ack as an engineering target and verify the current Meta docs for exact timeouts.
  2. The async worker consumes SQS messages, computes the customer identifier, and calls MCP tools or the AgentCore runtime as appropriate.
  3. AgentCore runs the conversation in an isolated microVM. Chat uses the Converse API to amazon.nova-2-lite-v1:0 and voice notes and real-time voice use amazon.nova-2-sonic-v1:0 for speech-to-text, synthesis, or speech-to-speech.
  4. For live voice calls, WebRTC signaling/TURN credentials are handled via KVS, and the voice runtime runs in a VPC with outbound NAT egress (the sample uses a single NAT gateway pattern).
  5. Tools persist orders, carts, and customers into DynamoDB. The sample persists orders with channel = “whatsapp”.

Deploying the sample, checklist and safety warnings

Repository: https://github.com/aws-samples/sample-multimodal-whatsapp-restaurant-agent

Local prerequisites:

  • Node.js 24.x or later, AWS CLI v2 configured with credentials, git.
  • CDK bootstrap (example): npx cdk bootstrap aws://<ACCOUNT_ID>/<REGION>

Typical deploy commands (as provided by the sample):

git clone https://github.com/aws-samples/sample-multimodal-whatsapp-restaurant-agent.git
cd sample-multimodal-whatsapp-restaurant-agent
./scripts/preflight-check.sh
./scripts/deploy-all.sh --deploymentPrefix qsr-wa
./scripts/deploy-all.sh --interactive-web-ui  # guided browser experience

WhatsApp setup helpers:

cd scripts/whatsapp-setup
npm start  # choose "Pre-deploy", then "Post-deploy" after deploy
node whatsapp-setup.mjs --doctor  # read-only end-to-end check

Secrets and parameters: Secrets Manager holds Meta Access Token, App Secret, Verify Token (the repo creates empty secrets to be populated out-of-band). Systems Manager Parameter Store holds the customer-id pepper. Note: the sample mentions the temporary Meta Access Token expires in about 24 hours, so automate or alert around token refresh.

Before you press deploy: inspect all CDK/IAM policies in the repo. Run deployments in a sandbox account or a dedicated test environment. Limit Secrets Manager read access, enable CloudTrail alerts for secret reads, and avoid running these scripts in a production account without an audit.

Operational considerations, observability, and cost drivers

  • Model inference and latency: Bedrock model calls (Nova) are a primary cost and latency driver. Track per-message token usage and model response times, and measure under expected concurrency.
  • Media egress and TURN: KVS TURN bandwidth and NAT gateway egress can dominate voice-call costs. Instrument bytes sent and received per call and set alerts for egress spikes.
  • Webhook timing and queue depth: measure webhook ack latency, SQS queue depth, and worker lag. Configure DLQ redrive counts and visibility timeouts explicitly for your tolerance to retries.
  • Build and container timing: the sample reports each first build of an ARM64 agent container takes roughly 8-12 minutes, plan CI/CD timeouts accordingly and cache where possible.
  • Guardrails and grounding: enable Bedrock Guardrails for content filtering and add domain validation at the tool layer. Guardrails reduce risky outputs but do not replace authoritative backend checks.
  • Privacy and compliance: hashed identifiers reduce exposure, but pseudonymous values may still be personal data under GDPR/CCPA. Limit retention, redact logs (API Gateway/CloudWatch), and document processing activities for legal review.
  • Observability metrics to collect: webhook ack latency, SQS depth, worker processing time, agent microVM cold-start time, model tokens per request, model latency, TURN bytes per call, DynamoDB throttling and errors, DLQ accumulation, and secret-access events.

Where to extend and experiments to run

  • Swap in other domains: retail returns, healthcare intake, and field service workflows, the same tool and memory pattern applies.
  • Add multimodal inputs: Nova models support multimodality, add validated image and document processing tools and escalate to humans for ambiguous cases.
  • Human-in-the-loop: expose an EscalateToAgent tool and define SLAs for handoff and ownership.
  • Performance experiments to run before production:
    • Soak test: run a 1‑hour soak at 10% of projected peak traffic and scale up to peak to measure cold-starts and concurrency limits.
    • Cost simulation: run a 24‑hour synthetic traffic replay matching expected message patterns to estimate Bedrock, KVS, NAT, Lambda, and DynamoDB costs.
    • Fault injection: simulate KVS or SQS backpressure and validate graceful degradation (for example, fallback to asynchronous callbacks or a retry UX).

Limits and open questions you should answer for your deployment

  • What are AgentCore microVM cold-start times at your concurrency? Consider a warm-pool for predictable peaks.
  • What are realistic per-minute costs given your expected model token usage and voice minutes?
  • How will you rotate peppers or transition to a stable mapping without breaking lookups?
  • What data residency or consent requirements apply to cross-channel memory in your regions?

Key takeaways, quick Q&A

  • How does the system recognize a customer without a login?

    The reference solution derives a pseudonymous customer_id using the formula “wa-” + sha256(E164 || Pepper)[:16]. For stronger security in your deployment, use HMAC-SHA256(key=pepper, message=E164), normalize E.164 first, and avoid unsafe truncation; consider a stable mapping table if you need low-latency lookups and smooth pepper rotation.

  • Which models power chat and voice?

    The sample uses amazon.nova-2-lite-v1:0 for chat (Converse API) and amazon.nova-2-sonic-v1:0 for speech flows. Verify current model identifiers, region availability, and pricing in the Bedrock docs before you deploy.

  • How does the solution meet Meta webhook timing?

    A lightweight ingest Lambda validates the signature, enqueues to Amazon SQS, immediately returns HTTP 200 to Meta (aim for <200 ms ack), and an async worker processes the message from the queue. Check Meta docs for exact webhook timeout rules and quotas.

  • Where are orders and business rules enforced?

    Authoritative pricing and order logic live as MCP tools (GetMenu, AddToCart, PlaceOrder) and persist to DynamoDB; the agent calls those tools rather than calculating totals itself, which prevents hallucinated charges.

  • What are the main cost drivers to watch?

    Bedrock model inference, Kinesis Video Streams TURN bandwidth and NAT gateway egress, Lambda and DynamoDB usage, and container build and storage for images are the primary cost drivers, instrument model tokens, call minutes, and egress to get an accurate picture.

Before you flip to live, a five-point checklist for leaders and eng teams

  • Audit CDK and IAM policies in the repo; deploy first into a sandbox AWS account.
  • Run cost and latency simulations (24‑hour replay and 1‑hour soak) to validate economics and model throughput.
  • Harden identity: implement HMAC-based derivation, plan pepper rotation (or stable mapping), and ensure E.164 normalization.
  • Lock down secrets: enable Secrets Manager rotation where possible, restrict read roles, and alert on secret access via CloudTrail.
  • Instrument and guard: implement Bedrock Guardrails, per-tool validation, webhook and queue observability, and a human escalation path with clear SLAs.

If you want to experiment quickly, clone the sample (https://github.com/aws-samples/sample-multimodal-whatsapp-restaurant-agent), run the preflight checks, and use the repo’s doctor script (node whatsapp-setup.mjs –doctor) to verify end-to-end plumbing. Treat the sample as a launchpad: validate model names and region support, measure cold-starts and costs, and harden identity and secrets before you serve paying customers.