Agent Architecture
Agent Architecture
Overview
The agent layer is the core intelligence of the WhatsApp shopping bot. Each user gets a durable Rivet actor that runs inside an AgentOS V8 isolate, powered by Pi Agent Core as the LLM orchestration runtime.
Design choice: Agents are Rivet actors, not an in-process Python pool. Rivet provides durability, distribution, built-in message queuing, serialized execution, and idle lifecycle management for free. The FastAPI layer is a thin gateway that only extracts messages and routes them to actors.
Agent Stack
graph TB
subgraph "Thin Gateway (FastAPI)"
WA_WEBHOOK[WhatsApp Webhook]
ROUTER[Router / Dispatcher]
end
subgraph "Rivet Actor Cluster"
RIVET[Rivet Runtime]
subgraph "Actor: User A"
AOS_A[AgentOS V8 Isolate]
PI_A[Pi Agent Core]
MCP_A[MCP Client Extension]
FMT_A[WhatsApp Formatter]
STATE_A[State Manager]
ANAL_A[Analytics]
end
subgraph "Actor: User B"
AOS_B[AgentOS V8 Isolate]
PI_B[Pi Agent Core]
MCP_B[MCP Client Extension]
end
subgraph "Actor: User N"
AOS_N[AgentOS V8 Isolate]
PI_N[Pi Agent Core]
MCP_N[MCP Client Extension]
end
end
subgraph "External Services"
MCP_SERVER["@shopify/dev-mcp"]
LLM[LLM Provider]
WA_API[WhatsApp Cloud API]
STATE[(Rivet Durable State)]
end
WA_WEBHOOK --> ROUTER
ROUTER -->|get_actor(user_id)| RIVET
RIVET --> AOS_A
RIVET --> AOS_B
RIVET --> AOS_N
AOS_A --> PI_A
PI_A --> MCP_A
PI_A --> FMT_A
PI_A --> STATE_A
PI_A --> ANAL_A
MCP_A --> MCP_SERVER
PI_A --> LLM
FMT_A --> WA_API
STATE_A --> STATE
style RIVET fill:#f3e5f5,stroke:#7b1fa2,stroke-width:3px
style PI_A fill:#e1f5fe,stroke:#0277bd,stroke-width:2px
style AOS_A fill:#fff9c4,stroke:#f9a825,stroke-width:2px
style MCP_SERVER fill:#c8e6c9,stroke:#388e3c
Layers of Responsibility
| Layer | Responsibility | Technology |
|---|---|---|
| Messaging Layer | Receive/send WhatsApp messages, verify signatures | WhatsApp Cloud API |
| Gateway Layer | Thin webhook handler, route to Rivet, return 200 immediately | FastAPI |
| Orchestration Layer | Durable actor lifecycle, routing, sleep/wake/terminate | Rivet |
| Sandbox Layer | Per-actor isolated OS (filesystem, network, processes) | AgentOS |
| Agent Runtime | LLM calls, tool orchestration, streaming, events | Pi Agent Core |
| Extension Layer | Shopify tools, WhatsApp formatting, state, analytics | Custom extensions |
| E-commerce Layer | Products, cart, checkout, orders, policies | @shopify/dev-mcp |
| State Layer | Durable persistence across sleep/wake/restarts | Rivet Durable State |
Data Flow
sequenceDiagram
actor User
participant WA as WhatsApp Cloud API
participant GW as FastAPI Gateway
participant RV as Rivet Runtime
participant ACTOR as ShoppingAgentActor
participant AOS as AgentOS Isolate
participant PI as Pi Agent
participant LLM as LLM Provider
participant MCP as @shopify/dev-mcp
participant SHOP as Shopify Storefront
User->>WA: "Find me red shoes under $50"
WA->>GW: POST /webhook
GW-->>WA: 200 OK (immediate)
GW->>RV: get_actor(ShoppingAgentActor, user_id)
alt First message (actor doesn't exist)
RV->>ACTOR: Create actor
ACTOR->>ACTOR: on_init()
ACTOR->>MCP: Initialize MCP client
ACTOR->>PI: Create Pi Agent, register tools
else Returning user
RV->>ACTOR: Wake actor (if sleeping)
ACTOR->>ACTOR: on_wake()
end
RV-->>GW: actor reference
GW->>ACTOR: on_message(text)
Note over ACTOR: Rivet serializes: one<br/>execution at a time per actor
ACTOR->>PI: agent.prompt(text)
PI->>LLM: Stream completion
LLM-->>PI: Tool call: search_shop_catalog
PI->>MCP: Execute tool
MCP->>SHOP: GraphQL query
SHOP-->>MCP: Product results
MCP-->>PI: Structured result
PI->>LLM: Continue with result
LLM-->>PI: Final response
PI-->>ACTOR: Response
ACTOR->>ACTOR: Save state (durable)
ACTOR-->>GW: Response
GW->>WA: POST /messages (send reply)
WA-->>User: "Found 5 products..."
Note over ACTOR: Actor sleeps after 5min idle
Extension Model
Each Rivet actor contains a Pi Agent instance with extensions registered at on_init():
graph LR
subgraph "Rivet Actor (per user)"
PI[Pi Agent Core]
TOOL_REG[Tool Registry]
EVENT_BUS[Event Bus]
CTX[Context Manager]
subgraph "Extensions"
E1["MCP Client<br/>(Shopify tools)"]
E2[WhatsApp Formatter]
E3[State Manager]
E4[Analytics]
end
end
PI --> E1
PI --> E2
PI --> E3
PI --> E4
TOOL_REG -.->|registers tools| E1
EVENT_BUS -.->|emits events| E2
EVENT_BUS -.->|emits events| E4
CTX -.->|persists| E3
style PI fill:#e1f5fe,stroke:#0277bd,stroke-width:2px
What Rivet Gives Us for Free
| Concern | In-Process Pool (rejected) | Rivet Actors (chosen) |
|---|---|---|
| Agent creation | Manual dict management | get_actor() creates on demand |
| Durability | ❌ Lost on process crash | ✅ Survives restarts |
| Distribution | ❌ Single process only | ✅ Cluster-wide |
| Concurrency | Build asyncio.Lock per user | ✅ Serialized per actor |
| Message queue | Build asyncio.Queue per user | ✅ Built-in per actor |
| State persistence | Manual save to S3/Redis | ✅ Rivet Durable State |
| Idle management | Build cleanup loop | ✅ Built-in sleep/wake/terminate |
| Failure recovery | ❌ Lose all state | ✅ Resume from last checkpoint |
| Scaling | ❌ Vertical only | ✅ Horizontal |
Decision: Rivet actors win on every axis except “no additional dependency”. We’re happy to pay that cost.
Actor Lifecycle Summary
stateDiagram-v2
[*] --> NotExists: User has never texted
NotExists --> Creating: First webhook hit
Creating --> Running: on_init() completes
Running --> Running: on_message() serialized
Running --> Sleeping: Idle timeout (5 min)
Sleeping --> Running: New message wakes
Sleeping --> Terminated: Extended idle (1 hr)
Terminated --> NotExists: Actor destroyed
Terminated --> Creating: Next message recreates
See Rivet Actor Model for the full implementation.
Key Design Principles
- Actor-per-user — Each WhatsApp user maps to one durable Rivet actor
- Thin gateway — FastAPI does no agent work, only routes
- Tool-first — Agents execute Shopify MCP tools, not just generate text
- Stateful conversations — Durable state survives sleep/wake
- E-commerce native — Official
@shopify/dev-mcpfor all shopping operations - Defense in depth — Rate limits, injection detection, input/output sanitization
Documents in This Vault
| Document | Scope |
|---|---|
| Architecture | Highest-level system overview |
| Agent Architecture | This document — agent stack |
| Rivet Actor Model | Actor implementation + code |
| Agent Lifecycle | Message → actor creation flow |
| AgentOS Configuration | Per-actor sandbox setup |
| Pi Agent Setup | Pi Agent Core installation |
| Pi Agent Core API Reference | Python API reference |
| Building Pi Extensions | MCP client, formatters, state, analytics |
| Concurrency & Security | Rate limiting, injection prevention |
| Shopify Integration Research | MCP decision |
| WhatsApp Business Cloud API | WhatsApp integration |
| Integration Guide | End-to-end wiring |