@falai/agent 0.9.0-alpha-1 → 0.9.0-alpha-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.
Files changed (166) hide show
  1. package/README.md +34 -22
  2. package/dist/cjs/src/core/Agent.d.ts +52 -24
  3. package/dist/cjs/src/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/src/core/Agent.js +266 -39
  5. package/dist/cjs/src/core/Agent.js.map +1 -1
  6. package/dist/cjs/src/core/PersistenceManager.d.ts.map +1 -1
  7. package/dist/cjs/src/core/PersistenceManager.js +48 -25
  8. package/dist/cjs/src/core/PersistenceManager.js.map +1 -1
  9. package/dist/cjs/src/core/PromptComposer.d.ts +1 -1
  10. package/dist/cjs/src/core/PromptComposer.d.ts.map +1 -1
  11. package/dist/cjs/src/core/PromptComposer.js.map +1 -1
  12. package/dist/cjs/src/core/ResponseEngine.d.ts +13 -12
  13. package/dist/cjs/src/core/ResponseEngine.d.ts.map +1 -1
  14. package/dist/cjs/src/core/ResponseEngine.js +4 -4
  15. package/dist/cjs/src/core/ResponseEngine.js.map +1 -1
  16. package/dist/cjs/src/core/ResponsePipeline.d.ts +66 -38
  17. package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -1
  18. package/dist/cjs/src/core/ResponsePipeline.js +71 -3
  19. package/dist/cjs/src/core/ResponsePipeline.js.map +1 -1
  20. package/dist/cjs/src/core/Route.d.ts +24 -5
  21. package/dist/cjs/src/core/Route.d.ts.map +1 -1
  22. package/dist/cjs/src/core/Route.js +45 -1
  23. package/dist/cjs/src/core/Route.js.map +1 -1
  24. package/dist/cjs/src/core/RoutingEngine.d.ts +31 -6
  25. package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -1
  26. package/dist/cjs/src/core/RoutingEngine.js +113 -9
  27. package/dist/cjs/src/core/RoutingEngine.js.map +1 -1
  28. package/dist/cjs/src/core/SessionManager.d.ts +14 -4
  29. package/dist/cjs/src/core/SessionManager.d.ts.map +1 -1
  30. package/dist/cjs/src/core/SessionManager.js +25 -5
  31. package/dist/cjs/src/core/SessionManager.js.map +1 -1
  32. package/dist/cjs/src/core/Step.d.ts +10 -10
  33. package/dist/cjs/src/core/Step.d.ts.map +1 -1
  34. package/dist/cjs/src/core/Step.js.map +1 -1
  35. package/dist/cjs/src/core/ToolExecutor.d.ts +4 -2
  36. package/dist/cjs/src/core/ToolExecutor.d.ts.map +1 -1
  37. package/dist/cjs/src/core/ToolExecutor.js +13 -3
  38. package/dist/cjs/src/core/ToolExecutor.js.map +1 -1
  39. package/dist/cjs/src/types/agent.d.ts +41 -21
  40. package/dist/cjs/src/types/agent.d.ts.map +1 -1
  41. package/dist/cjs/src/types/agent.js.map +1 -1
  42. package/dist/cjs/src/types/index.d.ts +1 -1
  43. package/dist/cjs/src/types/index.d.ts.map +1 -1
  44. package/dist/cjs/src/types/index.js.map +1 -1
  45. package/dist/cjs/src/types/persistence.d.ts +0 -1
  46. package/dist/cjs/src/types/persistence.d.ts.map +1 -1
  47. package/dist/cjs/src/types/route.d.ts +22 -16
  48. package/dist/cjs/src/types/route.d.ts.map +1 -1
  49. package/dist/cjs/src/types/session.d.ts +6 -11
  50. package/dist/cjs/src/types/session.d.ts.map +1 -1
  51. package/dist/cjs/src/types/tool.d.ts +12 -6
  52. package/dist/cjs/src/types/tool.d.ts.map +1 -1
  53. package/dist/cjs/src/utils/session.d.ts +2 -2
  54. package/dist/cjs/src/utils/session.d.ts.map +1 -1
  55. package/dist/cjs/src/utils/session.js +6 -26
  56. package/dist/cjs/src/utils/session.js.map +1 -1
  57. package/dist/src/core/Agent.d.ts +52 -24
  58. package/dist/src/core/Agent.d.ts.map +1 -1
  59. package/dist/src/core/Agent.js +266 -39
  60. package/dist/src/core/Agent.js.map +1 -1
  61. package/dist/src/core/PersistenceManager.d.ts.map +1 -1
  62. package/dist/src/core/PersistenceManager.js +48 -25
  63. package/dist/src/core/PersistenceManager.js.map +1 -1
  64. package/dist/src/core/PromptComposer.d.ts +1 -1
  65. package/dist/src/core/PromptComposer.d.ts.map +1 -1
  66. package/dist/src/core/PromptComposer.js.map +1 -1
  67. package/dist/src/core/ResponseEngine.d.ts +13 -12
  68. package/dist/src/core/ResponseEngine.d.ts.map +1 -1
  69. package/dist/src/core/ResponseEngine.js +4 -4
  70. package/dist/src/core/ResponseEngine.js.map +1 -1
  71. package/dist/src/core/ResponsePipeline.d.ts +66 -38
  72. package/dist/src/core/ResponsePipeline.d.ts.map +1 -1
  73. package/dist/src/core/ResponsePipeline.js +71 -3
  74. package/dist/src/core/ResponsePipeline.js.map +1 -1
  75. package/dist/src/core/Route.d.ts +24 -5
  76. package/dist/src/core/Route.d.ts.map +1 -1
  77. package/dist/src/core/Route.js +45 -1
  78. package/dist/src/core/Route.js.map +1 -1
  79. package/dist/src/core/RoutingEngine.d.ts +31 -6
  80. package/dist/src/core/RoutingEngine.d.ts.map +1 -1
  81. package/dist/src/core/RoutingEngine.js +113 -9
  82. package/dist/src/core/RoutingEngine.js.map +1 -1
  83. package/dist/src/core/SessionManager.d.ts +14 -4
  84. package/dist/src/core/SessionManager.d.ts.map +1 -1
  85. package/dist/src/core/SessionManager.js +25 -5
  86. package/dist/src/core/SessionManager.js.map +1 -1
  87. package/dist/src/core/Step.d.ts +10 -10
  88. package/dist/src/core/Step.d.ts.map +1 -1
  89. package/dist/src/core/Step.js.map +1 -1
  90. package/dist/src/core/ToolExecutor.d.ts +4 -2
  91. package/dist/src/core/ToolExecutor.d.ts.map +1 -1
  92. package/dist/src/core/ToolExecutor.js +13 -3
  93. package/dist/src/core/ToolExecutor.js.map +1 -1
  94. package/dist/src/types/agent.d.ts +41 -21
  95. package/dist/src/types/agent.d.ts.map +1 -1
  96. package/dist/src/types/agent.js.map +1 -1
  97. package/dist/src/types/index.d.ts +1 -1
  98. package/dist/src/types/index.d.ts.map +1 -1
  99. package/dist/src/types/index.js.map +1 -1
  100. package/dist/src/types/persistence.d.ts +0 -1
  101. package/dist/src/types/persistence.d.ts.map +1 -1
  102. package/dist/src/types/route.d.ts +22 -16
  103. package/dist/src/types/route.d.ts.map +1 -1
  104. package/dist/src/types/session.d.ts +6 -11
  105. package/dist/src/types/session.d.ts.map +1 -1
  106. package/dist/src/types/tool.d.ts +12 -6
  107. package/dist/src/types/tool.d.ts.map +1 -1
  108. package/dist/src/utils/session.d.ts +2 -2
  109. package/dist/src/utils/session.d.ts.map +1 -1
  110. package/dist/src/utils/session.js +6 -26
  111. package/dist/src/utils/session.js.map +1 -1
  112. package/docs/README.md +3 -3
  113. package/docs/api/README.md +35 -4
  114. package/docs/api/overview.md +166 -12
  115. package/docs/core/agent/README.md +162 -17
  116. package/docs/core/agent/context-management.md +39 -15
  117. package/docs/core/agent/session-management.md +49 -16
  118. package/docs/core/ai-integration/prompt-composition.md +38 -14
  119. package/docs/core/ai-integration/response-processing.md +28 -17
  120. package/docs/core/conversation-flows/data-collection.md +103 -25
  121. package/docs/core/conversation-flows/route-dsl.md +45 -22
  122. package/docs/core/conversation-flows/routes.md +74 -18
  123. package/docs/core/conversation-flows/step-transitions.md +3 -3
  124. package/docs/core/conversation-flows/steps.md +39 -15
  125. package/docs/core/routing/intelligent-routing.md +18 -9
  126. package/docs/core/tools/tool-definition.md +8 -8
  127. package/docs/core/tools/tool-execution.md +26 -26
  128. package/docs/core/tools/tool-scoping.md +5 -5
  129. package/docs/guides/getting-started/README.md +54 -32
  130. package/examples/advanced-patterns/knowledge-based-agent.ts +37 -28
  131. package/examples/advanced-patterns/persistent-onboarding.ts +70 -41
  132. package/examples/advanced-patterns/route-lifecycle-hooks.ts +28 -2
  133. package/examples/advanced-patterns/streaming-responses.ts +28 -23
  134. package/examples/ai-providers/anthropic-integration.ts +40 -33
  135. package/examples/ai-providers/openai-integration.ts +25 -25
  136. package/examples/conversation-flows/completion-transitions.ts +36 -32
  137. package/examples/core-concepts/basic-agent.ts +76 -78
  138. package/examples/core-concepts/schema-driven-extraction.ts +20 -16
  139. package/examples/core-concepts/session-management.ts +65 -53
  140. package/examples/integrations/database-integration.ts +49 -34
  141. package/examples/integrations/healthcare-integration.ts +96 -91
  142. package/examples/integrations/search-integration.ts +79 -82
  143. package/examples/integrations/server-session-management.ts +25 -17
  144. package/examples/persistence/database-persistence.ts +61 -45
  145. package/examples/persistence/memory-sessions.ts +52 -63
  146. package/examples/persistence/redis-persistence.ts +81 -95
  147. package/examples/tools/basic-tools.ts +73 -62
  148. package/examples/tools/data-enrichment-tools.ts +52 -44
  149. package/package.json +1 -1
  150. package/src/core/Agent.ts +418 -128
  151. package/src/core/PersistenceManager.ts +51 -27
  152. package/src/core/PromptComposer.ts +1 -1
  153. package/src/core/ResponseEngine.ts +21 -19
  154. package/src/core/ResponsePipeline.ts +174 -59
  155. package/src/core/Route.ts +58 -6
  156. package/src/core/RoutingEngine.ts +174 -27
  157. package/src/core/SessionManager.ts +32 -8
  158. package/src/core/Step.ts +20 -12
  159. package/src/core/ToolExecutor.ts +19 -5
  160. package/src/types/agent.ts +46 -23
  161. package/src/types/index.ts +2 -0
  162. package/src/types/persistence.ts +0 -1
  163. package/src/types/route.ts +22 -16
  164. package/src/types/session.ts +6 -12
  165. package/src/types/tool.ts +15 -9
  166. package/src/utils/session.ts +6 -31
@@ -8,28 +8,45 @@ The `@falai/agent` framework provides **automatic session management** through t
8
8
 
9
9
  ## 🎯 Automatic Session Management
10
10
 
11
- The `SessionManager` automatically tracks three key aspects of a conversation:
11
+ The `SessionManager` automatically tracks four key aspects of a conversation:
12
12
 
13
13
  1. **Current Route** - Which conversation flow the user is in
14
14
  2. **Current Step** - Where in the flow they currently are
15
- 3. **Collected data** - Structured data collected so far
15
+ 3. **Agent-Level Data** - Centralized structured data collected across all routes
16
16
  4. **Conversation History** - Complete message history within the session
17
17
 
18
18
  ```typescript
19
- // Define your data extraction type
20
- interface FlightData {
19
+ // Define your agent-level data extraction type
20
+ interface TravelData {
21
21
  destination: string;
22
22
  departureDate: string;
23
23
  passengers: number;
24
24
  cabinClass: "economy" | "business" | "first";
25
+ hotelPreference?: string;
26
+ budgetRange?: string;
27
+ specialRequests?: string;
25
28
  }
26
29
 
27
- // Agent with automatic session management
28
- const agent = new Agent({
30
+ // Agent with automatic session management and agent-level schema
31
+ const agent = new Agent<{}, TravelData>({
29
32
  name: "Travel Agent",
30
33
  provider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY }),
31
34
  persistence: { adapter: new PrismaAdapter({ prisma }) },
32
- sessionId: "user-123" // Automatically loads or creates session
35
+ sessionId: "user-123", // Automatically loads or creates session
36
+
37
+ // Agent-level schema for all data collection
38
+ schema: {
39
+ type: "object",
40
+ properties: {
41
+ destination: { type: "string" },
42
+ departureDate: { type: "string", format: "date" },
43
+ passengers: { type: "number", minimum: 1, maximum: 9 },
44
+ cabinClass: { type: "string", enum: ["economy", "business", "first"] },
45
+ hotelPreference: { type: "string" },
46
+ budgetRange: { type: "string" },
47
+ specialRequests: { type: "string" }
48
+ }
49
+ }
33
50
  });
34
51
 
35
52
  // Simple conversation - session managed automatically
@@ -37,7 +54,7 @@ const response = await agent.respond("I want to book a flight to Paris");
37
54
 
38
55
  // Access session information
39
56
  console.log(agent.session.id); // "user-123"
40
- console.log(agent.session.getData<FlightData>()); // { destination: "Paris", ... }
57
+ console.log(agent.session.getData<TravelData>()); // { destination: "Paris", ... }
41
58
  console.log(agent.session.getHistory()); // Conversation history
42
59
  ```
43
60
 
@@ -64,12 +81,13 @@ const sessionManager = agent.session;
64
81
  await sessionManager.getOrCreate("user-123");
65
82
  await sessionManager.getOrCreate(); // Auto-generates ID
66
83
 
67
- // Data management
68
- const data = sessionManager.getData<FlightData>();
84
+ // Agent-level data management
85
+ const data = sessionManager.getData<TravelData>();
69
86
  await sessionManager.setData({
70
87
  destination: "Paris",
71
88
  departureDate: "2025-10-15",
72
89
  passengers: 2,
90
+ cabinClass: "economy"
73
91
  });
74
92
 
75
93
  // History management
@@ -128,19 +146,25 @@ const agent = new Agent({
128
146
  await saveUserData(newContext.userId, newContext);
129
147
  },
130
148
 
131
- // NEW: Validate and enrich collected data
149
+ // Agent-level data validation and enrichment
132
150
  onDataUpdate: async (data, previousData) => {
133
151
  // Normalize passenger count
134
152
  if (data.passengers < 1) data.passengers = 1;
135
153
  if (data.passengers > 9) data.passengers = 9;
136
154
 
137
- // Enrich with computed fields
138
- if (data.destination) {
155
+ // Enrich with computed fields using agent-level data
156
+ if (data.destination && !data.destinationCode) {
139
157
  data.destinationCode = await lookupAirportCode(data.destination);
140
158
  }
141
159
 
142
- // Auto-trigger actions
143
- if (hasAllRequires(data)) {
160
+ // Auto-set budget range based on cabin class
161
+ if (data.cabinClass && !data.budgetRange) {
162
+ data.budgetRange = data.cabinClass === 'first' ? 'premium' :
163
+ data.cabinClass === 'business' ? 'high' : 'standard';
164
+ }
165
+
166
+ // Auto-trigger actions when we have complete booking data
167
+ if (data.destination && data.departureDate && data.passengers) {
144
168
  data.shouldSearchFlights = true;
145
169
  }
146
170
 
@@ -6,22 +6,28 @@ The `@falai/agent` framework provides **automatic session management** through t
6
6
 
7
7
  ## Core Design Principles
8
8
 
9
- ### 1. 🎯 Schema-First Data Extraction
9
+ ### 1. 🎯 Agent-Level Schema-First Data Extraction
10
10
 
11
- Define what data to collect upfront using JSON Schema, then extract it reliably:
11
+ Define what data to collect upfront using JSON Schema at the agent level, then extract it reliably across all routes:
12
12
 
13
13
  ```typescript
14
- // Define your data contract
15
- interface FlightData {
14
+ // Define your agent-level data contract
15
+ interface TravelData {
16
16
  destination: string;
17
17
  departureDate: string;
18
18
  passengers: number;
19
19
  cabinClass: "economy" | "business" | "first";
20
+ hotelPreference?: string;
21
+ budgetRange?: string;
22
+ specialRequests?: string;
20
23
  }
21
24
 
22
- const route = agent.createRoute<FlightData>({
23
- title: "Book Flight",
24
- description: "Help user book a flight",
25
+ // Agent with centralized schema
26
+ const agent = new Agent<{}, TravelData>({
27
+ name: "Travel Agent",
28
+ provider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY }),
29
+
30
+ // Agent-level schema defines all possible data fields
25
31
  schema: {
26
32
  type: "object",
27
33
  properties: {
@@ -33,40 +39,67 @@ const route = agent.createRoute<FlightData>({
33
39
  enum: ["economy", "business", "first"],
34
40
  default: "economy",
35
41
  },
42
+ hotelPreference: { type: "string" },
43
+ budgetRange: { type: "string" },
44
+ specialRequests: { type: "string" }
36
45
  },
37
46
  required: ["destination", "departureDate", "passengers"],
38
- },
47
+ }
48
+ });
49
+
50
+ // Routes specify required fields instead of schemas
51
+ const flightRoute = agent.createRoute({
52
+ title: "Book Flight",
53
+ description: "Help user book a flight",
54
+ requiredFields: ["destination", "departureDate", "passengers", "cabinClass"],
55
+ optionalFields: ["specialRequests"]
56
+ });
57
+
58
+ const hotelRoute = agent.createRoute({
59
+ title: "Book Hotel",
60
+ description: "Help user book accommodation",
61
+ requiredFields: ["destination", "departureDate", "hotelPreference"],
62
+ optionalFields: ["budgetRange", "specialRequests"]
39
63
  });
40
64
  ```
41
65
 
42
- **Why?** Schema-first extraction provides:
66
+ **Why?** Agent-level schema-first extraction provides:
43
67
 
44
- - **Type Safety** - Full TypeScript types from definition to extraction
68
+ - **Type Safety** - Full TypeScript types from definition to extraction across all routes
45
69
  - **Reliability** - Provider-enforced schemas, not prompt-based parsing
46
- - **Predictability** - Same data structure every time
70
+ - **Predictability** - Same data structure every time, shared across routes
47
71
  - **Efficiency** - Extract multiple fields in one LLM call
72
+ - **Cross-Route Data Sharing** - Data collected by any route is available to all routes
73
+ - **Route Completion** - Routes complete when their required fields are satisfied
48
74
 
49
75
  ### 2. 🤖 Automatic Session Management
50
76
 
51
77
  Sessions are automatically managed through the `SessionManager` class integrated into every `Agent`:
52
78
 
53
79
  ```typescript
54
- // Server-side: Agent with automatic session management
55
- const agent = new Agent({
80
+ // Server-side: Agent with automatic session management and agent-level data
81
+ const agent = new Agent<{}, TravelData>({
56
82
  name: "Travel Agent",
57
83
  provider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY }),
58
84
  persistence: { adapter: new PrismaAdapter({ prisma }) },
59
- sessionId: "user-123" // Automatically loads or creates this session
85
+ sessionId: "user-123", // Automatically loads or creates this session
86
+
87
+ // Agent-level schema
88
+ schema: { /* comprehensive travel data schema */ }
60
89
  });
61
90
 
62
91
  // Simple conversation - no manual session management
63
92
  const response1 = await agent.respond("I want to book a flight to Paris");
64
93
  console.log(agent.session.id); // Session ID
65
- console.log(agent.session.getData()); // Collected data
94
+ console.log(agent.session.getData<TravelData>()); // Agent-level collected data
66
95
 
67
96
  // Continue conversation - session automatically maintained
68
97
  const response2 = await agent.respond("Make that Tokyo instead");
69
- // Session automatically updated with new data
98
+ // Session automatically updated with new data in agent-level structure
99
+
100
+ // Switch to hotel booking - data is shared
101
+ const response3 = await agent.respond("Also book me a hotel in Tokyo");
102
+ // Hotel route can access destination data collected by flight route
70
103
  ```
71
104
 
72
105
  **SessionManager API:**
@@ -103,35 +103,59 @@ Assistant: Great! Let me check flights for next week. Could you tell me which ai
103
103
  Current session information including:
104
104
 
105
105
  - Active route and step
106
- - Collected data (with privacy filtering)
106
+ - Agent-level collected data (with privacy filtering)
107
107
  - Route progress and completion status
108
+ - Cross-route data availability
109
+
110
+ ```
111
+ Current Session:
112
+ - Route: Flight Booking (2/3 required fields collected)
113
+ - Step: ask_passengers
114
+ - Agent Data: { destination: "Paris", departureDate: "2025-01-15" }
115
+ - Missing Required: passengers
116
+ - Available from other routes: { hotelPreference: "luxury" }
117
+ ```
108
118
 
109
119
  ## Dynamic Schema Generation
110
120
 
111
- For data collection steps, the prompt includes JSON schemas:
121
+ For data collection steps, the prompt includes agent-level JSON schemas:
112
122
 
113
123
  ```typescript
114
- // Route schema
115
- schema: {
116
- type: "object",
117
- properties: {
118
- destination: { type: "string" },
119
- departureDate: { type: "string", format: "date" },
120
- passengers: { type: "number", minimum: 1 }
121
- },
122
- required: ["destination", "departureDate"]
123
- }
124
+ // Agent-level schema
125
+ const agent = new Agent<{}, TravelData>({
126
+ schema: {
127
+ type: "object",
128
+ properties: {
129
+ destination: { type: "string" },
130
+ departureDate: { type: "string", format: "date" },
131
+ passengers: { type: "number", minimum: 1 },
132
+ hotelPreference: { type: "string" },
133
+ budgetRange: { type: "string" }
134
+ },
135
+ required: ["destination", "departureDate"]
136
+ }
137
+ });
138
+
139
+ // Route specifies which fields to collect
140
+ const flightRoute = agent.createRoute({
141
+ title: "Flight Booking",
142
+ requiredFields: ["destination", "departureDate", "passengers"],
143
+ optionalFields: ["budgetRange"]
144
+ });
124
145
  ```
125
146
 
126
147
  Generates:
127
148
 
128
149
  ```
129
- Extract the following information from the user's response:
150
+ Extract the following information from the user's response based on the agent schema:
130
151
  - destination: string - Where the user wants to fly
131
152
  - departureDate: string (date format) - When they want to depart
132
153
  - passengers: number (minimum 1) - How many people are traveling
154
+ - budgetRange: string (optional) - Budget preference for the trip
133
155
 
134
- Return extracted data as valid JSON matching this schema.
156
+ Return extracted data as valid JSON matching the agent schema.
157
+ Current route requires: destination, departureDate, passengers
158
+ Route completion: 2/3 required fields collected
135
159
  ```
136
160
 
137
161
  ## Tool Integration
@@ -20,26 +20,33 @@ AI responses are parsed to extract:
20
20
  3. **Tool Calls** - Instructions to execute tools
21
21
  4. **Routing Decisions** - Route or step transitions
22
22
 
23
- ## Schema-Driven Extraction
23
+ ## Agent-Level Schema-Driven Extraction
24
24
 
25
- When steps specify `collect` fields, the AI response is validated against JSON schemas:
25
+ When steps specify `collect` fields, the AI response is validated against the agent-level JSON schema:
26
26
 
27
27
  ```typescript
28
- const step = route.initialStep.nextStep({
29
- prompt: "What's your name and email?",
30
- collect: ["name", "email"],
28
+ // Agent defines comprehensive schema
29
+ const agent = new Agent<{}, UserData>({
31
30
  schema: {
32
31
  type: "object",
33
32
  properties: {
34
33
  name: { type: "string" },
35
34
  email: { type: "string", format: "email" },
35
+ phone: { type: "string" },
36
+ preferences: { type: "object" }
36
37
  },
37
- required: ["name", "email"],
38
- },
38
+ required: ["name", "email"]
39
+ }
40
+ });
41
+
42
+ // Steps collect into agent schema
43
+ const step = route.initialStep.nextStep({
44
+ prompt: "What's your name and email?",
45
+ collect: ["name", "email"], // Maps to agent schema fields
39
46
  });
40
47
  ```
41
48
 
42
- The AI receives instructions to return structured data alongside natural language responses.
49
+ The AI receives instructions to return structured data that matches the agent-level schema, enabling cross-route data sharing.
43
50
 
44
51
  ## Tool Execution Pipeline
45
52
 
@@ -65,26 +72,30 @@ When tools are called, the response engine:
65
72
 
66
73
  ## Data Validation
67
74
 
68
- Extracted data is validated against route schemas:
75
+ Extracted data is validated against the agent-level schema:
69
76
 
70
- - **Type checking** - Ensures correct data types
71
- - **Required fields** - Validates mandatory data presence
72
- - **Format validation** - Email, dates, custom formats
73
- - **Business rules** - Custom validation logic
77
+ - **Type checking** - Ensures correct data types against agent schema
78
+ - **Required fields** - Validates mandatory data presence for route completion
79
+ - **Format validation** - Email, dates, custom formats from agent schema
80
+ - **Business rules** - Custom validation logic in agent-level hooks
81
+ - **Cross-route consistency** - Ensures data consistency across all routes
74
82
 
75
83
  ## Context Updates
76
84
 
77
85
  Response processing updates multiple context layers:
78
86
 
79
- ### Session Data
87
+ ### Agent-Level Data
80
88
 
81
89
  ```typescript
82
- // Collected data merged into session
83
- session.data = {
84
- ...session.data,
90
+ // Collected data merged into agent-level data structure
91
+ agent.collectedData = {
92
+ ...agent.collectedData,
85
93
  ...extractedData,
86
94
  ...toolResults,
87
95
  };
96
+
97
+ // Session references agent data
98
+ session.data = agent.collectedData;
88
99
  ```
89
100
 
90
101
  ### Route Context
@@ -1,20 +1,22 @@
1
- # Schema-Driven Data Collection
1
+ # Agent-Level Schema-Driven Data Collection
2
2
 
3
- @falai/agent implements a powerful schema-first approach to data collection, enabling type-safe, structured information extraction from natural conversations. Unlike traditional form-filling, this system uses AI to naturally gather information while maintaining data integrity.
3
+ @falai/agent implements a powerful agent-level schema-first approach to data collection, enabling type-safe, structured information extraction from natural conversations across all routes. Unlike traditional route-specific data collection, this system centralizes data schemas at the agent level while allowing routes to specify completion requirements.
4
4
 
5
5
  ## Overview
6
6
 
7
- The data collection system provides:
7
+ The agent-level data collection system provides:
8
8
 
9
- - **JSON Schema Contracts**: Define data structures upfront with validation
9
+ - **Centralized JSON Schema**: Define comprehensive data structures at the agent level
10
+ - **Cross-Route Data Sharing**: Data collected by any route is available to all routes
11
+ - **Route Completion Logic**: Routes complete when their required fields are satisfied
10
12
  - **Type-Safe Extraction**: Automatic mapping from AI responses to typed data
11
13
  - **Natural Conversations**: AI handles information gathering conversationally
12
- - **Validation & Enrichment**: Lifecycle hooks for data processing
13
- - **Session Persistence**: Data survives across conversation turns
14
+ - **Validation & Enrichment**: Agent-level lifecycle hooks for data processing
15
+ - **Session Persistence**: Data survives across conversation turns and route transitions
14
16
 
15
- ## Schema Definition
17
+ ## Agent-Level Schema Definition
16
18
 
17
- ### Basic Schema
19
+ ### Centralized Schema
18
20
 
19
21
  ```typescript
20
22
  interface UserProfile {
@@ -26,10 +28,19 @@ interface UserProfile {
26
28
  notifications: boolean;
27
29
  theme: "light" | "dark";
28
30
  };
31
+ // Additional fields for other routes
32
+ supportTicketId?: string;
33
+ issueType?: string;
34
+ feedbackRating?: number;
35
+ subscriptionTier?: "free" | "premium" | "enterprise";
29
36
  }
30
37
 
31
- const userProfileRoute = agent.createRoute<UserProfile>({
32
- title: "User Profile Collection",
38
+ // Define schema at agent level
39
+ const agent = new Agent<{}, UserProfile>({
40
+ name: "User Management Agent",
41
+ provider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY }),
42
+
43
+ // Comprehensive agent-level schema
33
44
  schema: {
34
45
  type: "object",
35
46
  properties: {
@@ -63,9 +74,32 @@ const userProfileRoute = agent.createRoute<UserProfile>({
63
74
  },
64
75
  },
65
76
  },
77
+ supportTicketId: { type: "string" },
78
+ issueType: { type: "string" },
79
+ feedbackRating: { type: "number", minimum: 1, maximum: 5 },
80
+ subscriptionTier: { type: "string", enum: ["free", "premium", "enterprise"] }
66
81
  },
67
82
  required: ["name", "email"],
68
- },
83
+ }
84
+ });
85
+
86
+ // Routes specify required fields instead of schemas
87
+ const profileRoute = agent.createRoute({
88
+ title: "User Profile Collection",
89
+ requiredFields: ["name", "email", "age"],
90
+ optionalFields: ["interests", "preferences"]
91
+ });
92
+
93
+ const supportRoute = agent.createRoute({
94
+ title: "Support Ticket",
95
+ requiredFields: ["name", "email", "issueType"],
96
+ optionalFields: ["supportTicketId"]
97
+ });
98
+
99
+ const feedbackRoute = agent.createRoute({
100
+ title: "Feedback Collection",
101
+ requiredFields: ["name", "email", "feedbackRating"],
102
+ optionalFields: ["subscriptionTier"]
69
103
  });
70
104
  ```
71
105
 
@@ -128,24 +162,33 @@ const complexSchema = {
128
162
 
129
163
  ## Step-Level Data Collection
130
164
 
131
- ### Basic Collection
165
+ ### Basic Collection with Agent-Level Data
132
166
 
133
167
  ```typescript
134
168
  const profileRoute = agent
135
169
  .createRoute({
136
170
  title: "Profile Collection",
137
- schema: userProfileSchema,
171
+ requiredFields: ["name", "email", "age"], // Required for route completion
172
+ optionalFields: ["interests"], // Optional but helpful
138
173
  initialStep: {
139
174
  prompt:
140
175
  "Hi! I'm collecting some information to personalize your experience. What's your name?",
141
- collect: ["name"], // Maps to schema field
176
+ collect: ["name"], // Maps to agent schema field
142
177
  },
143
178
  })
144
179
  .nextStep({
145
180
  prompt: "Thanks {{name}}! What's your email address?",
146
181
  collect: ["email"],
147
182
  requires: ["name"], // Must have name before collecting email
183
+ })
184
+ .nextStep({
185
+ prompt: "What's your age?",
186
+ collect: ["age"],
187
+ requires: ["name", "email"],
148
188
  });
189
+
190
+ // Route completes when all required fields are collected
191
+ // Data is available to all other routes
149
192
  ```
150
193
 
151
194
  ### Multi-Field Collection
@@ -160,12 +203,12 @@ const comprehensiveStep = {
160
203
  - Your preferred theme (light/dark)
161
204
  `,
162
205
  collect: [
163
- "age", // Single field
164
- "interests", // Array field
206
+ "age", // Single field from agent schema
207
+ "interests", // Array field from agent schema
165
208
  "preferences.notifications", // Nested field (dot notation)
166
209
  "preferences.theme", // Another nested field
167
210
  ],
168
- requires: ["name", "email"],
211
+ requires: ["name", "email"], // Prerequisites from agent data
169
212
  };
170
213
  ```
171
214
 
@@ -175,34 +218,69 @@ const comprehensiveStep = {
175
218
  const conditionalCollection = {
176
219
  prompt: "Would you like to set up notifications? (yes/no)",
177
220
  collect: ["preferences.notifications"],
178
- skipIf: (data) => data.preferences?.notifications !== undefined,
179
- requires: ["name", "email"],
221
+ skipIf: (data) => data.preferences?.notifications !== undefined, // Skip if already collected
222
+ requires: ["name", "email"], // Prerequisites from agent data
180
223
  };
181
224
  ```
182
225
 
226
+ ### Cross-Route Data Sharing
227
+
228
+ With agent-level data collection, routes can share data seamlessly:
229
+
230
+ ```typescript
231
+ // User starts with profile collection
232
+ const response1 = await agent.respond("Hi, I'm John Doe, email john@example.com");
233
+ // Agent data: { name: "John Doe", email: "john@example.com" }
234
+
235
+ // User switches to support - data is already available
236
+ const response2 = await agent.respond("Actually, I need help with a technical issue");
237
+ // Support route can access name and email, only needs to collect issue details
238
+ // Support route: 2/3 required fields already satisfied
239
+
240
+ // User provides issue details
241
+ const response3 = await agent.respond("My account won't sync properly");
242
+ // Support route completes: { name: "John Doe", email: "john@example.com", issueType: "technical" }
243
+
244
+ // Later, user wants to give feedback
245
+ const response4 = await agent.respond("I want to rate my support experience - 5 stars");
246
+ // Feedback route completes immediately: already has name, email, and now rating
247
+ ```
248
+
183
249
  ## Data Validation & Processing
184
250
 
185
- ### Lifecycle Hooks
251
+ ### Agent-Level Lifecycle Hooks
186
252
 
187
253
  ```typescript
188
- const validatedRoute = agent.createRoute({
189
- title: "Validated Collection",
254
+ const agent = new Agent<{}, UserProfile>({
255
+ name: "User Management Agent",
256
+ schema: { /* agent schema */ },
190
257
 
191
- // Agent-level data validation
258
+ // Agent-level data validation (applies to all routes)
192
259
  hooks: {
193
260
  onDataUpdate: (newData, previousData) => {
194
- // Cross-field validation
261
+ // Cross-field validation using complete agent data
195
262
  if (newData.email && newData.confirmEmail) {
196
263
  if (newData.email !== newData.confirmEmail) {
197
264
  throw new Error("Email addresses don't match");
198
265
  }
199
266
  }
200
267
 
201
- // Data enrichment
268
+ // Data enrichment based on agent-level data
202
269
  if (newData.name && !newData.displayName) {
203
270
  newData.displayName = newData.name.split(" ")[0]; // First name only
204
271
  }
205
272
 
273
+ // Auto-set subscription tier based on email domain
274
+ if (newData.email && !newData.subscriptionTier) {
275
+ newData.subscriptionTier = newData.email.includes('@enterprise.com') ? 'enterprise' : 'free';
276
+ }
277
+
278
+ // Validate against agent schema
279
+ const validation = agent.validateData(newData);
280
+ if (!validation.valid) {
281
+ throw new Error(`Data validation failed: ${validation.errors.map(e => e.message).join(', ')}`);
282
+ }
283
+
206
284
  return newData;
207
285
  },
208
286
  },