Skip to content

TypeScript Types Guide

Complete TypeScript reference for agentflow-react.

Table of Contents


Installation with TypeScript

The library includes full TypeScript support with type definitions.

Basic Setup

npm install agentflow-react

TypeScript Configuration:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "lib": ["ES2020", "DOM"],
    "moduleResolution": "node",
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true,
    "resolveJsonModule": true
  }
}

Importing Types

import {
  // Client
  AgentFlowClient,
  AgentFlowConfig,

  // Messages
  Message,
  TextBlock,
  ImageBlock,
  AudioBlock,
  RemoteToolCallBlock,
  ToolResultBlock,

  // Tools
  ToolRegistration,
  ToolHandler,
  ToolParameter,

  // Invoke
  InvokeRequest,
  InvokeResult,
  InvokePartialResult,
  InvokeCallback,

  // Stream
  StreamRequest,
  StreamChunk,
  StreamEventType,

  // Memory
  MemoryType,
  RetrievalStrategy,
  DistanceMetric,
  StoreMemoryRequest,
  SearchMemoryRequest,

  // Responses
  PingResponse,
  GraphResponse,
  StateSchemaResponse,
  ThreadStateResponse,

  // Errors
  AgentFlowError,
  AuthenticationError,
  NotFoundError,

  // Metadata
  ResponseMetadata
} from 'agentflow-react';

Core Interfaces

AgentFlowClient

The main client class for API interaction.

class AgentFlowClient {
  constructor(config: AgentFlowConfig);

  // Health & Metadata
  ping(): Promise<PingResponse>;
  graph(): Promise<GraphResponse>;
  graphStateSchema(): Promise<StateSchemaResponse>;

  // Execution
  invoke(request: InvokeRequest): Promise<InvokeResult>;
  stream(request: StreamRequest): AsyncIterableIterator<StreamChunk>;

  // Tools
  registerTool(registration: ToolRegistration): void;
  setup(): Promise<void>;

  // Threads
  threads(request?: ThreadsRequest): Promise<ThreadsResponse>;
  threadDetails(threadId: string): Promise<ThreadDetailsResponse>;
  threadState(threadId: string): Promise<ThreadStateResponse>;
  updateThreadState(threadId: string, request: UpdateThreadStateRequest): Promise<UpdateThreadStateResponse>;
  clearThreadState(threadId: string): Promise<ClearThreadStateResponse>;
  deleteThread(threadId: string, request?: DeleteThreadRequest): Promise<DeleteThreadResponse>;

  // Messages
  threadMessages(threadId: string, options?: ThreadMessagesRequest): Promise<ThreadMessagesResponse>;
  threadMessage(threadId: string, messageId: string): Promise<ThreadMessageResponse>;
  addThreadMessages(threadId: string, request: AddThreadMessagesRequest): Promise<AddThreadMessagesResponse>;
  deleteThreadMessage(threadId: string, messageId: string): Promise<DeleteThreadMessageResponse>;

  // Memory
  storeMemory(request: StoreMemoryRequest): Promise<StoreMemoryResponse>;
  searchMemory(request: SearchMemoryRequest): Promise<SearchMemoryResponse>;
  getMemory(memoryId: string): Promise<GetMemoryResponse>;
  updateMemory(memoryId: string, request: UpdateMemoryRequest): Promise<UpdateMemoryResponse>;
  deleteMemory(memoryId: string): Promise<DeleteMemoryResponse>;
  listMemories(request?: ListMemoriesRequest): Promise<ListMemoriesResponse>;
  forgetMemories(request: ForgetMemoriesRequest): Promise<ForgetMemoriesResponse>;
}

AgentFlowConfig

Client configuration options.

interface AgentFlowConfig {
  baseUrl: string;        // Required: API base URL
  authToken?: string;     // Optional: Authentication token
  timeout?: number;       // Optional: Request timeout in ms (default: 300000)
  debug?: boolean;        // Optional: Enable debug logging (default: false)
}

Example:

const config: AgentFlowConfig = {
  baseUrl: 'https://api.example.com',
  authToken: process.env.API_TOKEN,
  timeout: 60000,
  debug: true
};

const client: AgentFlowClient = new AgentFlowClient(config);

Message Types

Message

The main message class with helper methods.

class Message {
  message_id: string | null;
  role: 'user' | 'assistant' | 'system' | 'tool';
  content: ContentBlock[];
  delta: boolean;
  tools_calls?: Record<string, any>[];
  timestamp: number;
  metadata: Record<string, any>;
  usages?: TokenUsages;
  raw?: Record<string, any>;

  constructor(
    role: 'user' | 'assistant' | 'system' | 'tool',
    content: ContentBlock[],
    message_id?: string | null
  );

  // Static helper methods
  static text_message(
    content: string,
    role?: 'user' | 'assistant' | 'system' | 'tool',
    message_id?: string | null
  ): Message;

  static tool_message(
    content: ContentBlock[],
    message_id?: string | null,
    meta?: Record<string, any>
  ): Message;

  // Instance methods
  text(): string;
  attach_media(media: MediaRef, as_type: 'image' | 'audio' | 'video' | 'document'): void;
}

Content Blocks

// Base content block types
type ContentBlock = 
  | TextBlock 
  | ImageBlock 
  | AudioBlock 
  | VideoBlock 
  | DocumentBlock
  | DataBlock
  | ToolCallBlock
  | RemoteToolCallBlock 
  | ToolResultBlock
  | ReasoningBlock
  | AnnotationBlock
  | ErrorBlock;

// Text block
class TextBlock {
  type: 'text' = 'text';
  text: string;
  annotations: AnnotationRef[];

  constructor(text?: string, annotations?: AnnotationRef[]);
}

// Image block
class ImageBlock {
  type: 'image' = 'image';
  media: MediaRef;
  alt_text?: string;
  bbox?: number[];

  constructor(media?: MediaRef, alt_text?: string, bbox?: number[]);
}

// Audio block
class AudioBlock {
  type: 'audio' = 'audio';
  media: MediaRef;
  transcript?: string;
  sample_rate?: number;
  channels?: number;

  constructor(media?: MediaRef, transcript?: string, sample_rate?: number, channels?: number);
}

// Video block
class VideoBlock {
  type: 'video' = 'video';
  media: MediaRef;
  thumbnail?: MediaRef;

  constructor(media?: MediaRef, thumbnail?: MediaRef);
}

// Document block
class DocumentBlock {
  type: 'document' = 'document';
  media: MediaRef;
  pages?: number[];
  excerpt?: string;

  constructor(media?: MediaRef, pages?: number[], excerpt?: string);
}

// Data block
class DataBlock {
  type: 'data' = 'data';
  mime_type: string;
  data_base64?: string;
  media?: MediaRef;

  constructor(mime_type?: string, data_base64?: string, media?: MediaRef);
}

// Tool call block
class ToolCallBlock {
  type: 'tool_call' = 'tool_call';
  id: string;
  name: string;
  args: Record<string, any>;
  tool_type?: string;

  constructor(id?: string, name?: string, args?: Record<string, any>, tool_type?: string);
}

// Remote tool call (from API)
class RemoteToolCallBlock {
  type: 'remote_tool_call' = 'remote_tool_call';
  id: string;
  name: string;
  args: Record<string, any>;
  tool_type: string;

  constructor(id?: string, name?: string, args?: Record<string, any>, tool_type?: string);
}

// Tool result (sent back to API)
class ToolResultBlock {
  type: 'tool_result' = 'tool_result';
  call_id: string;
  output: any;
  is_error: boolean;
  status?: 'completed' | 'failed';

  constructor(props: { call_id: string; output: any; status: 'completed' | 'failed'; is_error: boolean });
}

// Reasoning block
class ReasoningBlock {
  type: 'reasoning' = 'reasoning';
  summary: string;
  details?: string[];

  constructor(summary?: string, details?: string[]);
}

// Annotation block
class AnnotationBlock {
  type: 'annotation' = 'annotation';
  kind: 'citation' | 'note';
  refs: AnnotationRef[];
  spans?: [number, number][];

  constructor(kind?: 'citation' | 'note', refs?: AnnotationRef[], spans?: [number, number][]);
}

// Error block
class ErrorBlock {
  type: 'error' = 'error';
  message: string;
  code?: string;
  data?: Record<string, any>;

  constructor(message?: string, code?: string, data?: Record<string, any>);
}

Media References

class MediaRef {
  kind: 'url' | 'file_id' | 'data';
  url?: string;
  file_id?: string;
  data_base64?: string;
  mime_type?: string;
  size_bytes?: number;
  sha256?: string;
  filename?: string;
  width?: number;
  height?: number;
  duration_ms?: number;
  page?: number;

  constructor(
    kind?: 'url' | 'file_id' | 'data',
    url?: string,
    file_id?: string,
    data_base64?: string,
    mime_type?: string,
    size_bytes?: number,
    sha256?: string,
    filename?: string,
    width?: number,
    height?: number,
    duration_ms?: number,
    page?: number
  );
}

class AnnotationRef {
  url?: string;
  file_id?: string;
  page?: number;
  index?: number;
  title?: string;

  constructor(url?: string, file_id?: string, page?: number, index?: number, title?: string);
}

class TokenUsages {
  completion_tokens: number;
  prompt_tokens: number;
  total_tokens: number;
  reasoning_tokens: number;
  cache_creation_input_tokens: number;
  cache_read_input_tokens: number;
  image_tokens?: number;
  audio_tokens?: number;
}

Example:

import { Message, TextBlock, ImageBlock, MediaRef } from 'agentflow-react';

// Simple text message
const userMessage: Message = Message.text_message('Hello', 'user');

// Message with multiple blocks
const complexMessage = new Message('user', [
  new TextBlock('Here is an image:'),
  new ImageBlock(
    new MediaRef('url', 'https://example.com/image.jpg'),
    'A beautiful landscape'
  )
]);

Request & Response Types

Invoke

interface InvokeRequest {
  messages: Message[];
  config?: Record<string, any>;
  stream?: boolean;
  granularity?: 'low' | 'partial' | 'full';
  recursion_limit?: number;
  on_progress?: InvokeCallback;
}

interface InvokeResult {
  messages: Message[];
  all_messages: Message[];
  state?: Record<string, any>;
  context?: any;
  summary?: string;
  iterations: number;
  recursion_limit_reached: boolean;
  metadata: ResponseMetadata;
}

interface InvokePartialResult {
  messages: Message[];
  all_messages: Message[];
  state?: Record<string, any>;
  context?: any;
  iterations: number;
  recursion_limit_reached: boolean;
}

type InvokeCallback = (result: InvokePartialResult) => void;

Example:

**Example:**

```typescript
const request: InvokeRequest = {
  messages: [Message.text_message('What is the weather?', 'user')],
  granularity: 'full',
  recursion_limit: 10,
  on_progress: (partial: InvokePartialResult) => {
    console.log(`Iteration ${partial.iterations}`);
  }

const result: InvokeResult = await client.invoke(request);

### State Schema

```typescript
interface StateSchemaResponse {
  data: {
    fields: {
      [fieldName: string]: FieldSchema;
    };
  };
  metadata: ResponseMetadata;
}

interface FieldSchema {
  type: string;
  description?: string;
  default?: any;
  required?: boolean;
  enum?: any[];
  items?: FieldSchema;
  properties?: Record<string, FieldSchema>;
}

Example:

const schema: StateSchemaResponse = await client.graphStateSchema();

// Iterate fields
for (const [name, field] of Object.entries(schema.data.fields)) {
  const fieldSchema: FieldSchema = field;
  console.log(`${name}: ${fieldSchema.type}`);
}

Thread State

interface ThreadStateResponse {
  data: {
    state: Record<string, any>;
    [key: string]: any;
  };
  metadata: ResponseMetadata;
}

interface UpdateThreadStateRequest {
  config?: Record<string, any>;
  state: Record<string, any>;
}

interface UpdateThreadStateResponse {
  data: {
    state: Record<string, any>;
    [key: string]: any;
  };
  metadata: ResponseMetadata;
}

Example:

// Get current state
const currentState: ThreadStateResponse = await client.threadState('thread_123');

// Update state
const updateRequest: UpdateThreadStateRequest = {
  state: {
    step: 'completed',
    result: { success: true }
  }
};

const updated: UpdateThreadStateResponse = await client.updateThreadState(
  'thread_123',
  updateRequest
);

Tool Types

Tool Registration

interface ToolRegistration {
  node: string;
  name: string;
  description?: string;
  parameters?: ToolParameter;
  handler: ToolHandler;
}

interface ToolParameter {
  type: 'object';
  properties: Record<string, any>;
  required: string[];
}

type ToolHandler = (args: any) => Promise<any>;

Example with Strong Typing:

// Define parameter interface
interface WeatherArgs {
  location: string;
  units?: 'metric' | 'imperial';
}

// Define result interface
interface WeatherResult {
  temperature: number;
  condition: string;
  humidity: number;
}

// Typed tool registration
const weatherTool: ToolRegistration = {
  node: 'assistant',
  name: 'get_weather',
  description: 'Get current weather',
  parameters: {
    type: 'object',
    properties: {
      location: { type: 'string', description: 'City name' },
      units: { type: 'string', enum: ['metric', 'imperial'] }
    },
    required: ['location']
  },
  handler: async (args: WeatherArgs): Promise<WeatherResult> => {
    const data = await fetchWeather(args.location, args.units);
    return {
      temperature: data.temp,
      condition: data.condition,
      humidity: data.humidity
    };
  }
};

client.registerTool(weatherTool);

Memory Types

Memory Enums

enum MemoryType {
  EPISODIC = "episodic",
  SEMANTIC = "semantic",
  PROCEDURAL = "procedural",
  ENTITY = "entity",
  RELATIONSHIP = "relationship",
  CUSTOM = "custom",
  DECLARATIVE = "declarative"
}

enum RetrievalStrategy {
  SIMILARITY = "similarity",
  TEMPORAL = "temporal",
  RELEVANCE = "relevance",
  HYBRID = "hybrid",
  GRAPH_TRAVERSAL = "graph_traversal"
}

enum DistanceMetric {
  COSINE = "cosine",
  EUCLIDEAN = "euclidean",
  DOT_PRODUCT = "dot_product",
  MANHATTAN = "manhattan"
}

Memory Requests

interface StoreMemoryRequest {
  config?: Record<string, any>;
  options?: Record<string, any>;
  content: string;
  memory_type: MemoryType;
  category: string;
  metadata?: Record<string, any>;
}

interface SearchMemoryRequest {
  config?: Record<string, any>;
  options?: Record<string, any>;
  query: string;
  memory_type?: MemoryType;
  category?: string;
  limit?: number;
  score_threshold?: number;
  filters?: Record<string, any>;
  retrieval_strategy?: RetrievalStrategy;
  distance_metric?: DistanceMetric;
  max_tokens?: number;
}

interface UpdateMemoryRequest {
  config?: Record<string, any>;
  options?: Record<string, any>;
  content?: string;
  memory_type?: MemoryType;
  category?: string;
  metadata?: Record<string, any>;
}

Memory Result

interface MemoryResult {
  id: string;
  content: string;
  score: number;
  memory_type: string;
  metadata: Record<string, any>;
  vector: number[];
  user_id: string;
  thread_id: string;
  timestamp: string;
}

Example:

import { MemoryType, RetrievalStrategy, DistanceMetric } from 'agentflow-react';

// Store memory
const storeRequest: StoreMemoryRequest = {
  content: 'User prefers dark mode',
  memory_type: MemoryType.SEMANTIC,
  category: 'preferences',
  metadata: { user_id: 'user_123' }
};

await client.storeMemory(storeRequest);

// Search memory
const searchRequest: SearchMemoryRequest = {
  query: 'user interface preferences',
  memory_type: MemoryType.SEMANTIC,
  limit: 5,
  score_threshold: 0.7,
  retrieval_strategy: RetrievalStrategy.SIMILARITY,
  distance_metric: DistanceMetric.COSINE
};

const results = await client.searchMemory(searchRequest);

results.data.results.forEach((result: MemoryResult) => {
  console.log(`[${result.score.toFixed(2)}] ${result.content}`);
});

Stream Types

Stream Request & Events

interface StreamRequest {
  messages: Message[];
  config?: Record<string, any>;
  stream?: boolean;
  granularity?: 'low' | 'partial' | 'full';
}

interface StreamChunk {
  event: StreamEventType;
  data: any;
}

type StreamEventType =
  | 'metadata'
  | 'on_chain_start'
  | 'on_chain_stream'
  | 'on_chain_end'
  | 'messages_chunk'
  | 'state_chunk'
  | 'context_chunk'
  | 'summary_chunk'
  | 'error';

Example with Type Guards:

async function handleStream(messages: Message[]) {
  for await (const chunk of client.stream({ messages })) {
    switch (chunk.event) {
      case 'metadata':
        const metadata = chunk.data as ResponseMetadata;
        console.log('Request ID:', metadata.request_id);
        break;

      case 'messages_chunk':
        const text = chunk.data as string;
        process.stdout.write(text);
        break;

      case 'state_chunk':
        const state = chunk.data as Record<string, any>;
        console.log('State:', state);
        break;

      case 'error':
        const error = chunk.data as { message: string };
        console.error('Error:', error.message);
        break;
    }
  }
}

Error Types

Error Classes

class AgentFlowError extends Error {
  status: number;
  requestId?: string;

  constructor(message: string, status: number, requestId?: string);
}

class BadRequestError extends AgentFlowError {
  constructor(message: string, requestId?: string);
}

class AuthenticationError extends AgentFlowError {
  constructor(message: string, requestId?: string);
}

class PermissionError extends AgentFlowError {
  constructor(message: string, requestId?: string);
}

class NotFoundError extends AgentFlowError {
  constructor(message: string, requestId?: string);
}

class ValidationError extends AgentFlowError {
  constructor(message: string, requestId?: string);
}

class ServerError extends AgentFlowError {
  constructor(message: string, status: number, requestId?: string);
}

Example:

import { 
  AgentFlowError, 
  AuthenticationError, 
  NotFoundError 
} from 'agentflow-react';

try {
  const result = await client.invoke({ messages });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Auth failed:', error.message);
    console.error('Request ID:', error.requestId);
  } else if (error instanceof NotFoundError) {
    console.error('Resource not found:', error.message);
  } else if (error instanceof AgentFlowError) {
    console.error(`Error ${error.status}:`, error.message);
  } else {
    console.error('Unknown error:', error);
  }
}

Type Guards

Message Type Guards

function isTextBlock(block: ContentBlock): block is TextBlock {
  return block.type === 'text';
}

function isImageBlock(block: ContentBlock): block is ImageBlock {
  return block.type === 'image';
}

function isRemoteToolCall(block: ContentBlock): block is RemoteToolCallBlock {
  return block.type === 'remote_tool_call';
}

function isToolResult(block: ContentBlock): block is ToolResultBlock {
  return block.type === 'tool_result';
}

Usage:

const message: Message = result.messages[0];

for (const block of message.content) {
  if (isTextBlock(block)) {
    console.log('Text:', block.text);
  } else if (isImageBlock(block)) {
    console.log('Image URL:', block.media.url);
  } else if (isRemoteToolCall(block)) {
    console.log('Tool call:', block.name, block.args);
  }
}

Error Type Guards

function isAgentFlowError(error: unknown): error is AgentFlowError {
  return error instanceof AgentFlowError;
}

function isAuthError(error: unknown): error is AuthenticationError {
  return error instanceof AuthenticationError;
}

function isNotFoundError(error: unknown): error is NotFoundError {
  return error instanceof NotFoundError;
}

Usage:

try {
  await client.invoke({ messages });
} catch (error) {
  if (isAuthError(error)) {
    // TypeScript knows error is AuthenticationError
    redirectToLogin(error.requestId);
  } else if (isNotFoundError(error)) {
    // TypeScript knows error is NotFoundError
    showNotFoundPage(error.message);
  } else if (isAgentFlowError(error)) {
    // TypeScript knows error is AgentFlowError
    logError(error.status, error.message);
  }
}

Generic Types

Typed Invoke Result

Create typed results for specific use cases:

interface ChatResult extends InvokeResult {
  messages: Message[];
  conversationState: {
    topic: string;
    sentiment: 'positive' | 'negative' | 'neutral';
  };
}

async function invokeChat(messages: Message[]): Promise<ChatResult> {
  const result = await client.invoke({
    messages,
    granularity: 'full'
  });

  return {
    ...result,
    conversationState: result.state as any
  };
}

Typed Tool Handlers

// Generic typed tool handler
type TypedToolHandler<TArgs, TResult> = (args: TArgs) => Promise<TResult>;

// Weather tool types
interface WeatherArgs {
  location: string;
  units?: 'metric' | 'imperial';
}

interface WeatherResult {
  temperature: number;
  condition: string;
}

const weatherHandler: TypedToolHandler<WeatherArgs, WeatherResult> = async (args) => {
  const data = await fetchWeather(args.location, args.units);
  return {
    temperature: data.temp,
    condition: data.condition
  };
};

client.registerTool({
  node: 'assistant',
  name: 'get_weather',
  handler: weatherHandler
});

Custom Type Extensions

Extend Client Configuration

interface CustomAgentFlowConfig extends AgentFlowConfig {
  retryAttempts?: number;
  retryDelay?: number;
  customHeaders?: Record<string, string>;
}

class CustomAgentFlowClient extends AgentFlowClient {
  private retryAttempts: number;
  private retryDelay: number;

  constructor(config: CustomAgentFlowConfig) {
    super(config);
    this.retryAttempts = config.retryAttempts ?? 3;
    this.retryDelay = config.retryDelay ?? 1000;
  }

  async invokeWithRetry(request: InvokeRequest): Promise<InvokeResult> {
    for (let attempt = 1; attempt <= this.retryAttempts; attempt++) {
      try {
        return await this.invoke(request);
      } catch (error) {
        if (attempt === this.retryAttempts) throw error;
        await this.sleep(this.retryDelay * attempt);
      }
    }
    throw new Error('Max retries exceeded');
  }

  private sleep(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

Extend Message Types

// Add custom message metadata
interface ExtendedMessage extends Message {
  metadata: {
    timestamp: Date;
    userId: string;
    sessionId: string;
  };
}

function createExtendedMessage(
  text: string,
  userId: string,
  sessionId: string
): ExtendedMessage {
  const message = Message.text_message(text, 'user') as ExtendedMessage;
  message.metadata = {
    timestamp: new Date(),
    userId,
    sessionId
  };
  return message;
}

Custom Tool Types

// Tool with middleware
interface ToolWithMiddleware extends ToolRegistration {
  beforeExecute?: (args: any) => Promise<void>;
  afterExecute?: (result: any) => Promise<void>;
}

function registerToolWithMiddleware(
  client: AgentFlowClient,
  tool: ToolWithMiddleware
) {
  const originalHandler = tool.handler;

  const wrappedHandler: ToolHandler = async (args) => {
    if (tool.beforeExecute) {
      await tool.beforeExecute(args);
    }

    const result = await originalHandler(args);

    if (tool.afterExecute) {
      await tool.afterExecute(result);
    }

    return result;
  };

  client.registerTool({
    ...tool,
    handler: wrappedHandler
  });
}

Response Metadata

All API responses include metadata:

interface ResponseMetadata {
  message: string;
  request_id: string;
  timestamp: string;
}

Usage:

const result: InvokeResult = await client.invoke({ messages });

console.log('Request ID:', result.metadata.request_id);
console.log('Timestamp:', result.metadata.timestamp);
console.log('Message:', result.metadata.message);

Complete Example

Here's a complete TypeScript example using all type features:

import {
  AgentFlowClient,
  AgentFlowConfig,
  Message,
  InvokeRequest,
  InvokeResult,
  ToolRegistration,
  MemoryType,
  StoreMemoryRequest,
  SearchMemoryRequest,
  AuthenticationError,
  NotFoundError
} from 'agentflow-react';

// Configuration
const config: AgentFlowConfig = {
  baseUrl: process.env.AGENTFLOW_API_URL!,
  authToken: process.env.AGENTFLOW_TOKEN,
  timeout: 60000,
  debug: true
};

const client = new AgentFlowClient(config);

// Tool types
interface CalculatorArgs {
  expression: string;
}

interface CalculatorResult {
  result: number;
  expression: string;
}

// Register tool
const calculatorTool: ToolRegistration = {
  node: 'assistant',
  name: 'calculate',
  description: 'Perform calculations',
  parameters: {
    type: 'object',
    properties: {
      expression: { type: 'string' }
    },
    required: ['expression']
  },
  handler: async (args: CalculatorArgs): Promise<CalculatorResult> => {
    const result = evaluateMath(args.expression);
    return { result, expression: args.expression };
  }
};

client.registerTool(calculatorTool);

// Invoke with types
async function chat(userInput: string): Promise<InvokeResult> {
  const request: InvokeRequest = {
    messages: [Message.text_message(userInput, 'user')],
    granularity: 'full',
    recursion_limit: 10
  };

  try {
    const result: InvokeResult = await client.invoke(request);

    // Store memory
    const memoryRequest: StoreMemoryRequest = {
      content: `User asked: ${userInput}`,
      memory_type: MemoryType.EPISODIC,
      category: 'conversations',
      metadata: {
        timestamp: new Date().toISOString(),
        result_iterations: result.iterations
      }
    };

    await client.storeMemory(memoryRequest);

    return result;
  } catch (error) {
    if (error instanceof AuthenticationError) {
      console.error('Authentication failed:', error.requestId);
      throw new Error('Please check your API token');
    } else if (error instanceof NotFoundError) {
      console.error('Resource not found:', error.message);
      throw new Error('API endpoint not available');
    } else {
      throw error;
    }
  }
}

// Usage
const result = await chat('Calculate 123 * 456');
console.log('Response:', result.messages[0].content);
console.log('Iterations:', result.iterations);
console.log('Request ID:', result.metadata.request_id);

See Also


Pro Tip: Enable strict mode in tsconfig.json for maximum type safety!