Production AI systems—like automated email support pipelines, financial dispute resolvers, and technical triage agents—require far more than basic model invocation. Here is the end-to-end AWS architecture combining event-driven serverless orchestration, Hybrid RRF + cross-encoder RAG, strict inference latency budgeting, tool-loop guardrails, and scoped KMS encryption.
Celoris AI Architecture & Cloud Lab
AWS Serverless AI, Hybrid RAG & Zero-Trust Security • Nov 2026

Achieving a contextually accurate response rate exceeding 90% while holding end-to-end processing latency strictly under 20 seconds demands an integrated systems approach spanning asynchronous event-driven serverless orchestration, multi-stage hybrid retrieval with mathematically robust rank fusion, granular inference latency budgeting, defense-in-depth safety guardrails across unseen execution vectors, and cryptographic isolation via customer-managed encryption policies.
Binding deep MIME payload decoding, malware scanning, semantic RAG, multi-agent evaluation, and safety verification to a synchronous API gateway introduces tail-latency amplification and cascading timeouts. Production architectures decouple transport, state tracking, intent classification, and domain execution into modular serverless boundaries.
The Agent Broker Lambda queries AWS AppConfig for registered tool definitions and invokes Amazon Bedrock Converse (Amazon Nova Micro / Claude 3 Haiku) to resolve user intent dynamically. Execution then transitions to a Supervisor Agent Lambda, which tracks correlation state in DynamoDB, retrieves missing context via an Answers Agent, invokes specialized action-group Lambdas, and coordinates safety validation before SES dispatch.
| Pipeline Stage | AWS Service | Primary Function | P95 SLA |
|---|---|---|---|
| Inbound Perimeter | SES Mail Manager | IP reputation, allowlisting, malware bounce | < 200 ms |
| Payload Extraction | Lambda & S3 | MIME parsing, attachment isolation | < 500 ms |
| State & Bus | DynamoDB & EventBridge | Transaction tracking & async routing | < 100 ms |
| Intent Routing | AppConfig & Bedrock Converse | Dynamic tool schema intent resolution | < 800 ms |
| Agent Supervision | Lambda (Broker/Supervisor) | Multi-agent orchestration & APIs | < 1,200 ms |
| Hybrid RAG | OpenSearch Serverless | Concurrent BM25 + Titan V2 search | < 400 ms |
| Response Generation | Bedrock (Nova / Claude) | Context-grounded draft generation | < 14,000 ms |
| Safety Verification | Bedrock Guardrails | Grounding check, PII masking, injection defense | < 800 ms |
| Outbound Dispatch | SES Outbound | Authenticated SMTP reply dispatch | < 200 ms |
Single-mode search fails at scale: dense vectors smooth over exact error strings and SKUs, while sparse BM25 lexical search misses synonyms. Merging their raw scores via min-max normalization also fails because BM25 is unbounded ([0, ∞)) while cosine similarity is bounded ([-1, 1]).
RRF discards incompatible raw score magnitudes and scores documents purely by ordinal rank across retrievers:
GET enterprise-knowledge-base/_search
{
"retriever": {
"rrf": {
"retrievers": [
{ "standard": { "query": { "match": { "body": "error code ERR-8492 connection timeout" } } } },
{ "knn": { "field": "embedding", "query_vector": [0.012, -0.045, 0.089, 0.124], "k": 50, "num_candidates": 100 } }
],
"rank_window_size": 50,
"rank_constant": 60
}
},
"size": 10
}WITH bm25_hits AS (
SELECT id, ROW_NUMBER() OVER (ORDER BY score DESC) AS bm25_rank
FROM (
SELECT id, score() AS score FROM enterprise_docs
WHERE body MATCH_ANY 'ERR-8492 connection timeout'
ORDER BY score DESC LIMIT 50
)
),
vector_hits AS (
SELECT id, ROW_NUMBER() OVER (ORDER BY dist ASC) AS vec_rank
FROM (
SELECT id, l2_distance_approximate(embedding, [0.012, -0.045, 0.089, 0.124]) AS dist
FROM enterprise_docs ORDER BY dist ASC LIMIT 50
)
)
SELECT
COALESCE(b.id, v.id) AS document_id,
COALESCE(1.0 / (60 + b.bm25_rank), 0.0) + COALESCE(1.0 / (60 + v.vec_rank), 0.0) AS rrf_score
FROM bm25_hits b
FULL OUTER JOIN vector_hits v ON b.id = v.id
ORDER BY rrf_score DESC LIMIT 10;| Retrieval Methodology | Recall@10 | Precision@5 | Latency Overhead |
|---|---|---|---|
| Sparse BM25 Alone | 64.2% | 58.1% | ~40 ms |
| Dense Vector Alone | 78.5% | 71.3% | ~120 ms |
| Hybrid RRF (k=60) | 91.4% | 84.6% | ~180 ms |
| Hybrid RRF + Cross-Encoder Rerank | 96.8% | 92.1% | ~380 ms |
LLM latency splits into compute-bound parallel Prefill (T_TTFT) and memory-bandwidth-bound auto-regressive Decode (N_out × T_ITL), where generating a single output token can take up to 300× longer than reading an input token.
T_TTFT from >2,000ms to <400ms.| Step | Component | P95 Allocation | Cumulative |
|---|---|---|---|
| 1–3 | SES Ingress + Lambda MIME + EventBridge Broker | 1,250 ms | 1,250 ms |
| 4–5 | OpenSearch Hybrid RRF + Cross-Encoder Rerank | 550 ms | 1,800 ms |
| 6–8 | Input Guardrail + LLM Prefill + Decode (≤500 tok) | 12,300 ms | 14,100 ms |
| 9–10 | Output Guardrail + PII Redaction + SES Outbound | 600 ms | 14,700 ms (5.3s buffer) |
An attached agent guardrail only screens the initial user prompt and final synthesized reply—leaving intermediate Tool Inputs and Tool Outputs dangerously exposed to indirect prompt injection. Production Lambda action groups must call the standalone ApplyGuardrail API explicitly around tool boundaries and wrap untrusted text with cryptographic UUID nonces.
import boto3, json, uuid
bedrock_runtime = boto3.client("bedrock-runtime", region_name="us-east-1")
def wrap_untrusted_input(user_payload: str) -> tuple[str, str]:
nonce = uuid.uuid4().hex[:12]
tag_name = f"amazon-bedrock-guardrails-guardContent_{nonce}"
return f"<{tag_name}>\n{user_payload}\n</{tag_name}>", tag_name
def lambda_handler(event, context):
tool_input_args = event.get("parameters", {})
# 1. Screen Tool Inputs before DB / API execution
in_guard = bedrock_runtime.apply_guardrail(
guardrailIdentifier="support-core-guardrail",
guardrailVersion="3",
source="INPUT",
content=[{"text": {"text": json.dumps(tool_input_args), "qualifiers": ["guard_content"]}}]
)
if in_guard.get("action") == "GUARDRAIL_INTERVENED":
return {"statusCode": 403, "action": "BLOCKED"}
raw_result = execute_database_query(tool_input_args)
# 2. Screen Tool Outputs before re-entering the Agent reasoning loop
out_guard = bedrock_runtime.apply_guardrail(
guardrailIdentifier="support-core-guardrail",
guardrailVersion="3",
source="OUTPUT",
content=[{"text": {"text": raw_result, "qualifiers": ["guard_content"]}}]
)
if out_guard.get("action") == "GUARDRAIL_INTERVENED":
return {"statusCode": 403, "action": "BLOCKED"}
return {"statusCode": 200, "result": raw_result}For persistent memory poisoning threats (such as Unit 42 indirect memory injections), pair Bedrock Guardrails (0.7 Grounding threshold + ANONYMIZE PII redaction + Standard cross-region profiles) with kernel-level eBPF telemetry and IRSA identity auditing feeding AWS Security Hub.
Every S3 bucket, DynamoDB table, and OpenSearch Serverless collection is encrypted with Customer Managed Keys (CMKs) using kms:ViaService and kms:EncryptionContext:ServiceDomain conditions, paired with mandatory tenant filter predicates (tenant_id.keyword) on every vector query and AWS Organizations SCPs.
{
"Sid": "AllowRestrictedServiceDecryptionViaAuthorizedServices",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:role/EmailSupportExecutionRole" },
"Action": ["kms:Decrypt", "kms:GenerateDataKey*", "kms:DescribeKey"],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": [
"bedrock.us-east-1.amazonaws.com",
"s3.us-east-1.amazonaws.com",
"dynamodb.us-east-1.amazonaws.com"
],
"kms:EncryptionContext:ServiceDomain": "CustomerSupportAI",
"kms:CallerAccount": "123456789012"
}
}
}SES Mail Manager IP/malware filtering → S3 MIME parser → OpenSearch BM25 + Titan V2 (N=50) → RRF (k=60) → Cross-Encoder (K=5, >95% recall).
max_tokens 500 + 80/20 routing + prefix caching (<15s P95) → tool-loop ApplyGuardrail + UUID nonces → scoped KMS CMKs + X-Ray & SCP governance.
Pass our 10-minute AI & NLP Engineer (Email Support Automation) certification exam in the Celoris Job Center and apply directly for verified client projects (`₹21,250 – ₹63,750`).
Loading comments...