@falai/agent 0.1.5 → 0.3.0
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 +65 -4
- package/dist/cjs/core/Agent.d.ts +11 -0
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +44 -2
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/State.d.ts +1 -1
- package/dist/cjs/core/State.d.ts.map +1 -1
- package/dist/cjs/core/State.js +4 -10
- package/dist/cjs/core/State.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/agent.d.ts +24 -0
- package/dist/cjs/types/agent.d.ts.map +1 -1
- package/dist/cjs/types/route.d.ts +4 -6
- package/dist/cjs/types/route.d.ts.map +1 -1
- package/dist/cjs/types/tool.d.ts +6 -2
- package/dist/cjs/types/tool.d.ts.map +1 -1
- package/dist/core/Agent.d.ts +11 -0
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +44 -2
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/State.d.ts +1 -1
- package/dist/core/State.d.ts.map +1 -1
- package/dist/core/State.js +4 -10
- package/dist/core/State.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/agent.d.ts +24 -0
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/route.d.ts +4 -6
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/tool.d.ts +6 -2
- package/dist/types/tool.d.ts.map +1 -1
- package/docs/API_REFERENCE.md +25 -1
- package/docs/CONTEXT_MANAGEMENT.md +447 -0
- package/docs/GETTING_STARTED.md +3 -3
- package/examples/healthcare-agent.ts +15 -15
- package/examples/openai-agent.ts +2 -2
- package/examples/persistent-onboarding.ts +464 -0
- package/examples/travel-agent.ts +17 -17
- package/package.json +1 -1
- package/src/core/Agent.ts +56 -2
- package/src/core/State.ts +6 -25
- package/src/index.ts +2 -0
- package/src/types/agent.ts +32 -0
- package/src/types/route.ts +7 -9
- package/src/types/tool.ts +6 -2
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
# Context Management & Persistence
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The `@falai/agent` framework provides flexible patterns for managing context in both **single-turn** and **multi-turn persistent** conversations. This guide explains how to handle stateful conversations that persist across requests.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🤔 The Context Lifecycle Problem
|
|
10
|
+
|
|
11
|
+
### Single-Turn Conversations (Simple)
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// ✅ Works great for single-turn conversations
|
|
15
|
+
const agent = new Agent({
|
|
16
|
+
name: "Bot",
|
|
17
|
+
ai: provider,
|
|
18
|
+
context: { userId: "123", preferences: {} },
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const response = await agent.respond({ history });
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Works because:** Agent is used once and discarded.
|
|
25
|
+
|
|
26
|
+
### Multi-Turn Conversations (Complex)
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// ❌ PROBLEM: Context updates don't persist
|
|
30
|
+
const agent = new Agent({
|
|
31
|
+
name: "Bot",
|
|
32
|
+
ai: provider,
|
|
33
|
+
context: { userId: "123", preferences: {} },
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Turn 1
|
|
37
|
+
await agent.respond({ history: [message1] });
|
|
38
|
+
// Tool modifies context in memory...
|
|
39
|
+
|
|
40
|
+
// Turn 2 (new request, agent recreated)
|
|
41
|
+
const agent2 = new Agent({ context: { userId: "123", preferences: {} } });
|
|
42
|
+
await agent2.respond({ history: [message2] });
|
|
43
|
+
// ❌ Lost the context changes from Turn 1!
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Problem:** When agents are recreated (e.g., across HTTP requests), context updates are lost.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 💡 Solution: Context Lifecycle Hooks
|
|
51
|
+
|
|
52
|
+
The framework provides **lifecycle hooks** to integrate with your persistence layer (database, cache, etc.).
|
|
53
|
+
|
|
54
|
+
### Pattern 1: `beforeRespond` + `onContextUpdate` (Recommended)
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { Agent, type ContextLifecycleHooks } from "@falai/agent";
|
|
58
|
+
|
|
59
|
+
// Define hooks
|
|
60
|
+
const hooks: ContextLifecycleHooks<MyContext> = {
|
|
61
|
+
// Load fresh context before each response
|
|
62
|
+
beforeRespond: async (currentContext) => {
|
|
63
|
+
return await database.loadContext(sessionId);
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
// Persist context after updates
|
|
67
|
+
onContextUpdate: async (newContext, previousContext) => {
|
|
68
|
+
await database.saveContext(sessionId, newContext);
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Create agent with hooks
|
|
73
|
+
const agent = new Agent({
|
|
74
|
+
name: "Bot",
|
|
75
|
+
ai: provider,
|
|
76
|
+
context: initialContext,
|
|
77
|
+
hooks, // 🔑 Enable persistence
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**How it works:**
|
|
82
|
+
|
|
83
|
+
1. `beforeRespond` fetches fresh context from your database before `respond()` is called
|
|
84
|
+
2. Tools can update context using `toolContext.updateContext()` or returning `{ contextUpdate }`
|
|
85
|
+
3. `onContextUpdate` automatically persists changes to your database
|
|
86
|
+
4. Next request creates a new agent, `beforeRespond` loads the updated context
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 🔧 Tool Context Updates
|
|
91
|
+
|
|
92
|
+
Tools can update context in **two ways**:
|
|
93
|
+
|
|
94
|
+
### Option A: Return `contextUpdate`
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const saveName = defineTool<MyContext, [name: string], boolean>(
|
|
98
|
+
"save_name",
|
|
99
|
+
async (toolContext, name) => {
|
|
100
|
+
return {
|
|
101
|
+
data: true,
|
|
102
|
+
contextUpdate: {
|
|
103
|
+
userName: name,
|
|
104
|
+
updatedAt: new Date(),
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Pros:**
|
|
112
|
+
|
|
113
|
+
- Declarative and functional
|
|
114
|
+
- Easy to test
|
|
115
|
+
- Context update is part of the result
|
|
116
|
+
|
|
117
|
+
### Option B: Call `updateContext()` directly
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
const saveName = defineTool<MyContext, [name: string], boolean>(
|
|
121
|
+
"save_name",
|
|
122
|
+
async (toolContext, name) => {
|
|
123
|
+
await toolContext.updateContext({
|
|
124
|
+
userName: name,
|
|
125
|
+
updatedAt: new Date(),
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return { data: true };
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Pros:**
|
|
134
|
+
|
|
135
|
+
- More imperative and direct
|
|
136
|
+
- Can update context at any point in the tool
|
|
137
|
+
- Useful for complex logic
|
|
138
|
+
|
|
139
|
+
**Both approaches trigger the `onContextUpdate` hook automatically.**
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 🌐 Context Provider Pattern
|
|
144
|
+
|
|
145
|
+
For scenarios where context is **always loaded from an external source**, use the `contextProvider` pattern:
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
const agent = new Agent({
|
|
149
|
+
name: "Bot",
|
|
150
|
+
ai: provider,
|
|
151
|
+
|
|
152
|
+
// Instead of static context:
|
|
153
|
+
contextProvider: async () => {
|
|
154
|
+
// Fetch context fresh on every respond() call
|
|
155
|
+
return await database.loadContext(sessionId);
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
hooks: {
|
|
159
|
+
// Still persist updates
|
|
160
|
+
onContextUpdate: async (newContext) => {
|
|
161
|
+
await database.saveContext(sessionId, newContext);
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**When to use:**
|
|
168
|
+
|
|
169
|
+
- Context is always loaded from a database/cache
|
|
170
|
+
- You never have a static starting context
|
|
171
|
+
- You want guaranteed fresh data on every request
|
|
172
|
+
|
|
173
|
+
**Difference from `beforeRespond`:**
|
|
174
|
+
|
|
175
|
+
- `contextProvider`: **Replaces** the context entirely
|
|
176
|
+
- `beforeRespond`: **Updates** the existing context (can access previous state)
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 🎯 Complete Example: Multi-Turn Onboarding
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import { Agent, defineTool } from "@falai/agent";
|
|
184
|
+
|
|
185
|
+
interface OnboardingContext {
|
|
186
|
+
sessionId: string;
|
|
187
|
+
userId: string;
|
|
188
|
+
businessName?: string;
|
|
189
|
+
industry?: string;
|
|
190
|
+
completedSteps: string[];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Database simulation
|
|
194
|
+
const db = {
|
|
195
|
+
async loadSession(sessionId: string) {
|
|
196
|
+
return await database.findSession(sessionId);
|
|
197
|
+
},
|
|
198
|
+
async saveSession(sessionId: string, data: Partial<OnboardingContext>) {
|
|
199
|
+
await database.updateSession(sessionId, data);
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// Factory function for creating agents
|
|
204
|
+
async function createOnboardingAgent(sessionId: string) {
|
|
205
|
+
const session = await db.loadSession(sessionId);
|
|
206
|
+
|
|
207
|
+
const agent = new Agent<OnboardingContext>({
|
|
208
|
+
name: "OnboardingBot",
|
|
209
|
+
ai: provider,
|
|
210
|
+
context: {
|
|
211
|
+
sessionId,
|
|
212
|
+
userId: session.userId,
|
|
213
|
+
businessName: session.businessName,
|
|
214
|
+
industry: session.industry,
|
|
215
|
+
completedSteps: session.completedSteps || [],
|
|
216
|
+
},
|
|
217
|
+
hooks: {
|
|
218
|
+
// Load fresh context before responding
|
|
219
|
+
beforeRespond: async (current) => {
|
|
220
|
+
const fresh = await db.loadSession(sessionId);
|
|
221
|
+
return { ...current, ...fresh };
|
|
222
|
+
},
|
|
223
|
+
|
|
224
|
+
// Persist context after updates
|
|
225
|
+
onContextUpdate: async (newContext) => {
|
|
226
|
+
await db.saveSession(sessionId, {
|
|
227
|
+
businessName: newContext.businessName,
|
|
228
|
+
industry: newContext.industry,
|
|
229
|
+
completedSteps: newContext.completedSteps,
|
|
230
|
+
});
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Define tools with context updates
|
|
236
|
+
const saveBusinessName = defineTool(
|
|
237
|
+
"save_business_name",
|
|
238
|
+
async (ctx, name: string) => {
|
|
239
|
+
return {
|
|
240
|
+
data: true,
|
|
241
|
+
contextUpdate: {
|
|
242
|
+
businessName: name,
|
|
243
|
+
completedSteps: [...ctx.context.completedSteps, "business_name"],
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
const saveIndustry = defineTool(
|
|
250
|
+
"save_industry",
|
|
251
|
+
async (ctx, industry: string) => {
|
|
252
|
+
// Alternative: use updateContext directly
|
|
253
|
+
await ctx.updateContext({
|
|
254
|
+
industry,
|
|
255
|
+
completedSteps: [...ctx.context.completedSteps, "industry"],
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
return { data: true };
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
// Build conversation routes...
|
|
263
|
+
const route = agent.createRoute({ title: "Onboarding" });
|
|
264
|
+
// ...
|
|
265
|
+
|
|
266
|
+
return agent;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Usage across multiple turns
|
|
270
|
+
async function handleUserMessage(sessionId: string, message: string) {
|
|
271
|
+
// Recreate agent for each turn (context is loaded fresh)
|
|
272
|
+
const agent = await createOnboardingAgent(sessionId);
|
|
273
|
+
|
|
274
|
+
const response = await agent.respond({
|
|
275
|
+
history: [createMessageEvent(EventSource.CUSTOMER, "User", message)],
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
return response.message;
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## 📋 Best Practices
|
|
285
|
+
|
|
286
|
+
### ✅ DO
|
|
287
|
+
|
|
288
|
+
- **Recreate agents** for each request in multi-turn conversations
|
|
289
|
+
- **Use lifecycle hooks** to integrate with your database
|
|
290
|
+
- **Store context** in your database/cache (Redis, PostgreSQL, etc.)
|
|
291
|
+
- **Load fresh context** via `beforeRespond` or `contextProvider`
|
|
292
|
+
- **Test persistence** by simulating multiple turns
|
|
293
|
+
- **Handle errors** in hooks gracefully (fallback to current context)
|
|
294
|
+
|
|
295
|
+
### ❌ DON'T
|
|
296
|
+
|
|
297
|
+
- **Cache agent instances** across requests (context gets stale)
|
|
298
|
+
- **Mutate context directly** without using `updateContext()` or `contextUpdate`
|
|
299
|
+
- **Rely on in-memory state** for multi-turn conversations
|
|
300
|
+
- **Forget to handle** `onContextUpdate` failures (could lose data)
|
|
301
|
+
- **Mix** `context` and `contextProvider` (will throw an error)
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## 🔍 Debugging Context Issues
|
|
306
|
+
|
|
307
|
+
### Problem: Context updates aren't persisting
|
|
308
|
+
|
|
309
|
+
**Check:**
|
|
310
|
+
|
|
311
|
+
1. Are you using `onContextUpdate` hook?
|
|
312
|
+
2. Is your database save actually working?
|
|
313
|
+
3. Are you recreating the agent with fresh context each turn?
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
// Debug your hooks
|
|
317
|
+
hooks: {
|
|
318
|
+
beforeRespond: async (current) => {
|
|
319
|
+
console.log("📥 Loading context:", current);
|
|
320
|
+
const fresh = await db.load(sessionId);
|
|
321
|
+
console.log("✅ Loaded fresh:", fresh);
|
|
322
|
+
return fresh;
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
onContextUpdate: async (newContext) => {
|
|
326
|
+
console.log("💾 Saving context:", newContext);
|
|
327
|
+
await db.save(sessionId, newContext);
|
|
328
|
+
console.log("✅ Saved successfully");
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Problem: Context is null/undefined
|
|
334
|
+
|
|
335
|
+
**Check:**
|
|
336
|
+
|
|
337
|
+
1. Did you provide either `context` or `contextProvider`?
|
|
338
|
+
2. Is your `contextProvider` returning valid data?
|
|
339
|
+
3. Is `beforeRespond` returning valid context?
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
// Validate your contextProvider
|
|
343
|
+
contextProvider: async () => {
|
|
344
|
+
const ctx = await db.load(sessionId);
|
|
345
|
+
if (!ctx) {
|
|
346
|
+
console.error("❌ Context not found!");
|
|
347
|
+
throw new Error("Session not found");
|
|
348
|
+
}
|
|
349
|
+
return ctx;
|
|
350
|
+
},
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Problem: Tools not updating context
|
|
354
|
+
|
|
355
|
+
**Check:**
|
|
356
|
+
|
|
357
|
+
1. Are you returning `{ contextUpdate }` or calling `toolContext.updateContext()`?
|
|
358
|
+
2. Is `onContextUpdate` being called? (Add console.log)
|
|
359
|
+
3. Are your tools being executed at all?
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## 🚀 Advanced Patterns
|
|
364
|
+
|
|
365
|
+
### Pattern: Context Versioning
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
interface VersionedContext extends MyContext {
|
|
369
|
+
version: number;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
hooks: {
|
|
373
|
+
onContextUpdate: async (newContext) => {
|
|
374
|
+
await db.save(sessionId, {
|
|
375
|
+
...newContext,
|
|
376
|
+
version: newContext.version + 1,
|
|
377
|
+
});
|
|
378
|
+
},
|
|
379
|
+
|
|
380
|
+
beforeRespond: async (current) => {
|
|
381
|
+
const fresh = await db.load(sessionId);
|
|
382
|
+
if (fresh.version > current.version) {
|
|
383
|
+
console.log("⚠️ Context changed by another request!");
|
|
384
|
+
}
|
|
385
|
+
return fresh;
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Pattern: Selective Persistence
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
// Only persist specific fields
|
|
394
|
+
hooks: {
|
|
395
|
+
onContextUpdate: async (newContext) => {
|
|
396
|
+
// Don't persist temporary/computed fields
|
|
397
|
+
const { tempData, ...persistable } = newContext;
|
|
398
|
+
await db.save(sessionId, persistable);
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Pattern: Multi-User Context
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
interface MultiUserContext {
|
|
407
|
+
conversationId: string;
|
|
408
|
+
participants: Map<string, UserData>;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
hooks: {
|
|
412
|
+
beforeRespond: async (current) => {
|
|
413
|
+
// Load all participant data
|
|
414
|
+
const conversation = await db.loadConversation(conversationId);
|
|
415
|
+
return {
|
|
416
|
+
conversationId,
|
|
417
|
+
participants: new Map(conversation.participants),
|
|
418
|
+
};
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## 📚 Related Resources
|
|
426
|
+
|
|
427
|
+
- [Complete Example: Persistent Onboarding](../examples/persistent-onboarding.ts)
|
|
428
|
+
- [API Reference: AgentOptions](./API_REFERENCE.md#agentoptions)
|
|
429
|
+
- [API Reference: ContextLifecycleHooks](./API_REFERENCE.md#contextlifecyclehooks)
|
|
430
|
+
- [Getting Started](./GETTING_STARTED.md)
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## 🆘 Need Help?
|
|
435
|
+
|
|
436
|
+
If you're still having issues:
|
|
437
|
+
|
|
438
|
+
1. Check the [examples](../examples/) for working implementations
|
|
439
|
+
2. Review the [API Reference](./API_REFERENCE.md) for detailed type information
|
|
440
|
+
3. Open an issue on GitHub with your use case
|
|
441
|
+
|
|
442
|
+
**Remember:** The key to persistent conversations is:
|
|
443
|
+
|
|
444
|
+
1. **Recreate agents** each turn
|
|
445
|
+
2. **Load fresh context** via hooks/provider
|
|
446
|
+
3. **Persist updates** via `onContextUpdate`
|
|
447
|
+
4. **Never cache** agent instances across requests
|
package/docs/GETTING_STARTED.md
CHANGED
|
@@ -159,16 +159,16 @@ const step1 = onboardingRoute.initialState.transitionTo({
|
|
|
159
159
|
chatState: "Ask for user's name",
|
|
160
160
|
});
|
|
161
161
|
|
|
162
|
-
const step2 = step1.
|
|
162
|
+
const step2 = step1.transitionTo({
|
|
163
163
|
chatState: "Ask for user's email",
|
|
164
164
|
});
|
|
165
165
|
|
|
166
|
-
const step3 = step2.
|
|
166
|
+
const step3 = step2.transitionTo({
|
|
167
167
|
chatState: "Confirm details and welcome user",
|
|
168
168
|
});
|
|
169
169
|
|
|
170
170
|
// End the route
|
|
171
|
-
step3.
|
|
171
|
+
step3.transitionTo({ state: END_ROUTE });
|
|
172
172
|
```
|
|
173
173
|
|
|
174
174
|
### Handle Context Dynamically
|
|
@@ -107,54 +107,54 @@ async function createHealthcareAgent() {
|
|
|
107
107
|
chatState: "Determine the reason for the visit",
|
|
108
108
|
});
|
|
109
109
|
|
|
110
|
-
const t1 = t0.
|
|
110
|
+
const t1 = t0.transitionTo({
|
|
111
111
|
toolState: getUpcomingSlots,
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
-
const t2 = t1.
|
|
114
|
+
const t2 = t1.transitionTo({
|
|
115
115
|
chatState: "List available times and ask which ones works for them",
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
-
const t3 = t2.
|
|
118
|
+
const t3 = t2.transitionTo(
|
|
119
119
|
{
|
|
120
120
|
chatState: "Confirm the details with the patient before scheduling",
|
|
121
121
|
},
|
|
122
122
|
"The patient picks a time"
|
|
123
123
|
);
|
|
124
124
|
|
|
125
|
-
const t4 = t3.
|
|
125
|
+
const t4 = t3.transitionTo(
|
|
126
126
|
{
|
|
127
127
|
toolState: scheduleAppointment,
|
|
128
128
|
},
|
|
129
129
|
"The patient confirms the details"
|
|
130
130
|
);
|
|
131
131
|
|
|
132
|
-
const t5 = t4.
|
|
132
|
+
const t5 = t4.transitionTo({
|
|
133
133
|
chatState: "Confirm the appointment has been scheduled",
|
|
134
134
|
});
|
|
135
135
|
|
|
136
|
-
t5.
|
|
136
|
+
t5.transitionTo({ state: END_ROUTE });
|
|
137
137
|
|
|
138
138
|
// Alternative path: no times work
|
|
139
|
-
const t6 = t2.
|
|
139
|
+
const t6 = t2.transitionTo(
|
|
140
140
|
{
|
|
141
141
|
toolState: getLaterSlots,
|
|
142
142
|
},
|
|
143
143
|
"None of those times work for the patient"
|
|
144
144
|
);
|
|
145
145
|
|
|
146
|
-
const t7 = t6.
|
|
146
|
+
const t7 = t6.transitionTo({
|
|
147
147
|
chatState: "List later times and ask if any of them works",
|
|
148
148
|
});
|
|
149
149
|
|
|
150
|
-
t7.
|
|
150
|
+
t7.transitionTo(
|
|
151
151
|
{
|
|
152
|
-
state: t3
|
|
152
|
+
state: t3,
|
|
153
153
|
},
|
|
154
154
|
"The patient picks a time"
|
|
155
155
|
);
|
|
156
156
|
|
|
157
|
-
const t8 = t7.
|
|
157
|
+
const t8 = t7.transitionTo(
|
|
158
158
|
{
|
|
159
159
|
chatState:
|
|
160
160
|
"Ask the patient to call the office to schedule an appointment",
|
|
@@ -162,7 +162,7 @@ async function createHealthcareAgent() {
|
|
|
162
162
|
"None of those times work for the patient either"
|
|
163
163
|
);
|
|
164
164
|
|
|
165
|
-
t8.
|
|
165
|
+
t8.transitionTo({ state: END_ROUTE });
|
|
166
166
|
|
|
167
167
|
schedulingRoute.createGuideline({
|
|
168
168
|
condition: "The patient says their visit is urgent",
|
|
@@ -180,7 +180,7 @@ async function createHealthcareAgent() {
|
|
|
180
180
|
toolState: getLabResults,
|
|
181
181
|
});
|
|
182
182
|
|
|
183
|
-
l0.
|
|
183
|
+
l0.transitionTo(
|
|
184
184
|
{
|
|
185
185
|
chatState:
|
|
186
186
|
"Tell the patient that the results are not available yet, and to try again later",
|
|
@@ -188,7 +188,7 @@ async function createHealthcareAgent() {
|
|
|
188
188
|
"The lab results could not be found"
|
|
189
189
|
);
|
|
190
190
|
|
|
191
|
-
l0.
|
|
191
|
+
l0.transitionTo(
|
|
192
192
|
{
|
|
193
193
|
chatState:
|
|
194
194
|
"Explain the lab results to the patient - that they are normal",
|
|
@@ -196,7 +196,7 @@ async function createHealthcareAgent() {
|
|
|
196
196
|
"The lab results are good - i.e., nothing to worry about"
|
|
197
197
|
);
|
|
198
198
|
|
|
199
|
-
l0.
|
|
199
|
+
l0.transitionTo(
|
|
200
200
|
{
|
|
201
201
|
chatState:
|
|
202
202
|
"Present the results and ask them to call the office for clarifications on the results as you are not a doctor",
|
package/examples/openai-agent.ts
CHANGED
|
@@ -108,12 +108,12 @@ async function main() {
|
|
|
108
108
|
chatState: "Ask which city they want weather for",
|
|
109
109
|
});
|
|
110
110
|
|
|
111
|
-
const fetchWeather = askLocation.
|
|
111
|
+
const fetchWeather = askLocation.transitionTo({
|
|
112
112
|
toolState: getWeather,
|
|
113
113
|
condition: "User provides a city name",
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
-
const showWeather = fetchWeather.
|
|
116
|
+
const showWeather = fetchWeather.transitionTo({
|
|
117
117
|
chatState:
|
|
118
118
|
"Present the weather information in a friendly way with temperature and condition",
|
|
119
119
|
});
|