You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Every integration block **must** export a `{Service}BlockMeta` object at the bottom of the block file. This metadata drives the integration catalog, tag filters, and workflow template suggestions shown to users.
tags: ['messaging', 'automation'], // Same tags as the block's tags field
643
+
templates: [ // Optional but strongly encouraged
644
+
{
645
+
icon: {Service}Icon,
646
+
title: '{Service} use-case title',
647
+
prompt: 'Build a workflow that ...',
648
+
modules: ['agent', 'workflows'], // Modules the template uses
649
+
category: 'productivity', // Template category
650
+
tags: ['automation'], // Template-level tags
651
+
alsoIntegrations: ['slack'], // Other blocks referenced in the prompt (optional)
652
+
},
653
+
],
654
+
} asconstsatisfiesBlockMeta
655
+
```
656
+
657
+
### Rules
658
+
659
+
-**Import `BlockMeta`** from `@/blocks/types` alongside `BlockConfig`
660
+
-**`tags`** must match the `tags` array on the block config exactly
661
+
-**Templates are optional** but should be added for any integration that has a recognizable use case — aim for 2–4 templates per block
662
+
-**Template `prompt`** should start with "Build a workflow that..." or "Create a workflow that..." and be concrete enough to generate a real workflow in Mothership
663
+
-**Template `modules`** lists the Sim modules the template relies on: `'knowledge-base' | 'tables' | 'files' | 'workflows' | 'scheduled' | 'agent'`
664
+
-**Template `category`** is one of: `'popular' | 'sales' | 'support' | 'engineering' | 'marketing' | 'productivity' | 'operations'`
665
+
-**`alsoIntegrations`** names other block types (e.g. `'slack'`, `'linear'`) referenced in the template prompt — helps the catalog surface this template when those blocks are selected
666
+
- Place the export **after** the main `{Service}Block` export, at the very bottom of the file
667
+
668
+
### Register in the blocksMeta object
669
+
670
+
After adding `{Service}BlockMeta` to the block file, register it in `apps/sim/blocks/registry.ts`:
671
+
672
+
```typescript
673
+
// Add import (alongside the block import, alphabetically)
tags: ['tag1', 'tag2'], // IntegrationTag values matching the service's capabilities
183
+
templates: [
184
+
{
185
+
icon: {Service}Icon,
186
+
title: '{Service} use-case title',
187
+
prompt: 'Build a workflow that ...',
188
+
modules: ['agent', 'workflows'],
189
+
category: 'productivity',
190
+
tags: ['automation'],
191
+
alsoIntegrations: ['slack'], // Optional: other blocks referenced in the prompt
192
+
},
193
+
],
194
+
} asconstsatisfiesBlockMeta
180
195
```
181
196
197
+
### BlockMeta rules
198
+
199
+
-**Tags**: Use `IntegrationTag` values from `@/blocks/types`. Do NOT add a `tags` field to the `BlockConfig` object — tags belong only in `BlockMeta`.
200
+
-**`integrationType`**: Must be a valid `IntegrationType` enum value (AI, Analytics, Commerce, Communication, Databases, DevOps, Documents, Email, HR, Marketing, Observability, Productivity, Sales, Search, Security, Support). Never invent a value that doesn't exist in the enum.
201
+
-**Templates**: Aim for 2–4 templates per integration. Prompts should be concrete enough to generate a real workflow in Mothership. Start with "Build a workflow that..." or "Create a workflow that...".
202
+
-**`alsoIntegrations`**: List other block type IDs referenced in the template prompt (e.g. `'slack'`, `'linear'`).
203
+
- Place `{Service}BlockMeta` at the very bottom of the file, after the main block export.
204
+
- Register it in both the import and the `blocksMeta` object in `registry.ts`.
Copy file name to clipboardExpand all lines: .claude/commands/add-block.md
+36-20Lines changed: 36 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -429,7 +429,7 @@ Maps multiple UI fields to a single serialized parameter:
429
429
430
430
**Critical constraints:**
431
431
-`canonicalParamId` must NOT match any other subblock's `id` in the same block (causes conflicts)
432
-
-`canonicalParamId`must be unique per block (only one basic/advanced pair per canonicalParamId)
432
+
-A `canonicalParamId`links exactly one basic/advanced pair for a single logical parameter. Do NOT reuse the same `canonicalParamId` for different parameters, even under mutually-exclusive conditions/operations
433
433
- ONLY use `canonicalParamId` to link basic/advanced mode alternatives for the same logical parameter
434
434
- Do NOT use it for any other purpose
435
435
@@ -519,7 +519,10 @@ tools: {
519
519
Block outputs only support:
520
520
-`type` - The data type ('string', 'number', 'boolean', 'json', 'array')
521
521
-`description` - Human readable description
522
-
- Nested object structure (for complex types)
522
+
-`condition` - Optional visibility condition
523
+
-`hiddenFromDisplay` - Optional flag to hide from the output display
524
+
525
+
**Nested object/`properties` outputs are tool-output-only and will fail TypeScript at build time on block outputs.** For complex shapes use `type: 'json'` and describe the inner fields in the `description` string.
523
526
524
527
```typescript
525
528
outputs: {
@@ -542,7 +545,7 @@ outputs: {
542
545
543
546
### Typed JSON Outputs
544
547
545
-
When using `type: 'json'` and you know the object shape in advance, **describe the inner fields in the description** so downstream blocks know what properties are available. For well-known, stable objects, use nested output definitions instead:
548
+
When using `type: 'json'` and you know the object shape in advance, **describe the inner fields in the description** so downstream blocks know what properties are available. Block outputs have no nested `properties` form — always keep the output flat and put the shape in the `description`:
546
549
547
550
```typescript
548
551
outputs: {
@@ -554,26 +557,10 @@ outputs: {
554
557
type: 'json',
555
558
description: 'Zone plan information (id, name, price, currency, frequency, is_subscribed)',
556
559
},
557
-
558
-
// BEST: Use nested output definition when the shape is stable and well-known
- The object has a small, stable set of fields (< 10)
570
-
- Downstream blocks will commonly access specific properties
571
-
- The API response shape is well-documented and unlikely to change
572
-
573
-
Use `type: 'json'` with a descriptive string when:
574
-
- The object has many fields or a dynamic shape
575
-
- It represents a list/array of items
576
-
- The shape varies by operation
563
+
Nested object outputs (`plan: { id: { type: 'string' }, ... }`) are a **tool-output** feature only — `OutputFieldDefinition` for blocks does not allow them and they fail TypeScript at build time.
577
564
578
565
## V2 Block Pattern
579
566
@@ -798,6 +785,33 @@ Use `wandConfig` for fields that are hard to fill out manually, such as timestam
798
785
799
786
All tool IDs referenced in `tools.access` and returned by `tools.config.tool` MUST use `snake_case` (e.g., `x_create_tweet`, `slack_send_message`). Never use camelCase or PascalCase.
800
787
788
+
## BlockMeta (Required)
789
+
790
+
Every block file must export a `{Service}BlockMeta` alongside the block — **minimum 7 templates**. Look at existing examples in `apps/sim/blocks/blocks/` (e.g. `browser_use.ts`, `google_sheets.ts`) for the pattern.
791
+
792
+
```typescript
793
+
importtype { BlockMeta } from'@/blocks/types'
794
+
795
+
exportconst {Service}BlockMeta = {
796
+
tags: ['tag1', 'tag2'], // IntegrationTag[]
797
+
templates: [
798
+
{
799
+
icon: {Service}Icon,
800
+
title: '{Service} <use-case>', // 2–5 words
801
+
prompt: 'Build a workflow that...', // specific use case, 1–3 sentences
alsoIntegrations: ['slack'], // optional — other block IDs referenced in the prompt
806
+
featured: true, // optional
807
+
},
808
+
// ... at least 6 more
809
+
],
810
+
} asconstsatisfiesBlockMeta
811
+
```
812
+
813
+
Derive templates from the service's real use cases. Each prompt should name a concrete trigger, transformation, and output — not a generic description of what the service does.
814
+
801
815
## Checklist Before Finishing
802
816
803
817
-[ ]`integrationType` is set to the correct `IntegrationType` enum value
@@ -816,6 +830,7 @@ All tool IDs referenced in `tools.access` and returned by `tools.config.tool` MU
Copy file name to clipboardExpand all lines: .claude/commands/add-hosted-key.md
+10-5Lines changed: 10 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ When a tool has hosted key support, Sim provides its own API key if the user has
11
11
12
12
| Step | What | Where |
13
13
|------|------|-------|
14
-
| 1 | Register BYOK provider ID |`tools/types.ts`, `app/api/workspaces/[id]/byok-keys/route.ts`|
14
+
| 1 | Register BYOK provider ID |`tools/types.ts`, `lib/api/contracts/byok-keys.ts`|
15
15
| 2 | Research the API's pricing and rate limits | API docs / pricing page (before writing any code) |
16
16
| 3 | Add `hosting` config to the tool |`tools/{service}/{action}.ts`|
17
17
| 4 | Hide API key field when hosted |`blocks/blocks/{service}.ts`|
@@ -30,10 +30,15 @@ export type BYOKProviderId =
30
30
|'your_service'
31
31
```
32
32
33
-
Then add it to `VALID_PROVIDERS`in `app/api/workspaces/[id]/byok-keys/route.ts`:
33
+
Then add the same provider id to the `byokProviderIdSchema` enum in `lib/api/contracts/byok-keys.ts` (this is what the byok-keys route validates against):
0 commit comments