@falai/agent 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -863
- package/docs/ADAPTERS.md +12 -0
- package/docs/DOCS.md +239 -0
- package/docs/EXAMPLES.md +419 -0
- package/docs/README.md +2 -0
- package/examples/business-onboarding.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -140,930 +140,156 @@ yarn add @falai/agent
|
|
|
140
140
|
|
|
141
141
|
## 🚀 Quick Start
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
Build a conversational AI agent in 2 minutes:
|
|
144
144
|
|
|
145
145
|
```typescript
|
|
146
146
|
import {
|
|
147
147
|
Agent,
|
|
148
|
-
AnthropicProvider,
|
|
149
148
|
GeminiProvider,
|
|
150
|
-
|
|
151
|
-
OpenRouterProvider,
|
|
149
|
+
defineTool,
|
|
152
150
|
createMessageEvent,
|
|
153
151
|
EventSource,
|
|
154
152
|
} from "@falai/agent";
|
|
155
153
|
|
|
156
|
-
// 1️⃣
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
apiKey: process.env.ANTHROPIC_API_KEY!,
|
|
166
|
-
model: "claude-sonnet-4-5",
|
|
154
|
+
// 1️⃣ Create your agent
|
|
155
|
+
const agent = new Agent({
|
|
156
|
+
name: "BookingBot",
|
|
157
|
+
description: "Hotel booking assistant",
|
|
158
|
+
ai: new GeminiProvider({
|
|
159
|
+
apiKey: process.env.GEMINI_API_KEY!,
|
|
160
|
+
model: "models/gemini-2.5-flash",
|
|
161
|
+
}),
|
|
162
|
+
context: { userId: "user_123" },
|
|
167
163
|
});
|
|
168
164
|
|
|
169
|
-
//
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
// const ai = new OpenAIProvider({
|
|
176
|
-
// apiKey: process.env.OPENAI_API_KEY!,
|
|
177
|
-
// model: "gpt-5",
|
|
178
|
-
// });
|
|
179
|
-
|
|
180
|
-
// const ai = new OpenRouterProvider({
|
|
181
|
-
// apiKey: process.env.OPENROUTER_API_KEY!,
|
|
182
|
-
// model: "anthropic/claude-sonnet-4-5", // Access to 200+ models
|
|
183
|
-
// });
|
|
184
|
-
|
|
185
|
-
// 3️⃣ Initialize your agent - two ways!
|
|
186
|
-
|
|
187
|
-
// Option A: Declarative initialization (recommended for complex setups)
|
|
188
|
-
const agent = new Agent<SupportContext>({
|
|
189
|
-
name: "SupportBot",
|
|
190
|
-
description: "A helpful and empathetic customer support assistant",
|
|
191
|
-
goal: "Resolve customer issues efficiently while maintaining a positive experience",
|
|
192
|
-
ai,
|
|
193
|
-
context: {
|
|
194
|
-
userId: "usr_123",
|
|
195
|
-
userName: "Alex",
|
|
196
|
-
tier: "premium",
|
|
165
|
+
// 2️⃣ Define a simple tool
|
|
166
|
+
const checkAvailability = defineTool(
|
|
167
|
+
"check_availability",
|
|
168
|
+
async (ctx, hotelName: string, date: string) => {
|
|
169
|
+
return { data: `${hotelName} has rooms available on ${date}` };
|
|
197
170
|
},
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
],
|
|
205
|
-
guidelines: [
|
|
206
|
-
{
|
|
207
|
-
condition: "Customer asks about account issues",
|
|
208
|
-
action: "Prioritize account security and verify identity first",
|
|
209
|
-
tags: ["security", "account"],
|
|
210
|
-
},
|
|
211
|
-
],
|
|
212
|
-
routes: [
|
|
213
|
-
{
|
|
214
|
-
title: "Account Recovery",
|
|
215
|
-
description: "Help users regain access to their accounts",
|
|
216
|
-
conditions: ["User cannot access their account"],
|
|
217
|
-
},
|
|
218
|
-
],
|
|
171
|
+
{ description: "Check hotel availability" }
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
// 3️⃣ Create a route with 2 states
|
|
175
|
+
const bookingRoute = agent.createRoute({
|
|
176
|
+
title: "Book Hotel",
|
|
177
|
+
conditions: ["User wants to book a hotel"],
|
|
219
178
|
});
|
|
220
179
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
name: "SLA",
|
|
230
|
-
description: "Service Level Agreement - our response time commitment",
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// 4️⃣ Generate intelligent responses
|
|
180
|
+
bookingRoute.initialState
|
|
181
|
+
.transitionTo(
|
|
182
|
+
{ toolState: checkAvailability },
|
|
183
|
+
"User provided hotel name and date"
|
|
184
|
+
)
|
|
185
|
+
.transitionTo({ chatState: "Confirm booking and provide summary" });
|
|
186
|
+
|
|
187
|
+
// 4️⃣ Start conversing
|
|
234
188
|
const response = await agent.respond({
|
|
235
189
|
history: [
|
|
236
190
|
createMessageEvent(
|
|
237
191
|
EventSource.CUSTOMER,
|
|
238
|
-
"
|
|
239
|
-
"
|
|
192
|
+
"Alice",
|
|
193
|
+
"Book me a room at Grand Hotel for tomorrow"
|
|
240
194
|
),
|
|
241
195
|
],
|
|
242
196
|
});
|
|
243
197
|
|
|
244
|
-
console.log(response.message); // 🎉 AI
|
|
198
|
+
console.log(response.message); // 🎉 AI handles the rest!
|
|
245
199
|
```
|
|
246
200
|
|
|
247
|
-
|
|
201
|
+
**That's it!** The agent will:
|
|
202
|
+
- ✅ Route to the correct conversation flow
|
|
203
|
+
- ✅ Execute tools automatically when conditions match
|
|
204
|
+
- ✅ Generate natural responses based on state
|
|
205
|
+
|
|
206
|
+
📖 **[See more examples →](./docs/EXAMPLES.md)** | **[Full tutorial →](./docs/GETTING_STARTED.md)**
|
|
248
207
|
|
|
249
|
-
|
|
208
|
+
### ⚡ Advanced Features
|
|
250
209
|
|
|
210
|
+
**Streaming responses** for real-time UX:
|
|
251
211
|
```typescript
|
|
252
|
-
// Use respondStream for real-time streaming
|
|
253
212
|
for await (const chunk of agent.respondStream({ history })) {
|
|
254
|
-
// chunk.delta contains the new text
|
|
255
213
|
process.stdout.write(chunk.delta);
|
|
256
|
-
|
|
257
|
-
if (chunk.done) {
|
|
258
|
-
// Stream complete - access final metadata
|
|
259
|
-
console.log("\n✅ Complete!");
|
|
260
|
-
console.log("Route:", chunk.route?.title);
|
|
261
|
-
console.log("Tool calls:", chunk.toolCalls?.length);
|
|
262
|
-
}
|
|
263
214
|
}
|
|
264
215
|
```
|
|
265
216
|
|
|
266
|
-
**
|
|
267
|
-
|
|
268
|
-
- ✨ Real-time response generation
|
|
269
|
-
- 🎯 Better perceived performance
|
|
270
|
-
- 🛑 Cancellable with AbortSignal
|
|
271
|
-
- 📊 Access to route/state/tool information in final chunk
|
|
272
|
-
|
|
273
|
-
**Supported Providers:** All providers support streaming (Anthropic, OpenAI, Gemini, OpenRouter)
|
|
274
|
-
|
|
275
|
-
See [streaming-agent.ts](./examples/streaming-agent.ts) for complete examples.
|
|
276
|
-
|
|
277
|
-
---
|
|
278
|
-
|
|
279
|
-
## 🔒 Domain-Based Security (Optional)
|
|
280
|
-
|
|
281
|
-
Domains let you **optionally** organize and restrict tools for security. **If you never use domains, your agent works perfectly** - all tools are available everywhere.
|
|
282
|
-
|
|
283
|
-
### Without Domains (Simple & Default)
|
|
284
|
-
|
|
217
|
+
**Session state** for multi-turn conversations:
|
|
285
218
|
```typescript
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
//
|
|
289
|
-
const saveName = defineTool(/* ... */);
|
|
290
|
-
const processPayment = defineTool(/* ... */);
|
|
291
|
-
|
|
292
|
-
// All tools work everywhere
|
|
293
|
-
const route = agent.createRoute({ title: "Onboarding" });
|
|
294
|
-
route.initialState
|
|
295
|
-
.transitionTo({ toolState: saveName }) // ✅ Works
|
|
296
|
-
.transitionTo({ toolState: processPayment }); // ✅ Works
|
|
219
|
+
let session = createSession<MyData>();
|
|
220
|
+
const response = await agent.respond({ history, session });
|
|
221
|
+
session = response.session!; // Tracks progress across turns
|
|
297
222
|
```
|
|
298
223
|
|
|
299
|
-
|
|
300
|
-
|
|
224
|
+
**Database persistence** with any adapter:
|
|
301
225
|
```typescript
|
|
302
|
-
|
|
303
|
-
agent
|
|
304
|
-
|
|
305
|
-
/* ... */
|
|
306
|
-
},
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
agent.addDomain("payment", {
|
|
310
|
-
processPayment: async (amount) => {
|
|
311
|
-
/* ... */
|
|
312
|
-
},
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
// Restrict which tools each route can use
|
|
316
|
-
const onboardingRoute = agent.createRoute({
|
|
317
|
-
title: "Onboarding",
|
|
318
|
-
domains: ["user"], // ONLY user tools can execute
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
const checkoutRoute = agent.createRoute({
|
|
322
|
-
title: "Checkout",
|
|
323
|
-
domains: ["payment"], // ONLY payment tools can execute
|
|
226
|
+
import { PrismaAdapter } from "@falai/agent";
|
|
227
|
+
const agent = new Agent({
|
|
228
|
+
persistence: { adapter: new PrismaAdapter({ prisma }) }
|
|
324
229
|
});
|
|
325
|
-
|
|
326
|
-
// Security: payment tools can't execute in onboarding route
|
|
327
|
-
onboardingRoute.initialState
|
|
328
|
-
.transitionTo({ toolState: agent.domain.user.saveName }) // ✅ Allowed
|
|
329
|
-
.transitionTo({ toolState: agent.domain.payment.processPayment }); // ❌ Blocked!
|
|
330
230
|
```
|
|
331
231
|
|
|
332
|
-
**
|
|
333
|
-
|
|
334
|
-
- ✅ Production systems with sensitive operations
|
|
335
|
-
- ✅ Preventing prompt injection attacks
|
|
336
|
-
- ✅ Route isolation (checkout can't trigger account deletion)
|
|
337
|
-
- ❌ Skip for prototypes and simple agents
|
|
338
|
-
|
|
339
|
-
📖 **[Full Domain Guide →](./docs/DOMAINS.md)** | [Example →](./examples/domain-scoping.ts)
|
|
232
|
+
📖 **[See full feature docs →](./docs)**
|
|
340
233
|
|
|
341
234
|
---
|
|
342
235
|
|
|
343
236
|
## 📚 Documentation
|
|
344
237
|
|
|
345
|
-
|
|
238
|
+
📋 **[Complete Documentation Index →](docs/DOCS.md)** - Searchable index of all docs
|
|
346
239
|
|
|
347
|
-
|
|
348
|
-
- **[Getting Started](./docs/GETTING_STARTED.md)** -
|
|
349
|
-
- **[
|
|
350
|
-
- **[
|
|
351
|
-
- **[
|
|
352
|
-
- **[API Reference](./docs/API_REFERENCE.md)** - Complete API documentation
|
|
240
|
+
**Core Guides:**
|
|
241
|
+
- 📘 **[Getting Started](./docs/GETTING_STARTED.md)** - Build your first agent in 5 minutes
|
|
242
|
+
- 🏗️ **[Architecture](./docs/ARCHITECTURE.md)** - Design principles & philosophy
|
|
243
|
+
- 🔧 **[API Reference](./docs/API_REFERENCE.md)** - Complete API documentation
|
|
244
|
+
- 📝 **[Examples](./docs/EXAMPLES.md)** - Production-ready code examples
|
|
353
245
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
```typescript
|
|
361
|
-
import { EventSource, createMessageEvent, createToolEvent } from "@falai/agent";
|
|
362
|
-
|
|
363
|
-
const history = [
|
|
364
|
-
createMessageEvent(
|
|
365
|
-
EventSource.CUSTOMER,
|
|
366
|
-
"Alice",
|
|
367
|
-
"Book me a flight to Paris"
|
|
368
|
-
),
|
|
369
|
-
createMessageEvent(
|
|
370
|
-
EventSource.AI_AGENT,
|
|
371
|
-
"TravelBot",
|
|
372
|
-
"I'd love to help! When would you like to travel?"
|
|
373
|
-
),
|
|
374
|
-
createMessageEvent(EventSource.CUSTOMER, "Alice", "Next Friday"),
|
|
375
|
-
// Tool calls are tracked too
|
|
376
|
-
createToolEvent("search_flights", {
|
|
377
|
-
destination: "Paris",
|
|
378
|
-
date: "2025-10-20",
|
|
379
|
-
}),
|
|
380
|
-
];
|
|
381
|
-
|
|
382
|
-
const response = await agent.respond({ history });
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
### 🔧 Defining Type-Safe Tools
|
|
386
|
-
|
|
387
|
-
Tools are first-class citizens:
|
|
388
|
-
|
|
389
|
-
```typescript
|
|
390
|
-
import { defineTool } from "@falai/agent";
|
|
391
|
-
|
|
392
|
-
const fetchUserProfile = defineTool<
|
|
393
|
-
SupportContext,
|
|
394
|
-
[userId: string],
|
|
395
|
-
{ name: string; email: string; tier: string }
|
|
396
|
-
>(
|
|
397
|
-
"fetch_user_profile",
|
|
398
|
-
async ({ context }, userId) => {
|
|
399
|
-
// Full access to typed context
|
|
400
|
-
console.log(`Fetching for ${context.userName}`);
|
|
401
|
-
|
|
402
|
-
const profile = await db.users.findById(userId);
|
|
403
|
-
return { data: profile };
|
|
404
|
-
},
|
|
405
|
-
{
|
|
406
|
-
id: "tool_fetch_user_profile", // Optional: custom ID for persistence
|
|
407
|
-
description: "Retrieves user profile information from the database",
|
|
408
|
-
}
|
|
409
|
-
);
|
|
410
|
-
|
|
411
|
-
// Use in guidelines
|
|
412
|
-
agent.createGuideline({
|
|
413
|
-
condition: "Customer asks about their account details",
|
|
414
|
-
action: "Fetch and present their profile information",
|
|
415
|
-
tools: [fetchUserProfile],
|
|
416
|
-
});
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
### 🛤️ Creating Conversation Routes
|
|
420
|
-
|
|
421
|
-
Build sophisticated conversation flows - declaratively or programmatically:
|
|
422
|
-
|
|
423
|
-
```typescript
|
|
424
|
-
import { END_ROUTE } from "@falai/agent";
|
|
425
|
-
|
|
426
|
-
// Option A: Declarative (in constructor)
|
|
427
|
-
const agent = new Agent({
|
|
428
|
-
name: "OnboardingBot",
|
|
429
|
-
ai: provider,
|
|
430
|
-
routes: [
|
|
431
|
-
{
|
|
432
|
-
id: "route_user_onboarding", // Optional: custom ID for consistency
|
|
433
|
-
title: "User Onboarding",
|
|
434
|
-
description: "Guide new users through account setup",
|
|
435
|
-
conditions: ["User is new and needs onboarding"],
|
|
436
|
-
guidelines: [
|
|
437
|
-
{
|
|
438
|
-
condition: "User provides invalid email",
|
|
439
|
-
action: "Politely ask for a valid email format",
|
|
440
|
-
tags: ["validation"],
|
|
441
|
-
},
|
|
442
|
-
],
|
|
443
|
-
},
|
|
444
|
-
],
|
|
445
|
-
});
|
|
446
|
-
|
|
447
|
-
// Option B: Programmatic (build flows dynamically)
|
|
448
|
-
const onboardingRoute = agent.createRoute({
|
|
449
|
-
id: "route_user_onboarding", // Optional: custom ID
|
|
450
|
-
title: "User Onboarding",
|
|
451
|
-
description: "Guide new users through account setup",
|
|
452
|
-
conditions: ["User is new and needs onboarding"],
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
// Option 1: Step-by-step (clear and explicit)
|
|
456
|
-
const askName = onboardingRoute.initialState.transitionTo({
|
|
457
|
-
chatState: "Ask for user's full name",
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
const askEmail = askName.transitionTo(
|
|
461
|
-
{
|
|
462
|
-
chatState: "Request email address",
|
|
463
|
-
},
|
|
464
|
-
"Customer has only provided name but not email yet"
|
|
465
|
-
);
|
|
466
|
-
|
|
467
|
-
const confirmDetails = askEmail.transitionTo({
|
|
468
|
-
chatState: "Confirm all details before proceeding",
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
confirmDetails.transitionTo({ state: END_ROUTE });
|
|
472
|
-
|
|
473
|
-
// Option 2: Fluent chaining (concise and elegant)
|
|
474
|
-
onboardingRoute.initialState
|
|
475
|
-
.transitionTo({ chatState: "Ask for user's full name" })
|
|
476
|
-
.transitionTo({ chatState: "Request email address" })
|
|
477
|
-
.transitionTo({ chatState: "Confirm all details before proceeding" })
|
|
478
|
-
.transitionTo({ state: END_ROUTE });
|
|
479
|
-
|
|
480
|
-
// Both approaches work identically - choose what fits your style!
|
|
481
|
-
|
|
482
|
-
// Add guidelines dynamically (can also be in route options)
|
|
483
|
-
onboardingRoute.createGuideline({
|
|
484
|
-
condition: "User provides invalid email",
|
|
485
|
-
action: "Politely ask for a valid email format",
|
|
486
|
-
enabled: true,
|
|
487
|
-
tags: ["validation"],
|
|
488
|
-
});
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
### 📜 Rules & Prohibitions Per Route
|
|
492
|
-
|
|
493
|
-
Control agent behavior and communication style for each route:
|
|
494
|
-
|
|
495
|
-
```typescript
|
|
496
|
-
// WhatsApp support bot with different styles per route
|
|
497
|
-
agent.createRoute({
|
|
498
|
-
title: "Quick Support",
|
|
499
|
-
description: "Fast answers for common questions",
|
|
500
|
-
conditions: ["User has a simple question"],
|
|
501
|
-
rules: [
|
|
502
|
-
"Keep messages extremely short (1-2 lines maximum)",
|
|
503
|
-
"Use bullet points for lists",
|
|
504
|
-
"Maximum 1 emoji per message 👍",
|
|
505
|
-
"Be direct and to the point",
|
|
506
|
-
],
|
|
507
|
-
prohibitions: [
|
|
508
|
-
"Never send long paragraphs",
|
|
509
|
-
"Do not over-explain",
|
|
510
|
-
"Never use more than 2 emojis",
|
|
511
|
-
],
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
agent.createRoute({
|
|
515
|
-
title: "Sales Consultation",
|
|
516
|
-
description: "Help customer discover needs",
|
|
517
|
-
conditions: ["User is interested in buying"],
|
|
518
|
-
rules: [
|
|
519
|
-
"Ask open-ended questions to discover needs",
|
|
520
|
-
"Use storytelling when presenting solutions",
|
|
521
|
-
"Present value before mentioning price",
|
|
522
|
-
],
|
|
523
|
-
prohibitions: [
|
|
524
|
-
"Never talk about price before showing value",
|
|
525
|
-
"Do not pressure or push",
|
|
526
|
-
"Avoid technical jargon",
|
|
527
|
-
],
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
agent.createRoute({
|
|
531
|
-
title: "Emergency Support",
|
|
532
|
-
description: "Handle urgent issues",
|
|
533
|
-
conditions: ["Customer is frustrated", "Urgent issue"],
|
|
534
|
-
rules: [
|
|
535
|
-
"Acknowledge the urgency immediately",
|
|
536
|
-
"Express empathy and understanding",
|
|
537
|
-
"Set clear expectations on resolution time",
|
|
538
|
-
],
|
|
539
|
-
prohibitions: [
|
|
540
|
-
"Never downplay the customer's concern",
|
|
541
|
-
"Do not use emojis (keep it professional)",
|
|
542
|
-
'Never say "calm down"',
|
|
543
|
-
],
|
|
544
|
-
});
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
**Use Cases:**
|
|
548
|
-
|
|
549
|
-
- 📱 Different message styles per channel (WhatsApp, email, chat)
|
|
550
|
-
- 🎭 Context-specific tone and behavior
|
|
551
|
-
- 🎨 Brand consistency across routes
|
|
552
|
-
- ⚡ Automatic enforcement without manual checking
|
|
553
|
-
|
|
554
|
-
### 🔐 Domain Scoping for Security
|
|
555
|
-
|
|
556
|
-
Restrict which tools are available in each route:
|
|
557
|
-
|
|
558
|
-
```typescript
|
|
559
|
-
// Register different tool domains
|
|
560
|
-
agent.addDomain("payment", {
|
|
561
|
-
processPayment: async (amount: number) => {
|
|
562
|
-
/* ... */
|
|
563
|
-
},
|
|
564
|
-
refund: async (txId: string) => {
|
|
565
|
-
/* ... */
|
|
566
|
-
},
|
|
567
|
-
});
|
|
568
|
-
|
|
569
|
-
agent.addDomain("calendar", {
|
|
570
|
-
scheduleEvent: async (date: Date, title: string) => {
|
|
571
|
-
/* ... */
|
|
572
|
-
},
|
|
573
|
-
});
|
|
574
|
-
|
|
575
|
-
agent.addDomain("analytics", {
|
|
576
|
-
trackEvent: async (name: string) => {
|
|
577
|
-
/* ... */
|
|
578
|
-
},
|
|
579
|
-
});
|
|
580
|
-
|
|
581
|
-
// Route 1: Customer Support - NO access to payment tools
|
|
582
|
-
agent.createRoute({
|
|
583
|
-
title: "Customer Support",
|
|
584
|
-
description: "Answer general questions",
|
|
585
|
-
domains: [], // 🔒 No tools (conversation only)
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
// Route 2: Checkout - ONLY payment and analytics
|
|
589
|
-
agent.createRoute({
|
|
590
|
-
title: "Checkout Process",
|
|
591
|
-
description: "Process purchases",
|
|
592
|
-
domains: ["payment", "analytics"], // 🔒 Limited access
|
|
593
|
-
});
|
|
594
|
-
|
|
595
|
-
// Route 3: Admin - ALL tools available
|
|
596
|
-
agent.createRoute({
|
|
597
|
-
title: "Admin Support",
|
|
598
|
-
description: "Full system access",
|
|
599
|
-
// domains not specified = all domains available
|
|
600
|
-
});
|
|
601
|
-
```
|
|
602
|
-
|
|
603
|
-
**Benefits:**
|
|
604
|
-
|
|
605
|
-
- 🔒 Prevent unauthorized tool calls
|
|
606
|
-
- ⚡ Improve AI performance (reduced decision space)
|
|
607
|
-
- 📋 Clear documentation of route capabilities
|
|
608
|
-
- 🛡️ Security by design
|
|
609
|
-
|
|
610
|
-
### 🎨 Context Override
|
|
611
|
-
|
|
612
|
-
Dynamically update context per request:
|
|
613
|
-
|
|
614
|
-
```typescript
|
|
615
|
-
const response = await agent.respond({
|
|
616
|
-
history,
|
|
617
|
-
contextOverride: {
|
|
618
|
-
tier: "premium", // Temporarily upgrade user for this request
|
|
619
|
-
},
|
|
620
|
-
});
|
|
621
|
-
```
|
|
622
|
-
|
|
623
|
-
### 🔄 Persistent Context Management
|
|
624
|
-
|
|
625
|
-
For **multi-turn conversations** that persist across requests, use lifecycle hooks:
|
|
626
|
-
|
|
627
|
-
```typescript
|
|
628
|
-
import { Agent, type ContextLifecycleHooks } from "@falai/agent";
|
|
629
|
-
|
|
630
|
-
// Define persistence hooks
|
|
631
|
-
const hooks: ContextLifecycleHooks<MyContext> = {
|
|
632
|
-
// Load fresh context before each response
|
|
633
|
-
beforeRespond: async (currentContext) => {
|
|
634
|
-
return await database.loadContext(sessionId);
|
|
635
|
-
},
|
|
636
|
-
|
|
637
|
-
// Persist context after updates
|
|
638
|
-
onContextUpdate: async (newContext, previousContext) => {
|
|
639
|
-
await database.saveContext(sessionId, newContext);
|
|
640
|
-
},
|
|
641
|
-
};
|
|
642
|
-
|
|
643
|
-
const agent = new Agent({
|
|
644
|
-
name: "PersistentBot",
|
|
645
|
-
ai: provider,
|
|
646
|
-
context: initialContext,
|
|
647
|
-
hooks, // Enable automatic persistence
|
|
648
|
-
});
|
|
649
|
-
|
|
650
|
-
// Tools can update context
|
|
651
|
-
const saveTool = defineTool("save_data", async (ctx, data) => {
|
|
652
|
-
// Option 1: Return context update
|
|
653
|
-
return {
|
|
654
|
-
data: true,
|
|
655
|
-
contextUpdate: { savedData: data },
|
|
656
|
-
};
|
|
657
|
-
|
|
658
|
-
// Option 2: Call updateContext directly
|
|
659
|
-
// await ctx.updateContext({ savedData: data });
|
|
660
|
-
// return { data: true };
|
|
661
|
-
});
|
|
662
|
-
```
|
|
663
|
-
|
|
664
|
-
**Key patterns:**
|
|
665
|
-
|
|
666
|
-
- ✅ **Recreate agents** for each request (context loaded fresh via hooks)
|
|
667
|
-
- ✅ **Use `onContextUpdate`** to persist to database/cache
|
|
668
|
-
- ✅ **Use `beforeRespond`** to load fresh context before responding
|
|
669
|
-
- ❌ **Don't cache agent instances** across requests (context gets stale)
|
|
670
|
-
|
|
671
|
-
See [Context Management Guide](./docs/CONTEXT_MANAGEMENT.md) for complete patterns and best practices.
|
|
672
|
-
|
|
673
|
-
### 💾 Optional Database Persistence (NEW!)
|
|
674
|
-
|
|
675
|
-
For **production applications** that need to persist sessions and messages:
|
|
676
|
-
|
|
677
|
-
```typescript
|
|
678
|
-
import { Agent, PrismaAdapter } from "@falai/agent";
|
|
679
|
-
import { PrismaClient } from "@prisma/client";
|
|
680
|
-
|
|
681
|
-
const prisma = new PrismaClient();
|
|
682
|
-
|
|
683
|
-
const agent = new Agent({
|
|
684
|
-
name: "My Agent",
|
|
685
|
-
ai: provider,
|
|
686
|
-
// ✨ Just add this!
|
|
687
|
-
persistence: {
|
|
688
|
-
adapter: new PrismaAdapter({ prisma }),
|
|
689
|
-
autoSave: true,
|
|
690
|
-
userId: "user_123",
|
|
691
|
-
},
|
|
692
|
-
});
|
|
693
|
-
|
|
694
|
-
// Access persistence manager
|
|
695
|
-
const persistence = agent.getPersistenceManager();
|
|
696
|
-
|
|
697
|
-
// Create a session
|
|
698
|
-
const session = await persistence.createSession({
|
|
699
|
-
userId: "user_123",
|
|
700
|
-
agentName: "My Agent",
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
// Load history
|
|
704
|
-
const history = await persistence.loadSessionHistory(session.id);
|
|
705
|
-
|
|
706
|
-
// Generate response
|
|
707
|
-
const response = await agent.respond({ history });
|
|
708
|
-
|
|
709
|
-
// Optionally Save message (automatically saves if autoSave: true)
|
|
710
|
-
await persistence.saveMessage({
|
|
711
|
-
sessionId: session.id,
|
|
712
|
-
role: "agent",
|
|
713
|
-
content: response.message,
|
|
714
|
-
});
|
|
715
|
-
```
|
|
716
|
-
|
|
717
|
-
**Features:**
|
|
718
|
-
|
|
719
|
-
- ✅ **Provider Pattern** - Simple API like AI providers
|
|
720
|
-
- ✅ **Prisma Built-in** - Ready-to-use ORM adapter
|
|
721
|
-
- ✅ **Auto-save** - Automatic message tracking
|
|
722
|
-
- ✅ **Custom Adapters** - Create for any database (MongoDB, Redis, etc.)
|
|
723
|
-
- ✅ **Lifecycle Integration** - Works seamlessly with context hooks
|
|
724
|
-
|
|
725
|
-
**Setup (3 steps):**
|
|
726
|
-
|
|
727
|
-
1. Install: `npm install @prisma/client prisma`
|
|
728
|
-
2. Copy schema from `examples/prisma-schema.example.prisma`
|
|
729
|
-
3. Run: `npx prisma generate && npx prisma migrate dev`
|
|
730
|
-
|
|
731
|
-
See [Persistence Guide](./docs/PERSISTENCE.md) for complete documentation and custom adapter examples.
|
|
732
|
-
|
|
733
|
-
### 📖 Domain Glossary
|
|
734
|
-
|
|
735
|
-
Teach your agent business-specific language:
|
|
736
|
-
|
|
737
|
-
```typescript
|
|
738
|
-
agent
|
|
739
|
-
.createTerm({
|
|
740
|
-
name: "SLA",
|
|
741
|
-
description: "Service Level Agreement - our commitment to response times",
|
|
742
|
-
synonyms: ["service agreement", "support guarantee"],
|
|
743
|
-
})
|
|
744
|
-
.createTerm({
|
|
745
|
-
name: "Priority Support",
|
|
746
|
-
description: "Premium tier feature with <1hr response time",
|
|
747
|
-
synonyms: ["premium support", "fast track"],
|
|
748
|
-
});
|
|
749
|
-
```
|
|
750
|
-
|
|
751
|
-
### 🆔 Deterministic IDs & Persistence
|
|
752
|
-
|
|
753
|
-
All entities (routes, states, tools) have **deterministic IDs** by default, ensuring consistency across server restarts:
|
|
754
|
-
|
|
755
|
-
```typescript
|
|
756
|
-
import { generateRouteId, generateToolId } from "@falai/agent";
|
|
757
|
-
|
|
758
|
-
// Auto-generated deterministic IDs (recommended)
|
|
759
|
-
const route = agent.createRoute({
|
|
760
|
-
title: "User Onboarding",
|
|
761
|
-
// ID will be: route_user_onboarding_{hash}
|
|
762
|
-
});
|
|
763
|
-
|
|
764
|
-
// Or provide custom IDs when you need specific control
|
|
765
|
-
const route = agent.createRoute({
|
|
766
|
-
id: "my_custom_route_id", // Custom ID for database persistence
|
|
767
|
-
title: "User Onboarding",
|
|
768
|
-
});
|
|
769
|
-
|
|
770
|
-
// Generate IDs manually if needed
|
|
771
|
-
const routeId = generateRouteId("User Onboarding");
|
|
772
|
-
const toolId = generateToolId("fetch_user_data");
|
|
773
|
-
|
|
774
|
-
// Custom timestamps for events (useful for historical data)
|
|
775
|
-
const event = createMessageEvent(
|
|
776
|
-
EventSource.CUSTOMER,
|
|
777
|
-
"Alice",
|
|
778
|
-
"Hello!",
|
|
779
|
-
"2025-10-13T10:30:00Z" // Optional: custom timestamp
|
|
780
|
-
);
|
|
781
|
-
```
|
|
782
|
-
|
|
783
|
-
**Why this matters:**
|
|
784
|
-
|
|
785
|
-
- ✅ **Database Safe** - Store IDs in your database without worrying about changes
|
|
786
|
-
- ✅ **Analytics Ready** - Track metrics and user journeys reliably
|
|
787
|
-
- ✅ **Multi-Instance** - Deploy multiple server instances with consistent IDs
|
|
788
|
-
- ✅ **Migration Friendly** - IDs remain stable during deployments
|
|
789
|
-
|
|
790
|
-
### ⚙️ Advanced Configuration
|
|
791
|
-
|
|
792
|
-
Fine-tune AI provider behavior - works with all providers:
|
|
793
|
-
|
|
794
|
-
```typescript
|
|
795
|
-
// Anthropic (Claude) configuration
|
|
796
|
-
const anthropicProvider = new AnthropicProvider({
|
|
797
|
-
apiKey: process.env.ANTHROPIC_API_KEY!,
|
|
798
|
-
model: "claude-sonnet-4-5", // Primary model
|
|
799
|
-
backupModels: [
|
|
800
|
-
"claude-opus-4-1", // Backup if primary fails
|
|
801
|
-
"claude-sonnet-4-0", // Stable fallback
|
|
802
|
-
],
|
|
803
|
-
config: {
|
|
804
|
-
temperature: 0.7,
|
|
805
|
-
top_p: 0.9,
|
|
806
|
-
},
|
|
807
|
-
retryConfig: {
|
|
808
|
-
timeout: 60000, // 60s timeout
|
|
809
|
-
retries: 3, // 3 attempts with exponential backoff
|
|
810
|
-
},
|
|
811
|
-
});
|
|
812
|
-
|
|
813
|
-
// Gemini configuration
|
|
814
|
-
const geminiProvider = new GeminiProvider({
|
|
815
|
-
apiKey: process.env.GEMINI_API_KEY!,
|
|
816
|
-
model: "models/gemini-2.5-flash", // Primary model
|
|
817
|
-
backupModels: [
|
|
818
|
-
"models/gemini-2.5-pro", // Backup if primary fails
|
|
819
|
-
"models/gemini-2.0-flash",
|
|
820
|
-
],
|
|
821
|
-
retryConfig: {
|
|
822
|
-
timeout: 60000,
|
|
823
|
-
retries: 3,
|
|
824
|
-
},
|
|
825
|
-
});
|
|
826
|
-
|
|
827
|
-
// OpenAI configuration
|
|
828
|
-
const openaiProvider = new OpenAIProvider({
|
|
829
|
-
apiKey: process.env.OPENAI_API_KEY!,
|
|
830
|
-
model: "gpt-5",
|
|
831
|
-
backupModels: ["gpt-5-mini", "gpt-5-nano"],
|
|
832
|
-
retryConfig: {
|
|
833
|
-
timeout: 60000,
|
|
834
|
-
retries: 3,
|
|
835
|
-
},
|
|
836
|
-
});
|
|
837
|
-
|
|
838
|
-
// OpenRouter configuration (access to 200+ models)
|
|
839
|
-
const openrouterProvider = new OpenRouterProvider({
|
|
840
|
-
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
841
|
-
model: "anthropic/claude-sonnet-4-5",
|
|
842
|
-
backupModels: ["openai/gpt-5", "google/gemini-2.5-flash"],
|
|
843
|
-
siteUrl: "https://yourapp.com",
|
|
844
|
-
siteName: "Your App Name",
|
|
845
|
-
retryConfig: {
|
|
846
|
-
timeout: 60000,
|
|
847
|
-
retries: 3,
|
|
848
|
-
},
|
|
849
|
-
});
|
|
850
|
-
```
|
|
246
|
+
**Feature Guides:**
|
|
247
|
+
- 💾 **[Persistence](./docs/PERSISTENCE.md)** - Database integration with adapters
|
|
248
|
+
- 🔒 **[Domains](./docs/DOMAINS.md)** - Optional tool security & organization
|
|
249
|
+
- 🎛️ **[Constructor Options](./docs/CONSTRUCTOR_OPTIONS.md)** - Configuration patterns
|
|
250
|
+
- 📊 **[Context Management](./docs/CONTEXT_MANAGEMENT.md)** - Session state & lifecycle hooks
|
|
251
|
+
- 🤖 **[AI Providers](./docs/PROVIDERS.md)** - Anthropic, OpenAI, Gemini, OpenRouter
|
|
851
252
|
|
|
852
253
|
---
|
|
853
254
|
|
|
854
255
|
## 🎯 Examples
|
|
855
256
|
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
**
|
|
859
|
-
|
|
860
|
-
-
|
|
861
|
-
-
|
|
862
|
-
- ➕ Dynamic additions after construction
|
|
863
|
-
|
|
864
|
-
### ⚡ [Streaming Responses](./examples/streaming-agent.ts) **(NEW!)**
|
|
865
|
-
|
|
866
|
-
**Real-time streaming responses for better UX:**
|
|
867
|
-
|
|
868
|
-
- 🌊 Stream responses from all providers (Anthropic, OpenAI, Gemini, OpenRouter)
|
|
869
|
-
- 📡 Real-time text generation with `respondStream`
|
|
870
|
-
- 🛑 Cancellable streams with AbortSignal
|
|
871
|
-
- 📊 Access route, state, and tool information
|
|
872
|
-
- 🎯 5 comprehensive examples covering different use cases
|
|
873
|
-
|
|
874
|
-
### 💾 [Persistent Onboarding Agent](./examples/persistent-onboarding.ts)
|
|
875
|
-
|
|
876
|
-
**Multi-turn conversation with state persistence:**
|
|
877
|
-
|
|
878
|
-
- 🔄 Context lifecycle hooks for database integration
|
|
879
|
-
- 💾 Automatic persistence on context updates
|
|
880
|
-
- 🏭 Factory pattern for agent creation
|
|
881
|
-
- 🔧 Two approaches: lifecycle hooks vs context provider
|
|
882
|
-
- 📝 Complete onboarding flow across multiple turns
|
|
883
|
-
|
|
884
|
-
### 💾 [Prisma Persistence](./examples/prisma-persistence.ts) **(NEW!)**
|
|
885
|
-
|
|
886
|
-
**Production-ready database persistence:**
|
|
887
|
-
|
|
888
|
-
- ✨ Provider pattern - simple as `new PrismaAdapter({ prisma })`
|
|
889
|
-
- 🗄️ Automatic session and message persistence
|
|
890
|
-
- 🔄 Seamless lifecycle hook integration
|
|
891
|
-
- 📊 Complete examples: basic, advanced, and minimal
|
|
892
|
-
- 🎯 3-step setup with Prisma ORM
|
|
893
|
-
|
|
894
|
-
### 🏢 [Business Onboarding](./examples/business-onboarding.ts)
|
|
895
|
-
|
|
896
|
-
**Production-ready business onboarding with advanced patterns:**
|
|
897
|
-
|
|
898
|
-
- 🎯 Real-world multi-step business setup flow
|
|
899
|
-
- 🔀 Complex branching logic (physical vs online business)
|
|
900
|
-
- 🔄 Tools with `contextUpdate` for automatic state management
|
|
901
|
-
- 🔗 Both step-by-step and fluent chaining approaches
|
|
902
|
-
- 🎨 Lifecycle hooks for agent caching and persistence
|
|
903
|
-
- 📊 Dynamic route creation based on collected data
|
|
904
|
-
|
|
905
|
-
### 🌍 [Travel Booking Agent](./examples/travel-agent.ts)
|
|
906
|
-
|
|
907
|
-
A complete travel agent implementation featuring:
|
|
908
|
-
|
|
909
|
-
- ✈️ Multi-step flight booking flow
|
|
910
|
-
- 🔄 Alternative options handling
|
|
911
|
-
- 🛠️ Real-world tool integration
|
|
912
|
-
- 📋 Status checking route
|
|
913
|
-
- 🎭 Edge case guidelines
|
|
914
|
-
|
|
915
|
-
### 🏥 [Healthcare Assistant](./examples/healthcare-agent.ts)
|
|
916
|
-
|
|
917
|
-
Healthcare-focused agent demonstrating:
|
|
918
|
-
|
|
919
|
-
- 🩺 Appointment scheduling with alternatives
|
|
920
|
-
- 🔬 Lab results retrieval
|
|
921
|
-
- 🤔 Route-based disambiguation with conditions
|
|
922
|
-
- 🔐 Sensitive data handling
|
|
923
|
-
- ⚠️ Urgent case prioritization
|
|
924
|
-
|
|
925
|
-
### 🌐 Multiple Provider Examples
|
|
926
|
-
|
|
927
|
-
See how different AI providers work:
|
|
928
|
-
|
|
929
|
-
- **[OpenAI Agent](./examples/openai-agent.ts)** - GPT-5 integration
|
|
930
|
-
- **[Healthcare Agent](./examples/healthcare-agent.ts)** - Claude 3.5 Sonnet
|
|
931
|
-
- **[Travel Agent](./examples/travel-agent.ts)** - OpenRouter with backup models
|
|
932
|
-
- 🔄 All with backup model configuration and retry settings
|
|
933
|
-
- 🌤️ Weather checking example
|
|
934
|
-
|
|
935
|
-
### 🔐 [Domain Scoping](./examples/domain-scoping.ts)
|
|
936
|
-
|
|
937
|
-
Control tool access per route for security and clarity:
|
|
938
|
-
|
|
939
|
-
- 🔒 Restrict which tools are available in each route
|
|
940
|
-
- 🎯 Prevent unauthorized tool calls
|
|
941
|
-
- ⚡ Improve AI performance by reducing decision space
|
|
942
|
-
- 📋 Clear documentation of route capabilities
|
|
943
|
-
|
|
944
|
-
### 📜 [Rules & Prohibitions](./examples/rules-prohibitions.ts)
|
|
945
|
-
|
|
946
|
-
Control agent behavior and communication style per route:
|
|
947
|
-
|
|
948
|
-
- ✅ Define absolute rules the agent must follow
|
|
949
|
-
- ❌ Set prohibitions for what agent must never do
|
|
950
|
-
- 💬 Different communication styles per route
|
|
951
|
-
- 🎨 Perfect for multi-channel bots (WhatsApp, email, chat)
|
|
257
|
+
**Core Examples:**
|
|
258
|
+
- 🏢 **[Business Onboarding](./examples/business-onboarding.ts)** - Complex multi-step flow with branching
|
|
259
|
+
- ✈️ **[Travel Agent](./examples/travel-agent.ts)** - Multi-route booking system with session state
|
|
260
|
+
- 🏥 **[Healthcare Assistant](./examples/healthcare-agent.ts)** - Appointment scheduling & lab results
|
|
261
|
+
- 📋 **[Declarative Agent](./examples/declarative-agent.ts)** - Full constructor-based configuration
|
|
262
|
+
- ⚡ **[Streaming Responses](./examples/streaming-agent.ts)** - Real-time response streaming
|
|
952
263
|
|
|
953
|
-
|
|
264
|
+
**Persistence & Advanced:**
|
|
265
|
+
- 💾 **[Prisma Persistence](./examples/prisma-persistence.ts)** - Auto-save with Prisma ORM
|
|
266
|
+
- ⚡ **[Redis Persistence](./examples/redis-persistence.ts)** - Fast in-memory sessions
|
|
267
|
+
- 🔐 **[Domain Scoping](./examples/domain-scoping.ts)** - Tool security per route
|
|
268
|
+
- 📜 **[Rules & Prohibitions](./examples/rules-prohibitions.ts)** - Fine-grained behavior control
|
|
954
269
|
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
- 💾 Auto-save sessions and messages to database
|
|
958
|
-
- 🔄 Load conversation history on agent initialization
|
|
959
|
-
- 📊 Track conversation state across restarts
|
|
960
|
-
- 🎯 Full example with lifecycle hooks
|
|
961
|
-
- 📝 Includes schema example
|
|
962
|
-
|
|
963
|
-
### ⚡ [Redis Persistence](./examples/redis-persistence.ts)
|
|
964
|
-
|
|
965
|
-
Fast, in-memory persistence for high-throughput applications:
|
|
966
|
-
|
|
967
|
-
- 🚀 Lightning-fast session storage
|
|
968
|
-
- ⏰ Configurable TTLs for auto-cleanup
|
|
969
|
-
- 🔑 Custom key prefixes
|
|
970
|
-
- 💨 Perfect for real-time chat applications
|
|
971
|
-
|
|
972
|
-
### 🔍 [OpenSearch Persistence](./examples/opensearch-persistence.ts)
|
|
973
|
-
|
|
974
|
-
Full-text search and analytics-powered persistence:
|
|
975
|
-
|
|
976
|
-
- 🔍 Built-in full-text search across all messages
|
|
977
|
-
- 📊 Powerful aggregations and analytics
|
|
978
|
-
- 🌐 Compatible with Elasticsearch 7.x
|
|
979
|
-
- ☁️ AWS OpenSearch Service ready
|
|
980
|
-
|
|
981
|
-
### 🗄️ [Custom Database Integration](./examples/custom-database-persistence.ts)
|
|
982
|
-
|
|
983
|
-
Manual session state management for existing database schemas:
|
|
984
|
-
|
|
985
|
-
- 🔧 Full control over database operations
|
|
986
|
-
- 📦 Works with any database (no adapter needed)
|
|
987
|
-
- 🔄 Manual session state save/restore
|
|
988
|
-
- 🎯 Perfect for integrating with existing schemas
|
|
989
|
-
- ✅ Complete example with validation hooks
|
|
270
|
+
📖 **[See all examples with descriptions →](./docs/EXAMPLES.md)**
|
|
990
271
|
|
|
991
272
|
---
|
|
992
273
|
|
|
993
|
-
##
|
|
994
|
-
|
|
995
|
-
**Optional persistence** - Choose the database that fits your needs. All adapters follow the same simple provider pattern:
|
|
274
|
+
## 🏗️ How It Works
|
|
996
275
|
|
|
997
|
-
|
|
276
|
+
`@falai/agent` uses a **state machine-driven architecture** where conversations flow through explicit states:
|
|
998
277
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
| **PostgreSQLAdapter** | Raw SQL with auto table creation | `npm install pg` |
|
|
1005
|
-
| **SQLiteAdapter** | Lightweight local database | `npm install better-sqlite3` |
|
|
1006
|
-
| **OpenSearchAdapter** | Full-text search & analytics | `npm install @opensearch-project/opensearch` |
|
|
1007
|
-
| **MemoryAdapter** | Testing & development (no install) | Built-in (no dependencies) ✨ |
|
|
278
|
+
1. **Router** - AI selects the best route based on conversation context
|
|
279
|
+
2. **State Machine** - Routes define explicit states and transitions
|
|
280
|
+
3. **Data Extraction** - JSON Schema defines data to extract during conversation
|
|
281
|
+
4. **Tool Execution** - Tools run automatically when state conditions match
|
|
282
|
+
5. **Message Generation** - AI generates natural responses based on current state
|
|
1008
283
|
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
284
|
+
**Behind the scenes:**
|
|
285
|
+
- The AI only generates messages and extracts data - it never decides which tools to call
|
|
286
|
+
- Tools execute deterministically based on state transitions and code-based conditions
|
|
287
|
+
- Session state tracks progress and extracted data across conversation turns
|
|
288
|
+
- Always-on routing lets users change direction mid-conversation
|
|
1014
289
|
|
|
1015
|
-
|
|
290
|
+
This creates **predictable, testable agents** perfect for production use cases.
|
|
1016
291
|
|
|
1017
|
-
|
|
1018
|
-
name: "My Agent",
|
|
1019
|
-
ai: provider,
|
|
1020
|
-
persistence: {
|
|
1021
|
-
adapter: new PrismaAdapter({ prisma }),
|
|
1022
|
-
userId: "user_123",
|
|
1023
|
-
autoSave: true, // Automatically save all messages
|
|
1024
|
-
},
|
|
1025
|
-
});
|
|
1026
|
-
```
|
|
1027
|
-
|
|
1028
|
-
That's it! Sessions and messages are now automatically persisted.
|
|
1029
|
-
|
|
1030
|
-
### 📚 Full Documentation
|
|
1031
|
-
|
|
1032
|
-
See [**docs/PERSISTENCE.md**](./docs/PERSISTENCE.md) for:
|
|
1033
|
-
|
|
1034
|
-
- Complete adapter API reference
|
|
1035
|
-
- Custom table names & field mappings
|
|
1036
|
-
- Lifecycle hooks for persistence
|
|
1037
|
-
- Creating custom adapters
|
|
1038
|
-
- Migration guides
|
|
1039
|
-
|
|
1040
|
-
See [**docs/ADAPTERS.md**](./docs/ADAPTERS.md) for:
|
|
1041
|
-
|
|
1042
|
-
- Detailed adapter comparison
|
|
1043
|
-
- Configuration examples for each database
|
|
1044
|
-
- Performance characteristics
|
|
1045
|
-
- Type safety guarantees
|
|
1046
|
-
|
|
1047
|
-
---
|
|
1048
|
-
|
|
1049
|
-
## 🏗️ Architecture
|
|
1050
|
-
|
|
1051
|
-
```
|
|
1052
|
-
src/
|
|
1053
|
-
├── types/ # Type definitions (strongly typed contracts)
|
|
1054
|
-
├── core/ # Core framework (Agent, Route, State, Tools, etc.)
|
|
1055
|
-
├── providers/ # AI providers (Anthropic, Gemini, OpenAI, OpenRouter)
|
|
1056
|
-
├── utils/ # Utilities (retry, timeout, helpers)
|
|
1057
|
-
├── constants/ # Constants (END_ROUTE, symbols)
|
|
1058
|
-
└── index.ts # Public API exports
|
|
1059
|
-
```
|
|
1060
|
-
|
|
1061
|
-
**Design Principles:**
|
|
1062
|
-
|
|
1063
|
-
- **Modularity** - Clean separation of concerns
|
|
1064
|
-
- **Type Safety** - TypeScript generics throughout
|
|
1065
|
-
- **Extensibility** - Pluggable providers & tools
|
|
1066
|
-
- **Developer Experience** - Fluent APIs & clear patterns
|
|
292
|
+
📖 **[Read the full architecture guide →](./docs/ARCHITECTURE.md)**
|
|
1067
293
|
|
|
1068
294
|
---
|
|
1069
295
|
|