Skip to content
reaatechREAATECH

@reaatech/structured-function-calling-ai-engine

pending npm

Provides a `ToolExecutor` class that manages the lifecycle of AI tool calls, including Zod schema validation, retry logic, and circuit breaking via a composable middleware pipeline. It wraps a tool registry to execute functions with built-in telemetry, error handling, and exponential backoff.

@reaatech/structured-function-calling-ai-engine

Execution engine with retry, circuit breakers, and telemetry hooks wrapping a tool registry.

Installation

terminal
pnpm add @reaatech/structured-function-calling-ai-engine

API

ToolExecutor

typescript
class ToolExecutor {
  constructor(registry: ToolRegistry, middlewares?: Middleware[]);
  execute(
    name: string,
    input: Record<string, unknown>,
    opts?: ExecuteOptions,
  ): Promise<ExecutionResult>;
}

Resolves a tool by name from the registry, parses input against its Zod schema, runs the middleware pipeline (onBefore → execute → onAfter; onError on exception), and returns an ExecutionResult.

ExecuteOptions

typescript
interface ExecuteOptions {
  signal?: AbortSignal;
}

Currently accepts an AbortSignal; in-flight execution is not yet abortable.

Middleware

typescript
interface Middleware {
  onBefore?(ctx: ExecutionContext): Promise<void>;
  onAfter?(ctx: ExecutionContext, result: ExecutionResult): Promise<void>;
  onError?(ctx: ExecutionContext, error: Error): Promise<void>;
}

Composable hooks. All three methods are optional. onBefore runs before execution; onAfter runs after a successful result; onError runs when execution throws.

ExecutionContext

typescript
interface ExecutionContext {
  toolName: string;
  input: Record<string, unknown>;
  startTime: number;
  attempt: number;
}

ExecutionResult

typescript
interface ExecutionResult {
  success: boolean;
  data?: unknown;
  error?: Error;
  attempts: number;
  durationMs: number;
}

createRetryMiddleware

typescript
function createRetryMiddleware(opts?: RetryOptions): Middleware;

Tracks attempt count in the ExecutionContext. Used internally by withRetry. This middleware does not itself implement the retry loop — use withRetry for a retrying executor.

withRetry

typescript
function withRetry(executor: ToolExecutor, opts?: RetryOptions): ToolExecutor;

Wraps a ToolExecutor in a retry loop. Uses exponential backoff (baseDelayMs * 2^attempt). Attempts to repair partial JSON responses using partial-json. Retries on non-success results whose error message matches partial-JSON patterns. Returns a Proxy of the original executor with execute replaced.

RetryOptions

typescript
interface RetryOptions {
  maxAttempts?: number;   // default: 3
  baseDelayMs?: number;   // default: 200
}

CircuitBreaker

typescript
class CircuitBreaker {
  constructor(opts?: { threshold?: number; resetTimeoutMs?: number });
  async call<T>(toolName: string, fn: () => Promise<T>): Promise<T>;
  recordSuccess(toolName: string): void;
  recordFailure(toolName: string): void;
  getState(toolName: string): 'closed' | 'open' | 'half-open';
}

Per-tool in-memory circuit breaker. Default threshold: 5 failures. Default reset timeout: 30 s. Transitions: closed → open (after threshold failures) → half-open (after resetTimeoutMs) → closed (probe succeeds) or open (probe fails).

createCircuitBreakerMiddleware

typescript
function createCircuitBreakerMiddleware(opts?: CircuitBreakerOptions): Middleware;

Throws CircuitBreakerOpenError when the circuit is open, records success on onAfter, records failure on onError.

CircuitBreakerOptions

typescript
interface CircuitBreakerOptions {
  threshold?: number;      // default: 5
  resetTimeoutMs?: number; // default: 30000
}

createTelemetryMiddleware

typescript
function createTelemetryMiddleware(logger?: pino.Logger): Middleware;

Logs onBefore, onAfter, and onError lifecycle events via pino. Silently skips all logging when logger is undefined.

ExecutionError

typescript
class ExecutionError extends Error {
  readonly toolName: string;
  readonly cause: Error;
}

CircuitBreakerOpenError

typescript
class CircuitBreakerOpenError extends Error;

Usage example

typescript
import { z } from 'zod/v3';
import { ToolRegistry } from '@reaatech/structured-function-calling-ai-core';
import {
  ToolExecutor,
  withRetry,
  createTelemetryMiddleware,
  createCircuitBreakerMiddleware,
} from '@reaatech/structured-function-calling-ai-engine';
import pino from 'pino';
 
const schema = z.object({ city: z.string() });
 
const registry = new ToolRegistry();
registry.register({
  name: 'get_weather',
  description: 'Get weather for a city',
  schema,
  execute: async (input) => ({ temp: 22, conditions: 'sunny' }),
});
 
const logger = pino({ level: 'info' });
const baseExecutor = new ToolExecutor(registry, [
  createTelemetryMiddleware(logger),
  createCircuitBreakerMiddleware({ threshold: 3 }),
]);
 
const executor = withRetry(baseExecutor, { maxAttempts: 3, baseDelayMs: 200 });
const result = await executor.execute('get_weather', { city: 'NYC' });

Dependencies

  • @reaatech/structured-function-calling-ai-core (workspace:*)
  • partial-json 0.1.7
  • pino 10.3.1