@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.
- package/README.md +88 -864
- package/dist/cjs/core/ResponseEngine.js +2 -2
- package/dist/cjs/core/ResponseEngine.js.map +1 -1
- package/dist/cjs/core/Route.d.ts +6 -1
- package/dist/cjs/core/Route.d.ts.map +1 -1
- package/dist/cjs/core/Route.js +19 -1
- package/dist/cjs/core/Route.js.map +1 -1
- package/dist/cjs/core/State.d.ts +1 -2
- package/dist/cjs/core/State.d.ts.map +1 -1
- package/dist/cjs/core/State.js +5 -6
- package/dist/cjs/core/State.js.map +1 -1
- package/dist/cjs/core/Transition.d.ts +2 -2
- package/dist/cjs/core/Transition.d.ts.map +1 -1
- package/dist/cjs/core/Transition.js +3 -2
- package/dist/cjs/core/Transition.js.map +1 -1
- package/dist/cjs/types/route.d.ts +15 -4
- package/dist/cjs/types/route.d.ts.map +1 -1
- package/dist/core/ResponseEngine.js +2 -2
- package/dist/core/ResponseEngine.js.map +1 -1
- package/dist/core/Route.d.ts +6 -1
- package/dist/core/Route.d.ts.map +1 -1
- package/dist/core/Route.js +19 -1
- package/dist/core/Route.js.map +1 -1
- package/dist/core/State.d.ts +1 -2
- package/dist/core/State.d.ts.map +1 -1
- package/dist/core/State.js +5 -6
- package/dist/core/State.js.map +1 -1
- package/dist/core/Transition.d.ts +2 -2
- package/dist/core/Transition.d.ts.map +1 -1
- package/dist/core/Transition.js +3 -2
- package/dist/core/Transition.js.map +1 -1
- package/dist/types/route.d.ts +15 -4
- package/dist/types/route.d.ts.map +1 -1
- package/docs/ADAPTERS.md +13 -1
- package/docs/API_REFERENCE.md +22 -25
- package/docs/ARCHITECTURE.md +18 -22
- package/docs/CONSTRUCTOR_OPTIONS.md +2 -2
- package/docs/CONTEXT_MANAGEMENT.md +1 -1
- package/docs/EXAMPLES.md +419 -0
- package/docs/GETTING_STARTED.md +1 -1
- package/docs/PERSISTENCE.md +3 -3
- package/examples/business-onboarding.ts +88 -70
- package/examples/company-qna-agent.ts +4 -4
- package/examples/custom-database-persistence.ts +2 -2
- package/examples/declarative-agent.ts +3 -3
- package/examples/extracted-data-modification.ts +1 -1
- package/examples/healthcare-agent.ts +24 -30
- package/examples/openai-agent.ts +1 -1
- package/examples/opensearch-persistence.ts +2 -2
- package/examples/persistent-onboarding.ts +2 -2
- package/examples/prisma-persistence.ts +3 -3
- package/examples/redis-persistence.ts +3 -3
- package/examples/travel-agent.ts +73 -96
- package/package.json +1 -1
- package/src/core/ResponseEngine.ts +2 -2
- package/src/core/Route.ts +34 -3
- package/src/core/State.ts +6 -13
- package/src/core/Transition.ts +6 -3
- package/src/types/route.ts +15 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../src/types/route.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,UAAU,GAAG,OAAO;IAChD,qGAAqG;IACrG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,wCAAwC;IACxC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,gBAAgB,CAAC;IACvC,6EAA6E;IAC7E,oBAAoB,CAAC,EAAE,gBAAgB,CAAC;IACxC;;;OAGG;IACH,
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../src/types/route.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,UAAU,GAAG,OAAO;IAChD,qGAAqG;IACrG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,wCAAwC;IACxC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,gBAAgB,CAAC;IACvC,6EAA6E;IAC7E,oBAAoB,CAAC,EAAE,gBAAgB,CAAC;IACxC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAClC;;;;OAIG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,QAAQ,GAAG,OAAO,EAAE,UAAU,GAAG,OAAO;IACtE,2FAA2F;IAC3F,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IAEnC,SAAS,CAAC,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;IAC1C,mDAAmD;IACnD,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC;IACrD;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB,CAAC,QAAQ,GAAG,OAAO,EAAE,UAAU,GAAG,OAAO,CACxE,SAAQ,QAAQ;IAChB,iCAAiC;IACjC,YAAY,EAAE,CACZ,IAAI,EAAE,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC,KACvC,gBAAgB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;CAC7C"}
|
package/docs/ADAPTERS.md
CHANGED
|
@@ -4,6 +4,18 @@ All adapters follow the **provider pattern** - no dependencies required in the p
|
|
|
4
4
|
|
|
5
5
|
**NEW**: All adapters now support the new **Session State** pattern with automatic persistence of extracted data, current route/state, and conversation progress!
|
|
6
6
|
|
|
7
|
+
### 🎯 Available Adapters
|
|
8
|
+
|
|
9
|
+
| Adapter | Use Case | Install |
|
|
10
|
+
| --------------------- | ---------------------------------- | -------------------------------------------- |
|
|
11
|
+
| **PrismaAdapter** | Type-safe ORM with migrations | `npm install @prisma/client` |
|
|
12
|
+
| **RedisAdapter** | Fast in-memory for real-time apps | `npm install ioredis` |
|
|
13
|
+
| **MongoAdapter** | Flexible document storage | `npm install mongodb` |
|
|
14
|
+
| **PostgreSQLAdapter** | Raw SQL with auto table creation | `npm install pg` |
|
|
15
|
+
| **SQLiteAdapter** | Lightweight local database | `npm install better-sqlite3` |
|
|
16
|
+
| **OpenSearchAdapter** | Full-text search & analytics | `npm install @opensearch-project/opensearch` |
|
|
17
|
+
| **MemoryAdapter** | Testing & development (no install) | Built-in (no dependencies) ✨ |
|
|
18
|
+
|
|
7
19
|
## ✅ Implemented Adapters
|
|
8
20
|
|
|
9
21
|
### 1. **PrismaAdapter**
|
|
@@ -102,7 +114,7 @@ const agent = new Agent({
|
|
|
102
114
|
// Create a route with data extraction
|
|
103
115
|
const route = agent.createRoute<YourDataType>({
|
|
104
116
|
title: "My Route",
|
|
105
|
-
|
|
117
|
+
extractionSchema: {
|
|
106
118
|
type: "object",
|
|
107
119
|
properties: {
|
|
108
120
|
field1: { type: "string" },
|
package/docs/API_REFERENCE.md
CHANGED
|
@@ -321,7 +321,7 @@ interface RouteOptions<TExtracted = unknown> {
|
|
|
321
321
|
prohibitions?: string[]; // Absolute prohibitions the agent MUST NEVER do in this route
|
|
322
322
|
|
|
323
323
|
// NEW: Schema-first data extraction
|
|
324
|
-
|
|
324
|
+
extractionSchema?: {
|
|
325
325
|
type: "object";
|
|
326
326
|
properties: Record<string, any>;
|
|
327
327
|
required?: string[];
|
|
@@ -395,7 +395,7 @@ Represents a state within a conversation route.
|
|
|
395
395
|
|
|
396
396
|
#### Methods
|
|
397
397
|
|
|
398
|
-
##### `transitionTo(spec: TransitionSpec
|
|
398
|
+
##### `transitionTo(spec: TransitionSpec): TransitionResult`
|
|
399
399
|
|
|
400
400
|
Creates a transition from this state and returns a chainable result.
|
|
401
401
|
|
|
@@ -413,22 +413,23 @@ interface TransitionSpec<TExtracted = unknown> {
|
|
|
413
413
|
|
|
414
414
|
// NEW: Prerequisites that must be met to enter this state
|
|
415
415
|
requiredData?: string[];
|
|
416
|
+
|
|
417
|
+
// Optional: AI-evaluated text condition for this transition
|
|
418
|
+
condition?: string;
|
|
416
419
|
}
|
|
417
420
|
|
|
418
421
|
interface TransitionResult<TExtracted = unknown> {
|
|
419
422
|
id: string; // State identifier
|
|
420
423
|
routeId: string; // Route identifier
|
|
421
424
|
transitionTo: (
|
|
422
|
-
spec: TransitionSpec<TExtracted
|
|
423
|
-
condition?: string // Optional: AI-evaluated text condition for this transition
|
|
425
|
+
spec: TransitionSpec<TExtracted>
|
|
424
426
|
) => TransitionResult<TExtracted>;
|
|
425
427
|
}
|
|
426
428
|
```
|
|
427
429
|
|
|
428
430
|
**Parameters:**
|
|
429
431
|
|
|
430
|
-
- `spec`: The transition specification (see `TransitionSpec` above)
|
|
431
|
-
- `condition` (optional): Human-readable condition text that the AI evaluates when selecting states. Use this to guide the AI's state selection based on conversation context. Examples: "Customer confirmed payment", "All required data collected", "User wants to modify order"
|
|
432
|
+
- `spec`: The transition specification (see `TransitionSpec` above). Can include an optional `condition` property for AI-evaluated state selection guidance.
|
|
432
433
|
|
|
433
434
|
**Returns:** A `TransitionResult` that includes the target state's reference (`id`, `routeId`) and a `transitionTo` method for chaining additional transitions.
|
|
434
435
|
|
|
@@ -445,7 +446,7 @@ interface FlightData {
|
|
|
445
446
|
// Create a data-driven route
|
|
446
447
|
const flightRoute = agent.createRoute<FlightData>({
|
|
447
448
|
title: "Book Flight",
|
|
448
|
-
|
|
449
|
+
extractionSchema: {
|
|
449
450
|
type: "object",
|
|
450
451
|
properties: {
|
|
451
452
|
destination: { type: "string" },
|
|
@@ -457,24 +458,20 @@ const flightRoute = agent.createRoute<FlightData>({
|
|
|
457
458
|
});
|
|
458
459
|
|
|
459
460
|
// Approach 1: Step-by-step with data extraction and text conditions
|
|
460
|
-
const askDestination = flightRoute.initialState.transitionTo(
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
"Customer hasn't specified destination yet" // AI-evaluated condition
|
|
467
|
-
);
|
|
461
|
+
const askDestination = flightRoute.initialState.transitionTo({
|
|
462
|
+
chatState: "Ask where they want to fly",
|
|
463
|
+
gather: ["destination"],
|
|
464
|
+
skipIf: (extracted) => !!extracted.destination, // Skip if already have destination
|
|
465
|
+
condition: "Customer hasn't specified destination yet", // AI-evaluated condition
|
|
466
|
+
});
|
|
468
467
|
|
|
469
|
-
const askDates = askDestination.transitionTo(
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
"Destination confirmed, need travel dates"
|
|
477
|
-
);
|
|
468
|
+
const askDates = askDestination.transitionTo({
|
|
469
|
+
chatState: "Ask about travel dates",
|
|
470
|
+
gather: ["departureDate"],
|
|
471
|
+
skipIf: (extracted) => !!extracted.departureDate,
|
|
472
|
+
requiredData: ["destination"], // Must have destination first
|
|
473
|
+
condition: "Destination confirmed, need travel dates",
|
|
474
|
+
});
|
|
478
475
|
|
|
479
476
|
const askPassengers = askDates.transitionTo({
|
|
480
477
|
chatState: "How many passengers?",
|
|
@@ -1557,7 +1554,7 @@ interface SessionState<TExtracted = Record<string, unknown>> {
|
|
|
1557
1554
|
**Key Features:**
|
|
1558
1555
|
|
|
1559
1556
|
- **`id`** - Optional session identifier that persists across database operations
|
|
1560
|
-
- **`extracted`** - Type-safe data collected via `
|
|
1557
|
+
- **`extracted`** - Type-safe data collected via `extractionSchema`
|
|
1561
1558
|
- **`currentRoute`** / **`currentState`** - Track conversation position
|
|
1562
1559
|
- **`routeHistory`** - Full audit trail of route transitions
|
|
1563
1560
|
- **`metadata`** - Custom data (timestamps, user info, etc.)
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -22,7 +22,7 @@ interface FlightData {
|
|
|
22
22
|
const route = agent.createRoute<FlightData>({
|
|
23
23
|
title: "Book Flight",
|
|
24
24
|
description: "Help user book a flight",
|
|
25
|
-
|
|
25
|
+
extractionSchema: {
|
|
26
26
|
type: "object",
|
|
27
27
|
properties: {
|
|
28
28
|
destination: { type: "string" },
|
|
@@ -112,26 +112,22 @@ Use TypeScript functions for deterministic flow control AND text conditions for
|
|
|
112
112
|
|
|
113
113
|
```typescript
|
|
114
114
|
// State with smart bypassing based on extracted data
|
|
115
|
-
const askDestination = route.initialState.transitionTo(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
"Customer hasn't specified destination yet" // Text condition for AI
|
|
123
|
-
);
|
|
115
|
+
const askDestination = route.initialState.transitionTo({
|
|
116
|
+
id: "ask_destination", // Optional: custom state ID
|
|
117
|
+
chatState: "Ask where they want to fly",
|
|
118
|
+
gather: ["destination"],
|
|
119
|
+
skipIf: (extracted) => !!extracted.destination, // Code-based condition!
|
|
120
|
+
condition: "Customer hasn't specified destination yet", // Text condition for AI
|
|
121
|
+
});
|
|
124
122
|
|
|
125
|
-
const askDate = askDestination.transitionTo(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
"Destination confirmed, need travel dates now"
|
|
134
|
-
);
|
|
123
|
+
const askDate = askDestination.transitionTo({
|
|
124
|
+
id: "ask_date", // Optional: custom state ID for easier tracking
|
|
125
|
+
chatState: "Ask about travel dates",
|
|
126
|
+
gather: ["departureDate"],
|
|
127
|
+
skipIf: (extracted) => !!extracted.departureDate,
|
|
128
|
+
requiredData: ["destination"], // Prerequisites
|
|
129
|
+
condition: "Destination confirmed, need travel dates now",
|
|
130
|
+
});
|
|
135
131
|
});
|
|
136
132
|
```
|
|
137
133
|
|
|
@@ -374,7 +370,7 @@ interface BookingData {
|
|
|
374
370
|
|
|
375
371
|
const bookingRoute = agent.createRoute<BookingData>({
|
|
376
372
|
title: "Flight Booking",
|
|
377
|
-
|
|
373
|
+
extractionSchema: {
|
|
378
374
|
/* schema for all fields */
|
|
379
375
|
},
|
|
380
376
|
});
|
|
@@ -404,7 +400,7 @@ For simple question-answering without state:
|
|
|
404
400
|
const qnaRoute = agent.createRoute({
|
|
405
401
|
title: "Company Q&A",
|
|
406
402
|
conditions: ["User asks about company"],
|
|
407
|
-
// NO
|
|
403
|
+
// NO extractionSchema - stateless!
|
|
408
404
|
});
|
|
409
405
|
|
|
410
406
|
// Just use initial state
|
|
@@ -103,7 +103,7 @@ const agent = new Agent<FlightBookingContext>({
|
|
|
103
103
|
title: 'Book Flight',
|
|
104
104
|
description: 'Help user book a flight',
|
|
105
105
|
conditions: ['User wants to book a flight'],
|
|
106
|
-
|
|
106
|
+
extractionSchema: {
|
|
107
107
|
type: 'object',
|
|
108
108
|
properties: {
|
|
109
109
|
destination: { type: 'string' },
|
|
@@ -175,7 +175,7 @@ interface RouteOptions<TExtracted = unknown> {
|
|
|
175
175
|
prohibitions?: string[]; // Absolute prohibitions the agent MUST NEVER do
|
|
176
176
|
|
|
177
177
|
// NEW: Schema-first data extraction
|
|
178
|
-
|
|
178
|
+
extractionSchema?: {
|
|
179
179
|
type: "object";
|
|
180
180
|
properties: Record<string, any>;
|
|
181
181
|
required?: string[];
|
package/docs/EXAMPLES.md
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
This directory contains production-ready examples demonstrating all features of `@falai/agent`.
|
|
4
|
+
|
|
5
|
+
## 🚀 Getting Started Examples
|
|
6
|
+
|
|
7
|
+
### 📋 [Declarative Agent](../examples/declarative-agent.ts)
|
|
8
|
+
|
|
9
|
+
**Perfect for:** Learning the full configuration API
|
|
10
|
+
|
|
11
|
+
Comprehensive example showing declarative agent configuration:
|
|
12
|
+
|
|
13
|
+
- ✅ Full constructor-based setup
|
|
14
|
+
- ✅ Terms, guidelines, capabilities, routes defined upfront
|
|
15
|
+
- ✅ Session state management with data extraction
|
|
16
|
+
- ✅ Custom IDs for routes, states, and tools
|
|
17
|
+
- ✅ Dynamic additions after construction
|
|
18
|
+
|
|
19
|
+
**Key concepts:** Declarative configuration, session state, data extraction schemas
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
const agent = new Agent({
|
|
23
|
+
name: "HealthBot",
|
|
24
|
+
ai: provider,
|
|
25
|
+
terms: [...],
|
|
26
|
+
guidelines: [...],
|
|
27
|
+
routes: [{
|
|
28
|
+
extractionSchema: { /* JSON Schema */ }
|
|
29
|
+
}]
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 🏢 Real-World Applications
|
|
36
|
+
|
|
37
|
+
### 🏢 [Business Onboarding](../examples/business-onboarding.ts)
|
|
38
|
+
|
|
39
|
+
**Perfect for:** Building complex multi-step workflows
|
|
40
|
+
|
|
41
|
+
Production-ready business onboarding with advanced patterns:
|
|
42
|
+
|
|
43
|
+
- ✅ Multi-step data collection flow
|
|
44
|
+
- ✅ Branching logic (physical vs online business)
|
|
45
|
+
- ✅ Tools with `contextUpdate` for automatic state management
|
|
46
|
+
- ✅ Both step-by-step and fluent chaining approaches
|
|
47
|
+
- ✅ Lifecycle hooks for persistence
|
|
48
|
+
- ✅ Dynamic route creation based on collected data
|
|
49
|
+
|
|
50
|
+
**Key concepts:** Complex flows, branching logic, context updates, lifecycle hooks
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// Branching based on business type
|
|
54
|
+
const askPhysicalLocation = askLocation.transitionTo({
|
|
55
|
+
chatState: "Get physical store address",
|
|
56
|
+
condition: "User has a physical store",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const askOnlineLocation = askLocation.transitionTo({
|
|
60
|
+
chatState: "Get website and online support hours",
|
|
61
|
+
condition: "User does not have a physical store",
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### ✈️ [Travel Agent](../examples/travel-agent.ts)
|
|
66
|
+
|
|
67
|
+
**Perfect for:** Multi-route systems with session state
|
|
68
|
+
|
|
69
|
+
Complete travel booking system featuring:
|
|
70
|
+
|
|
71
|
+
- ✅ Multi-step flight booking flow
|
|
72
|
+
- ✅ Data extraction with JSON Schema
|
|
73
|
+
- ✅ Session state tracking across turns
|
|
74
|
+
- ✅ Tools with data access via `extracted` context
|
|
75
|
+
- ✅ Alternative flow handling (booking vs status check)
|
|
76
|
+
- ✅ Route-specific guidelines
|
|
77
|
+
|
|
78
|
+
**Key concepts:** Session state, data extraction, multiple routes, tool data access
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
const searchFlights = defineTool(
|
|
82
|
+
"search_flights",
|
|
83
|
+
async ({ context, extracted }) => {
|
|
84
|
+
// Tool has access to extracted booking data
|
|
85
|
+
if (!extracted?.destination || !extracted?.departureDate) {
|
|
86
|
+
return { data: [] };
|
|
87
|
+
}
|
|
88
|
+
// Use extracted data to search
|
|
89
|
+
const flights = await searchAPI(extracted);
|
|
90
|
+
return { data: flights };
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 🏥 [Healthcare Assistant](../examples/healthcare-agent.ts)
|
|
96
|
+
|
|
97
|
+
**Perfect for:** Sensitive data handling and compliance
|
|
98
|
+
|
|
99
|
+
Healthcare-focused agent demonstrating:
|
|
100
|
+
|
|
101
|
+
- ✅ Appointment scheduling with validation
|
|
102
|
+
- ✅ Lab results retrieval
|
|
103
|
+
- ✅ Route-based disambiguation with conditions
|
|
104
|
+
- ✅ Sensitive data handling best practices
|
|
105
|
+
- ✅ Urgent case prioritization
|
|
106
|
+
- ✅ HIPAA-style security patterns
|
|
107
|
+
|
|
108
|
+
**Key concepts:** Data security, route disambiguation, validation, compliance
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## ⚡ Advanced Features
|
|
113
|
+
|
|
114
|
+
### ⚡ [Streaming Responses](../examples/streaming-agent.ts)
|
|
115
|
+
|
|
116
|
+
**Perfect for:** Real-time UX and better perceived performance
|
|
117
|
+
|
|
118
|
+
Real-time streaming responses:
|
|
119
|
+
|
|
120
|
+
- ✅ Stream responses from all providers (Anthropic, OpenAI, Gemini, OpenRouter)
|
|
121
|
+
- ✅ Real-time text generation with `respondStream`
|
|
122
|
+
- ✅ Cancellable streams with AbortSignal
|
|
123
|
+
- ✅ Access route, state, and tool information in final chunk
|
|
124
|
+
- ✅ 5 comprehensive examples covering different use cases
|
|
125
|
+
|
|
126
|
+
**Key concepts:** Streaming, real-time UX, cancellation
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
for await (const chunk of agent.respondStream({ history })) {
|
|
130
|
+
process.stdout.write(chunk.delta);
|
|
131
|
+
|
|
132
|
+
if (chunk.done) {
|
|
133
|
+
console.log("Route:", chunk.route?.title);
|
|
134
|
+
console.log("Extracted:", chunk.extracted);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 🔐 [Domain Scoping](../examples/domain-scoping.ts)
|
|
140
|
+
|
|
141
|
+
**Perfect for:** Security-conscious applications
|
|
142
|
+
|
|
143
|
+
Control tool access per route for security:
|
|
144
|
+
|
|
145
|
+
- ✅ Organize tools into security domains
|
|
146
|
+
- ✅ Restrict which tools each route can use
|
|
147
|
+
- ✅ Prevent unauthorized tool calls
|
|
148
|
+
- ✅ Improve AI performance by reducing decision space
|
|
149
|
+
- ✅ Clear documentation of route capabilities
|
|
150
|
+
|
|
151
|
+
**Key concepts:** Security, tool isolation, domain organization
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
agent.addDomain("payment", { processPayment, refund });
|
|
155
|
+
agent.addDomain("user", { updateProfile, sendEmail });
|
|
156
|
+
|
|
157
|
+
// Checkout route can ONLY use payment tools
|
|
158
|
+
agent.createRoute({
|
|
159
|
+
title: "Checkout",
|
|
160
|
+
domains: ["payment"], // ← Security boundary
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 📜 [Rules & Prohibitions](../examples/rules-prohibitions.ts)
|
|
165
|
+
|
|
166
|
+
**Perfect for:** Multi-channel bots with different styles
|
|
167
|
+
|
|
168
|
+
Control agent behavior and communication style per route:
|
|
169
|
+
|
|
170
|
+
- ✅ Define absolute rules the agent must follow
|
|
171
|
+
- ✅ Set prohibitions for what agent must never do
|
|
172
|
+
- ✅ Different communication styles per route
|
|
173
|
+
- ✅ Perfect for multi-channel bots (WhatsApp, email, chat)
|
|
174
|
+
- ✅ Automatic enforcement without manual checking
|
|
175
|
+
|
|
176
|
+
**Key concepts:** Behavior control, tone management, channel-specific styling
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
agent.createRoute({
|
|
180
|
+
title: "WhatsApp Support",
|
|
181
|
+
rules: ["Keep messages under 2 lines", "Use max 1 emoji"],
|
|
182
|
+
prohibitions: ["Never send long paragraphs", "Don't over-explain"],
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
agent.createRoute({
|
|
186
|
+
title: "Email Support",
|
|
187
|
+
rules: ["Use professional tone", "Include clear next steps"],
|
|
188
|
+
prohibitions: ["No emojis", "Avoid slang"],
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 💾 Persistence Examples
|
|
195
|
+
|
|
196
|
+
### 💾 [Prisma Persistence](../examples/prisma-persistence.ts)
|
|
197
|
+
|
|
198
|
+
**Perfect for:** Production apps with relational databases
|
|
199
|
+
|
|
200
|
+
Auto-save sessions and messages with Prisma ORM:
|
|
201
|
+
|
|
202
|
+
- ✅ Provider pattern - simple as `new PrismaAdapter({ prisma })`
|
|
203
|
+
- ✅ Automatic session and message persistence
|
|
204
|
+
- ✅ Seamless lifecycle hook integration
|
|
205
|
+
- ✅ Type-safe database operations
|
|
206
|
+
- ✅ 3-step setup guide
|
|
207
|
+
|
|
208
|
+
**Key concepts:** Database persistence, Prisma ORM, auto-save
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
const agent = new Agent({
|
|
212
|
+
persistence: {
|
|
213
|
+
adapter: new PrismaAdapter({ prisma }),
|
|
214
|
+
autoSave: true,
|
|
215
|
+
userId: "user_123",
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### ⚡ [Redis Persistence](../examples/redis-persistence.ts)
|
|
221
|
+
|
|
222
|
+
**Perfect for:** High-throughput real-time applications
|
|
223
|
+
|
|
224
|
+
Fast, in-memory persistence:
|
|
225
|
+
|
|
226
|
+
- ✅ Lightning-fast session storage
|
|
227
|
+
- ✅ Configurable TTLs for auto-cleanup
|
|
228
|
+
- ✅ Custom key prefixes
|
|
229
|
+
- ✅ Perfect for real-time chat applications
|
|
230
|
+
- ✅ Simple setup with ioredis
|
|
231
|
+
|
|
232
|
+
**Key concepts:** In-memory persistence, Redis, TTL management
|
|
233
|
+
|
|
234
|
+
### 🔍 [OpenSearch Persistence](../examples/opensearch-persistence.ts)
|
|
235
|
+
|
|
236
|
+
**Perfect for:** Analytics and full-text search requirements
|
|
237
|
+
|
|
238
|
+
Full-text search and analytics-powered persistence:
|
|
239
|
+
|
|
240
|
+
- ✅ Built-in full-text search across all messages
|
|
241
|
+
- ✅ Powerful aggregations and analytics
|
|
242
|
+
- ✅ Compatible with Elasticsearch 7.x
|
|
243
|
+
- ✅ AWS OpenSearch Service ready
|
|
244
|
+
- ✅ Index management and optimization
|
|
245
|
+
|
|
246
|
+
**Key concepts:** Search, analytics, OpenSearch, Elasticsearch
|
|
247
|
+
|
|
248
|
+
### 🗄️ [Custom Database Integration](../examples/custom-database-persistence.ts)
|
|
249
|
+
|
|
250
|
+
**Perfect for:** Integrating with existing database schemas
|
|
251
|
+
|
|
252
|
+
Manual session state management for existing schemas:
|
|
253
|
+
|
|
254
|
+
- ✅ Full control over database operations
|
|
255
|
+
- ✅ Works with any database (no adapter needed)
|
|
256
|
+
- ✅ Manual session state save/restore
|
|
257
|
+
- ✅ Perfect for integrating with existing schemas
|
|
258
|
+
- ✅ Complete example with validation hooks
|
|
259
|
+
|
|
260
|
+
**Key concepts:** Custom persistence, existing schemas, manual control
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## 🔧 Context & State Management
|
|
265
|
+
|
|
266
|
+
### 💾 [Persistent Onboarding Agent](../examples/persistent-onboarding.ts)
|
|
267
|
+
|
|
268
|
+
**Perfect for:** Multi-turn conversations with persistence
|
|
269
|
+
|
|
270
|
+
Multi-turn conversation with state persistence:
|
|
271
|
+
|
|
272
|
+
- ✅ Context lifecycle hooks for database integration
|
|
273
|
+
- ✅ Automatic persistence on context updates
|
|
274
|
+
- ✅ Factory pattern for agent creation
|
|
275
|
+
- ✅ Two approaches: lifecycle hooks vs context provider
|
|
276
|
+
- ✅ Complete onboarding flow across multiple turns
|
|
277
|
+
|
|
278
|
+
**Key concepts:** Context lifecycle, multi-turn conversations, factory pattern
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
const agent = new Agent({
|
|
282
|
+
hooks: {
|
|
283
|
+
beforeRespond: async (context) => {
|
|
284
|
+
return await database.loadContext(sessionId);
|
|
285
|
+
},
|
|
286
|
+
onContextUpdate: async (newContext) => {
|
|
287
|
+
await database.saveContext(sessionId, newContext);
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### 🔄 [Extracted Data Modification](../examples/extracted-data-modification.ts)
|
|
294
|
+
|
|
295
|
+
**Perfect for:** Data validation and enrichment
|
|
296
|
+
|
|
297
|
+
Tools that validate and enrich extracted data:
|
|
298
|
+
|
|
299
|
+
- ✅ Tools can modify extracted data with `extractedUpdate`
|
|
300
|
+
- ✅ Data validation and enrichment patterns
|
|
301
|
+
- ✅ Flag-based conditional execution
|
|
302
|
+
- ✅ Error handling and data correction
|
|
303
|
+
- ✅ Multi-step data refinement
|
|
304
|
+
|
|
305
|
+
**Key concepts:** Data validation, enrichment, extractedUpdate, flags
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
const validateEmail = defineTool(
|
|
309
|
+
"validate_email",
|
|
310
|
+
async ({ extracted }) => {
|
|
311
|
+
const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(extracted.email);
|
|
312
|
+
return {
|
|
313
|
+
data: isValid,
|
|
314
|
+
extractedUpdate: {
|
|
315
|
+
emailValid: isValid, // Enrich extracted data
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
);
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## 🤖 Provider Examples
|
|
325
|
+
|
|
326
|
+
### 🌐 [OpenAI Agent](../examples/openai-agent.ts)
|
|
327
|
+
|
|
328
|
+
**Perfect for:** Using GPT models
|
|
329
|
+
|
|
330
|
+
GPT-5 integration with backup models:
|
|
331
|
+
|
|
332
|
+
- ✅ OpenAI provider configuration
|
|
333
|
+
- ✅ Backup model fallback
|
|
334
|
+
- ✅ Retry configuration
|
|
335
|
+
- ✅ Weather checking example
|
|
336
|
+
|
|
337
|
+
**Key concepts:** OpenAI integration, model fallback
|
|
338
|
+
|
|
339
|
+
### 🌐 Multiple Providers
|
|
340
|
+
|
|
341
|
+
See how different AI providers work:
|
|
342
|
+
|
|
343
|
+
- **[OpenAI Agent](../examples/openai-agent.ts)** - GPT-5 integration
|
|
344
|
+
- **[Healthcare Agent](../examples/healthcare-agent.ts)** - Claude 3.5 Sonnet (Anthropic)
|
|
345
|
+
- **[Travel Agent](../examples/travel-agent.ts)** - OpenRouter with backup models
|
|
346
|
+
- All examples include backup model configuration and retry settings
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## 📚 Additional Examples
|
|
351
|
+
|
|
352
|
+
### 📊 [Company Q&A Agent](../examples/company-qna-agent.ts)
|
|
353
|
+
|
|
354
|
+
**Perfect for:** Stateless question-answering systems
|
|
355
|
+
|
|
356
|
+
Simple Q&A agent with knowledge base:
|
|
357
|
+
|
|
358
|
+
- ✅ Stateless routes (no data extraction)
|
|
359
|
+
- ✅ Knowledge base integration
|
|
360
|
+
- ✅ Simple request-response pattern
|
|
361
|
+
- ✅ Perfect for FAQ bots
|
|
362
|
+
|
|
363
|
+
**Key concepts:** Stateless routing, Q&A patterns
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## 🎯 How to Use These Examples
|
|
368
|
+
|
|
369
|
+
### Running Examples
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
# Install dependencies
|
|
373
|
+
bun install
|
|
374
|
+
|
|
375
|
+
# Set up environment variables
|
|
376
|
+
echo "GEMINI_API_KEY=your_key" > .env
|
|
377
|
+
|
|
378
|
+
# Run an example
|
|
379
|
+
bun examples/travel-agent.ts
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Learning Path
|
|
383
|
+
|
|
384
|
+
1. **Start here:** [Declarative Agent](../examples/declarative-agent.ts) - Learn the basics
|
|
385
|
+
2. **Simple flow:** [Travel Agent](../examples/travel-agent.ts) - Session state & extraction
|
|
386
|
+
3. **Complex flow:** [Business Onboarding](../examples/business-onboarding.ts) - Branching & lifecycle
|
|
387
|
+
4. **Add persistence:** [Prisma Persistence](../examples/prisma-persistence.ts) - Database integration
|
|
388
|
+
5. **Add security:** [Domain Scoping](../examples/domain-scoping.ts) - Tool isolation
|
|
389
|
+
|
|
390
|
+
### Quick Reference
|
|
391
|
+
|
|
392
|
+
| Example | Best For | Key Features |
|
|
393
|
+
|---------|----------|--------------|
|
|
394
|
+
| Declarative Agent | Learning basics | Full API coverage |
|
|
395
|
+
| Travel Agent | Session state | Multi-turn conversations |
|
|
396
|
+
| Business Onboarding | Complex flows | Branching, lifecycle hooks |
|
|
397
|
+
| Healthcare Agent | Security | Data validation, compliance |
|
|
398
|
+
| Streaming Agent | Real-time UX | Streaming responses |
|
|
399
|
+
| Domain Scoping | Security | Tool isolation |
|
|
400
|
+
| Prisma Persistence | Production | Database integration |
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## 💡 Tips
|
|
405
|
+
|
|
406
|
+
**For Production:**
|
|
407
|
+
- Use [Prisma Persistence](../examples/prisma-persistence.ts) for relational data
|
|
408
|
+
- Use [Redis Persistence](../examples/redis-persistence.ts) for high-throughput
|
|
409
|
+
- Implement [Domain Scoping](../examples/domain-scoping.ts) for security
|
|
410
|
+
- Add [Rules & Prohibitions](../examples/rules-prohibitions.ts) for brand consistency
|
|
411
|
+
|
|
412
|
+
**For Development:**
|
|
413
|
+
- Start with [Declarative Agent](../examples/declarative-agent.ts)
|
|
414
|
+
- Use [Streaming Agent](../examples/streaming-agent.ts) for better UX
|
|
415
|
+
- Check [Custom Database Integration](../examples/custom-database-persistence.ts) for existing schemas
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
**Need help?** Check the [full documentation](./README.md) or [open an issue](https://github.com/gusnips/falai/issues).
|
package/docs/GETTING_STARTED.md
CHANGED
|
@@ -86,7 +86,7 @@ const bookingRoute = agent.createRoute<FlightData>({
|
|
|
86
86
|
title: "Book Flight",
|
|
87
87
|
description: "Help user book a flight",
|
|
88
88
|
conditions: ["User wants to book a flight"],
|
|
89
|
-
|
|
89
|
+
extractionSchema: {
|
|
90
90
|
type: "object",
|
|
91
91
|
properties: {
|
|
92
92
|
destination: { type: "string" },
|