Complete API documentation for @falai/agent. This framework provides a strongly-typed, modular agent architecture with AI-powered routing and schema-driven data collection.
The central orchestrator class that manages conversation flow, routing, tool execution, and agent-level data collection.
new Agent<TContext = unknown, TData = unknown>(options: AgentOptions<TContext, TData>)name: string- Agent display namedescription?: string- Detailed descriptiongoal?: string- Primary objectivecontext?: TContext- Static context datasession?: SessionState- Current session state
createRoute(options: RouteOptions<TContext, TData>): Route<TContext, TData>Creates a new conversation route with required fields specification that references the agent-level schema.
updateContext(updates: Partial<TContext>): Promise<void>Updates agent context and triggers lifecycle hooks.
getContext(): Promise<TContext | undefined>Gets current context, fetching from provider if configured.
getCollectedData(): Partial<TData>Gets the current agent-level collected data.
updateCollectedData(updates: Partial<TData>): Promise<void>Updates agent-level collected data and triggers validation and lifecycle hooks.
validateData(data: Partial<TData>): ValidationResultValidates data against the agent-level schema, returning detailed validation results.
respond(params: {
history: Event[];
session?: SessionState;
contextOverride?: Partial<TContext>;
signal?: AbortSignal;
}): Promise<{
message: string;
session?: SessionState;
toolCalls?: ToolCall[];
isRouteComplete?: boolean;
}>Generates a single response based on conversation history.
respondStream(params: {
history: Event[];
session?: SessionState;
contextOverride?: Partial<TContext>;
signal?: AbortSignal;
}): AsyncGenerator<{
delta: string;
accumulated: string;
done: boolean;
session?: SessionState;
toolCalls?: ToolCall[];
isRouteComplete?: boolean;
}>Generates a streaming response with real-time updates. Note: Now delegates to internal ResponseModal class.
stream(message?: string, options?: StreamOptions<TContext>): AsyncGenerator<AgentResponseStreamChunk<TData>>NEW: Modern streaming API with automatic session management. Recommended for new implementations.
// Simple streaming
for await (const chunk of agent.stream("Hello")) {
console.log(chunk.delta);
}addTool(definition: Tool<TContext, TData, TResult>): this
tool: ToolManager<TContext, TData> // Access to ToolManager instanceComprehensive Tool Examples:
// 1. Simple return value (most common)
agent.addTool({
id: "calculate_tip",
description: "Calculate tip amount",
handler: async ({ context, data }, args) => {
const tip = args.amount * args.percentage;
return `Tip: $${tip.toFixed(2)}`; // Simple string return
}
});
// 2. Complex ToolResult pattern
agent.addTool({
id: "process_order",
description: "Process customer order",
handler: async ({ context, data }, args) => {
const order = await orderService.process(args.items);
return {
data: `Order ${order.id} processed successfully`,
success: true,
contextUpdate: { lastOrderId: order.id },
dataUpdate: { orderStatus: 'processed' }
}; // Detailed ToolResult object
}
});
// 3. Registry for reuse
agent.tool.register({
id: "send_notification",
description: "Send notification to user",
handler: async ({ context }, args) => {
await notificationService.send(context.userId, args.message);
return "Notification sent"; // Simple return
}
});
// 4. Pattern helper
const validationTool = agent.tool.createValidation({
id: "validate_email",
fields: ['email'],
validator: async (context, data) => ({
valid: /\S+@\S+\.\S+/.test(data.email),
errors: []
})
});
agent.tool.register(validationTool);createTerm(term: Term<TContext>): this
createGuideline(guideline: Guideline<TContext>): this
getTerms(): Term<TContext>[]
getGuidelines(): Guideline<TContext>[]
getKnowledgeBase(): Record<string, unknown>setCurrentSession(session: SessionState): void
getCurrentSession(): SessionState | undefined
clearCurrentSession(): void
getData<TData = unknown>(routeId?: string): Partial<TData>nextStepRoute(
routeIdOrTitle: string,
session?: SessionState,
condition?: Template<TContext, unknown>,
history?: Event[]
): Promise<SessionState>Manually transitions to a different route.
getPersistenceManager(): PersistenceManager | undefined
hasPersistence(): booleanNEW: Internal class that centralizes all response generation logic for improved architecture and maintainability.
new ResponseModal<TContext = unknown, TData = unknown>(
agent: Agent<TContext, TData>,
options?: ResponseModalOptions
)stream(message?: string, options?: StreamOptions<TContext>): AsyncGenerator<AgentResponseStreamChunk<TData>>
generate(message?: string, options?: GenerateOptions<TContext>): Promise<AgentResponse<TData>>Modern streaming and non-streaming APIs with automatic session management.
respond(params: RespondParams<TContext, TData>): Promise<AgentResponse<TData>>
respondStream(params: RespondParams<TContext, TData>): AsyncGenerator<AgentResponseStreamChunk<TData>>Legacy APIs that maintain full backward compatibility with existing code.
ResponseGenerationError: Error class for response-specific errorsComprehensive error handling with detailed context and phase information.
- Unified Logic: Both streaming and non-streaming use the same underlying logic
- Modern APIs: Simple
stream()andgenerate()methods for new code - Backward Compatibility: Existing
respond()andrespondStream()methods work unchanged - Error Handling: Detailed error context with phase and original error information
- Performance: Optimized response pipeline with minimal code duplication
Represents a conversational journey with required fields specification and steps that collect data into the agent-level schema.
new Route<TContext = unknown, TData = unknown>(options: RouteOptions<TContext, TData>)id: string- Unique route identifiertitle: string- Human-readable titledescription?: string- Detailed descriptionidentity?: Template<TContext, TData>- Route-specific identitypersonality?: Template<TContext, TData>- Route-specific personalityinitialStep: Step<TContext, TData>- Entry point for the route
createStep(options: StepOptions<TContext, TData>): Step<TContext, TData>
getStep(stepId: string): Step<TContext, TData> | undefined
getAllSteps(): Step<TContext, TData>[]isComplete(data: Partial<TData>): booleanChecks if all required fields are collected based on agent-level data.
getMissingRequiredFields(data: Partial<TData>): (keyof TData)[]Returns the fields still needed for route completion.
getCompletionProgress(data: Partial<TData>): numberReturns completion progress as a number between 0 and 1.
getRules(): Template<TContext, TData>[]
getProhibitions(): Template<TContext, TData>[]
getTerms(): Term<TContext>[]
getKnowledgeBase(): Record<string, unknown>getResponseOutputSchema(): StructuredSchema | undefined
getRoutingExtrasSchema(): StructuredSchema | undefinedaddTool(definition: Tool<TContext, TData, TResult>): thishandleDataUpdate(data: Partial<TData>, previousData: Partial<TData>): Promise<Partial<TData>>
handleContextUpdate(newContext: TContext, previousContext: TContext): Promise<void>
evaluateOnComplete(session: { data?: Partial<TData> }, context?: TContext): Promise<RouteTransitionConfig | undefined>Represents an individual conversation state within a route.
new Step<TContext = unknown, TData = unknown>(routeId: string, options?: StepOptions<TContext, TData>)id: string- Unique step identifierrouteId: string- Parent route identifierdescription?: string- Human-readable descriptioncollect?: string[]- Fields to extract from AI responsesrequires?: string[]- Required data fieldsprompt?: Template<TContext, TData>- Step-specific prompttools?: (string | Tool)[]- Step-specific tools
configure(config: Partial<StepOptions<TContext, TData>>): thisnextStep(spec: StepOptions<TContext, TData>): StepResult<TContext, TData>
branch(branches: BranchSpec<TContext, TData>[]): BranchResult<TContext, TData>
endRoute(options?: Omit<StepOptions<TContext, TData>, 'step'>): StepResult<TContext, TData>shouldSkip(data: Partial<TData>): boolean
hasRequires(data: Partial<TData>): booleanaddGuideline(guideline: Guideline<TContext>): void
getGuidelines(): Guideline<TContext>[]
getTransitions(): Step<TContext, TData>[]getRef(): StepRefResult interface returned by step transition methods that enables fluent chaining of conversation flows.
interface StepResult<TContext = unknown, TData = unknown> extends StepRef {
nextStep: (spec: StepOptions<TContext, TData>) => StepResult<TContext, TData>;
branch: (branches: BranchSpec<TContext, TData>[]) => BranchResult<TContext, TData>;
endRoute: (options?: Omit<StepOptions<TContext, TData>, "step">) => StepResult<TContext, TData>;
}nextStep(spec: StepOptions<TContext, TData>): StepResult<TContext, TData>Creates a transition and returns a chainable result for building linear flows.
branch(branches: BranchSpec<TContext, TData>[]): BranchResult<TContext, TData>Creates multiple conditional branches for complex conversation flows.
endRoute(options?: Omit<StepOptions<TContext, TData>, "step">): StepResult<TContext, TData>Shortcut method to end the current route with optional completion configuration.
Inherits from StepRef:
id: string- Step identifierrouteId: string- Route this step belongs to
AI-powered routing system that intelligently selects routes and steps based on conversation context.
new RoutingEngine(options?: RoutingEngineOptions)decideRouteAndStep(params: {
routes: Route[];
session: SessionState;
history: Event[];
agentOptions?: AgentOptions;
provider: AiProvider;
context: unknown;
signal?: AbortSignal;
}): Promise<{
selectedRoute?: Route;
selectedStep?: Step;
responseDirectives?: string[];
session: SessionState;
isRouteComplete?: boolean;
}>decideSingleRouteStep(params: {
route: Route;
session: SessionState;
history: Event[];
agentOptions?: AgentOptions;
provider: AiProvider;
context: unknown;
signal?: AbortSignal;
}): Promise<{
selectedRoute?: Route;
selectedStep?: Step;
responseDirectives?: string[];
session: SessionState;
isRouteComplete?: boolean;
}>getCandidateSteps<TData>(
route: Route,
currentStep: Step | undefined,
data: Partial<TData>
): CandidateStep[]buildRoutingPrompt(params: BuildRoutingPromptParams): Promise<string>
buildStepSelectionPrompt(params: BuildStepSelectionPromptParams): Promise<string>Handles prompt composition and response schema generation for AI interactions.
responseSchemaForRoute(route: Route, currentStep?: Step): StructuredSchemabuildResponsePrompt(params: BuildResponsePromptParams): Promise<string>
buildFallbackPrompt(params: BuildFallbackPromptParams): Promise<string>Utility for composing structured prompts with agent metadata, knowledge, and context.
new PromptComposer<TContext = unknown, TData = unknown>(context?: TemplateContext<TContext, TData>)addAgentMeta(agent: AgentOptions): Promise<this>
addGlossary(terms: Term[]): Promise<this>
addGuidelines(guidelines: Guideline[]): Promise<this>
addKnowledgeBase(agentKb?: Record<string, unknown>, routeKb?: Record<string, unknown>): Promise<this>addInstruction(text: string): Promise<this>
addInteractionHistory(history: Event[], note?: string): Promise<this>
addLastMessage(message: string): Promise<this>
addRoutingOverview(routes: Route[]): Promise<this>
addDirectives(directives?: string[]): Promise<this>build(): Promise<string>Executes tools as they arrive from the LLM stream with concurrency control, abort handling, and ordered result yielding.
new StreamingToolExecutor<TContext, TData>(
toolContext: ToolContext<TContext, TData>,
options?: {
maxParallel?: number; // default: 10
signal?: AbortSignal;
}
)addTool(toolCall: ToolCallRequest, tool: EnhancedTool<TContext, TData>): voidQueue a tool for execution. Concurrency safety is evaluated once at queue time.
getCompletedResults(): Generator<ToolExecutionUpdate<TData>>Synchronous generator yielding available results in request order.
getRemainingResults(): AsyncGenerator<ToolExecutionUpdate<TData>>Async generator yielding all results, waiting for pending tools.
discard(): void
getUpdatedContext(): TContext
hasUnfinishedTools(): booleanSee Streaming Execution Guide for detailed usage.
Manages conversation history size through multi-layered compaction strategies.
CompactionEngine.estimateTokens(history: HistoryItem[]): number
CompactionEngine.applyToolResultBudget(history: HistoryItem[], maxCharsPerResult: number): HistoryItem[]
CompactionEngine.validateOptions(options: CompactionOptions): void
CompactionEngine.checkAndCompact(history: HistoryItem[], options: CompactionOptions): Promise<CompactionResult>See Context Compaction Guide for detailed usage.
Memoizes static prompt sections across turns, recomputing only dynamic sections per-turn. Integrates with PromptComposer for optimized prompt generation.
new PromptSectionCache(config?: PromptCacheConfig)interface PromptCacheConfig {
enabled?: boolean; // default: true
volatileKeys?: string[]; // keys that always recompute
}register(key: string, type: PromptSectionType, compute: () => string | null | Promise<string | null>): voidRegister a section as 'static' (cached) or 'dynamic' (recomputed every turn).
get(key: string): Promise<string | null>Get a section's value, using cache for static sections.
resolveAll(): Promise<(string | null)[]>Resolve all sections in registration order.
invalidate(key: string): void
invalidateAll(): voidInvalidate a specific section or all sections.
See Prompt Optimization Guide for detailed usage.
new OpenAIProvider(options: OpenAIProviderOptions)
generateMessage(input: GenerateMessageInput): Promise<GenerateMessageOutput>
generateMessageStream(input: GenerateMessageInput): AsyncGenerator<GenerateMessageStreamChunk>new GeminiProvider(options: GeminiProviderOptions)
generateMessage(input: GenerateMessageInput): Promise<GenerateMessageOutput>
generateMessageStream(input: GenerateMessageInput): AsyncGenerator<GenerateMessageStreamChunk>new AnthropicProvider(options: AnthropicProviderOptions)
generateMessage(input: GenerateMessageInput): Promise<GenerateMessageOutput>
generateMessageStream(input: GenerateMessageInput): AsyncGenerator<GenerateMessageStreamChunk>new OpenRouterProvider(options: OpenRouterProviderOptions)
generateMessage(input: GenerateMessageInput): Promise<GenerateMessageOutput>
generateMessageStream(input: GenerateMessageInput): AsyncGenerator<GenerateMessageStreamChunk>new PrismaAdapter(options: {
prisma: PrismaClient;
tables?: { sessions?: string; messages?: string };
fieldMappings?: FieldMappings;
})
sessionRepository: SessionRepository
messageRepository: MessageRepositorynew RedisAdapter(options: {
redis: Redis;
keyPrefix?: string;
sessionTTL?: number;
messageTTL?: number;
})
sessionRepository: SessionRepository
messageRepository: MessageRepositorynew MongoAdapter(options: {
client: MongoClient;
databaseName: string;
collections?: { sessions?: string; messages?: string };
})
sessionRepository: SessionRepository
messageRepository: MessageRepositorynew PostgreSQLAdapter(options: {
client: Client;
tables?: { sessions?: string; messages?: string };
})
sessionRepository: SessionRepository
messageRepository: MessageRepository
initialize(): Promise<void> // Auto-create tablesnew SQLiteAdapter(options: { db: Database })
sessionRepository: SessionRepository
messageRepository: MessageRepository
initialize(): Promise<void> // Auto-create tablesnew OpenSearchAdapter(client: Client, options: {
indices?: { sessions?: string; messages?: string };
autoCreateIndices?: boolean;
refresh?: string;
})
sessionRepository: SessionRepository
messageRepository: MessageRepositorynew MemoryAdapter()
sessionRepository: SessionRepository
messageRepository: MessageRepository
clear(): void
getSnapshot(): { sessions: SessionData[]; messages: MessageData[] }interface AgentOptions<TContext = unknown, TData = unknown> {
name: string;
provider: AiProvider;
description?: string;
goal?: string;
personality?: Template<TContext, TData>;
identity?: Template<TContext, TData>;
context?: TContext;
contextProvider?: ContextProvider<TContext>;
// NEW: Agent-level data schema and initial data
schema?: StructuredSchema;
initialData?: Partial<TData>;
// NEW: Agent-wide rules and prohibitions
rules?: Template<TContext, TData>[];
prohibitions?: Template<TContext, TData>[];
// NEW: Control multi-step batching
maxStepsPerBatch?: number; // Default: 1 (single-step). Set higher or Infinity to batch.
hooks?: ContextLifecycleHooks<TContext, TData>;
debug?: boolean;
session?: SessionState;
persistence?: PersistenceConfig;
terms?: Term<TContext>[];
guidelines?: Guideline<TContext>[];
tools?: Tool<TContext, unknown[], unknown, TData>[];
routes?: RouteOptions<TContext, TData>[];
knowledgeBase?: Record<string, unknown>;
}
interface RouteOptions<TContext = unknown, TData = unknown> {
id?: string;
title: string;
description?: string;
identity?: Template<TContext, TData>;
personality?: Template<TContext, TData>;
when?: ConditionTemplate<TContext, TData>;
skipIf?: ConditionTemplate<TContext, TData>;
rules?: Template<TContext, TData>[];
prohibitions?: Template<TContext, TData>[];
// NEW: Required fields for route completion (replaces schema)
requiredFields?: (keyof TData)[];
optionalFields?: (keyof TData)[];
// REMOVED: schema (now at agent level)
// schema?: StructuredSchema;
initialData?: Partial<TData>;
steps?: StepOptions<TContext, TData>[];
initialStep?: Omit<StepOptions<TContext, TData>, "step">;
endStep?: Omit<StepOptions<TContext, TData>, "step" | "condition" | "skipIf">;
onComplete?: string | RouteTransitionConfig | RouteCompletionHandler;
hooks?: RouteLifecycleHooks<TContext, TData>;
guidelines?: Guideline<TContext>[];
terms?: Term<TContext>[];
tools?: Tool<TContext, unknown[], unknown, TData>[];
knowledgeBase?: Record<string, unknown>;
}
interface StepOptions<TContext = unknown, TData = unknown> {
id?: string;
description?: string;
prompt?: Template<TContext, TData>;
collect?: string[];
skipIf?: (data: Partial<TData>) => boolean;
requires?: string[];
when?: Template<TContext, TData>;
prepare?: string | Tool<TContext, unknown[], unknown, TData> | ((
context: TContext,
data?: Partial<TData>
) => void | Promise<void>);
finalize?: string | Tool<TContext, unknown[], unknown, TData> | ((
context: TContext,
data?: Partial<TData>
) => void | Promise<void>);
tools?: (string | Tool<TContext, unknown[], unknown, TData>)[];
}
interface StepResult<TContext = unknown, TData = unknown> extends StepRef {
nextStep: (spec: StepOptions<TContext, TData>) => StepResult<TContext, TData>;
branch: (branches: BranchSpec<TContext, TData>[]) => BranchResult<TContext, TData>;
endRoute: (options?: Omit<StepOptions<TContext, TData>, "step">) => StepResult<TContext, TData>;
}
interface BranchResult<TContext = unknown, TData = unknown> {
[branchName: string]: StepResult<TContext, TData>;
}
interface BranchSpec<TContext = unknown, TData = unknown> {
name: string;
id?: string;
step: StepOptions<TContext, TData>;
}
interface StepRef {
id: string;
routeId: string;
}
interface RouteRef {
id: string;
}
// ==============================================================================
// LIFECYCLE HOOKS: prepare & finalize
// ==============================================================================
/**
* Step lifecycle hooks allow you to execute custom logic before and after AI responses.
* Both prepare and finalize can be functions, tool references, or inline tool definitions.
*/
// Example: Using functions (traditional approach)
{
prepare: (context, data) => {
console.log("Preparing step execution...");
},
finalize: (context, data) => {
console.log("Finalizing step execution...");
}
}
// Example: Using existing tools (unified Tool interface)
{
prepare: "validate_user_data", // Tool ID string - simple return value
finalize: "send_notification", // Tool ID string - ToolResult pattern
}
// Example: Inline tool definition with flexible returns
{
prepare: {
id: "setup_step_context",
description: "Prepare context for this step",
parameters: { type: "object", properties: {} },
handler: ({ context, data }) => {
// Simple return value
return "Setup complete";
}
},
finalize: {
id: "cleanup_step_context",
description: "Clean up after step completion",
handler: ({ context, data }) => {
// Complex ToolResult pattern
return {
data: "Cleanup complete",
success: true,
contextUpdate: { lastCleanup: new Date() }
};
}
}
}interface SessionState<TData = unknown> {
id?: string;
data: Partial<TData>;
dataByRoute: Record<string, Partial<TData>>;
routeHistory: RouteHistoryEntry[];
currentRoute?: RouteRef;
currentStep?: StepRef;
metadata?: SessionMetadata;
}
interface SessionData {
id: string;
userId?: string;
agentName?: string;
status: SessionStatus;
currentRoute?: string;
currentStep?: string;
collectedData?: Record<string, unknown>;
messageCount: number;
lastMessageAt?: Date;
completedAt?: Date;
createdAt: Date;
updatedAt: Date;
}Types for multi-step batch execution:
/**
* Reason why batch execution stopped
*/
type StoppedReason =
| 'needs_input' // Step requires uncollected data
| 'end_route' // Reached END_ROUTE
| 'route_complete' // All Steps processed
| 'max_steps_reached' // Batch hit the maxStepsPerBatch limit
| 'prepare_error' // Error in prepare hook
| 'llm_error' // Error during LLM call
| 'validation_error' // Error validating collected data
| 'finalize_error'; // Error in finalize hook (non-fatal)
/**
* Result of batch determination - which steps can execute together
*/
interface BatchResult<TContext = unknown, TData = unknown> {
/** Steps included in this batch */
steps: StepOptions<TContext, TData>[];
/** Why the batch stopped */
stoppedReason: StoppedReason;
/** The Step that caused the stop (if applicable) */
stoppedAtStep?: StepOptions<TContext, TData>;
}
/**
* Result of executing a batch of steps
*/
interface BatchExecutionResult<TData = unknown> {
/** The generated message */
message: string;
/** Updated session state */
session: SessionState<TData>;
/** Steps that were executed */
executedSteps: StepRef[];
/** Why execution stopped */
stoppedReason: StoppedReason;
/** Collected data from the batch */
collectedData?: Partial<TData>;
/** Any errors that occurred */
error?: BatchExecutionError;
}
/**
* Error details for batch execution failures
*/
interface BatchExecutionError {
/** Type of error that occurred */
type: 'pre_extraction' | 'skipif_evaluation' | 'prepare_hook' |
'llm_call' | 'data_validation' | 'finalize_hook';
/** Error message */
message: string;
/** Step where error occurred (if applicable) */
stepId?: string;
/** Additional error details */
details?: unknown;
}
/**
* Event emitted during batch execution for debugging
*/
interface BatchExecutionEvent {
/** Type of batch execution event */
type: 'batch_start' | 'step_included' | 'step_skipped' | 'batch_stop' | 'batch_complete';
/** Timestamp when the event occurred */
timestamp: Date;
/** Event-specific details */
details: {
stepId?: string;
reason?: string;
batchSize?: number;
stoppedReason?: StoppedReason;
timing?: BatchExecutionTiming;
};
}
/**
* Timing information for batch execution phases
*/
interface BatchExecutionTiming {
/** Total batch execution time in milliseconds */
totalMs: number;
/** Time spent in batch determination phase */
determinationMs?: number;
/** Time spent executing prepare hooks */
prepareHooksMs?: number;
/** Time spent in LLM call */
llmCallMs?: number;
/** Time spent collecting data */
dataCollectionMs?: number;
/** Time spent executing finalize hooks */
finalizeHooksMs?: number;
}The AgentResponse interface includes batch execution fields:
interface AgentResponse<TData = unknown> {
/** The generated message */
message: string;
/** Updated session state */
session?: SessionState<TData>;
/** Tool calls made during response */
toolCalls?: Array<{ toolName: string; arguments: Record<string, unknown> }>;
/** Whether the route is complete */
isRouteComplete?: boolean;
// Multi-step execution fields
/** Steps executed in this response */
executedSteps?: StepRef[];
/** Why execution stopped */
stoppedReason?: StoppedReason;
/** Error information if execution failed */
error?: BatchExecutionError;
}interface Tool<TContext, TArgs extends unknown[], TResult, TData> {
id: string;
description: string;
parameters: StructuredSchema;
execute: ToolHandler<TContext, TArgs, TResult, TData>;
}
type ToolHandler<TContext, TArgs extends unknown[], TResult, TData> = (
args: TArgs[0],
context: {
context: TContext;
data: Partial<TData>;
}
) => Promise<{
data: unknown;
contextUpdate?: Partial<TContext>;
dataUpdate?: Partial<TData>;
}>;Extends Tool with optional metadata for concurrency, permissions, validation, and result budgeting. See EnhancedTool Reference for full documentation.
interface EnhancedTool<TContext, TData, TResult> extends Tool<TContext, TData, TResult> {
isConcurrencySafe?(input?: Record<string, unknown>): boolean;
isReadOnly?(input?: Record<string, unknown>): boolean;
isDestructive?(input?: Record<string, unknown>): boolean;
interruptBehavior?(): 'cancel' | 'block';
maxResultSizeChars?: number;
validateInput?(input: Record<string, unknown>, context: ToolContext<TContext, TData>): Promise<ToolValidationResult> | ToolValidationResult;
checkPermissions?(input: Record<string, unknown>, context: ToolContext<TContext, TData>): Promise<ToolPermissionResult> | ToolPermissionResult;
}
interface ToolValidationResult { valid: boolean; error?: string; correctedInput?: Record<string, unknown>; }
interface ToolPermissionResult { allowed: boolean; reason?: string; canOverride?: boolean; }
interface ToolCallRequest { id: string; toolName: string; arguments: Record<string, unknown>; }
interface ToolExecutionUpdate<TData> { toolCallId: string; result?: ToolExecutionResult; progress?: string; contextUpdate?: Record<string, unknown>; dataUpdate?: Partial<TData>; }
interface CompactionOptions { maxTokens: number; compactionThreshold: number; preserveRecentCount: number; maxToolResultChars: number; provider: AiProvider; }
interface CompactionResult<TData> { history: HistoryItem[]; strategy: 'none' | 'tool_result_budget' | 'micro_compact' | 'auto_compact'; estimatedTokens: number; messagesCompacted: number; summary?: string; }interface AiProvider {
name: string;
generateMessage(input: GenerateMessageInput): Promise<GenerateMessageOutput>;
generateMessageStream(
input: GenerateMessageInput
): AsyncGenerator<GenerateMessageStreamChunk>;
}
interface GenerateMessageInput<TContext = unknown> {
prompt: string;
history: Event[];
context?: TContext;
tools?: ToolDefinition[];
parameters?: {
jsonSchema?: StructuredSchema;
schemaName?: string;
maxOutputTokens?: number;
reasoning?: { effort: "low" | "medium" | "high" };
};
signal?: AbortSignal;
}// Overload 1: Classic — ID + metadata
createSession<TData = unknown>(sessionId?: string, metadata?: SessionMetadata): SessionState<TData>
// Overload 2: Partial state — merge with defaults
createSession<TData = unknown>(state: Partial<SessionState<TData>>): SessionState<TData>
// Generate a unique session ID without creating a full session
createSessionId(): string
enterRoute<TData>(
session: SessionState<TData>,
routeId: string,
routeTitle: string
): SessionState<TData>
enterStep<TData>(
session: SessionState<TData>,
stepId: string,
stepDescription?: string
): SessionState<TData>
mergeCollected<TData>(
session: SessionState<TData>,
data: Partial<TData>
): SessionState<TData>render<TContext, TData>(
template: Template<TContext, TData> | undefined,
params: TemplateContext<TContext, TData>
): Promise<string>
renderMany<TContext, TData>(
templates: Template<TContext, TData>[] | undefined,
params: TemplateContext<TContext, TData>
): Promise<string[]>
formatKnowledgeBase(
data: Record<string, unknown>,
title?: string,
maxDepth?: number
): stringgenerateRouteId(title: string): string
generateStepId(routeId: string, description?: string): string
generateToolId(name: string): stringHere's a comprehensive example showing the new agent-level data collection architecture:
import { Agent, OpenAIProvider } from "@falai/agent";
// Define comprehensive agent-level data interface
interface CustomerServiceData {
// Customer identification
customerId?: string;
customerName?: string;
email?: string;
phone?: string;
// Issue tracking
issueType?: 'booking' | 'billing' | 'technical' | 'other';
issueDescription?: string;
priority?: 'low' | 'medium' | 'high';
// Feedback
rating?: number;
comments?: string;
recommendToFriend?: boolean;
}
// Create agent with centralized schema
const agent = new Agent<{}, CustomerServiceData>({
name: "Customer Service Agent",
provider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY, model: "gpt-4" }),
// Agent-level schema defines all possible data fields
schema: {
type: "object",
properties: {
customerId: { type: "string" },
customerName: { type: "string" },
email: { type: "string", format: "email" },
phone: { type: "string" },
issueType: { type: "string", enum: ["booking", "billing", "technical", "other"] },
issueDescription: { type: "string" },
priority: { type: "string", enum: ["low", "medium", "high"] },
rating: { type: "number", minimum: 1, maximum: 5 },
comments: { type: "string" },
recommendToFriend: { type: "boolean" }
}
},
// Agent-level data validation and enrichment
hooks: {
onDataUpdate: async (data, previousData) => {
// Auto-set priority based on issue type
if (data.issueType === 'billing' && !data.priority) {
data.priority = 'high';
}
// Enrich customer data
if (data.customerName && !data.customerId) {
data.customerId = await lookupCustomerId(data.customerName);
}
return data;
}
}
});
// Routes specify required fields instead of schemas
const supportRoute = agent.createRoute({
title: "Customer Support",
requiredFields: ["customerName", "email", "issueType", "issueDescription"],
optionalFields: ["phone", "priority"],
initialStep: {
prompt: "I'm here to help with your issue. Can you tell me your name and email?",
collect: ["customerName", "email"]
}
});
const feedbackRoute = agent.createRoute({
title: "Feedback Collection",
requiredFields: ["customerName", "email", "rating"],
optionalFields: ["comments", "recommendToFriend"],
initialStep: {
prompt: "I'd love to get your feedback. What's your name and email?",
collect: ["customerName", "email"]
}
});
// Cross-route data sharing example
const response1 = await agent.respond("Hi, I'm John Doe, email john@example.com, I have a billing issue");
// Agent data: { customerName: "John Doe", email: "john@example.com", issueType: "billing" }
const response2 = await agent.respond("Actually, I want to leave feedback instead. I'd rate you 5 stars.");
// Feedback route completes immediately: already has name, email, and now rating
// { customerName: "John Doe", email: "john@example.com", rating: 5 }
// Check route completion
console.log(feedbackRoute.isComplete(agent.getCollectedData())); // true
console.log(feedbackRoute.getCompletionProgress(agent.getCollectedData())); // 1.0This API reference covers the complete @falai/agent framework. For more detailed examples and usage patterns, see the examples directory and guides.