Audit an existing Sim integration against the service API docs and repository conventions, then report and fix issues across tools, blocks, outputs, OAuth scopes, triggers, and registry entries. Use when validating or repairing a service integration under `apps/sim/tools`, `apps/sim/blocks`, or `apps/sim/triggers`.
You are an expert auditor for Sim integrations. Your job is to thoroughly validate that an existing integration is correct, complete, and follows all conventions.
When the user asks you to validate an integration:
Read every file for the integration — do not skip any:
apps/sim/tools/{service}/ # All tool files, types.ts, index.ts
apps/sim/blocks/blocks/{service}.ts # Block definition
apps/sim/tools/registry.ts # Tool registry entries for this service
apps/sim/blocks/registry.ts # Block registry entry for this service
apps/sim/components/icons.tsx # Icon definition
apps/sim/lib/auth/auth.ts # OAuth config — should use getCanonicalScopesForProvider()
apps/sim/lib/oauth/oauth.ts # OAuth provider config — single source of truth for scopes
apps/sim/lib/oauth/utils.ts # Scope utilities, SCOPE_DESCRIPTIONS for modal UI
Fetch the official API docs for the service. This is the source of truth for:
If the official docs do not clearly show the response JSON shape for an endpoint, you MUST tell the user instead of guessing.
If a response schema is unknown, the validation must explicitly call that out and require:
For every tool file, check:
snake_case: {service}_{action} (e.g., x_create_tweet, slack_send_message)name is human-readable (e.g., 'X Create Tweet')description is a concise one-liner describing what it doesversion is set ('1.0.0' or '2.0.0' for V2)required: truerequired: falserequired: true or required: false — never omitted'string', 'number', 'boolean', 'json')'hidden' — ONLY for OAuth access tokens and system-injected params'user-only' — for API keys, credentials, and account-specific IDs the user must provide'user-or-llm' — for everything else (search queries, content, filters, IDs that could come from other blocks)description that explains what it doesAuthorization: Bearer ${params.accessToken}Content-Type header is set for POST/PUT/PATCH requests.trim()-ed to prevent copy-paste whitespace errors`https://api.service.com/v1/${params.id.trim()}`await response.json())data.data vs data vs data.results)?? null?? []optional: true is set on fields that may not exist in all responsestype: 'json' and the shape is known, properties defines the inner fieldstype: 'array', items defines the item structure with propertiesXCreateTweetParams)ToolResponse)? in the interface (e.g., replyTo?: string)XTweetResponse shared across tweet tools)export * from './types')This is the most important validation — the block must be perfectly aligned with every tool it references.
For each tool in tools.access:
tools.config.tool function correctly maps to it)accessToken) has a corresponding subBlock input that is:
condition)required: true (or conditionally required)id values are unique across the entire block — no duplicates even across different conditionstools.config.tool function returns the correct tool ID for every possible operation valuetools.config.params function correctly maps subBlock IDs to tool param names when they differtools.access{ field: 'operation', value: 'x_create_tweet' }{ field: 'operation', value: ['x_create_tweet', 'x_delete_tweet'] }{ field: 'operation', value: 'delete', not: true }{ field: 'op', value: 'send', and: { field: 'type', value: 'dm' } }dependsOn is set for fields that need other values (selectors depending on credential, cascading dropdowns)dropdownshort-inputlong-inputdropdown with Yes/No options (not switch unless purely UI toggle)oauth-input with correct serviceIdvalue: () => 'default' is set for dropdowns with a sensible defaultmode: 'advanced':
mode: 'advanced'mode: 'advanced'wandConfig with generationType: 'timestamp'wandConfig with a descriptive promptwandConfig with format examples in the promptwandConfig prompts end with "Return ONLY the [format] - no explanations, no extra text."wandConfig.placeholder describes what to type in natural languagetools.access lists every tool ID the block can use — none missingtools.config.tool returns the correct tool ID for each operationtools.config.params (runs at execution time), NOT in tools.config.tool (runs at serialization time before variable resolution)tools.config.params handles:
Number() conversion for numeric params that come as strings from inputsBoolean / string-to-boolean conversion for toggle paramsundefined conversion for optional dropdown valuesNumber(), JSON.parse(), or other coercions in tools.config.tool — these would destroy dynamic references like <Block.output>'string', 'number', 'boolean', 'json')type: 'json' outputs either:
'User profile (id, name, username, bio)'{ id: { type: 'string' }, name: { type: 'string' } }type: 'json' with vague descriptions like 'Response data'condition if supported, or document which operations return themtype is snake_case (e.g., 'x', 'cloudflare')name is human-readable (e.g., 'X', 'Cloudflare')description is a concise one-linerlongDescription provides detail for docsdocsLink points to 'https://docs.sim.ai/tools/{service}'category is 'tools'bgColor uses the service's brand color hexicon references the correct icon component from @/components/iconsauthMode is set correctly (AuthMode.OAuth or AuthMode.ApiKey)blocks/registry.ts alphabeticallyinputs section lists all subBlock params that the block acceptscanonicalParamId, inputs list the canonical ID (not the raw subBlock IDs)Scopes are centralized — the single source of truth is OAUTH_PROVIDERS in lib/oauth/oauth.ts.
lib/oauth/oauth.ts under OAUTH_PROVIDERS[provider].services[service].scopesauth.ts uses getCanonicalScopesForProvider(providerId) — NOT a hardcoded arrayrequiredScopes uses getScopesForService(serviceId) — NOT a hardcoded arrayauth.ts or block files (should all use utility functions)SCOPE_DESCRIPTIONS within lib/oauth/utils.tsIf any tools support pagination:
pagination_token vs next_token vs cursor)nextToken, cursor, etc.) are included in tool outputsmode: 'advanced'transformResponse checks for error conditions before accessing dataresponse.ok or status codes)Group findings by severity:
Critical (will cause runtime errors or incorrect behavior):
required flagtools.accessauth.ts that tools needtools.config.tool returning wrong tool ID for an operationtools.config.tool instead of tools.config.paramsWarning (follows conventions incorrectly or has usability issues):
mode: 'advanced'wandConfig on timestamp/complex fieldsvisibility on params (e.g., 'hidden' instead of 'user-or-llm')optional: true on nullable outputstype: 'json' without property descriptions.trim() on ID fields in request URLs?? null on nullable response fieldsgetScopesForService() / getCanonicalScopesForProvider()SCOPE_DESCRIPTIONS within lib/oauth/utils.tsSuggestion (minor improvements):
longDescription or docsLinkwandConfigAfter reporting, fix every critical and warning issue. Apply suggestions where they don't add unnecessary complexity.
After fixing, confirm:
bun run lint passes with no fixes neededSCOPE_DESCRIPTIONS within lib/oauth/utils.ts for all scopesbun run lint after fixes