How Tools Are Defined and Registered in the SimStudio AI Tools Registry

SimStudio AI registers external integrations as TypeScript modules in a central TOOL_REGISTRY map, where each tool defines its Zod schemas, OAuth requirements, and HTTP request logic in apps/sim/tools/<service>/ before being imported into apps/sim/tools/registry.ts.

The simstudioai/sim repository implements a modular tool system that treats every third-party integration—such as Zoom, Google BigQuery, and Cal.com—as a self-contained TypeScript module. Each tool declares its configuration, validation schemas, and API logic in dedicated files under apps/sim/tools/, then exports through an index file to the central registry. This architecture enables type-safe workflow execution and straightforward registration of new capabilities.

Tool Configuration Structure

Individual tools are defined as ToolConfig objects that encapsulate everything the workflow engine needs to execute an external API call. Each tool resides in its own subdirectory under apps/sim/tools/<service>/ and exports a configuration object from a concrete implementation file.

A tool definition includes:

  • id: A unique namespaced identifier (e.g., zoom.create_meeting)
  • params: A Zod schema validating input fields from the workflow block
  • oauth: Authentication requirements specifying the provider and scope
  • request: HTTP method, URL, headers, and body construction logic
  • transformResponse: Optional function to reshape API responses for downstream blocks

Here is the Zoom create meeting tool defined in apps/sim/tools/zoom/create_meeting.ts:

import { z } from 'zod'
import type { ToolConfig } from '@/tools/types'

export const createMeetingTool: ToolConfig = {
  id: 'zoom.create_meeting',
  name: 'Create Zoom Meeting',
  description: 'Creates a new Zoom meeting for a given host.',
  version: '1.0.0',
  oauth: { required: true, provider: 'zoom' },

  params: z.object({
    topic: z.string().min(1, 'Topic must not be empty'),
    start_time: z.string().datetime(),
    duration: z.number().int().positive(),
  }),

  request: {
    method: 'POST',
    url: '/v2/users/me/meetings',
    body: (input) => ({
      topic: input.topic,
      type: 2,
      start_time: input.start_time,
      duration: input.duration,
    }),
  },

  transformResponse: async (response) => ({
    meetingId: response.id,
    joinUrl: response.join_url,
  }),
}

The Registration Pattern

Tools are registered through a two-level export pattern that isolates implementation details from the central registry.

Service-Level Index Files

Each service folder contains an index.ts that re-exports concrete tool configurations under stable names. For example, apps/sim/tools/zoom/index.ts exports the create meeting tool:

// apps/sim/tools/zoom/index.ts
export { createMeetingTool as zoomCreateMeeting } from './create_meeting'

Central Registry Population

The apps/sim/tools/registry.ts file imports these exports and assembles them into TOOL_REGISTRY, a constant Record<string, ToolConfig> that serves as the runtime lookup table. The registry enforces alphabetical ordering by tool ID to maintain consistency and simplify automated validation.

// apps/sim/tools/registry.ts
import { zoomCreateMeeting } from '@/tools/zoom'
import { googleBigQueryQuery } from '@/tools/google_bigquery'
import { calComCreateBooking } from '@/tools/calcom'

export const TOOL_REGISTRY = {
  'calcom.create_booking': calComCreateBooking,
  'google_bigquery.query': googleBigQueryQuery,
  'zoom.create_meeting': zoomCreateMeeting,
} as const

When a workflow block references a tool ID, the executor retrieves the corresponding ToolConfig from this map to access validation schemas and request definitions.

Runtime Tool Resolution

During workflow execution, the system resolves tool configurations through the registry map. Functions like getToolConfig(id) in the workflow executor import TOOL_REGISTRY and return the matching configuration for the requested tool ID.

// apps/sim/tools/workflow/executor.ts (conceptual)
import { TOOL_REGISTRY } from '@/tools/registry'

export function getToolConfig(id: string) {
  const tool = TOOL_REGISTRY[id]
  if (!tool) throw new Error(`Tool ${id} not found in registry`)
  return tool
}

The executor uses this configuration to:

  1. Validate input parameters against the tool's Zod schema
  2. Construct the HTTP request using the tool's request definition
  3. Execute the API call with OAuth credentials if required
  4. Apply transformResponse to shape the output for subsequent blocks

Registry Maintenance and Validation

The repository includes automated checks to ensure registry integrity. The script apps/sim/scripts/check-block-registry.ts validates that:

  1. All entries in TOOL_REGISTRY follow strict alphabetical ordering by key
  2. Every tool folder under apps/sim/tools/ has a corresponding entry in the registry
  3. No duplicate tool IDs exist in the map

This CI enforcement prevents merge conflicts and ensures that the runtime lookup table remains predictable and complete.

Summary

  • Tool definition: Each integration is a ToolConfig object in apps/sim/tools/<service>/<action>.ts containing Zod schemas, OAuth config, and request logic.
  • Export pattern: Service-level index.ts files re-export tools to provide stable import targets for the registry.
  • Central registration: apps/sim/tools/registry.ts exports TOOL_REGISTRY, a strictly ordered Record<string, ToolConfig> mapping tool IDs to configurations.
  • Runtime lookup: The workflow executor imports TOOL_REGISTRY to resolve tool configurations by ID during block execution.
  • Automated validation: apps/sim/scripts/check-block-registry.ts enforces alphabetical ordering and completeness in CI.

Frequently Asked Questions

How do I add a new tool to the SimStudio AI registry?

Create a new tool configuration file in apps/sim/tools/<service>/<action>.ts implementing the ToolConfig interface with your Zod schemas and request logic. Export it from apps/sim/tools/<service>/index.ts, then import and add it to the TOOL_REGISTRY object in apps/sim/tools/registry.ts following alphabetical order by tool ID.

What happens if a tool is not found in the registry at runtime?

The workflow executor calls getToolConfig(id) which accesses TOOL_REGISTRY[id]. If the ID does not exist in the map, the function throws an error indicating the tool was not found, preventing execution of undefined tools.

Why does the registry enforce alphabetical ordering?

Alphabetical ordering in TOOL_REGISTRY prevents merge conflicts when multiple developers add tools simultaneously and enables the check-block-registry.ts script to perform deterministic validation. The CI script checks this ordering automatically on every pull request.

What is the purpose of the transformResponse field in ToolConfig?

The transformResponse function allows tools to reshape raw API responses into a standardized format before passing data to downstream workflow blocks. This abstraction ensures that workflow users receive consistent field names and data structures regardless of third-party API conventions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →