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
**Scope descriptions:** When adding a new OAuth provider, also add human-readable descriptions for all scopes in `SCOPE_DESCRIPTIONS` within `lib/oauth/utils.ts`.
146
146
147
+
**Service accounts (shared, app-level credentials):** A plain `oauth-input` already lets users *select* an existing service account — those credentials fold into the picker automatically (a Google service account created for any Google service appears in every Google block's picker). You only set `credentialKind` when you want to change the *connect* action:
-**omit (default):** lists OAuth accounts + any existing service accounts; the only connect action is "Connect account" (OAuth). Use this for the common "let users pick a service account someone set up elsewhere, but don't offer inline setup" case — no config needed.
161
+
-**`'service-account'`:** service-account credentials *only*, plus an inline setup action that opens the provider's connect modal. Use when a block accepts *only* an app credential.
162
+
-**`'any'`:** merged picker — OAuth accounts *and* service accounts in one grouped dropdown, with a connect action for each. Use when a block supports both (e.g. Slack: a personal account *or* a custom bot).
163
+
164
+
Optional companions: `credentialLabels` (override the picker's section/connect-row copy) and `allowServiceAccounts: true` (trigger-mode only — list service accounts, which triggers otherwise exclude; set only when the trigger's polling path can resolve a service-account token). The connect modal, provider families (Google JSON key, Atlassian token, token-paste, client-credential, Slack bot), and the preview gate are all resolved from `serviceAccountProviderId` — you don't wire them per block.
165
+
147
166
### Selectors (with dynamic options)
148
167
```typescript
149
168
// Channel selector (Slack, Discord, etc.)
@@ -238,48 +257,94 @@ When your block accepts file uploads, use the basic/advanced mode pattern with `
238
257
},
239
258
```
240
259
260
+
**Keep the pair to one logical thing.** Basic is the file upload, advanced is *only* a reference to
261
+
a file from a previous block. Gmail attachments are the reference implementation
Note neither subblock `id` is `channel` — the canonical id is a third name that both members map
232
+
onto, and it is the only one that survives serialization.
233
+
231
234
**Critical Canonical Param Rules:**
232
235
-`canonicalParamId` must NOT match any subblock's `id` in the block
233
-
-`canonicalParamId` must be unique per operation/condition context
234
-
- Only use `canonicalParamId` to link basic/advanced alternatives for the same logical parameter
236
+
-`canonicalParamId` must be unique **block-wide**, not per operation. `buildCanonicalIndex` keys
237
+
groups by `canonicalParamId` across all subblocks and a group holds exactly one `basicId`, so two
238
+
operations that each need their own pair must use two different canonical ids
239
+
- Only use `canonicalParamId` to link basic/advanced alternatives for the same logical parameter.
240
+
A pair carries ONE concept — for files that means upload (basic) + file reference (advanced), as
241
+
in Gmail attachments (`blocks/blocks/gmail.ts`). Never overload the advanced side with alternate
242
+
identifiers like a URL or a provider asset ID; give those their own subblocks, mark all the
243
+
mutually exclusive sources `required: false`, and enforce "exactly one" at execution
235
244
-`mode` only controls UI visibility, NOT serialization. Without `canonicalParamId`, both basic and advanced field values would be sent
236
245
- Every subblock `id` must be unique within the block. Duplicate IDs cause conflicts even with different conditions
237
246
-**Required consistency:** If one subblock in a canonical group has `required: true`, ALL subblocks in that group must have `required: true` (prevents bypassing validation by switching modes)
Copy file name to clipboardExpand all lines: .agents/skills/add-model/SKILL.md
+12Lines changed: 12 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -52,6 +52,7 @@ Use a precise WebFetch prompt: *"Extract for {model_id}: exact model id string,
52
52
|`reasoningEffort`|`openai/core.ts`, `azure-openai`, `anthropic/core.ts` (mapped to thinking), `gemini/core.ts`|**Dead on xai, deepseek, mistral, groq, cerebras, openrouter, fireworks, bedrock, vertex** unless their core consumes it — re-grep before assuming |
53
53
|`verbosity`|`openai/core.ts`, `azure-openai/index.ts` only | Dead elsewhere |
54
54
|`thinking`|`anthropic/core.ts`, `gemini/core.ts`| Dead elsewhere |
55
+
|`thinking.streamed`| Docs generator + `getThinkingStreamVisibility` (`models.ts`); `anthropic/core.ts` uses `'summary'` to request `display: 'summarized'` on agent-events runs |**Mandatory on Anthropic-family thinking models** (`agent-stream-docs:check` fails without it); other families fall back to provider defaults |
55
56
|`nativeStructuredOutputs`|`anthropic/core.ts`, `fireworks/index.ts`, `openrouter/index.ts`| Dead on openai, xai, google, vertex, bedrock, azure-openai, deepseek, mistral, groq, cerebras |
56
57
|`maxOutputTokens`| Read by UI + executor for token estimation | Always meaningful — set if provider documents a cap |
57
58
|`computerUse`|`anthropic/core.ts`| Dead elsewhere |
@@ -146,6 +147,15 @@ If anything matches, run the affected provider tests and update assertions as ne
146
147
147
148
The Consumption Matrix (Step 2) tells you which capability *flags* are honored by existing provider code. But if the new model needs **net-new** request handling that the provider doesn't implement yet — a new beta header (e.g. Anthropic's `anthropic-beta` structured-outputs header in `anthropic/index.ts`), a new thinking/reasoning encoding, a Responses-API quirk — you must edit `apps/sim/providers/<provider>/core.ts` / `index.ts`. Setting a flag whose behavior isn't implemented is a silent no-op. When you do edit provider code, reuse the shared helpers rather than hand-rolling: streaming responses are assembled via `createStreamingExecution` (`@/providers/streaming-execution`) and tool schemas via `adaptOpenAIChatToolSchema` / `adaptAnthropicToolSchema` (`@/providers/tool-schema-adapter`).
If the entry has `capabilities.thinking` or `capabilities.reasoningEffort`, it appears in the autogenerated "Streamed thinking and tool calls" table on the Agent block docs page:
153
+
154
+
-**Anthropic-family (`anthropic`, `azure-anthropic`) thinking models MUST declare `capabilities.thinking.streamed`** (`'full' | 'summary' | 'none'`). Verify against Anthropic's current thinking-display and streaming docs: visible thinking returned by the API is summarized, including when Sim opts models whose default display is `omitted` into `display: 'summarized'` on agent-events runs, so current Claude thinking models use `'summary'`. Use `'full'` only if future official API docs explicitly guarantee raw thinking deltas. `bun run agent-stream-docs:check` (CI) fails if the field is missing.
155
+
- Other families usually omit the field and inherit the provider default in `getThinkingStreamVisibility` (Gemini/OpenAI → summaries; Bedrock/Meta → none; OpenAI-compatible vendors with documented reasoning fields → full deltas). Set it explicitly only when the model deviates from its family.
156
+
- After inserting the entry, run `bun run agent-stream-docs:generate` and commit the regenerated `apps/docs/content/docs/en/workflows/blocks/agent.mdx` — CI diffs it.
157
+
- Include the `streamed` value (with its source URL) in the verification report when set.
158
+
149
159
### Wrong family entirely?
150
160
151
161
-**Embedding or rerank model** → it does NOT go in the `models[]` array. Use `EMBEDDING_MODEL_PRICING` / `RERANK_MODEL_PRICING` in `models.ts` instead.
@@ -155,6 +165,7 @@ The Consumption Matrix (Step 2) tells you which capability *flags* are honored b
155
165
156
166
```bash
157
167
bun run lint
168
+
bun run agent-stream-docs:generate # only when the entry has thinking/reasoningEffort
158
169
```
159
170
160
171
Lint must pass before reporting done. **If lint fails:** read the error, fix the syntax/typing issue in the entry you just wrote (do not delete the entry — it's the work product), re-run lint, and note the fix in a "Lint adjustments" line in the verification report. Never report done with lint failing.
@@ -201,6 +212,7 @@ Omitting a field is **not the same as verifying it**. Any field you cannot confi
201
212
- ❌ Trusting a marketing email (xAI's grok-4.3 email claimed "3 reasoning efforts" but the API rejects `reasoning_effort` — verified by official docs only)
202
213
- ❌ Setting `nativeStructuredOutputs: true` on xai/openai/google (dead — only anthropic/fireworks/openrouter consume it)
203
214
- ❌ Setting `thinking` on non-Anthropic/non-Gemini providers
215
+
- ❌ Adding an Anthropic-family thinking model without `thinking.streamed` (CI `agent-stream-docs:check` fails), or skipping `bun run agent-stream-docs:generate` after adding any thinking/reasoning model
204
216
- ❌ Setting `verbosity` on anything other than OpenAI gpt-5.x
205
217
- ❌ Copying `pricing.updatedAt` from a sibling instead of using today's date
206
218
- ❌ Inventing a `cachedInput` price by dividing input by 4 (varies by provider — find an explicit number)
0 commit comments