Aelio
Overview

How It Works

Step-by-step flow of how Aelio processes a customer conversation.

This page walks through exactly what happens when a customer sends a message through the Aelio chat widget or WhatsApp.

Web chat flow

Customer opens your website — the chat widget loads and connects to Aelio Server over WebSocket at /widget/ws.

Widget sends an init frame with customerId + authToken. The server responds with a ready frame that includes chat history.

Customer types: "What is my order status?" — the widget sends a message frame.

Aelio Server runs processTurn():

  • Recalls relevant customer facts from memory
  • LLM decides to call getOrderStatus tool
  • Safety gate: read action → auto-allowed
  • Server sends invoke frame to your SDK (WebSocket /sdk)

Your SDK handler runs locally:

return await db.orders.findOne({ id: orderId, userId: ctx.customerId })

SDK sends a result frame back to the server.

Server synthesizes a natural-language reply and sends a message frame to the widget: "Your order #A123 is shipped!"

Write action flow (with confirmation)

When the customer asks to cancel an order:

LLM decides to call cancelOrder (safety: write).

Safety gate triggers — write action requires user confirmation. Server pauses execution.

Widget shows a confirmation prompt: "Cancel order #A123? Reply yes to confirm."

Customer clicks Confirm (or types "yes") — server executes the tool via SDK invoke.

Handler runs: db.orders.cancel(orderId, ctx.customerId)

Reply: "Done! Order #A123 has been cancelled."

SDK connection model

The SDK dials out to the server. Your backend initiates the connection:

Your Backend                          Aelio Server
     │                                     │
     │──── WebSocket connect /sdk ────────▶│
     │     Authorization: Bearer secret    │
     │                                     │
     │──── register frame ────────────────▶│  (functions, states, policies)
     │                                     │
     │◀─── invoke frame ──────────────────│  (LLM wants getOrderStatus)
     │                                     │
     │──── result frame ──────────────────▶│  (handler return value)
     │                                     │
     │◀─── ping ──────────────────────────│  (keepalive every 30s)
     │──── pong ──────────────────────────▶│

Key point

The server never calls your REST API. It sends tool invocations over the WebSocket you opened.

Memory and intelligence

After every turn, the analytical agent runs in the background:

Turn completes — the analytical agent wakes up.

Extract durable facts — e.g. "customer prefers express shipping".

Embed fact as a vector and store it in SQLite + sqlite-vec.

Next conversation — relevant facts are injected into the LLM prompt automatically via top-K similarity search.

Lifecycle enforcement

Your SDK declares customer states. Your backend pushes the current state:

// Customer adds item to cart
await aelio.setCustomerState(customerId, 'cart_building');

// Now only cart-related tools are available
// checkout_cart is allowed, but list_invoices is blocked

State-gated tools

Tools not permitted in the current lifecycle state are silently blocked at the safety gate — the LLM cannot invoke them regardless of what the customer asks.

Channel-agnostic

The same SDK tools work across all channels. A customer can start on Web and continue on WhatsApp — Aelio resolves identity and recalls memory across channels.

What you build vs what Aelio handles

You buildAelio handles
Business logic (tool handlers)LLM orchestration and tool selection
Database queriesSafety gates and write confirmations
User authenticationCustomer identity resolution
Chat widget placementWebSocket connection and reconnect
WhatsApp webhook (if BYO)Memory extraction and recall
Lifecycle state managementChannel delivery (Web, WhatsApp)
Proactive messaging guardrails
Harness turn engine (plan → execute → synthesize)

On this page