@falai/agent 0.3.24 → 0.3.30

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/docs/STRUCTURE.md CHANGED
@@ -3,6 +3,15 @@
3
3
  ```
4
4
  src/
5
5
  ├── types/ # Type definitions (interfaces, types, enums)
6
+ │ ├── agent.ts # Agent types and configuration
7
+ │ ├── ai.ts # AI provider interfaces
8
+ │ ├── history.ts # Event and message history types
9
+ │ ├── observation.ts # Observation and disambiguation types
10
+ │ ├── persistence.ts # Persistence adapter interfaces
11
+ │ ├── prompt.ts # Prompt building types
12
+ │ ├── route.ts # Route and state types
13
+ │ ├── tool.ts # Tool definition types
14
+ │ └── index.ts # Type exports
6
15
  ├── core/ # Core framework classes
7
16
  │ ├── Agent.ts # Main agent class
8
17
  │ ├── Route.ts # Route/Journey DSL
@@ -12,13 +21,28 @@ src/
12
21
  │ ├── Tool.ts # Tool definitions
13
22
  │ ├── PromptBuilder.ts # Prompt construction
14
23
  │ ├── Events.ts # Event history
15
- └── DomainRegistry.ts # Domain organization
24
+ ├── DomainRegistry.ts # Domain organization
25
+ │ └── PersistenceManager.ts # Persistence lifecycle management
16
26
  ├── providers/ # AI provider implementations
17
- └── GeminiProvider.ts # Google Gemini AI
27
+ ├── AnthropicProvider.ts # Claude (Anthropic)
28
+ │ ├── GeminiProvider.ts # Google Gemini
29
+ │ ├── OpenAIProvider.ts # OpenAI GPT
30
+ │ ├── OpenRouterProvider.ts # OpenRouter (200+ models)
31
+ │ └── index.ts # Provider exports
32
+ ├── adapters/ # Database persistence adapters
33
+ │ ├── MemoryAdapter.ts # In-memory (testing/dev)
34
+ │ ├── PrismaAdapter.ts # Prisma ORM
35
+ │ ├── RedisAdapter.ts # Redis
36
+ │ ├── MongoAdapter.ts # MongoDB
37
+ │ ├── PostgreSQLAdapter.ts # PostgreSQL
38
+ │ ├── SQLiteAdapter.ts # SQLite
39
+ │ ├── OpenSearchAdapter.ts # OpenSearch/Elasticsearch
40
+ │ └── index.ts # Adapter exports
18
41
  ├── utils/ # Utility functions
19
- └── retry.ts # Retry/timeout logic
42
+ ├── retry.ts # Retry/timeout logic
43
+ │ └── id.ts # Deterministic ID generation
20
44
  ├── constants/ # Constants and symbols
21
- │ └── index.ts # END_ROUTE, etc.
45
+ │ └── index.ts # END_ROUTE, EventSource, etc.
22
46
  └── index.ts # Public API exports
23
47
  ```
24
48
 
@@ -27,6 +51,8 @@ src/
27
51
  1. **Flat, organized structure** - Clear separation by purpose
28
52
  2. **Types-first** - All types in dedicated folder
29
53
  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
54
+ 4. **Provider pattern** - Pluggable AI backends and database adapters
55
+ 5. **Optional persistence** - Multiple database adapters following the same pattern
56
+ 6. **Extensibility** - Easy to add new providers, adapters, and tools
57
+ 7. **Path aliases** - Clean imports with \`@/types\`, \`@/core\`, etc.
58
+ 8. **Fluent API** - Methods return \`this\` for chaining
@@ -2,7 +2,13 @@
2
2
  * Domain Scoping Example
3
3
  *
4
4
  * This example demonstrates how to use domain scoping to restrict which tools
5
- * are available in different conversation routes for security and clarity.
5
+ * can EXECUTE in different conversation routes for security and isolation.
6
+ *
7
+ * Important: Domains are OPTIONAL. If you never use domains, all tools are
8
+ * available everywhere. Use domains when you need security and organization.
9
+ *
10
+ * Key Concept: The AI never sees tools. Domains control which tools can
11
+ * execute automatically when triggered by the state machine or guidelines.
6
12
  */
7
13
 
8
14
  import { Agent, createMessageEvent, EventSource } from "../src/index";
@@ -186,19 +192,21 @@ async function demonstrateScoping() {
186
192
  // Benefits demonstration
187
193
  console.log(`
188
194
  🔒 Security Benefits:
189
- - Customer Support route cannot accidentally call payment.processPayment()
190
- - Data Collection route cannot access calendar.scheduleEvent()
191
- - Each route has minimum necessary permissions
195
+ - Customer Support route cannot execute payment.processPayment()
196
+ - Data Collection route cannot execute calendar.scheduleEvent()
197
+ - Each route has minimum necessary tool permissions
198
+ - Prevents prompt injection attacks from calling sensitive tools
192
199
 
193
- Performance Benefits:
194
- - AI only sees relevant tools for each route
195
- - Faster decision making with reduced context
196
- - Clearer intent and fewer errors
200
+ 🎯 Isolation Benefits:
201
+ - Route execution is isolated - tools can't cross boundaries
202
+ - Checkout can't accidentally trigger admin operations
203
+ - Clear separation of concerns by capability
197
204
 
198
- 🎯 Clarity Benefits:
205
+ 📋 Clarity Benefits:
199
206
  - Routes clearly document their capabilities
200
- - Easy to audit what each route can do
207
+ - Easy to audit what each route can execute
201
208
  - Better debugging when tools are called
209
+ - Self-documenting security model
202
210
  `);
203
211
 
204
212
  // Inspect route configurations
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@falai/agent",
3
- "version": "0.3.24",
3
+ "version": "0.3.30",
4
4
  "description": "Standalone, strongly-typed AI Agent framework with route DSL and AI provider strategy",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
package/src/core/Agent.ts CHANGED
@@ -328,11 +328,9 @@ export class Agent<TContext = unknown> {
328
328
  );
329
329
  }
330
330
 
331
- // Add domains (tools) information if any domains are registered
332
- const allDomains = this.domainRegistry.all();
333
- if (Object.keys(allDomains).length > 0) {
334
- promptBuilder.addDomains(allDomains);
335
- }
331
+ // NOTE: Domains/tools are NOT added to the prompt.
332
+ // Tools execute automatically based on state transitions and guideline matching,
333
+ // NOT based on AI decisions. The AI should never see available tools.
336
334
 
337
335
  // Add JSON response schema instructions
338
336
  promptBuilder.addJsonResponseSchema();
@@ -500,11 +498,9 @@ export class Agent<TContext = unknown> {
500
498
  );
501
499
  }
502
500
 
503
- // Add domains (tools) information if any domains are registered
504
- const allDomains = this.domainRegistry.all();
505
- if (Object.keys(allDomains).length > 0) {
506
- promptBuilder.addDomains(allDomains);
507
- }
501
+ // NOTE: Domains/tools are NOT added to the prompt.
502
+ // Tools execute automatically based on state transitions and guideline matching,
503
+ // NOT based on AI decisions. The AI should never see available tools.
508
504
 
509
505
  // Add JSON response schema instructions
510
506
  promptBuilder.addJsonResponseSchema();
@@ -449,7 +449,7 @@ When you detect any of these situations, consider which route would be most appr
449
449
  ? `\n Triggered when: ${route.conditions.join(" OR ")}`
450
450
  : "";
451
451
  const desc = route.description ? `\n ${route.description}` : "";
452
-
452
+
453
453
  let domainInfo = "";
454
454
  if (route.domains !== undefined) {
455
455
  if (route.domains.length === 0) {
@@ -461,17 +461,23 @@ When you detect any of these situations, consider which route would be most appr
461
461
 
462
462
  let rulesInfo = "";
463
463
  if (route.rules && route.rules.length > 0) {
464
- const rulesList = route.rules.map((r, idx) => `${idx + 1}. ${r}`).join("; ");
464
+ const rulesList = route.rules
465
+ .map((r, idx) => `${idx + 1}. ${r}`)
466
+ .join("; ");
465
467
  rulesInfo = `\n RULES: ${rulesList}`;
466
468
  }
467
469
 
468
470
  let prohibitionsInfo = "";
469
471
  if (route.prohibitions && route.prohibitions.length > 0) {
470
- const prohibitionsList = route.prohibitions.map((p, idx) => `${idx + 1}. ${p}`).join("; ");
472
+ const prohibitionsList = route.prohibitions
473
+ .map((p, idx) => `${idx + 1}. ${p}`)
474
+ .join("; ");
471
475
  prohibitionsInfo = `\n PROHIBITIONS: ${prohibitionsList}`;
472
476
  }
473
477
 
474
- return `${i + 1}) ${route.title}${desc}${conditions}${domainInfo}${rulesInfo}${prohibitionsInfo}`;
478
+ return `${i + 1}) ${
479
+ route.title
480
+ }${desc}${conditions}${domainInfo}${rulesInfo}${prohibitionsInfo}`;
475
481
  })
476
482
  .join("\n\n");
477
483
 
@@ -497,9 +503,7 @@ IMPORTANT:
497
503
  /**
498
504
  * Add domains (tools) information
499
505
  */
500
- addDomains(
501
- domains: Record<string, Record<string, unknown>>
502
- ): this {
506
+ addDomains(domains: Record<string, Record<string, unknown>>): this {
503
507
  const domainNames = Object.keys(domains);
504
508
  if (domainNames.length > 0) {
505
509
  const domainsString = domainNames
@@ -526,21 +530,18 @@ When calling tools, use the format: domain.toolName (e.g., "payment.processPayme
526
530
  return this;
527
531
  }
528
532
 
529
-
530
533
  /**
531
534
  * Add JSON response schema instructions
535
+ *
536
+ * NOTE: toolCalls are NOT included. Tools execute automatically based on
537
+ * state transitions and guideline matching, NOT based on AI decisions.
532
538
  */
533
539
  addJsonResponseSchema(): this {
534
540
  const schema = {
535
541
  message: "The actual message to send to the user",
536
542
  route: "The title of the route you chose (or null if no specific route)",
537
- state: "The current state within the route (or null if not in a route)",
538
- toolCalls: [
539
- {
540
- toolName: "Name of the tool to call",
541
- arguments: "Object with tool arguments",
542
- },
543
- ],
543
+ state:
544
+ "The current state within the chosen route (or null if not in a route)",
544
545
  reasoning: "Optional: Your internal reasoning for this response",
545
546
  };
546
547
 
@@ -556,7 +557,6 @@ Instructions:
556
557
  - "message": The actual message to send to the user (required)
557
558
  - "route": If you chose a specific conversation route, provide its exact title. If not in a route, use null.
558
559
  - "state": The current state within the chosen route. If not in a route or at initial state, use null.
559
- - "toolCalls": If you need to call any tools, provide an array of tool calls. If no tools needed, use an empty array or omit.
560
560
  - "reasoning": Optional field for your internal thinking process.
561
561
 
562
562
  Your entire response must be valid JSON. Do not include any text before or after the JSON object.`,