API reference for Flutch SDK in TypeScript. Core classes and services for building graphs with NestJS.
Installation
bashflutch graph create my-graph cd my-graph npm install
Main imports:
typescriptimport { AbstractGraphBuilder, WithCallbacks, Callback } from '@flutch/sdk'; import { ModelInitializer, McpRuntimeClient } from '@flutch/sdk'; import { Injectable } from '@nestjs/common';
Graph Builder
Base class for all graph versions. Every graph version must extend AbstractGraphBuilder.
Basic Structure
typescriptimport { Injectable, Inject } from '@nestjs/common'; import { AbstractGraphBuilder, IGraphRequestPayload } from '@flutch/sdk'; import { MongoDBSaver } from '@langchain/langgraph-checkpoint-mongodb'; @Injectable() export class MyGraphV1Builder extends AbstractGraphBuilder<'1.0.0'> { readonly version = '1.0.0' as const; constructor( @Inject('CHECKPOINTER') private readonly checkpointer: MongoDBSaver, private readonly generateNode: GenerateNode ) { super(); } async buildGraph(payload?: any): Promise<CompiledGraph> { // Build your workflow here // See framework-specific guides for details return compiledGraph; } }
Key methods:
| Method | Description |
|---|---|
buildGraph(payload?) | Build and return compiled workflow |
prepareConfig(payload) | Prepare config (auto-handled, override if needed) |
Key properties:
| Property | Type | Description |
|---|---|---|
version | string | Semantic version (required) |
graphType | string | Auto-generated from manifest (e.g., "acme.support::1.0.0") |
manifest | IGraphManifest | Loaded graph manifest |
logger | Logger | NestJS logger instance |
Models
Initialize AI models (chat, embedding, rerank) in your graph nodes.
ModelInitializer
Inject via NestJS:
typescriptimport { Injectable } from '@nestjs/common'; import { ModelInitializer } from '@flutch/sdk'; @Injectable() export class GenerateNode { constructor( private readonly modelInitializer: ModelInitializer ) {} async execute(state: any, config: any) { // Get model ID from agent config const modelId = config.configurable.graphSettings?.modelSettings?.modelId; const temperature = config.configurable.graphSettings?.modelSettings?.temperature; // Initialize chat model const model = await this.modelInitializer.initializeChatModel({ modelId, temperature }); // Use the model const result = await model.invoke(state.messages, config); return { messages: [result] }; } }
Methods:
| Method | Parameters | Returns |
|---|---|---|
initializeChatModel(config) | { modelId, temperature?, maxTokens? } | BaseChatModel |
initializeEmbeddingModel(config) | { modelId } | Embeddings |
initializeRerankModel(config) | { modelId, maxTokens? } | BaseDocumentCompressor |
Config object:
typescriptinterface ModelByIdConfig { modelId: string; // From model catalog temperature?: number; // Override default temperature maxTokens?: number; // Override default max tokens }
Example with tools:
typescript// Initialize model const model = await this.modelInitializer.initializeChatModel({ modelId: 'gpt-4o', temperature: 0.7 }); // Bind tools to model const modelWithTools = model.bindTools(tools); // Invoke with tools const result = await modelWithTools.invoke(messages, config);
Tools
Execute MCP tools from your graph nodes.
McpRuntimeClient
Client for MCP tool runtime.
Usage:
typescriptimport { Injectable } from '@nestjs/common'; import { ModelInitializer, McpRuntimeClient } from '@flutch/sdk'; @Injectable() export class GenerateNode { constructor( private readonly modelInitializer: ModelInitializer, private readonly mcpClient: McpRuntimeClient ) {} async execute(state: any, config: any) { const enabledTools = config.configurable.graphSettings?.availableTools || []; const modelId = config.configurable.graphSettings?.modelSettings?.modelId; // Initialize model const model = await this.modelInitializer.initializeChatModel({ modelId }); // Get tools (filtered and converted automatically) let modelWithTools = model; if (enabledTools.length > 0) { const tools = await this.mcpClient.getTools(enabledTools); modelWithTools = model.bindTools(tools); this.logger.debug(`Configured ${tools.length} tools`); } // Invoke model with tools const result = await modelWithTools.invoke(state.messages, config); return { messages: [result] }; } }
Methods:
| Method | Parameters | Returns |
|---|---|---|
getTools(enabledTools?) | string[]? | Promise<StructuredTool[]> |
executeTool(name, args) | name: string, args: object | Promise<McpToolResult> |
Execute tool calls:
typescriptasync executeTools(state: any, config: any) { const lastMessage = state.messages[state.messages.length - 1]; const toolCalls = lastMessage?.tool_calls || []; const toolMessages = []; for (const toolCall of toolCalls) { const result = await this.mcpClient.executeTool( toolCall.name, toolCall.args ); toolMessages.push({ type: 'tool', tool_call_id: toolCall.id, content: result.success ? JSON.stringify(result.data) : result.error, name: toolCall.name }); this.logger.debug(`Tool ${toolCall.name} executed successfully`); } return { messages: toolMessages }; }
Callbacks
Add interactive buttons that execute your code when clicked.
Decorator Pattern
Use @Callback() and @WithCallbacks() decorators to register callback handlers.
1. Create callback handler class:
typescriptimport { Injectable } from '@nestjs/common'; import { Callback, ExtendedCallbackContext, CallbackResult } from '@flutch/sdk'; @Injectable() export class MyCallbacks { private readonly logger = new Logger(MyCallbacks.name); @Callback('confirm-payment') async handleConfirmPayment( context: ExtendedCallbackContext ): Promise<CallbackResult> { const { amount, orderId } = context.params; this.logger.debug(`Processing payment: ${orderId}`); try { await this.processPayment(orderId, amount); return { success: true, message: 'Payment confirmed!', patch: { text: '✅ Payment processed successfully', disableButtons: true } }; } catch (error) { this.logger.error(`Payment failed: ${error.message}`); return { success: false, error: 'Payment processing failed. Please try again.' }; } } private async processPayment(orderId: string, amount: number) { // Payment processing logic } }
2. Register callbacks in builder:
typescriptimport { Injectable } from '@nestjs/common'; import { WithCallbacks, AbstractGraphBuilder } from '@flutch/sdk'; import { MyCallbacks } from '../callbacks/my.callbacks'; @Injectable() @WithCallbacks(MyCallbacks) export class MyGraphV1Builder extends AbstractGraphBuilder<'1.0.0'> { readonly version = '1.0.0' as const; // Builder implementation... }
Callback context:
typescriptinterface ExtendedCallbackContext { userId: string; // User who clicked threadId: string; // Conversation thread agentId: string; // Agent ID params: any; // Parameters from callback token platform?: string; // Platform (web, telegram, etc.) builder?: AbstractGraphBuilder; // Access to builder instance }
Callback result:
typescriptinterface CallbackResult { success: boolean; message?: string; error?: string; patch?: { text?: string; disableButtons?: boolean; }; }
Configuration
Access agent configuration defined in your config schema.
Runtime Configuration
Agent configuration is injected at runtime through config.configurable.graphSettings.
Access in node:
typescriptasync execute(state: any, config: any) { // Get all settings const graphSettings = config?.configurable?.graphSettings; // Access specific settings const systemPrompt = graphSettings?.systemPrompt || ''; const modelSettings = graphSettings?.modelSettings; const enabledTools = graphSettings?.availableTools || []; const customSettings = graphSettings?.customSettings; this.logger.debug('Model:', modelSettings?.modelId); this.logger.debug('Temperature:', modelSettings?.temperature); this.logger.debug('System prompt:', systemPrompt); this.logger.debug('Enabled tools:', enabledTools); // Use configuration const model = await this.modelInitializer.initializeChatModel({ modelId: modelSettings?.modelId, temperature: modelSettings?.temperature }); }
Settings structure (from config-schema.json):
typescriptinterface GraphSettings { systemPrompt: string; modelSettings: { modelId: string; temperature: number; maxTokens?: number; }; availableTools: string[]; customSettings?: { [key: string]: any; }; }
Module Setup
Configure your graph module with NestJS and bootstrap the application.
Graph Module
typescript// src/my-graph.module.ts import { Module } from '@nestjs/common'; import { UniversalGraphModule } from '@flutch/sdk'; import { MyGraphV1Builder } from './versions/v1.0.0/builder'; import { MyGraphV2Builder } from './versions/v2.0.0/builder'; import { GenerateNode } from './nodes/generate.node'; @Module({ imports: [ UniversalGraphModule.forRoot({ builders: [ MyGraphV1Builder, MyGraphV2Builder ] }) ], providers: [ GenerateNode, // ... other services ] }) export class MyGraphModule {}
Bootstrap
typescript// src/main.ts import { bootstrap } from '@flutch/sdk'; import { MyGraphModule } from './my-graph.module'; async function main() { await bootstrap(MyGraphModule); } main();
The bootstrap() function:
- Initializes NestJS application
- Registers all graph versions
- Starts HTTP server for graph execution
- Sets up health checks
- Configures callback handlers
Dependency Injection
Use NestJS dependency injection to inject services into your builders and nodes.
Inject Services
typescriptimport { Injectable, Inject } from '@nestjs/common'; import { AbstractGraphBuilder } from '@flutch/sdk'; import { ModelInitializer } from '@flutch/sdk'; import { MongoDBSaver } from '@langchain/langgraph-checkpoint-mongodb'; @Injectable() export class MyGraphV1Builder extends AbstractGraphBuilder<'1.0.0'> { readonly version = '1.0.0' as const; constructor( @Inject('CHECKPOINTER') private readonly checkpointer: MongoDBSaver, private readonly modelInitializer: ModelInitializer, private readonly generateNode: GenerateNode, private readonly toolsNode: ToolsNode ) { super(); } async buildGraph() { // Use injected services const workflow = buildWorkflow( this.generateNode, this.toolsNode, this.checkpointer ); return workflow; } }
Custom Services
typescript// src/services/my.service.ts import { Injectable } from '@nestjs/common'; @Injectable() export class MyService { async doSomething() { // Service logic } } // Register in module @Module({ providers: [MyService], exports: [MyService] }) export class MyGraphModule {} // Use in node @Injectable() export class MyNode { constructor( private readonly myService: MyService ) {} async execute(state: any, config: any) { await this.myService.doSomething(); return { result: 'done' }; } }