Infrastructure layer
CDK / CloudFormation: VPC, EKS, S3, ECR, Cognito, ACM, Bedrock budget ($50/mo), model-scoped IRSA.
These are working demonstrations and design studies—not invented client case studies. They show how we structure real deployments: a cloud research & document processing pipeline, voice intake, and web lead capture. Each maps data flow clearly and can be customized for a client’s business. Where models help—summaries, qualification, retrieval—they are optional layers on top of reliable intake, storage, and handoffs—not autonomous “agents” running your business. We are cloud fluent; we also work on-prem and hybrid, and build net-new infrastructure when your operation needs a cleaner foundation.
A security-conscious, cloud-native pipeline for uploading documents, embedding and indexing content with SWAG semantic profiles, and running structured research workflows with SWAG+CRAG retrieval-augmented generation. Orchestration runs on managed Kubernetes with Qdrant vector search, object storage, network policies, and model inference on Amazon Bedrock. SWAG reranks and filters candidates before CRAG grading (fewer Haiku tokens). Edge: HTTPS at langrag.automatico.llc with Cognito. Portable SWAG core is also available separately — see SWAG.
CDK / CloudFormation: VPC, EKS, S3, ECR, Cognito, ACM, Bedrock budget ($50/mo), model-scoped IRSA.
Showcase UI (SSE gateway), LangGraph agents, Ingestion, Qdrant, Redis.
ALB HTTPS + Cognito at langrag.automatico.llc. Network policies restrict internal traffic.
Bedrock (Claude Sonnet 4.6 + Haiku CRAG grader + Titan v2 embed), LangSmith Cloud, Tavily (optional).
Public HTTPS via ALB + Cognito at langrag.automatico.llc. Internal traffic restricted by NetworkPolicies.
flowchart TB
subgraph external["Outside AWS"]
User["Demo user"]
LangSmith["LangSmith Cloud"]
Tavily["Tavily API optional"]
end
subgraph aws["AWS us-east-1"]
CDK["CDK KubeRagLanggDemo"]
subgraph vpc["VPC"]
NAT["NAT Gateway"]
ALB["ALB HTTPS Cognito edge"]
subgraph eks["EKS kube-rag-langg"]
subgraph showcase["namespace showcase"]
UI["Showcase UI React FastAPI"]
end
subgraph agents_ns["namespace agents"]
Agents["LangGraph research-agents"]
end
subgraph rag_ns["namespace rag"]
Ingest["Ingestion API SWAG CRAG expansion"]
Qdrant["Qdrant EBS 20Gi"]
Redis["Redis in-cluster"]
end
Node["t3.large node group"]
end
S3["S3 documents"]
ECR["ECR images"]
Cognito["Cognito"]
Bedrock["Bedrock Sonnet Haiku Titan"]
end
end
User -->|HTTPS| ALB
ALB --> Cognito
ALB --> UI
UI --> Agents
UI --> Ingest
Agents --> Ingest
Ingest --> Qdrant
Ingest --> S3
Ingest --> Bedrock
Agents --> Bedrock
Agents -.-> LangSmith
Agents -.-> Tavily
CDK --> vpc
CDK --> S3
CDK --> ECR
CDK --> Cognito
POST /rag/search)Single Qdrant collection (research_docs) — vectors and swag_profile metadata in the same payload. Baseline retrieve, optional vector confidence floor, then mode branch: baseline · swag · crag · swag_crag. Same-document sibling expansion and body-only prune run before response. Shared by ingestion API, UI Search, and agent rag_search. Showcase uses strict SWAG filter defaults (one chunk per doc, noise ratio 0.62, sibling expansion off); see SWAG article.
flowchart TB
Q[User query] --> B[Baseline retrieve top_k]
B --> CF{Vector confidence floor RAG_MIN_VECTOR_SCORE 0.12}
CF -->|blocked non-CRAG modes| Z[0 hits confidence message]
CF -->|pass or CRAG mode| M{mode}
M -->|baseline| BL[Return baseline hits]
M -->|swag| SW[Candidate pool rerank]
M -->|crag| CR[Retrieve Haiku grade]
M -->|swag_crag| SC[SWAG pool then CRAG grade]
SW --> SE[Same-document sibling expansion]
CR --> SE
SC --> SE
BL --> SE
SE --> OUT[Response hits plus swag crag expansion meta]
swag / before CRAG in swag_crag)Widen the candidate pool (~20), ensure profiles, dedupe with chunk-kind weights, blend vector + SWAG + metadata, then noise gate and diversity cap. Showcase strict filter: one chunk per document, no backfill padding, nav/title hard gate.
flowchart LR C[Vector candidates about 20] --> P[Ensure SWAG profiles heuristic or cached] P --> D[Dedupe chunk-kind weights] D --> R[Blend vector SWAG metadata] R --> N[Noise gate diversity cap] N --> K[top_k hits]
The Search tab at langrag.automatico.llc defaults to Vector → SWAG with baseline compare. Click a scripted demo path to run validation-suite queries with the right topic filter — chrome trap, AP lane, cafeteria lane. CRAG modes are labeled optional; agents still use swag_crag for safety.
| Scripted path | Topic | What it proves |
|---|---|---|
| Chrome trap (RAG body) | validation-chrome | SWAG promotes body over README chrome |
| Chunking quality | validation-chrome | Same trap — substantive chunk at top-1 |
| AP · three-way match | ap-procurement | Domain lane + rerank on PO content |
| Cafeteria · food safety | cafeteria-ops | Isolated ops corpus, not mixed noise |
| CRAG · cross-domain bait (optional) | All topics | Full stack may return empty on invoice+cafeteria bait |
Same query through each pipeline with optional baseline compare. Lead demos with swag; switch to swag_crag only when discussing agent safety.
| Mode | What it shows | Typical outcome on messy HTML |
|---|---|---|
swag | Default demo. Rerank + noise filter | Body promoted; duplicates dropped — use lift cards |
baseline | Vector similarity only (naive RAG) | Chrome and nav chunks often at #1 |
crag | Haiku grades vector top-K (optional) | Some mis-ranked chunks still pass |
swag_crag | SWAG clean → CRAG grade (agents; optional demo) | Fewer hits; empty when grader rejects |
Enable Compare against baseline to see purged vs kept chunks side by side. Showcase regression: tuning 10/10, holdout 6/6. Product eval harness: five ugly corpora, strong baselines, four-pillar qrels — run-eval-harness.sh (+ --generate for answer spec). Retrieval policy knobs are env/config on the ingestion service.
Each qrel defines corpus, question, expected retrieval (gold doc + traps), and expected answer. One command scores retrieval metrics and, with --generate, answer correctness + citation + hallucination rate against brutal thresholds. Honest fail is a feature — it separates demo regression from product proof.
| Corpus | Messiness | Example trap |
|---|---|---|
| retail-furniture | Deprecated sizing, duplicate policies | v1 sizing guide vs v2 |
| terraform-cloud | Version docs, acronyms | Terraform 1.2 legacy vs 1.5 |
| legal-contracts | Archived MSAs, cross-refs | MSA v1 $10k cap vs v3 |
| medical-admin | HIPAA/PHI/BAA | 2019 infection policy outdated |
| mixed-garbage | Contradictions, partial PDFs | Conflicting refund policies |
UI gateway parses LangGraph SSE and streams node progress. Researchers call ingestion SWAG+CRAG (not raw Qdrant); traces go to LangSmith.
sequenceDiagram
actor User
participant UI as Showcase UI
participant LG as LangGraph agents
participant Ing as Ingestion
participant Q as Qdrant
participant BR as Bedrock
User->>UI: Research topic
UI->>LG: SSE stream
loop Researchers
LG->>Ing: POST rag search swag_crag
Ing->>Q: Vector candidates
Ing->>Ing: SWAG rerank sibling expansion
Ing->>BR: Haiku CRAG grade
BR-->>Ing: Graded chunks
Ing-->>LG: Hits or web_fallback
end
LG->>BR: Sonnet synthesis
BR-->>LG: Report draft
LG-->>UI: HITL checkpoints plan critique report
UI-->>User: Live progress editable report
Upload capped at 100 MB; rate limited at the API gateway. Chunking uses structural markdown split (nav vs body). Indexing stores Titan vectors and heuristic SWAG profiles on each chunk in one pass.
sequenceDiagram participant UI as Showcase UI participant Ing as Ingestion participant S3 as S3 participant BR as Bedrock Titan participant Q as Qdrant UI->>Ing: Upload or URL ingest Ing->>S3: Raw object Ing->>Ing: Chunk classify kind document_id Ing->>BR: Embed batch Ing->>Ing: SWAG profile heuristic default Ing->>Q: Upsert vector plus payload
| Control | Implementation |
|---|---|
| Edge auth | Cognito @ ALB on langrag.automatico.llc |
| TLS | ACM cert for langrag.automatico.llc |
| IAM | IRSA: agents → Sonnet 4.6 + Titan embed; ingestion → Titan embed + Haiku CRAG grader (SWAG profiles heuristic by default) |
| Secrets | AWS Secrets Manager + K8s app-secrets (LangSmith, S3 bucket) |
| Upload cap | 100 MB on UI gateway + ingestion |
| Rate limits | 10 ingest / 5 research per min per client IP |
| SSRF | URL ingest blocks private IPs, metadata, bad redirects |
| Network | NetworkPolicies: UI → agents/ingestion only |
| Spend | AWS Budget email alerts on Bedrock (80% / 100%) |
| Script | Creates |
|---|---|
infra-deploy.sh | VPC, EKS, S3, ECR, Cognito, ACM cert, Bedrock budget, model-scoped IRSA |
bootstrap.sh | EBS CSI + IRSA, ALB controller, External Secrets, Cluster Autoscaler, gp3 StorageClass |
deploy.sh | Qdrant, Redis, Ingestion, research-agents, Showcase UI, NetworkPolicies |
apply-showcase-access.sh | NLB (HTTP) or ALB ingress (HTTPS + Cognito) based on ACM status |
print-acm-validation.sh | Print DNS CNAME for ACM validation |
Reference lifecycle for demo and non-production environments—park when idle to control spend.
stateDiagram-v2 [*] --> Parked: demo-park.sh Parked --> Running: infra bootstrap deploy Running --> Stopped: demo-stop.sh Stopped --> Running: demo-start.sh Running --> Parked: demo-park.sh
| Mode | Command | Approx. monthly cost |
|---|---|---|
| Parked | demo-park.sh | $0–1 (S3 + ECR) |
| Stopped | demo-stop.sh | ~$105 (EKS + NAT, no ALB/nodes) |
| Running | deploy.sh | ~$185–205 if 24/7 + Bedrock usage |
Challenge: After-hours and overflow calls go to voicemail. Owners find out too late—or not at all—and a competitor may win the customer.
Proposed solution: An automated intake system that answers calls, gathers customer details, stores a structured record, and notifies staff immediately.
What this demonstration shows: Inbound calls via Amazon Connect, capture by a Node.js Lambda, storage in DynamoDB, and SNS email alerts to the team. Optional model-assisted summaries where they help staff respond faster. Provisioned with AWS CDK. This is a working proof of concept you can customize—not a published client case study.
CDK stack: Connect instance, inbound contact flow, Lambda, DynamoDB table, SNS topic, IAM roles.
PSTN caller → claimed DID in Connect → contact flow invokes Lambda on each captured lead.
DynamoDB voice-leads (PK leadId, GSI contactId-index) + SNS email to staff.
Bedrock InvokeModel for call summarization when enabled; alerts and records always in place.
Serverless voice intake — no EC2, no NAT. Connect contact flow is the orchestrator; Lambda is the only custom compute.
flowchart TB
subgraph external["Outside AWS"]
Caller["PSTN caller"]
Staff["Staff inbox"]
end
subgraph aws["AWS us-east-1"]
CDK["CDK voice intake stack"]
subgraph region["Managed voice + serverless"]
Connect["Amazon Connect instance"]
Flow["Inbound contact flow"]
Lambda["Lambda connect-lead-handler Node 20"]
DDB["DynamoDB voice-leads"]
SNS["SNS lead-notifications"]
Bedrock["Bedrock optional summary"]
end
end
Caller --> Connect
Connect --> Flow
Flow --> Lambda
Lambda --> DDB
Lambda --> SNS
Lambda -.-> Bedrock
SNS --> Staff
CDK --> region
Contact flow prompts the caller, invokes Lambda with contact attributes, persists a structured lead, and notifies staff before disconnect.
flowchart LR C[Inbound call PSTN] --> F[Connect contact flow] F --> P[MessageParticipant prompts] P --> L[InvokeLambdaFunction] L --> N[Normalize lead fields] N --> D[PutItem DynamoDB] D --> E[SNS email alert] L -.->|optional| B[Bedrock summarize] B --> D E --> X[Disconnect call]
Each call produces a durable lead record plus an immediate email alert. Raw Connect event payload is stored for audit and CRM export.
sequenceDiagram
actor Caller
participant Connect as Amazon Connect
participant Flow as Contact flow
participant Lambda as connect-lead-handler
participant DDB as DynamoDB
participant SNS as SNS
participant Staff as Staff email
participant BR as Bedrock optional
Caller->>Connect: Inbound PSTN
Connect->>Flow: Route to inbound-lead-flow
Flow->>Caller: Prompt capture name intent
Flow->>Lambda: InvokeLambdaFunction contact attrs
Lambda->>DDB: PutItem lead plus raw event
opt model assist enabled
Lambda->>BR: Summarize transcript
BR-->>Lambda: Summary text
Lambda->>DDB: Update lead summary
end
Lambda->>SNS: Publish new lead alert
SNS->>Staff: Email notification
Flow->>Caller: Disconnect
| Control | Implementation |
|---|---|
| IAM | Lambda: DynamoDB RW, SNS publish, Connect invoke, optional Bedrock InvokeModel |
| Data retention | DynamoDB RETAIN removal policy; on-demand billing |
| Connect integration | CfnIntegrationAssociation binds flow to Lambda |
| Observability | CloudWatch logs and metrics for Lambda and Connect |
| IaC lifecycle | CloudFormation stack from CDK — drift detection, change sets |
| Layer | Delivers |
|---|---|
| CDK deploy | Connect instance, inbound flow, Lambda, DynamoDB, SNS, IAM, integration association |
| Connect console | Claim phone number, attach flow, enable Contact Lens optional |
| Operator outcome | Structured leads queryable in DynamoDB; instant SNS email to staff |
Challenge: Website leads land in a shared inbox or spreadsheet. Qualification is inconsistent, follow-up depends on memory, and hot prospects cool off.
Proposed solution: A form-to-workflow path that validates submissions, applies clear qualification rules, stores durable records, and emails the right person immediately.
What this demonstration shows: HTTP API intake, Lambda validation and rules-based qualification (optional model scoring), DynamoDB storage, and SES staff notification. Reference architecture you can customize—not a published client case study.
SAM template: HTTP API, Lambda, DynamoDB table, IAM policies, CloudWatch log group.
Static form (frontend/index.html) hosted on Amplify, S3+CloudFront, or CMS embed.
DynamoDB leads (PK lead_id, GSI created_at_index, SSE, PITR) + SES to owner.
Bedrock scoring when enabled; rules-based qualify_lead path when model assist is off.
Serverless lead capture — API Gateway HTTP API fronts a single Lambda processor. Visitor gets JSON confirmation; sales gets an email with grade and summary.
flowchart TB
subgraph external["Outside AWS"]
Visitor["Website visitor"]
Owner["Sales owner inbox"]
end
subgraph aws["AWS us-east-1"]
SAM["SAM template.yaml stack"]
subgraph region["Serverless lead capture"]
Web["Static form frontend"]
API["API Gateway HTTP API"]
Lambda["Lambda lead-processor Python 3.12"]
DDB["DynamoDB leads table"]
SES["Amazon SES"]
Bedrock["Bedrock optional scoring"]
end
end
Visitor --> Web
Web -->|POST /lead| API
API --> Lambda
Lambda --> DDB
Lambda --> SES
Lambda -.-> Bedrock
SES --> Owner
SAM --> region
Validate required fields and CORS, qualify (rules or optional model), persist, notify — then return grade and summary to the visitor.
flowchart TB
POST[POST /lead JSON] --> CORS[CORS preflight OPTIONS]
CORS --> API[API Gateway HTTP API]
API --> V{validate_lead fields}
V -->|invalid| R[400 reject]
V -->|ok| Q{qualify_lead}
Q -->|rules path| S[save_lead DynamoDB]
Q -->|model path| M[Bedrock score grade]
M --> S
S --> N[send_notification SES]
N --> OUT[200 JSON grade summary]
X-Ray tracing active on Lambda. Access logs on the HTTP API stage go to CloudWatch.
sequenceDiagram
actor Visitor
participant Web as Static form
participant API as HTTP API prod
participant Lambda as lead-processor
participant DDB as DynamoDB
participant SES as Amazon SES
participant Owner as Sales email
participant BR as Bedrock optional
Visitor->>Web: Fill form submit
Web->>API: POST /lead JSON
API->>Lambda: Invoke app.lambda_handler
Lambda->>Lambda: validate_lead
alt model assist enabled
Lambda->>BR: Score and grade lead
BR-->>Lambda: Qualification result
else rules only
Lambda->>Lambda: qualify_lead rules
end
Lambda->>DDB: PutItem lead fields
Lambda->>SES: Send notification email
SES->>Owner: Alert with grade summary
Lambda-->>API: 200 response body
API-->>Visitor: Confirmation JSON
| Control | Implementation |
|---|---|
| CORS | HTTP API CORS — tighten AllowOrigins in production |
| Encryption | DynamoDB SSE at rest; PITR enabled |
| IAM | Lambda: DynamoDB RW, SES send, optional Bedrock InvokeModel |
| Tracing | AWS X-Ray active on Lambda |
| Logging | API access logs + Lambda logs → CloudWatch |
| SES | Verified sender identity; notifies NOTIFICATION_EMAIL |
| Layer | Delivers |
|---|---|
sam build + deploy | HttpApi, Lambda, DynamoDB, IAM, log group |
| Frontend host | Amplify / S3+CloudFront / CMS — points form at API URL |
| Operator outcome | Instant owner email; CRM-hook-ready JSON payload in DynamoDB |
Best for teams drowning in PDFs, policies, and research requests: ingest documents, index for retrieval, and run guided research workflows with human-readable output.
Best for businesses that live on the phone: after-hours capture, routing by intent (appointment, sales, support, urgent), and immediate staff alerts with structured summaries.
Best for marketing sites and landing pages: structured lead intake, qualification (rules or optional model assist), durable storage, and email notifications without running servers.
These examples span serverless AWS patterns and Kubernetes-based CRAG/RAG pipelines. We apply the same delivery discipline on-prem, in hybrid setups, and when standing up new infrastructure—and we can walk through which deployment and model layers fit your environment on a call.
We will walk a demonstration on a call, sketch a design study for your industry, or scope a first-workflow pilot with clear success metrics—then grow from there.