@falai/agent 0.5.5 → 0.6.1

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.
Files changed (59) hide show
  1. package/README.md +88 -864
  2. package/dist/cjs/core/ResponseEngine.js +2 -2
  3. package/dist/cjs/core/ResponseEngine.js.map +1 -1
  4. package/dist/cjs/core/Route.d.ts +6 -1
  5. package/dist/cjs/core/Route.d.ts.map +1 -1
  6. package/dist/cjs/core/Route.js +19 -1
  7. package/dist/cjs/core/Route.js.map +1 -1
  8. package/dist/cjs/core/State.d.ts +1 -2
  9. package/dist/cjs/core/State.d.ts.map +1 -1
  10. package/dist/cjs/core/State.js +5 -6
  11. package/dist/cjs/core/State.js.map +1 -1
  12. package/dist/cjs/core/Transition.d.ts +2 -2
  13. package/dist/cjs/core/Transition.d.ts.map +1 -1
  14. package/dist/cjs/core/Transition.js +3 -2
  15. package/dist/cjs/core/Transition.js.map +1 -1
  16. package/dist/cjs/types/route.d.ts +15 -4
  17. package/dist/cjs/types/route.d.ts.map +1 -1
  18. package/dist/core/ResponseEngine.js +2 -2
  19. package/dist/core/ResponseEngine.js.map +1 -1
  20. package/dist/core/Route.d.ts +6 -1
  21. package/dist/core/Route.d.ts.map +1 -1
  22. package/dist/core/Route.js +19 -1
  23. package/dist/core/Route.js.map +1 -1
  24. package/dist/core/State.d.ts +1 -2
  25. package/dist/core/State.d.ts.map +1 -1
  26. package/dist/core/State.js +5 -6
  27. package/dist/core/State.js.map +1 -1
  28. package/dist/core/Transition.d.ts +2 -2
  29. package/dist/core/Transition.d.ts.map +1 -1
  30. package/dist/core/Transition.js +3 -2
  31. package/dist/core/Transition.js.map +1 -1
  32. package/dist/types/route.d.ts +15 -4
  33. package/dist/types/route.d.ts.map +1 -1
  34. package/docs/ADAPTERS.md +13 -1
  35. package/docs/API_REFERENCE.md +22 -25
  36. package/docs/ARCHITECTURE.md +18 -22
  37. package/docs/CONSTRUCTOR_OPTIONS.md +2 -2
  38. package/docs/CONTEXT_MANAGEMENT.md +1 -1
  39. package/docs/EXAMPLES.md +419 -0
  40. package/docs/GETTING_STARTED.md +1 -1
  41. package/docs/PERSISTENCE.md +3 -3
  42. package/examples/business-onboarding.ts +88 -70
  43. package/examples/company-qna-agent.ts +4 -4
  44. package/examples/custom-database-persistence.ts +2 -2
  45. package/examples/declarative-agent.ts +3 -3
  46. package/examples/extracted-data-modification.ts +1 -1
  47. package/examples/healthcare-agent.ts +24 -30
  48. package/examples/openai-agent.ts +1 -1
  49. package/examples/opensearch-persistence.ts +2 -2
  50. package/examples/persistent-onboarding.ts +2 -2
  51. package/examples/prisma-persistence.ts +3 -3
  52. package/examples/redis-persistence.ts +3 -3
  53. package/examples/travel-agent.ts +73 -96
  54. package/package.json +1 -1
  55. package/src/core/ResponseEngine.ts +2 -2
  56. package/src/core/Route.ts +34 -3
  57. package/src/core/State.ts +6 -13
  58. package/src/core/Transition.ts +6 -3
  59. package/src/types/route.ts +15 -5
package/README.md CHANGED
@@ -140,930 +140,154 @@ yarn add @falai/agent
140
140
 
141
141
  ## 🚀 Quick Start
142
142
 
143
- Get up and running in 60 seconds:
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
- OpenAIProvider,
151
- OpenRouterProvider,
149
+ defineTool,
152
150
  createMessageEvent,
153
151
  EventSource,
154
152
  } from "@falai/agent";
155
153
 
156
- // 1️⃣ Define your custom context
157
- interface SupportContext {
158
- userId: string;
159
- userName: string;
160
- tier: "free" | "premium";
161
- }
162
-
163
- // 2️⃣ Create AI provider (choose one)
164
- const ai = new AnthropicProvider({
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
- // Or use other providers:
170
- // const ai = new GeminiProvider({
171
- // apiKey: process.env.GEMINI_API_KEY!,
172
- // model: "models/gemini-2.5-flash",
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
- // Initialize with arrays
199
- terms: [
200
- {
201
- name: "Premium Support",
202
- description: "24/7 priority support with dedicated account manager",
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
- // Option B: Fluent chaining (great for dynamic additions)
222
- agent
223
- .createGuideline({
224
- condition: "Customer is frustrated",
225
- action: "Show extra empathy and offer immediate escalation",
226
- tags: ["support", "escalation"],
227
- })
228
- .createTerm({
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
- "Alex",
239
- "I can't access my dashboard"
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-powered response ready!
198
+ console.log(response.message); // 🎉 AI handles the rest!
245
199
  ```
246
200
 
247
- ### Streaming Responses (NEW!)
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
- Stream AI responses in real-time for better user experience:
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
- **Benefits:**
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
- const agent = new Agent({ name: "My Agent", ai: provider });
287
-
288
- // Define tools normally
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
- ### With Domains (Security & Organization)
300
-
224
+ **Database persistence** with any adapter:
301
225
  ```typescript
302
- // Organize tools into security domains
303
- agent.addDomain("user", {
304
- saveName: async (name) => {
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
- **When to use domains:**
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
- ### 📖 Guides
346
-
347
- - **[Architecture](./docs/ARCHITECTURE.md)** - Design principles & philosophy
348
- - **[Getting Started](./docs/GETTING_STARTED.md)** - Your first agent in 5 minutes
349
- - **[Constructor Options](./docs/CONSTRUCTOR_OPTIONS.md)** - Declarative vs Fluent API patterns
350
- - **[Context Management](./docs/CONTEXT_MANAGEMENT.md)** - Persistent conversations & state management
351
- - **[Persistence](./docs/PERSISTENCE.md)** - Optional database persistence with Prisma **(NEW!)**
352
- - **[API Reference](./docs/API_REFERENCE.md)** - Complete API documentation
353
-
354
- ### 💡 Key Concepts
355
-
356
- ### 💬 Working with Conversation History
357
-
358
- Build rich conversation contexts:
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.
238
+ **Core Guides:**
239
+ - 📘 **[Getting Started](./docs/GETTING_STARTED.md)** - Build your first agent in 5 minutes
240
+ - 🏗️ **[Architecture](./docs/ARCHITECTURE.md)** - Design principles & philosophy
241
+ - 🔧 **[API Reference](./docs/API_REFERENCE.md)** - Complete API documentation
242
+ - 📝 **[Examples](./docs/EXAMPLES.md)** - Production-ready code examples
732
243
 
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
- ```
244
+ **Feature Guides:**
245
+ - 💾 **[Persistence](./docs/PERSISTENCE.md)** - Database integration with adapters
246
+ - 🔒 **[Domains](./docs/DOMAINS.md)** - Optional tool security & organization
247
+ - 🎛️ **[Constructor Options](./docs/CONSTRUCTOR_OPTIONS.md)** - Configuration patterns
248
+ - 📊 **[Context Management](./docs/CONTEXT_MANAGEMENT.md)** - Session state & lifecycle hooks
249
+ - 🤖 **[AI Providers](./docs/PROVIDERS.md)** - Anthropic, OpenAI, Gemini, OpenRouter
851
250
 
852
251
  ---
853
252
 
854
253
  ## 🎯 Examples
855
254
 
856
- ### 📋 [Declarative Agent](./examples/declarative-agent.ts)
857
-
858
- **Comprehensive declarative configuration example:**
859
-
860
- - 📦 Everything configured in constructor
861
- - 📚 Terms, guidelines, capabilities, routes
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)
255
+ **Core Examples:**
256
+ - 🏢 **[Business Onboarding](./examples/business-onboarding.ts)** - Complex multi-step flow with branching
257
+ - ✈️ **[Travel Agent](./examples/travel-agent.ts)** - Multi-route booking system with session state
258
+ - 🏥 **[Healthcare Assistant](./examples/healthcare-agent.ts)** - Appointment scheduling & lab results
259
+ - 📋 **[Declarative Agent](./examples/declarative-agent.ts)** - Full constructor-based configuration
260
+ - **[Streaming Responses](./examples/streaming-agent.ts)** - Real-time response streaming
952
261
 
953
- ### 💾 [Prisma Persistence](./examples/prisma-persistence.ts)
262
+ **Persistence & Advanced:**
263
+ - 💾 **[Prisma Persistence](./examples/prisma-persistence.ts)** - Auto-save with Prisma ORM
264
+ - ⚡ **[Redis Persistence](./examples/redis-persistence.ts)** - Fast in-memory sessions
265
+ - 🔐 **[Domain Scoping](./examples/domain-scoping.ts)** - Tool security per route
266
+ - 📜 **[Rules & Prohibitions](./examples/rules-prohibitions.ts)** - Fine-grained behavior control
954
267
 
955
- Complete example of auto-saving sessions and messages with Prisma ORM:
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
268
+ 📖 **[See all examples with descriptions →](./docs/EXAMPLES.md)**
990
269
 
991
270
  ---
992
271
 
993
- ## 💾 Database Adapters
994
-
995
- **Optional persistence** - Choose the database that fits your needs. All adapters follow the same simple provider pattern:
272
+ ## 🏗️ How It Works
996
273
 
997
- ### 🎯 Available Adapters
274
+ `@falai/agent` uses a **state machine-driven architecture** where conversations flow through explicit states:
998
275
 
999
- | Adapter | Use Case | Install |
1000
- | --------------------- | ---------------------------------- | -------------------------------------------- |
1001
- | **PrismaAdapter** | Type-safe ORM with migrations | `npm install @prisma/client` |
1002
- | **RedisAdapter** | Fast in-memory for real-time apps | `npm install ioredis` |
1003
- | **MongoAdapter** | Flexible document storage | `npm install mongodb` |
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) ✨ |
276
+ 1. **Router** - AI selects the best route based on conversation context
277
+ 2. **State Machine** - Routes define explicit states and transitions
278
+ 3. **Data Extraction** - JSON Schema defines data to extract during conversation
279
+ 4. **Tool Execution** - Tools run automatically when state conditions match
280
+ 5. **Message Generation** - AI generates natural responses based on current state
1008
281
 
1009
- ### Quick Setup
1010
-
1011
- ```typescript
1012
- import { Agent, PrismaAdapter } from "@falai/agent";
1013
- import { PrismaClient } from "@prisma/client";
282
+ **Behind the scenes:**
283
+ - The AI only generates messages and extracts data - it never decides which tools to call
284
+ - Tools execute deterministically based on state transitions and code-based conditions
285
+ - Session state tracks progress and extracted data across conversation turns
286
+ - Always-on routing lets users change direction mid-conversation
1014
287
 
1015
- const prisma = new PrismaClient();
288
+ This creates **predictable, testable agents** perfect for production use cases.
1016
289
 
1017
- const agent = new Agent({
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
290
+ 📖 **[Read the full architecture guide →](./docs/ARCHITECTURE.md)**
1067
291
 
1068
292
  ---
1069
293