At a glance
| Layer | Current | Target |
|---|---|---|
| Public URL | chat.think2earn.com |
Same domain; static UI + API split |
| Edge | Cloudflare Tunnel → always-on EC2 :8080 | Cloudflare DNS + email; API via Lambda URL or ALB; UI on S3 + CloudFront (or Pages) |
| Control plane | Single EC2 host (Node/Express + SPA) | Serverless API (Lambda); no always-on app server |
| Default chat | Bedrock ConverseStream tool loop on EC2 | Same pattern; runs in Lambda |
| Long / agent work | AgentCore Runtime for jobs; chat stays on EC2 Bedrock | AgentCore Runtime + Claude Agent SDK (Bedrock IAM) for agent + plan micro-VM lanes |
| Turn journal | In-memory on EC2 (~30 min TTL; lost on restart) | DynamoDB (durable; survives deploy and scale-out) |
| Thread session | Per-user Runtime session for agent chat; requestId for cancel/resume |
Per-thread agentSessionId + S3 SessionStore for agent transcripts |
| Artifacts | S3 + DynamoDB library assets; dock via GET /artifacts | Same store + inline placeholders, publish host pub.think2earn.com, global artifact events |
| Auth / billing | Cognito + app JWT; Stripe credits | Unchanged |
| Deploy | Manual SSM tarball → EC2 build + restart | CI → Lambda + static asset pipeline; EC2 decommissioned for API |
Current Production architecture
Verified against live prod (chat.think2earn.com, EC2 i-076d244b62ec4d8e8, account 995772916887, us-east-1).
One long-lived control-plane host fronts the entire web product.
flowchart TB
subgraph users [Users]
Browser[Browser]
end
subgraph edge [Cloudflare]
CF_DNS[DNS]
CF_Tunnel[Tunnel to origin]
end
subgraph ec2 [Control plane EC2]
Cloudflared[cloudflared daemon]
NodeApp[Node Express API plus Vite SPA]
TurnMem[In-memory turn journal]
LocalTerm[local_terminal shell on host]
IAMHost[Think2earnHostRole]
end
subgraph aws_data [AWS data]
DDB[(DynamoDB 16 tables)]
S3[(S3 artifact bucket)]
SSM[SSM secrets]
end
subgraph bedrock [Bedrock and AgentCore]
Converse[Bedrock ConverseStream]
CI[Code Interpreter]
BrowserAC[Browser CDP]
Memory[AgentCore Memory]
Gateway[Gateway Exa MCP]
Runtime[AgentCore Runtime microVM jobs only]
end
subgraph external [External]
Cognito[Cognito]
Stripe[Stripe]
end
Browser --> CF_DNS --> CF_Tunnel --> Cloudflared --> NodeApp
NodeApp --> TurnMem
NodeApp --> DDB
NodeApp --> S3
NodeApp --> SSM
NodeApp --> IAMHost
IAMHost --> Converse
IAMHost --> CI
IAMHost --> BrowserAC
IAMHost --> Memory
IAMHost --> Gateway
IAMHost --> Runtime
NodeApp --> LocalTerm
NodeApp --> Cognito
NodeApp --> Stripe
Request paths (today)
Default chat (simple mode)
- Browser POST → SSE on EC2
- Bedrock ConverseStream + native tool loop
- Tools:
run_code,browse_web,web_search,update_plan - Tool services called from host via AgentCore SDK
- Artifacts persisted to S3 on tool completion
Long jobs (Path B)
- Composer → Agent task (hours)
POST /workspaces/:id/task- InvokeAgentRuntime →
hermes_chatRuntime - Think2earn Agent binary in microVM
- Results + artifacts back to DynamoDB / S3
Characteristics
- Single point of compute — API, SSE, billing, and tool orchestration share one EC2 process.
- Ephemeral turn state — reconnect mid-turn uses in-memory journal; server restart drops in-flight UI state.
- Shared IAM — all tenants use
Think2earnHostRole; isolation is app-layer (org / user / conversation ids). - AgentCore Runtime underused for chat — live for dispatched jobs, not the default chat SSE path.
- Workspace —
local_terminalruns shell on the control-plane host (not an isolated sandbox per user). - UI — production redesign shell (DevLabChatTab); artifacts-only right pane.
Target North-star architecture
AWS-first: burn credits on Bedrock and AgentCore, keep Cloudflare for DNS and transactional email, eliminate the always-on EC2 API host, and externalize every piece of session state the UI depends on.
flowchart TB
subgraph users [Users]
Browser[Browser]
end
subgraph edge [Cloudflare]
CF_DNS[DNS]
CF_Email[Transactional email]
end
subgraph static [Static delivery]
CF_CDN[CloudFront or Pages]
SPA[Vite SPA bundle]
end
subgraph api [Serverless API]
Lambda[Lambda API]
DDB_Journal[(DynamoDB turn journal)]
DDB_Core[(DynamoDB core tables)]
SSE_Turn[POST chats messages SSE]
SSE_Global[GET events stream or poll]
end
subgraph storage [Object storage]
S3_Art[S3 artifacts and workspaces]
S3_Sess[S3 SessionStore transcripts]
PubCDN[pub.think2earn.com published HTML]
end
subgraph agent_compute [Isolated agent compute]
Runtime[AgentCore Runtime microVM]
AgentSDK[Claude Agent SDK Bedrock IAM]
Sweep[Post-turn workspace sweep to S3]
end
subgraph bedrock [Bedrock and AgentCore services]
Converse[Bedrock ConverseStream simple chat]
CI[Code Interpreter]
BrowserAC[Browser]
Memory[Memory]
Gateway[Gateway Exa]
end
subgraph external [External unchanged]
Cognito[Cognito]
Stripe[Stripe]
end
Browser --> CF_DNS
Browser --> CF_CDN --> SPA
Browser --> SSE_Turn
Browser --> SSE_Global
CF_DNS --> Lambda
SSE_Turn --> Lambda
SSE_Global --> Lambda
Lambda --> DDB_Journal
Lambda --> DDB_Core
Lambda --> S3_Art
Lambda --> Converse
Lambda --> CI
Lambda --> BrowserAC
Lambda --> Memory
Lambda --> Gateway
Lambda --> Runtime
Runtime --> AgentSDK
AgentSDK --> Converse
AgentSDK --> Sweep --> S3_Art
AgentSDK --> S3_Sess
S3_Art --> PubCDN
Lambda --> Cognito
Lambda --> Stripe
CF_Email -.-> Lambda
Request paths (target)
Default chat (simple mode)
- Static SPA → Lambda SSE
- Same Bedrock ConverseStream tool loop
- Events journaled to DynamoDB per turn
- Reload / reattach reads journal + active-turn
- No change to default model or tool gating
Agent / plan / long work
- InvokeAgentRuntime with
agentSessionIdper thread - Claude Agent SDK in microVM (
CLAUDE_CODE_USE_BEDROCK=1) - NDJSON stream → same SSE event vocabulary
- SessionStore on S3; resume across Runtime recycling
- HTML and files swept to S3 → artifact dock + publish
Product surfaces (target UI)
- Thread session continuity —
agentSessionIdon conversation; durable turn journal. - Right pane — Context doc tab + Artifacts (single / grid / filmstrip); HTML iframe + publish.
- Plan mode — Plan / Execute pill, Context checklist, Approve gate, sidebar waiting states.
- Inline artifacts — placeholder chips in messages + fallback map on conversation.
- Global awareness — artifact-published and cost-updated on a shared event channel.
Characteristics
- No always-on API EC2 — control plane scales with request volume; long compute stays on AgentCore Runtime.
- Durable streaming state — turn journal and context doc survive deploys and Lambda cold starts.
- Agent isolation — Bash / Write / Read run inside Runtime microVM, not on the API host.
- Bedrock billing throughout — simple chat and Agent SDK both use IAM to Bedrock (no third-party API keys in sandboxes).
- Publish tier — static HTML artifacts served from
pub.think2earn.comvia CloudFront.
What changes (current → target)
Control plane
Today: One EC2 runs API + SPA + in-memory journal + optional host subprocess agent.
Target: Lambda (or equivalent) for API/SSE only; SPA on CDN; EC2 retired for app traffic.
Session & reconnect
Today: requestId + in-memory journal; per-user Runtime session for agent mode.
Target: Per-thread agentSessionId; DynamoDB journal; S3 SessionStore for agent transcripts.
Agent runtime
Today: Think2earn Agent binary in Runtime for jobs; chat default stays on EC2 Bedrock loop.
Target: Claude Agent SDK container in same Runtime ARN for agent/plan lanes; JSONL contract unchanged for the UI.
Artifacts & HTML
Today: S3 + signed URLs; dock preview; no publish host or inline placeholders.
Target: Placeholder chips, version badges, publish pipeline, global artifact index.
Edge & ops
Today: Cloudflare Tunnel to EC2; manual SSM deploy.
Target: Cloudflare DNS + email; automated Lambda + static deploy; tunnel removed when API migrates.
What stays the same
- Cognito auth and app JWT session model
- Stripe subscriptions and credit ledger
- DynamoDB entity model (conversations, messages, jobs, library)
- S3 artifact bucket and AgentCore resource IDs (Browser, CI, Memory, Gateway, Runtime)
- Default
chatMode: simple+ Bedrock ConverseStream as the fast path - Shared
Think2earnHostRolecalling AgentCore (per-user IAM deferred)
Explicitly out of scope (for now)
- Per-user dedicated EC2 + DCV desktop (premium tier later)
- Standalone CLI binary
- Full integrations OAuth marketplace
- Replacing Exa Gateway with a native search API
Compute paths compared
| Workload | Current | Target |
|---|---|---|
| Quick chat + tools | EC2 → Bedrock ConverseStream; AgentCore CI/Browser/Gateway from host | Lambda → same Bedrock loop; same AgentCore services from Lambda role |
| Plan clarify (light) | Code Interpreter sandbox on host-driven loop | Same; optional promotion rules unchanged |
| Plan execute (heavy) | Checkpoint S3 → Runtime microVM → Think2earn Agent | Checkpoint S3 → Runtime → Claude Agent SDK |
| Multi-hour agent task | Runtime hermes_chat via job dispatch |
Runtime with SDK; same invoke contract |
| User shell / terminal | local_terminal on EC2 host |
Dropped for v1 migration; agent work in Runtime only |
| SSE relay | EC2 holds connection until turn completes (E8: bills after disconnect) | Lambda with same detached-turn semantics; journal in DynamoDB |
Data & state
| State | Current store | Target store |
|---|---|---|
| Conversations, messages, users, billing | DynamoDB | DynamoDB (unchanged) |
| Turn journal (SSE replay) | EC2 memory, 30 min TTL | DynamoDB per requestId |
| Thread context doc (goal, plan, checklist) | Not persisted | DynamoDB CONTEXTDOC + version snapshots |
agentSessionId |
Not on conversation | DynamoDB conversation field |
| Agent transcript files | Inside warm microVM only | S3 SessionStore mirror |
| Artifacts (images, HTML, files, plans) | S3 + library_assets; GET /artifacts | Same + artifactPlaceholderFallback + published prefix |
| Secrets | SSM + env files on EC2 | SSM / Lambda env (same params) |
Edge & clients
flowchart LR
subgraph today [Current edge]
U1[User] --> CF1[Cloudflare Tunnel]
CF1 --> EC2[EC2 serves API and SPA]
end
subgraph future [Target edge]
U2[User] --> CF2[Cloudflare DNS]
U2 --> CDN[CloudFront or Pages SPA]
U2 --> API2[Lambda API URL]
CF2 --> API2
end
- Browser client — single-page app; SSE for turns; optional global event stream for sidebar and dock.
- Auth — Cognito hosted + native email/password + Google/GitHub; httpOnly app JWT.
- Email — moving transactional sends to Cloudflare (
welcome@think2earn.com). - CLI — not in either architecture yet; same API surface reserved for a future client.