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 blockoauth: Authentication requirements specifying the provider and scoperequest: HTTP method, URL, headers, and body construction logictransformResponse: 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:
- Validate input parameters against the tool's Zod schema
- Construct the HTTP request using the tool's
requestdefinition - Execute the API call with OAuth credentials if required
- Apply
transformResponseto 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:
- All entries in
TOOL_REGISTRYfollow strict alphabetical ordering by key - Every tool folder under
apps/sim/tools/has a corresponding entry in the registry - 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
ToolConfigobject inapps/sim/tools/<service>/<action>.tscontaining Zod schemas, OAuth config, and request logic. - Export pattern: Service-level
index.tsfiles re-export tools to provide stable import targets for the registry. - Central registration:
apps/sim/tools/registry.tsexportsTOOL_REGISTRY, a strictly orderedRecord<string, ToolConfig>mapping tool IDs to configurations. - Runtime lookup: The workflow executor imports
TOOL_REGISTRYto resolve tool configurations by ID during block execution. - Automated validation:
apps/sim/scripts/check-block-registry.tsenforces 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →