Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Guide to the providerOptions structure in .prompt files — decision tree for where an option goes, common mistakes, per-provider quick reference, and Anthropic prompt caching. Use when writing or reviewing .prompt file frontmatter (provider, model, providerOptions, messageOptions).
.claude/skills/growthxai-prompt-file-provider-options/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-08 | ✗→✓ | ▲ Improved | 25% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 58% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 56% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 7% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 22% | 0% |
When creating .prompt files, understanding the providerOptions structure is critical.
Is the key on the prompt config allowlist (provider, model, temperature, maxOutputTokens, deprecated maxTokens, topP, topK, presencePenalty, frequencyPenalty, stopSequences, seed, maxSteps, skills, tools, providerOptions, messageOptions, n, maxImagesPerCall, size, aspectRatio)?
├─ YES -> Top-level config
└─ NO -> Nest under providerOptions (unknown top-level keys throw; snake_case aliases like max_output_tokens fail with a camelCase suggestion)
In providerOptions:
├─ Is it 'thinking' or 'order'? -> Top-level (special AI SDK features)
└─ Is it provider-specific? -> Nested under provider namespaceUse maxOutputTokens for new prompts. Deprecated maxTokens remains on the loaded config and populates maxOutputTokens when the canonical key is absent; when both are set, maxOutputTokens takes precedence.
❌ Mistake 1: Putting provider options at top-level
yamlprovider: anthropic effort: medium # WRONG: 'effort' is not a standard option
✅ Correct:
yamlprovider: anthropic providerOptions: anthropic: effort: medium
❌ Mistake 2: Nesting thinking under provider
yamlproviderOptions: anthropic: thinking: # WRONG: thinking is top-level type: enabled
✅ Correct:
yamlproviderOptions: thinking: # Correct: top-level special key type: enabled
❌ Mistake 3: Wrong namespace for Google Vertex Gemini
yamlprovider: google-vertex model: gemini-2.0-flash providerOptions: vertex: # WRONG: Gemini uses 'google' namespace useSearchGrounding: true
✅ Correct:
yamlprovider: google-vertex model: gemini-2.0-flash providerOptions: google: # Correct: Gemini is a Google model useSearchGrounding: true
❌ Mistake 4: Confusing standard and provider options
yamlproviderOptions: anthropic: temperature: 0.7 # WRONG: temperature is standard, goes top-level effort: medium
✅ Correct:
yamltemperature: 0.7 # Standard: top-level providerOptions: anthropic: effort: medium # Provider-specific: nested
❌ Mistake 5: Unknown or snake_case top-level keys
yamlprovider: openai max_output_tokens: 16000 # WRONG: snake_case alias of maxOutputTokens reasoningEffort: medium # WRONG: OpenAI-specific
✅ Correct:
yamlprovider: openai maxOutputTokens: 16000 topP: 0.9 providerOptions: openai: reasoningEffort: medium
Unknown top-level keys throw Invalid prompt file. A snake_case alias of a known field fails with a suggestion (max_output_tokens -> use maxOutputTokens). Nested providerOptions stays open.
Anthropic (Claude)
yamlprovider: anthropic providerOptions: anthropic: effort: medium # low | medium | high
OpenAI
yamlprovider: openai providerOptions: openai: maxToolCalls: 1 reasoningEffort: high
Google Vertex with Gemini
yamlprovider: google-vertex model: gemini-2.0-flash providerOptions: google: # Note: 'google', not 'google-vertex' useSearchGrounding: true
Google Vertex with Claude
yamlprovider: google-vertex model: claude-sonnet-4-20250514@vertex providerOptions: anthropic: # Note: 'anthropic', not 'google-vertex' effort: medium
Amazon Bedrock
yamlprovider: amazon-bedrock model: anthropic.claude-sonnet-4-20250514-v1:0 maxOutputTokens: 64000 # Recommended: Bedrock has no client-side defaults providerOptions: bedrock: # Note: AI SDK 'bedrock' namespace, not 'anthropic' guardrailConfig: guardrailIdentifier: my-guardrail guardrailVersion: "1"
Extended Thinking (any provider)
yamlproviderOptions: thinking: # Top-level, not nested type: enabled budgetTokens: 10000
AI SDK uses Record<string, Record<string, JSONValue>> for providerOptions to:
anthropic.effort and openai.reasoningEffort can coexistThe nesting is intentional architecture, not redundancy.
Anthropic prompt caching is a per-message directive. Mark the block that ends your static prefix and that prefix is cached and reused across calls. Define a cacheControl set in frontmatter messageOptions and attach it to the block with options:
yamlmessageOptions: cached: { anthropic: { cacheControl: { type: ephemeral } } } # add ttl: 1h for the 1-hour cache
text<system options="cached"> {{ long static instructions }} </system> <user> {{ per-call input }} </user>
Each set is a provider-namespaced providerOptions object (same namespace rules as call-level providerOptions); on Vertex with a Claude model use the same anthropic namespace. A block may list multiple sets: options="cached fast".
Rules:
{{ variables }} — a breakpoint on changing content rewrites the cache every call and never hits.options a value, such as options="cached"; bare <system options> throws at load.ttl inside the named messageOptions set. options is the only supported role-tag attribute, so <system ttl="1h"> throws.options must exist in frontmatter messageOptions.usage.inputTokenDetails.cacheReadTokens or a normalized cost item with group: 'input' and label: 'cache_read'.❌ caching a dynamic block: <user options="cached">{{ topic }}</user> (never hits)
✅ caching the static prefix: <system options="cached">{{ guide }}</system> then <user>{{ topic }}</user>
OpenAI / Azure: caching is automatic for prompts ≥1024 tokens — no messageOptions needed. Tune routing with providerOptions.openai.promptCacheKey (and promptCacheRetention: 24h on GPT-5.1+).
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-08 | fail→pass | 26,802 | 10,203 | -62% | 1 | 1 | 0% | 2,331 | 2,905 | +25% | 0 | 0 | — |
case-01 | fail→pass | 14,003 | 9,311 | -34% | 1 | 1 | 0% | 1,635 | 2,581 | +58% | 0 | 0 | — |
case-02 | fail→pass | 13,338 | 8,340 | -37% | 1 | 1 | 0% | 1,569 | 2,441 | +56% | 0 | 0 | — |
case-03 | fail→pass | 26,686 | 13,773 | -48% | 1 | 1 | 0% | 3,230 | 3,452 | +7% | 0 | 0 | — |
case-09 | pass→pass | 28,839 | 10,843 | -62% | 1 | 1 | 0% | 2,058 | 2,685 | +30% | 0 | 0 | — |
case-04 | fail→pass | 19,941 | 7,992 | -60% | 1 | 1 | 0% | 1,969 | 2,411 | +22% | 0 | 0 | — |
case-05 | fail→pass | 14,249 | 9,072 | -36% | 1 | 1 | 0% | 1,688 | 2,619 | +55% | 0 | 0 | — |
case-06 | fail→pass | 18,560 | 8,474 | -54% | 1 | 1 | 0% | 1,196 | 2,486 | +108% | 0 | 0 | — |
case-07 | fail→pass | 33,461 | 8,159 | -76% | 1 | 1 | 0% | 2,604 | 2,436 | -6% | 0 | 0 | — |
case-10 | fail→pass | 17,465 | 25,140 | +44% | 1 | 1 | 0% | 2,209 | 2,837 | +28% | 0 | 0 | — |
case-11 | fail→pass | 23,703 | 5,988 | -75% | 1 | 1 | 0% | 997 | 2,820 | +183% | 0 | 0 | — |
case-12 | fail→pass | 21,923 | 5,890 | -73% | 1 | 1 | 0% | 2,212 | 2,909 | +32% | 0 | 0 | — |
case-13 | fail→pass | 6,169 | 2,999 | -51% | 1 | 1 | 0% | 1,291 | 2,312 | +79% | 0 | 0 | — |
case-14 | fail→pass | 19,219 | 10,031 | -48% | 1 | 1 | 0% | 2,334 | 2,625 | +12% | 0 | 0 | — |
case-15 | fail→pass | 10,484 | 3,487 | -67% | 1 | 1 | 0% | 1,041 | 2,452 | +136% | 0 | 0 | — |
case-16 | fail→pass | 22,288 | 5,210 | -77% | 1 | 1 | 0% | 3,861 | 2,709 | -30% | 0 | 0 | — |
case-17 | fail→pass | 21,955 | 12,577 | -43% | 1 | 1 | 0% | 2,661 | 3,147 | +18% | 0 | 0 | — |
case-18 | fail→pass | 13,839 | 9,231 | -33% | 1 | 1 | 0% | 1,538 | 2,546 | +66% | 0 | 0 | — |
case-19 | fail→pass | 13,412 | 8,190 | -39% | 1 | 1 | 0% | 1,260 | 2,337 | +85% | 0 | 0 | — |
case-20 | pass→pass | 6,632 | 5,928 | -11% | 1 | 1 | 0% | 1,177 | 2,814 | +139% | 0 | 0 | — |
case-21 | pass→pass | 10,429 | 11,195 | +7% | 1 | 1 | 0% | 1,870 | 2,883 | +54% | 0 | 0 | — |
case-22 | pass→pass | 15,376 | 19,996 | +30% | 1 | 1 | 0% | 2,517 | 4,358 | +73% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +82 percentage points is the difference between those two pass rates over the 21 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/27/2026 | +64% |
| gemini-3.6-flash | verified | 8/20/2026 | +59% |
Other measured skills in the registry, with their headline benchmark lift.