@falai/agent 0.1.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 +516 -0
- package/dist/constants/index.d.ts +5 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +5 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/core/Agent.d.ts +98 -0
- package/dist/core/Agent.d.ts.map +1 -0
- package/dist/core/Agent.js +248 -0
- package/dist/core/Agent.js.map +1 -0
- package/dist/core/DomainRegistry.d.ts +26 -0
- package/dist/core/DomainRegistry.d.ts.map +1 -0
- package/dist/core/DomainRegistry.js +41 -0
- package/dist/core/DomainRegistry.js.map +1 -0
- package/dist/core/Events.d.ts +19 -0
- package/dist/core/Events.d.ts.map +1 -0
- package/dist/core/Events.js +79 -0
- package/dist/core/Events.js.map +1 -0
- package/dist/core/Observation.d.ts +24 -0
- package/dist/core/Observation.d.ts.map +1 -0
- package/dist/core/Observation.js +35 -0
- package/dist/core/Observation.js.map +1 -0
- package/dist/core/PromptBuilder.d.ts +121 -0
- package/dist/core/PromptBuilder.d.ts.map +1 -0
- package/dist/core/PromptBuilder.js +339 -0
- package/dist/core/PromptBuilder.js.map +1 -0
- package/dist/core/Route.d.ts +46 -0
- package/dist/core/Route.d.ts.map +1 -0
- package/dist/core/Route.js +113 -0
- package/dist/core/Route.js.map +1 -0
- package/dist/core/State.d.ts +50 -0
- package/dist/core/State.d.ts.map +1 -0
- package/dist/core/State.js +110 -0
- package/dist/core/State.js.map +1 -0
- package/dist/core/Tool.d.ts +31 -0
- package/dist/core/Tool.d.ts.map +1 -0
- package/dist/core/Tool.js +33 -0
- package/dist/core/Tool.js.map +1 -0
- package/dist/core/Transition.d.ts +32 -0
- package/dist/core/Transition.d.ts.map +1 -0
- package/dist/core/Transition.js +59 -0
- package/dist/core/Transition.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/GeminiProvider.d.ts +40 -0
- package/dist/providers/GeminiProvider.d.ts.map +1 -0
- package/dist/providers/GeminiProvider.js +126 -0
- package/dist/providers/GeminiProvider.js.map +1 -0
- package/dist/providers/OpenAIProvider.d.ts +42 -0
- package/dist/providers/OpenAIProvider.d.ts.map +1 -0
- package/dist/providers/OpenAIProvider.js +164 -0
- package/dist/providers/OpenAIProvider.js.map +1 -0
- package/dist/providers/OpenRouterProvider.d.ts +46 -0
- package/dist/providers/OpenRouterProvider.d.ts.map +1 -0
- package/dist/providers/OpenRouterProvider.js +171 -0
- package/dist/providers/OpenRouterProvider.js.map +1 -0
- package/dist/types/agent.d.ts +105 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +18 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/ai.d.ts +78 -0
- package/dist/types/ai.d.ts.map +1 -0
- package/dist/types/ai.js +5 -0
- package/dist/types/ai.js.map +1 -0
- package/dist/types/history.d.ts +112 -0
- package/dist/types/history.d.ts.map +1 -0
- package/dist/types/history.js +34 -0
- package/dist/types/history.js.map +1 -0
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/observation.d.ts +25 -0
- package/dist/types/observation.d.ts.map +1 -0
- package/dist/types/observation.js +5 -0
- package/dist/types/observation.js.map +1 -0
- package/dist/types/prompt.d.ts +46 -0
- package/dist/types/prompt.d.ts.map +1 -0
- package/dist/types/prompt.js +16 -0
- package/dist/types/prompt.js.map +1 -0
- package/dist/types/route.d.ts +59 -0
- package/dist/types/route.d.ts.map +1 -0
- package/dist/types/route.js +5 -0
- package/dist/types/route.js.map +1 -0
- package/dist/types/tool.d.ts +46 -0
- package/dist/types/tool.d.ts.map +1 -0
- package/dist/types/tool.js +5 -0
- package/dist/types/tool.js.map +1 -0
- package/dist/utils/retry.d.ts +13 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +70 -0
- package/dist/utils/retry.js.map +1 -0
- package/docs/API_REFERENCE.md +517 -0
- package/docs/CONSTRUCTOR_OPTIONS.md +256 -0
- package/docs/CONTRIBUTING.md +481 -0
- package/docs/GETTING_STARTED.md +328 -0
- package/docs/PROVIDERS.md +472 -0
- package/docs/PUBLISHING.md +174 -0
- package/docs/README.md +68 -0
- package/docs/STRUCTURE.md +32 -0
- package/examples/declarative-agent.ts +217 -0
- package/examples/healthcare-agent.ts +283 -0
- package/examples/openai-agent.ts +167 -0
- package/examples/travel-agent.ts +342 -0
- package/package.json +73 -0
- package/src/constants/index.ts +5 -0
- package/src/core/Agent.ts +307 -0
- package/src/core/DomainRegistry.ts +50 -0
- package/src/core/Events.ts +101 -0
- package/src/core/Observation.ts +46 -0
- package/src/core/PromptBuilder.ts +511 -0
- package/src/core/Route.ts +136 -0
- package/src/core/State.ts +153 -0
- package/src/core/Tool.ts +54 -0
- package/src/core/Transition.ts +66 -0
- package/src/index.ts +83 -0
- package/src/providers/GeminiProvider.ts +220 -0
- package/src/providers/OpenAIProvider.ts +272 -0
- package/src/providers/OpenRouterProvider.ts +282 -0
- package/src/types/agent.ts +112 -0
- package/src/types/ai.ts +85 -0
- package/src/types/history.ts +125 -0
- package/src/types/index.ts +56 -0
- package/src/types/observation.ts +27 -0
- package/src/types/prompt.ts +49 -0
- package/src/types/route.ts +68 -0
- package/src/types/tool.ts +53 -0
- package/src/utils/retry.ts +96 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Package Structure
|
|
2
|
+
|
|
3
|
+
\`\`\`
|
|
4
|
+
src/
|
|
5
|
+
βββ types/ # Type definitions (interfaces, types, enums)
|
|
6
|
+
βββ core/ # Core framework classes
|
|
7
|
+
β βββ Agent.ts # Main agent class
|
|
8
|
+
β βββ Route.ts # Route/Journey DSL
|
|
9
|
+
β βββ State.ts # State management
|
|
10
|
+
β βββ Transition.ts # State transitions
|
|
11
|
+
β βββ Observation.ts # Disambiguation
|
|
12
|
+
β βββ Tool.ts # Tool definitions
|
|
13
|
+
β βββ PromptBuilder.ts # Prompt construction
|
|
14
|
+
β βββ Events.ts # Event history
|
|
15
|
+
β βββ DomainRegistry.ts # Domain organization
|
|
16
|
+
βββ providers/ # AI provider implementations
|
|
17
|
+
β βββ GeminiProvider.ts # Google Gemini AI
|
|
18
|
+
βββ utils/ # Utility functions
|
|
19
|
+
β βββ retry.ts # Retry/timeout logic
|
|
20
|
+
βββ constants/ # Constants and symbols
|
|
21
|
+
β βββ index.ts # END_ROUTE, etc.
|
|
22
|
+
βββ index.ts # Public API exports
|
|
23
|
+
\`\`\`
|
|
24
|
+
|
|
25
|
+
## Design Principles
|
|
26
|
+
|
|
27
|
+
1. **Flat, organized structure** - Clear separation by purpose
|
|
28
|
+
2. **Types-first** - All types in dedicated folder
|
|
29
|
+
3. **Core logic isolated** - Business logic in \`core/\`
|
|
30
|
+
4. **Provider pattern** - Pluggable AI backends
|
|
31
|
+
5. **Path aliases** - Clean imports with \`@/types\`, \`@/core\`, etc.
|
|
32
|
+
6. **Fluent API** - Methods return \`this\` for chaining
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: Declarative Agent Configuration
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to configure an entire agent
|
|
5
|
+
* using declarative syntax in the constructor, including:
|
|
6
|
+
* - Terms (glossary)
|
|
7
|
+
* - Guidelines (behavior rules)
|
|
8
|
+
* - Capabilities
|
|
9
|
+
* - Routes with nested guidelines
|
|
10
|
+
* - Observations with route references
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
Agent,
|
|
15
|
+
GeminiProvider,
|
|
16
|
+
defineTool,
|
|
17
|
+
createMessageEvent,
|
|
18
|
+
EventSource,
|
|
19
|
+
type Term,
|
|
20
|
+
type Guideline,
|
|
21
|
+
type Capability,
|
|
22
|
+
type RouteOptions,
|
|
23
|
+
type ObservationOptions,
|
|
24
|
+
} from "../src/index";
|
|
25
|
+
|
|
26
|
+
// Context type
|
|
27
|
+
interface HealthcareContext {
|
|
28
|
+
patientId: string;
|
|
29
|
+
patientName: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Define tools
|
|
33
|
+
const getInsuranceProviders = defineTool<HealthcareContext, [], string[]>(
|
|
34
|
+
"get_insurance_providers",
|
|
35
|
+
async () => {
|
|
36
|
+
return { data: ["MegaCare Insurance", "HealthFirst", "WellnessPlus"] };
|
|
37
|
+
},
|
|
38
|
+
{ description: "Retrieves list of accepted insurance providers" }
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const getAvailableSlots = defineTool<
|
|
42
|
+
HealthcareContext,
|
|
43
|
+
[],
|
|
44
|
+
{ date: string; time: string }[]
|
|
45
|
+
>(
|
|
46
|
+
"get_available_slots",
|
|
47
|
+
async () => {
|
|
48
|
+
return {
|
|
49
|
+
data: [
|
|
50
|
+
{ date: "2025-10-20", time: "10:00 AM" },
|
|
51
|
+
{ date: "2025-10-20", time: "2:00 PM" },
|
|
52
|
+
{ date: "2025-10-21", time: "1:00 PM" },
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
{ description: "Gets available appointment slots" }
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const getLabResults = defineTool<
|
|
60
|
+
HealthcareContext,
|
|
61
|
+
[],
|
|
62
|
+
{ report: string; status: string }
|
|
63
|
+
>(
|
|
64
|
+
"get_lab_results",
|
|
65
|
+
async ({ context }) => {
|
|
66
|
+
return {
|
|
67
|
+
data: {
|
|
68
|
+
report: `Lab results for ${context.patientName}`,
|
|
69
|
+
status: "All values within normal range",
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
{ description: "Retrieves patient lab results" }
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// Declarative configuration
|
|
77
|
+
const terms: Term[] = [
|
|
78
|
+
{
|
|
79
|
+
name: "Office Phone Number",
|
|
80
|
+
description: "The phone number of our office, at +1-234-567-8900",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "Office Hours",
|
|
84
|
+
description: "Office hours are Monday to Friday, 9 AM to 5 PM",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "Dr. Charles Xavier",
|
|
88
|
+
description: "Neurologist specializing in brain disorders",
|
|
89
|
+
synonyms: ["Professor X", "Dr. Xavier"],
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const guidelines: Guideline[] = [
|
|
94
|
+
{
|
|
95
|
+
condition: "The patient asks about insurance",
|
|
96
|
+
action:
|
|
97
|
+
"List the insurance providers we accept and tell them to call the office for more details",
|
|
98
|
+
tools: [getInsuranceProviders],
|
|
99
|
+
tags: ["insurance", "billing"],
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
condition: "The patient asks to talk to a human agent",
|
|
103
|
+
action: "Provide the office phone number and office hours",
|
|
104
|
+
tags: ["escalation"],
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
condition: "The patient inquires about something unrelated to healthcare",
|
|
108
|
+
action:
|
|
109
|
+
"Kindly tell them you cannot assist with off-topic inquiries - do not engage",
|
|
110
|
+
tags: ["off-topic"],
|
|
111
|
+
},
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
const capabilities: Capability[] = [
|
|
115
|
+
{
|
|
116
|
+
title: "Appointment Scheduling",
|
|
117
|
+
description: "Schedule, reschedule, or cancel patient appointments",
|
|
118
|
+
tools: [getAvailableSlots],
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
title: "Lab Results Access",
|
|
122
|
+
description: "Retrieve and explain patient lab results",
|
|
123
|
+
tools: [getLabResults],
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
const routes: RouteOptions[] = [
|
|
128
|
+
{
|
|
129
|
+
title: "Schedule Appointment",
|
|
130
|
+
description: "Helps the patient schedule an appointment",
|
|
131
|
+
conditions: ["The patient wants to schedule an appointment"],
|
|
132
|
+
guidelines: [
|
|
133
|
+
{
|
|
134
|
+
condition: "The patient says their visit is urgent",
|
|
135
|
+
action: "Tell them to call the office immediately",
|
|
136
|
+
tags: ["urgent"],
|
|
137
|
+
enabled: true,
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
title: "Check Lab Results",
|
|
143
|
+
description: "Retrieves and explains patient lab results",
|
|
144
|
+
conditions: ["The patient wants to see their lab results"],
|
|
145
|
+
guidelines: [
|
|
146
|
+
{
|
|
147
|
+
condition: "The patient presses for more conclusions about results",
|
|
148
|
+
action:
|
|
149
|
+
"Assertively tell them they should call the office to speak with a doctor",
|
|
150
|
+
tags: ["escalation"],
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
const observations: ObservationOptions[] = [
|
|
157
|
+
{
|
|
158
|
+
description:
|
|
159
|
+
"The patient asks to follow up on their visit, but it's not clear in which way",
|
|
160
|
+
routeRefs: ["Schedule Appointment", "Check Lab Results"], // Reference by title
|
|
161
|
+
},
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
// Create the fully configured agent
|
|
165
|
+
const agent = new Agent<HealthcareContext>({
|
|
166
|
+
name: "HealthBot",
|
|
167
|
+
description: "A compassionate healthcare assistant",
|
|
168
|
+
goal: "Provide helpful information and assist with appointments",
|
|
169
|
+
context: {
|
|
170
|
+
patientId: "p_12345",
|
|
171
|
+
patientName: "Alice Johnson",
|
|
172
|
+
},
|
|
173
|
+
ai: new GeminiProvider({
|
|
174
|
+
apiKey: process.env.GEMINI_API_KEY || "demo-key",
|
|
175
|
+
}),
|
|
176
|
+
// Declarative initialization
|
|
177
|
+
terms,
|
|
178
|
+
guidelines,
|
|
179
|
+
capabilities,
|
|
180
|
+
routes,
|
|
181
|
+
observations,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// You can still add more dynamically after construction
|
|
185
|
+
agent
|
|
186
|
+
.createGuideline({
|
|
187
|
+
condition: "The patient seems confused or distressed",
|
|
188
|
+
action: "Speak slowly, clearly, and offer to connect them with a human",
|
|
189
|
+
tags: ["empathy", "support"],
|
|
190
|
+
})
|
|
191
|
+
.createTerm({
|
|
192
|
+
name: "Telemedicine",
|
|
193
|
+
description: "Remote medical consultation via video call",
|
|
194
|
+
synonyms: ["virtual visit", "video appointment"],
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Example usage
|
|
198
|
+
async function main() {
|
|
199
|
+
const history = [
|
|
200
|
+
createMessageEvent(
|
|
201
|
+
EventSource.CUSTOMER,
|
|
202
|
+
"Alice",
|
|
203
|
+
"Hi, I need to follow up on my recent visit"
|
|
204
|
+
),
|
|
205
|
+
];
|
|
206
|
+
|
|
207
|
+
const response = await agent.respond({ history });
|
|
208
|
+
console.log("Agent:", response.message);
|
|
209
|
+
|
|
210
|
+
// The agent will use the observation to disambiguate
|
|
211
|
+
// and ask which type of follow-up the patient needs
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Uncomment to run:
|
|
215
|
+
// main().catch(console.error);
|
|
216
|
+
|
|
217
|
+
export { agent };
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Healthcare agent example demonstrating observations and disambiguation
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Agent,
|
|
7
|
+
defineTool,
|
|
8
|
+
GeminiProvider,
|
|
9
|
+
END_ROUTE,
|
|
10
|
+
EventSource,
|
|
11
|
+
createMessageEvent,
|
|
12
|
+
} from "../src/index";
|
|
13
|
+
|
|
14
|
+
// Context type
|
|
15
|
+
interface HealthcareContext {
|
|
16
|
+
patientId: string;
|
|
17
|
+
patientName: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Tools
|
|
21
|
+
const getInsuranceProviders = defineTool<HealthcareContext, [], string[]>(
|
|
22
|
+
"get_insurance_providers",
|
|
23
|
+
async () => {
|
|
24
|
+
return { data: ["Mega Insurance", "Acme Insurance"] };
|
|
25
|
+
},
|
|
26
|
+
{ description: "Get list of accepted insurance providers" }
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const getUpcomingSlots = defineTool<HealthcareContext, [], string[]>(
|
|
30
|
+
"get_upcoming_slots",
|
|
31
|
+
async () => {
|
|
32
|
+
return { data: ["Monday 10 AM", "Tuesday 2 PM", "Wednesday 1 PM"] };
|
|
33
|
+
},
|
|
34
|
+
{ description: "Get upcoming appointment slots" }
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const getLaterSlots = defineTool<HealthcareContext, [], string[]>(
|
|
38
|
+
"get_later_slots",
|
|
39
|
+
async () => {
|
|
40
|
+
return { data: ["November 3, 11:30 AM", "November 12, 3 PM"] };
|
|
41
|
+
},
|
|
42
|
+
{ description: "Get later appointment slots" }
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const scheduleAppointment = defineTool<
|
|
46
|
+
HealthcareContext,
|
|
47
|
+
[datetime: string],
|
|
48
|
+
string
|
|
49
|
+
>("schedule_appointment", async (_, datetime) => {
|
|
50
|
+
return { data: `Appointment scheduled for ${datetime}` };
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const getLabResults = defineTool<HealthcareContext, [], object>(
|
|
54
|
+
"get_lab_results",
|
|
55
|
+
async ({ context }) => {
|
|
56
|
+
return {
|
|
57
|
+
data: {
|
|
58
|
+
report: "All tests are within the valid range",
|
|
59
|
+
prognosis: "Patient is healthy as a horse!",
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
async function createHealthcareAgent() {
|
|
66
|
+
const provider = new GeminiProvider({
|
|
67
|
+
apiKey: process.env.GEMINI_API_KEY || "test-key",
|
|
68
|
+
model: "models/gemini-2.5-flash",
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const agent = new Agent<HealthcareContext>({
|
|
72
|
+
name: "Healthcare Agent",
|
|
73
|
+
description: "Is empathetic and calming to the patient.",
|
|
74
|
+
ai: provider,
|
|
75
|
+
context: {
|
|
76
|
+
patientId: "patient-123",
|
|
77
|
+
patientName: "Test Patient",
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Add domain glossary
|
|
82
|
+
agent.createTerm({
|
|
83
|
+
name: "Office Phone Number",
|
|
84
|
+
description: "The phone number of our office, at +1-234-567-8900",
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
agent.createTerm({
|
|
88
|
+
name: "Office Hours",
|
|
89
|
+
description: "Office hours are Monday to Friday, 9 AM to 5 PM",
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
agent.createTerm({
|
|
93
|
+
name: "Charles Xavier",
|
|
94
|
+
synonyms: ["Professor X"],
|
|
95
|
+
description:
|
|
96
|
+
"The doctor who specializes in neurology and is available on Mondays and Tuesdays.",
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Create scheduling route
|
|
100
|
+
const schedulingRoute = agent.createRoute({
|
|
101
|
+
title: "Schedule an Appointment",
|
|
102
|
+
description: "Helps the patient find a time for their appointment.",
|
|
103
|
+
conditions: ["The patient wants to schedule an appointment"],
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const t0 = schedulingRoute.initialState.transitionTo({
|
|
107
|
+
chatState: "Determine the reason for the visit",
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const t1 = t0.target.transitionTo({
|
|
111
|
+
toolState: getUpcomingSlots,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const t2 = t1.target.transitionTo({
|
|
115
|
+
chatState: "List available times and ask which ones works for them",
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const t3 = t2.target.transitionTo(
|
|
119
|
+
{
|
|
120
|
+
chatState: "Confirm the details with the patient before scheduling",
|
|
121
|
+
},
|
|
122
|
+
"The patient picks a time"
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const t4 = t3.target.transitionTo(
|
|
126
|
+
{
|
|
127
|
+
toolState: scheduleAppointment,
|
|
128
|
+
},
|
|
129
|
+
"The patient confirms the details"
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const t5 = t4.target.transitionTo({
|
|
133
|
+
chatState: "Confirm the appointment has been scheduled",
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
t5.target.transitionTo({ state: END_ROUTE });
|
|
137
|
+
|
|
138
|
+
// Alternative path: no times work
|
|
139
|
+
const t6 = t2.target.transitionTo(
|
|
140
|
+
{
|
|
141
|
+
toolState: getLaterSlots,
|
|
142
|
+
},
|
|
143
|
+
"None of those times work for the patient"
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const t7 = t6.target.transitionTo({
|
|
147
|
+
chatState: "List later times and ask if any of them works",
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
t7.target.transitionTo(
|
|
151
|
+
{
|
|
152
|
+
state: t3.target,
|
|
153
|
+
},
|
|
154
|
+
"The patient picks a time"
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
const t8 = t7.target.transitionTo(
|
|
158
|
+
{
|
|
159
|
+
chatState:
|
|
160
|
+
"Ask the patient to call the office to schedule an appointment",
|
|
161
|
+
},
|
|
162
|
+
"None of those times work for the patient either"
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
t8.target.transitionTo({ state: END_ROUTE });
|
|
166
|
+
|
|
167
|
+
schedulingRoute.createGuideline({
|
|
168
|
+
condition: "The patient says their visit is urgent",
|
|
169
|
+
action: "Tell them to call the office immediately",
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Create lab results route
|
|
173
|
+
const labResultsRoute = agent.createRoute({
|
|
174
|
+
title: "Lab Results",
|
|
175
|
+
description: "Retrieves the patient's lab results and explains them.",
|
|
176
|
+
conditions: ["The patient wants to see their lab results"],
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const l0 = labResultsRoute.initialState.transitionTo({
|
|
180
|
+
toolState: getLabResults,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
l0.target.transitionTo(
|
|
184
|
+
{
|
|
185
|
+
chatState:
|
|
186
|
+
"Tell the patient that the results are not available yet, and to try again later",
|
|
187
|
+
},
|
|
188
|
+
"The lab results could not be found"
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
l0.target.transitionTo(
|
|
192
|
+
{
|
|
193
|
+
chatState:
|
|
194
|
+
"Explain the lab results to the patient - that they are normal",
|
|
195
|
+
},
|
|
196
|
+
"The lab results are good - i.e., nothing to worry about"
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
l0.target.transitionTo(
|
|
200
|
+
{
|
|
201
|
+
chatState:
|
|
202
|
+
"Present the results and ask them to call the office for clarifications on the results as you are not a doctor",
|
|
203
|
+
},
|
|
204
|
+
"The lab results are not good - i.e., there's an issue with the patient's health"
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
labResultsRoute.createGuideline({
|
|
208
|
+
condition:
|
|
209
|
+
"The patient presses you for more conclusions about the lab results",
|
|
210
|
+
action:
|
|
211
|
+
"Assertively tell them that you cannot help and they should call the office",
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Create observation for disambiguation
|
|
215
|
+
const statusInquiry = agent.createObservation(
|
|
216
|
+
"The patient asks to follow up on their visit, but it's not clear in which way"
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
// Use observation to disambiguate between the two routes
|
|
220
|
+
statusInquiry.disambiguate([schedulingRoute, labResultsRoute]);
|
|
221
|
+
|
|
222
|
+
// Global guidelines
|
|
223
|
+
agent.createGuideline({
|
|
224
|
+
condition: "The patient asks about insurance",
|
|
225
|
+
action:
|
|
226
|
+
"List the insurance providers we accept, and tell them to call the office for more details",
|
|
227
|
+
tools: [getInsuranceProviders],
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
agent.createGuideline({
|
|
231
|
+
condition: "The patient asks to talk to a human agent",
|
|
232
|
+
action: "Ask them to call the office, providing the phone number",
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
agent.createGuideline({
|
|
236
|
+
condition:
|
|
237
|
+
"The patient inquires about something that has nothing to do with our healthcare",
|
|
238
|
+
action:
|
|
239
|
+
"Kindly tell them you cannot assist with off-topic inquiries - do not engage with their request.",
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
return agent;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Example usage
|
|
246
|
+
async function main() {
|
|
247
|
+
const agent = await createHealthcareAgent();
|
|
248
|
+
|
|
249
|
+
const history = [
|
|
250
|
+
createMessageEvent(
|
|
251
|
+
EventSource.CUSTOMER,
|
|
252
|
+
"Patient",
|
|
253
|
+
"Hi, I need to follow up on my visit"
|
|
254
|
+
),
|
|
255
|
+
];
|
|
256
|
+
|
|
257
|
+
console.log("Agent:", agent.name);
|
|
258
|
+
console.log("Description:", agent.description);
|
|
259
|
+
console.log("\nRoutes:", agent.getRoutes().length);
|
|
260
|
+
console.log("Terms:", agent.getTerms().length);
|
|
261
|
+
console.log("Guidelines:", agent.getGuidelines().length);
|
|
262
|
+
console.log("Observations:", agent.getObservations().length);
|
|
263
|
+
|
|
264
|
+
// Print routes
|
|
265
|
+
const routes = agent.getRoutes();
|
|
266
|
+
for (const route of routes) {
|
|
267
|
+
console.log("\n" + route.describe());
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Print observations
|
|
271
|
+
console.log("\nObservations:");
|
|
272
|
+
for (const obs of agent.getObservations()) {
|
|
273
|
+
console.log(
|
|
274
|
+
`- "${obs.description}" (disambiguates ${obs.getRoutes().length} routes)`
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
280
|
+
main().catch(console.error);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export { createHealthcareAgent };
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: OpenAI Agent with multiple providers
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to use the OpenAI provider
|
|
5
|
+
* and how to switch between different AI providers
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
Agent,
|
|
10
|
+
OpenAIProvider,
|
|
11
|
+
defineTool,
|
|
12
|
+
createMessageEvent,
|
|
13
|
+
EventSource,
|
|
14
|
+
} from "../src/index";
|
|
15
|
+
|
|
16
|
+
// Custom context type
|
|
17
|
+
interface CustomerContext {
|
|
18
|
+
customerId: string;
|
|
19
|
+
name: string;
|
|
20
|
+
preferences: string[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Define a simple tool
|
|
24
|
+
const getWeather = defineTool<
|
|
25
|
+
CustomerContext,
|
|
26
|
+
[{ location: string }],
|
|
27
|
+
{ location: string; temperature: number; condition: string }
|
|
28
|
+
>(
|
|
29
|
+
"get_weather",
|
|
30
|
+
async (_context, args) => {
|
|
31
|
+
// Simulate API call
|
|
32
|
+
return {
|
|
33
|
+
data: {
|
|
34
|
+
location: args.location,
|
|
35
|
+
temperature: 72,
|
|
36
|
+
condition: "Sunny",
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
description: "Get current weather for a location",
|
|
42
|
+
parameters: {
|
|
43
|
+
location: { type: "string", description: "City name" },
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
async function main() {
|
|
49
|
+
// Initialize OpenAI provider
|
|
50
|
+
const openaiProvider = new OpenAIProvider({
|
|
51
|
+
apiKey: process.env.OPENAI_API_KEY || "",
|
|
52
|
+
model: "gpt-5", // Latest model
|
|
53
|
+
config: {
|
|
54
|
+
temperature: 0.7,
|
|
55
|
+
max_tokens: 1000,
|
|
56
|
+
},
|
|
57
|
+
// Optional: customize backup models
|
|
58
|
+
backupModels: ["gpt-5-mini", "gpt-5-nano"],
|
|
59
|
+
// Optional: customize retry config
|
|
60
|
+
retryConfig: {
|
|
61
|
+
timeout: 30000,
|
|
62
|
+
retries: 2,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Create agent with OpenAI
|
|
67
|
+
const agent = new Agent<CustomerContext>({
|
|
68
|
+
name: "Assistant",
|
|
69
|
+
description:
|
|
70
|
+
"A helpful AI assistant that can check weather and answer questions",
|
|
71
|
+
goal: "Assist users with information and weather queries",
|
|
72
|
+
context: {
|
|
73
|
+
customerId: "user123",
|
|
74
|
+
name: "Alice",
|
|
75
|
+
preferences: ["concise answers", "weather updates"],
|
|
76
|
+
},
|
|
77
|
+
ai: openaiProvider,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Add domain knowledge
|
|
81
|
+
agent
|
|
82
|
+
.createTerm({
|
|
83
|
+
name: "Weather Service",
|
|
84
|
+
description: "Our real-time weather information service",
|
|
85
|
+
synonyms: ["weather API", "forecast service"],
|
|
86
|
+
})
|
|
87
|
+
.createGuideline({
|
|
88
|
+
action:
|
|
89
|
+
"Always provide temperature in Fahrenheit and include the current condition",
|
|
90
|
+
tags: ["weather", "formatting"],
|
|
91
|
+
enabled: true,
|
|
92
|
+
})
|
|
93
|
+
.createGuideline({
|
|
94
|
+
condition: "User asks for weather in multiple cities",
|
|
95
|
+
action: "Offer to check weather for each city one by one",
|
|
96
|
+
enabled: true,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Create a simple route
|
|
100
|
+
const weatherRoute = agent.createRoute({
|
|
101
|
+
title: "Check Weather",
|
|
102
|
+
description: "Help user check weather for a location",
|
|
103
|
+
conditions: ["User wants to know the weather"],
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Add states and transitions
|
|
107
|
+
const askLocation = weatherRoute.initialState.transitionTo({
|
|
108
|
+
chatState: "Ask which city they want weather for",
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const fetchWeather = askLocation.target.transitionTo({
|
|
112
|
+
toolState: getWeather,
|
|
113
|
+
condition: "User provides a city name",
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const showWeather = fetchWeather.target.transitionTo({
|
|
117
|
+
chatState:
|
|
118
|
+
"Present the weather information in a friendly way with temperature and condition",
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Simulate a conversation
|
|
122
|
+
console.log("π€ Starting OpenAI Agent Example\n");
|
|
123
|
+
|
|
124
|
+
// Build history
|
|
125
|
+
const history = [
|
|
126
|
+
createMessageEvent(
|
|
127
|
+
EventSource.CUSTOMER,
|
|
128
|
+
"Alice",
|
|
129
|
+
"What's the weather like in San Francisco?"
|
|
130
|
+
),
|
|
131
|
+
];
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
// Generate response (this would call OpenAI)
|
|
135
|
+
console.log("π€ Sending request to OpenAI...");
|
|
136
|
+
|
|
137
|
+
// In a real scenario, you would call agent.generateMessage() or similar
|
|
138
|
+
// For now, let's just show the structure:
|
|
139
|
+
console.log("\nβ
Agent Configuration:");
|
|
140
|
+
console.log(` AI Provider: ${openaiProvider.name}`);
|
|
141
|
+
|
|
142
|
+
console.log("\nπΊοΈ Route Configuration:");
|
|
143
|
+
console.log(` Title: ${weatherRoute.title}`);
|
|
144
|
+
console.log(
|
|
145
|
+
` States: Initial β Ask Location β Fetch Weather β Show Weather`
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
console.log("\n㪠Conversation History:");
|
|
149
|
+
history.forEach((event, i) => {
|
|
150
|
+
console.log(` ${i + 1}. ${event.source}: ${event.data.message}`);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
console.log("\n⨠Ready to process with OpenAI provider!");
|
|
154
|
+
console.log(
|
|
155
|
+
" (Set OPENAI_API_KEY environment variable to make actual API calls)"
|
|
156
|
+
);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error("β Error:", error);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Run if executed directly
|
|
163
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
164
|
+
main().catch(console.error);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export { main };
|