Skip to content
reaatechREAATECH

Files · Persistent customer memory across support sessions

69 (1 binary, 579.3 kB total)attempt 2

README.md·9928 B·markdown
markdown
# Persistent customer memory across support sessions
 
> Your support agent remembers the last conversation, the open ticket, and the customer's preferences.
 
A tutorialized reference solution from [reaatech.com](https://reaatech.com) demonstrating how to build production-grade AI systems with token-budget-aware conversation memory using the `@reaatech/*` package family and Anthropic Claude.
 
## Problem
 
Customer-support agents — both human and AI — routinely forget prior conversations, leading to repetitive questions, lost context, and frustrated customers. Each session starts from scratch, wasting tokens and goodwill. Without persistent memory, support quality degrades as conversation history grows beyond the model's context window.
 
## Solution
 
This recipe provides a production-ready reference implementation of persistent customer memory across support sessions:
 
- **Session continuity** — per-customer conversation history survives across sessions
- **Token-budget-aware compression** — sliding window, summarization, or hybrid strategies keep context within budget
- **Dual storage adapters** — Redis for low-latency deployments or DynamoDB for serverless/AWS-native
- **Anthropic Claude integration**`claude-sonnet-4-6` as the default support agent model
- **REST API**`POST /api/chat`, `GET/POST /api/sessions`, `GET /api/memory` routes for integration
 
## Quick Start
 
### Prerequisites
 
- Node.js >= 22
- pnpm 10.x
 
### Setup
 
```bash
pnpm install
cp .env.example .env
```
 
Edit `.env` and set at minimum:
 
```
ANTHROPIC_API_KEY=sk-ant-...
REDIS_URL=redis://localhost:6379
```
 
Or configure DynamoDB:
 
```
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
DYNAMODB_TABLE_NAME=sessions
```
 
### Run
 
```bash
pnpm dev          # Start Next.js dev server on http://localhost:3000
pnpm test         # Run vitest with coverage
pnpm typecheck    # TypeScript type checking
pnpm lint         # ESLint
```
 
## Architecture
 
### Data Flow
 
```
┌──────────┐     ┌──────────────┐     ┌──────────────┐     ┌────────────┐     ┌──────────────┐
│  Browser │ ──> │  Next.js App  │ ──> │  API Route   │ ──> │  Memory    │ ──> │  Anthropic   │
│  (Chat   │     │  Router      │     │  /api/chat   │     │  Service   │     │  Claude API  │
│   UI)    │ <── │              │ <── │              │ <── │            │ <── │              │
└──────────┘     └──────────────┘     └──────────────┘     └─────┬──────┘     └──────────────┘

                                                         ┌────────▼────────┐
                                                         │  SessionManager │
                                                         │  (@reaatech/    │
                                                         │  session-       │
                                                         │  continuity)    │
                                                         └────────┬────────┘

                                            ┌─────────────────────┼─────────────────────┐
                                            │                     │                     │
                                   ┌────────▼──────┐    ┌────────▼──────┐    ┌────────▼──────┐
                                   │  Redis        │    │  DynamoDB     │    │  Tokenizer    │
                                   │  Adapter      │    │  Adapter      │    │  (tiktoken /  │
                                   │               │    │               │    │   anthropic)  │
                                   └───────────────┘    └───────────────┘    └───────────────┘
```
 
### Components
 
1. **API Routes** (`app/api/*`) — Next.js App Router handlers that validate requests with Zod and delegate to the services layer
2. **MemoryService** (`src/services/memory-service.ts`) — orchestrates session management and LLM calls for persistent memory
3. **AnthropicClient** (`src/services/anthropic-client.ts`) — wraps the `@anthropic-ai/sdk` for Claude API calls
4. **Session Store** (`src/services/session-store.ts`) — thin wrappers around `@reaatech/session-continuity`'s `SessionManager`
5. **Storage Factory** (`src/services/storage-factory.ts`) — instantiates Redis or DynamoDB adapters based on environment
 
## API Reference
 
### POST /api/chat
 
Send a message to the support agent. Creates a new session or resumes an existing one.
 
**Request body:**
 
| Field       | Type   | Required | Description                          |
|-------------|--------|----------|--------------------------------------|
| customerId  | string | yes      | Unique customer identifier           |
| message     | string | yes      | The customer's message               |
| sessionId   | string | no       | Resume an existing session           |
| model       | string | no       | Claude model override                |
 
**Response (200):**
 
```json
{
  "sessionId": "sess_abc123",
  "reply": "Hello! I see you had an issue with billing last week...",
  "tokenUsage": { "input": 350, "output": 120, "total": 470 },
  "memoryUpdated": true
}
```
 
**Errors:** 400 (validation), 500 (server error)
 
### GET /api/sessions?customerId={id}
 
List all sessions for a customer.
 
**Response (200):** Array of session summaries
 
### POST /api/sessions
 
Create a new session.
 
**Request body:** `{ "customerId": "cust-1" }`
 
**Response (201):** Created session object
 
### GET /api/sessions/{id}
 
Get a single session by ID.
 
**Errors:** 404 (not found)
 
### DELETE /api/sessions/{id}
 
Delete a session. Returns 204 on success.
 
**Errors:** 404 (not found)
 
### POST /api/memory
 
Store a memory entry for a customer.
 
**Request body:**
 
| Field       | Type   | Required | Description                                    |
|-------------|--------|----------|------------------------------------------------|
| customerId  | string | yes      | Customer identifier                            |
| key         | string | yes      | Memory key (e.g. `preferred_name`)             |
| value       | any    | no       | Memory value                                   |
| scope       | string | no       | One of `preference`, `note`, `ticket`          |
 
### GET /api/memory?customerId={id}
 
Retrieve stored memories for a customer.
 
## Storage
 
This recipe supports two storage backends via `@reaatech/session-continuity` adapters:
 
| Adapter    | Package                                         | Use Case                          |
|------------|-------------------------------------------------|-----------------------------------|
| Redis      | `@reaatech/session-continuity-storage-redis`    | Low-latency, high-throughput      |
| DynamoDB   | `@reaatech/session-continuity-storage-dynamodb` | Serverless, AWS-native            |
 
**Redis** uses hashes for sessions, sorted sets for messages, and native `EXPIRE` for TTL. Best for latency-sensitive deployments.
 
**DynamoDB** uses a single-table design with composite keys and two GSIs. Best for AWS serverless infrastructure.
 
When both are configured, Redis is selected as the primary adapter.
 
## Configuration
 
| Env Var                | Required | Default        | Description                              |
|------------------------|----------|----------------|------------------------------------------|
| `ANTHROPIC_API_KEY`    | yes      | —              | Anthropic Claude API key                 |
| `REDIS_URL`            | see note | —              | Redis connection URL                     |
| `AWS_REGION`           | see note | —              | AWS region for DynamoDB                  |
| `AWS_ACCESS_KEY_ID`    | see note | —              | AWS access key for DynamoDB              |
| `AWS_SECRET_ACCESS_KEY`| see note | —              | AWS secret key for DynamoDB              |
| `DYNAMODB_TABLE_NAME`  | no       | `sessions`     | DynamoDB table name                      |
| `SESSION_TTL_HOURS`    | no       | `24`           | Session TTL in hours                     |
| `TOKEN_BUDGET_MAX`     | no       | `4096`         | Max tokens in session context            |
| `TOKEN_BUDGET_RESERVE` | no       | `500`          | Tokens reserved for response             |
| `COMPRESSION_STRATEGY` | no       | `sliding_window`| Compression strategy                     |
 
**Note:** Either `REDIS_URL` or the `AWS_*` trio must be configured.
 
## Tech Stack
 
- **Framework:** Next.js 16+ (App Router, Turbopack)
- **Language:** TypeScript 5.8+
- **Testing:** Vitest 3.x with MSW for HTTP mocking
- **AI SDK:** `@anthropic-ai/sdk` 0.100.1
- **Validation:** Zod 4.4.3
- **Packages:**
  - `@reaatech/session-continuity` — session management, compression strategies, token budget enforcement
  - `@reaatech/session-continuity-storage-redis` — Redis storage adapter
  - `@reaatech/session-continuity-storage-dynamodb` — DynamoDB storage adapter
  - `@reaatech/session-continuity-tokenizers` — token counting (tiktoken, anthropic, estimate)
 
## License
 
MIT — see [LICENSE](./LICENSE).