@bastani/atomic 0.9.19-alpha.6 → 0.9.19-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +2 -2
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/CHANGELOG.md +6 -0
- package/dist/builtin/web-access/index.bundle.mjs +22 -3
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +19 -0
- package/dist/builtin/workflows/README.md +1 -1
- package/dist/builtin/workflows/builtin/adversarial-verification.js +2 -2
- package/dist/builtin/workflows/builtin/{chunk-vhmnzdj9.js → chunk-1jth021m.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-p8jjwfg6.js → chunk-2377r57g.js} +4 -2
- package/dist/builtin/workflows/builtin/{chunk-hbnwv56f.js → chunk-31j2gs7h.js} +2 -2
- package/dist/builtin/workflows/builtin/{chunk-n8zysf1t.js → chunk-ngkqkzej.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-1nbq96fh.js → chunk-nkrafh9s.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-1kx4aggw.js → chunk-wf741bv3.js} +2 -2
- package/dist/builtin/workflows/builtin/{chunk-t6x2d78s.js → chunk-z29qbehr.js} +1 -1
- package/dist/builtin/workflows/builtin/generate-and-filter.js +2 -2
- package/dist/builtin/workflows/builtin/goal.js +3 -3
- package/dist/builtin/workflows/builtin/index.js +7 -7
- package/dist/builtin/workflows/builtin/ralph.js +3 -3
- package/dist/builtin/workflows/builtin/tournament.js +2 -2
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +590 -256
- package/dist/builtin/workflows/src/index.js +67 -19
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -0
- package/dist/modes/interactive/components/task-live-transcript.d.ts +1 -1
- package/dist/modes/interactive/components/task-live-transcript.d.ts.map +1 -1
- package/dist/modes/interactive/components/task-live-transcript.js +19 -11
- package/dist/modes/interactive/components/task-live-transcript.js.map +1 -1
- package/docs/background-tasks.md +1 -1
- package/docs/build.md +51 -0
- package/docs/changelog.mdx +8 -8
- package/docs/compaction/reference.md +267 -0
- package/docs/compaction.md +36 -219
- package/docs/computer-use.md +35 -0
- package/docs/containerization.md +2 -0
- package/docs/custom-provider/api-reference.md +145 -0
- package/docs/custom-provider/oauth.md +131 -0
- package/docs/custom-provider/override.md +34 -0
- package/docs/custom-provider/registration.md +163 -0
- package/docs/custom-provider/streaming.md +214 -0
- package/docs/custom-provider.md +43 -607
- package/docs/development.md +76 -0
- package/docs/docs.json +199 -77
- package/docs/environment-variables.md +1 -1
- package/docs/extensions/api-reference.md +1001 -0
- package/docs/extensions/authoring.md +676 -0
- package/docs/extensions/events.md +793 -0
- package/docs/extensions/examples.md +94 -0
- package/docs/extensions/ui.md +470 -0
- package/docs/extensions.md +270 -2768
- package/docs/getting-started/authentication.md +55 -0
- package/docs/getting-started/first-session.md +172 -0
- package/docs/getting-started/installation.md +154 -0
- package/docs/getting-started/project-instructions.md +43 -0
- package/docs/guides/configuration.md +65 -0
- package/docs/guides/intercom.md +24 -0
- package/docs/guides/non-interactive.md +33 -0
- package/docs/guides/subagents.md +24 -0
- package/docs/guides/workflows.md +27 -0
- package/docs/guides.md +41 -0
- package/docs/index.md +13 -45
- package/docs/intercom/operations.md +178 -0
- package/docs/intercom/reference.md +146 -0
- package/docs/intercom.md +54 -259
- package/docs/json.md +17 -0
- package/docs/llama-cpp.md +5 -0
- package/docs/models/artificial-analysis-index.md +89 -0
- package/docs/models/evals.md +2 -2
- package/docs/models/model-selection.md +3 -3
- package/docs/models/pareto-efficiency.md +2 -2
- package/docs/models/reference.md +601 -0
- package/docs/models.md +45 -550
- package/docs/packages/authoring.md +88 -0
- package/docs/packages/reference.md +43 -0
- package/docs/packages.md +28 -107
- package/docs/programmatic.md +29 -0
- package/docs/prompt-templates.md +11 -0
- package/docs/providers/reference.md +23 -0
- package/docs/providers.md +10 -15
- package/docs/quickstart.md +44 -238
- package/docs/reference/cli.md +252 -0
- package/docs/reference.md +52 -0
- package/docs/rpc/examples.md +64 -0
- package/docs/rpc/extension-ui.md +198 -0
- package/docs/rpc/protocol.md +1341 -0
- package/docs/rpc.md +109 -1346
- package/docs/sdk/reference.md +1090 -0
- package/docs/sdk.md +56 -1002
- package/docs/session-format.md +2 -0
- package/docs/sessions.md +6 -10
- package/docs/settings.md +6 -45
- package/docs/skills/authoring.md +95 -0
- package/docs/skills/reference.md +60 -0
- package/docs/skills.md +20 -122
- package/docs/subagents/authoring.md +37 -0
- package/docs/subagents/reference.md +60 -0
- package/docs/subagents.md +39 -95
- package/docs/terminal-setup.md +1 -1
- package/docs/themes/reference.md +176 -0
- package/docs/themes.md +21 -135
- package/docs/tmux.md +5 -0
- package/docs/tools/edit.md +5 -0
- package/docs/tools.md +5 -0
- package/docs/tui/reference.md +343 -0
- package/docs/tui.md +23 -286
- package/docs/usage.md +26 -209
- package/docs/web-access.md +2 -0
- package/docs/windows.md +2 -1
- package/docs/workflows/api-reference.md +11 -4
- package/docs/workflows/authoring.md +4 -2
- package/docs/workflows/builtins.md +2 -2
- package/docs/workflows/operations.md +15 -10
- package/docs/workflows/reliable-design.md +21 -3
- package/docs/workflows/verification.md +8 -0
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
package/docs/models.md
CHANGED
|
@@ -1,26 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Custom models"
|
|
3
|
+
description: "Add model entries for a supported provider API with minimal and full examples."
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Custom Models
|
|
2
7
|
|
|
3
8
|
Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via the single `models.json` in the active Atomic agent directory, normally `~/.atomic/agent/models.json`, or the directory selected by `ATOMIC_CODING_AGENT_DIR`/`PI_CODING_AGENT_DIR`. Atomic reads only that file: it does not read project-scoped `.atomic/models.json`, fall back to `~/.pi/agent/models.json`, or merge `.pi` and `.atomic` model configuration files. The legacy `.pi` read fallback remains available for configuration surfaces that explicitly use layered config paths, such as `auth.json`; it does not apply to `models.json`.
|
|
4
9
|
|
|
5
10
|
The interactive `/model` selector and `/scoped-models` render the current authenticated snapshot immediately and refresh network-backed catalogs in the background for up to 15 seconds. A direct `/model <model_name>` checks an exact cached match first; only a miss waits for the same bounded refresh, then falls back to the current cache when refresh stalls or fails. Closing either selector cancels its background refresh. The terminal owns that deadline: it stops waiting and replaces `Refreshing model catalogs…` with a cached-model timeout or error status even when lower-level work rejects or ignores cancellation. In isolated-engine sessions the same deadline covers both credential reload and catalog work inside the engine, and model selection does not queue behind the refresh. Login and logout publish credential changes independently of catalog refresh, and a refresh that started against an older credential generation is discarded instead of restoring stale provider availability. A slow catalog therefore falls back to cached models without requiring an `auth.json` or `~/.atomic` reset.
|
|
6
11
|
|
|
7
|
-
A complete `defaultProvider`/`defaultModel` pair in `settings.json` is resolved after built-in, configured, and extension providers register. If the provider remains unsupported, interactive mode reports a generic saved-configuration warning and leaves model selection open instead of routing the session to a different provider. Print and JSON modes write that diagnostic to stderr and exit nonzero before prompting, keeping JSON stdout JSONL-clean. RPC rejects `prompt` with the same correlated diagnostic until an explicit successful `set_model` selects an available model or an explicit model cycle returns a different available model. A null or unchanged cycle result does not clear the condition. If the provider is supported but the model is unknown or lacks authentication, normal automatic selection of an available authenticated model continues. Valid custom- and extension-provider defaults resolve once their provider registration is available. See [Settings](/settings#model
|
|
12
|
+
A complete `defaultProvider`/`defaultModel` pair in `settings.json` is resolved after built-in, configured, and extension providers register. If the provider remains unsupported, interactive mode reports a generic saved-configuration warning and leaves model selection open instead of routing the session to a different provider. Print and JSON modes write that diagnostic to stderr and exit nonzero before prompting, keeping JSON stdout JSONL-clean. RPC rejects `prompt` with the same correlated diagnostic until an explicit successful `set_model` selects an available model or an explicit model cycle returns a different available model. A null or unchanged cycle result does not clear the condition. If the provider is supported but the model is unknown or lacks authentication, normal automatic selection of an available authenticated model continues. Valid custom- and extension-provider defaults resolve once their provider registration is available. See [Settings](/settings#model-&-thinking).
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## Where to go next
|
|
16
|
+
|
|
17
|
+
This page shows minimal and full `models.json` examples you can copy. Every field, override, derived variant, and API compatibility contract lives in the [Model configuration reference](/models/reference).
|
|
8
18
|
|
|
19
|
+
For choosing which model to use rather than how to declare one, see [Model selection](/models/model-selection).
|
|
9
20
|
|
|
10
21
|
## Table of Contents
|
|
11
22
|
|
|
12
|
-
- [Minimal Example](#minimal-example)
|
|
13
|
-
- [Full Example](#full-example)
|
|
14
|
-
- [Supported APIs](#supported-apis)
|
|
15
|
-
- [Provider Configuration](#provider-configuration)
|
|
16
|
-
- [Model Configuration](#model-configuration)
|
|
17
|
-
- [GPT-6-Astra Built-in Models](#gpt-6-astra-built-in-models)
|
|
18
|
-
- [Request-wide Cost Tiers](#request-wide-cost-tiers)
|
|
19
|
-
- [Overriding Built-in Providers](#overriding-built-in-providers)
|
|
20
|
-
- [Per-model Overrides](#per-model-overrides)
|
|
21
|
-
- [Derived Fast Model Variants](#derived-fast-model-variants)
|
|
22
|
-
- [Anthropic Messages Compatibility](#anthropic-messages-compatibility)
|
|
23
|
-
- [OpenAI Compatibility](#openai-compatibility)
|
|
23
|
+
- [Minimal Example](/models#minimal-example)
|
|
24
|
+
- [Full Example](/models#full-example)
|
|
25
|
+
- [Supported APIs](/models/reference#supported-apis)
|
|
26
|
+
- [Provider Configuration](/models/reference#provider-configuration)
|
|
27
|
+
- [Model Configuration](/models/reference#model-configuration)
|
|
28
|
+
- [GPT-6-Astra Built-in Models](/models/reference#gpt-6-astra-built-in-models)
|
|
29
|
+
- [Request-wide Cost Tiers](/models/reference#request-wide-cost-tiers)
|
|
30
|
+
- [Overriding Built-in Providers](/models/reference#overriding-built-in-providers)
|
|
31
|
+
- [Per-model Overrides](/models/reference#per-model-overrides)
|
|
32
|
+
- [Derived Fast Model Variants](/models/reference#derived-fast-model-variants)
|
|
33
|
+
- [Anthropic Messages Compatibility](/models/reference#anthropic-messages-compatibility)
|
|
34
|
+
- [OpenAI Compatibility](/models/reference#openai-compatibility)
|
|
24
35
|
|
|
25
36
|
## Minimal Example
|
|
26
37
|
|
|
@@ -128,592 +139,76 @@ The `baseUrl` is required when adding custom models to the `google-generative-ai
|
|
|
128
139
|
|
|
129
140
|
## Supported APIs
|
|
130
141
|
|
|
131
|
-
|
|
132
|
-
| ---------------------- | ----------------------------------------- |
|
|
133
|
-
| `openai-completions` | OpenAI Chat Completions (most compatible) |
|
|
134
|
-
| `openai-responses` | OpenAI Responses API |
|
|
135
|
-
| `anthropic-messages` | Anthropic Messages API |
|
|
136
|
-
| `google-generative-ai` | Google Generative AI |
|
|
137
|
-
|
|
138
|
-
Set `api` at provider level (default for all models) or model level (override per model).
|
|
139
|
-
|
|
140
|
-
These four values are the generic custom-provider APIs supported by `models.json`. Atomic's installed native provider runtime also implements provider-owned APIs including `mistral-conversations`, `azure-openai-responses`, `openai-codex-responses`, `bedrock-converse-stream`, `google-vertex`, and `pi-messages`; those native APIs are not implied to be stable generic custom-provider contracts.
|
|
142
|
+
Moved to [Model configuration reference](/models/reference#supported-apis).
|
|
141
143
|
|
|
142
144
|
## Provider Configuration
|
|
143
145
|
|
|
144
|
-
|
|
145
|
-
| ---------------- | ---------------------------------------------------------------- |
|
|
146
|
-
| `baseUrl` | API endpoint or gateway URL |
|
|
147
|
-
| `api` | Generic custom-provider API type (see above) |
|
|
148
|
-
| `apiKey` | Optional API key (see value resolution below); omit when auth comes from `/login`, `auth.json`, or `--api-key` |
|
|
149
|
-
| `oauth` | Dynamic OAuth provider type. Currently `"radius"`; requires the gateway `baseUrl` |
|
|
150
|
-
| `headers` | Custom headers (see value resolution below) |
|
|
151
|
-
| `authHeader` | Set `true` to add `Authorization: Bearer <apiKey>` automatically |
|
|
152
|
-
| `models` | Array of model configurations |
|
|
153
|
-
| `modelOverrides` | Per-model overrides for matching built-in or extension-registered models on this provider |
|
|
154
|
-
|
|
155
|
-
For a custom Radius gateway, set `"oauth": "radius"` and its `baseUrl`. Atomic uses Radius OAuth credentials and the gateway's dynamic `pi-messages` catalog.
|
|
156
|
-
### Value Resolution
|
|
157
|
-
|
|
158
|
-
The `apiKey` and `headers` fields support three formats:
|
|
159
|
-
|
|
160
|
-
- **Shell command:** `"!command"` executes and uses stdout
|
|
161
|
-
```json
|
|
162
|
-
"apiKey": "!security find-generic-password -ws 'anthropic'"
|
|
163
|
-
"apiKey": "!op read 'op://vault/item/credential'"
|
|
164
|
-
```
|
|
165
|
-
- **Environment variable:** Prefix the variable name with `$` (or use `${VAR}`) to resolve it from the environment
|
|
166
|
-
```json
|
|
167
|
-
"apiKey": "$MY_API_KEY"
|
|
168
|
-
```
|
|
169
|
-
- **Literal value:** Used directly when the value does not use shell-command or explicit environment-variable syntax. Use `$MY_API_KEY`/`${MY_API_KEY}` for new environment-variable references; legacy uppercase env-var-like values may be migrated as described below.
|
|
170
|
-
```json
|
|
171
|
-
"apiKey": "sk-..."
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
Legacy uppercase env-var-like values in existing `models.json` provider config, such as `MY_API_KEY`, are migrated to `$MY_API_KEY` on startup only when that environment variable is present during migration; otherwise the value is preserved as a literal. New configs should use explicit `$ENV_VAR`/`${ENV_VAR}` syntax for environment variables.
|
|
175
|
-
|
|
176
|
-
For `models.json`, shell commands are resolved at request time. Atomic intentionally does not apply built-in TTL, stale reuse, or recovery logic for arbitrary commands. Different commands need different caching and failure strategies, and Atomic cannot infer the right one.
|
|
146
|
+
Moved to [Model configuration reference](/models/reference#provider-configuration).
|
|
177
147
|
|
|
178
|
-
|
|
148
|
+
### Value Resolution
|
|
179
149
|
|
|
180
|
-
|
|
150
|
+
Moved to [Model configuration reference](/models/reference#value-resolution).
|
|
181
151
|
|
|
182
152
|
### Custom Headers
|
|
183
153
|
|
|
184
|
-
|
|
185
|
-
{
|
|
186
|
-
"providers": {
|
|
187
|
-
"custom-proxy": {
|
|
188
|
-
"baseUrl": "https://proxy.example.com/v1",
|
|
189
|
-
"apiKey": "$MY_API_KEY",
|
|
190
|
-
"api": "anthropic-messages",
|
|
191
|
-
"headers": {
|
|
192
|
-
"x-portkey-api-key": "$PORTKEY_API_KEY",
|
|
193
|
-
"x-secret": "!op read 'op://vault/item/secret'"
|
|
194
|
-
},
|
|
195
|
-
"models": [...]
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
In `models.json`, `headers` values must be strings. A `null` suppression marker is supplied only by provider/catalog auth or a `before_provider_headers` extension hook; when present there, `null` suppresses the provider's default header with the same name.
|
|
154
|
+
Moved to [Model configuration reference](/models/reference#custom-headers).
|
|
202
155
|
|
|
203
156
|
## Model Configuration
|
|
204
157
|
|
|
205
|
-
|
|
206
|
-
| ------------------ | -------- | ----------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
207
|
-
| `id` | Yes | — | Model identifier (passed to the API) |
|
|
208
|
-
| `name` | No | `id` | Human-readable model label. Used for matching (`--model` patterns) and shown as secondary model detail text. |
|
|
209
|
-
| `api` | No | provider's `api` | Override provider's API for this model |
|
|
210
|
-
| `reasoning` | No | `false` | Supports extended thinking |
|
|
211
|
-
| `thinkingLevelMap` | No | omitted | Maps Atomic thinking levels to provider values and marks unsupported levels (see below) |
|
|
212
|
-
| `input` | No | `["text"]` | Input types: `["text"]` or `["text", "image"]` |
|
|
213
|
-
| `contextWindow` | No | `128000` | Default/effective context window size in tokens |
|
|
214
|
-
| `maxTokens` | No | `16384` | Maximum output tokens |
|
|
215
|
-
| `samplingParams` | No | omitted | Sampling parameters merged verbatim into every request body for OpenAI-compatible APIs (see below) |
|
|
216
|
-
| `cost` | No | all zeros | Complete base rates per million tokens plus optional request-wide `tiers` (see below) |
|
|
217
|
-
| `compat` | No | provider `compat` | Provider compatibility overrides. Merged with provider-level `compat` when both are set. |
|
|
218
|
-
| `deferredToolsMode` | No | omitted | Deferred tool-loading protocol; set to `"kimi"` for Kimi-compatible deferred tools |
|
|
219
|
-
|
|
220
|
-
Current behavior:
|
|
221
|
-
- `/model`, `--list-models`, and the interactive footer display entries by model `id`.
|
|
222
|
-
- The configured `name` is used for model matching and secondary model detail text. It does not replace the footer/status-bar model id.
|
|
223
|
-
- `input` lists the modalities **Atomic can send**. `["text"]`, `["text", "image"]`, and `["text", "image", "pdf"]` are the possible values. PDF is a platform capability rather than a per-model one — Anthropic documents that ["All active models support PDF processing"](https://platform.claude.com/docs/en/build-with-claude/pdf-support), routed through the same vision path as images — so upstream metadata carries it on every Claude entry. Atomic advertises it only where a runtime can serialize a document block: the Anthropic Messages and Amazon Bedrock Converse paths. A Claude mirror on any other provider stays at `["text", "image"]`, and a document sent to such a model is replaced by a visible placeholder rather than dropped silently. Note that Bedrock's Converse API needs citations enabled for full visual PDF understanding; without them it falls back to text extraction. `"pdf"` means PDF specifically: a document block's media type must be `application/pdf`, and any other value is rejected by name rather than sent mislabelled, because both request builders hardcode PDF rather than reading the field.
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
### GPT-6-Astra Built-in Models
|
|
227
|
-
|
|
228
|
-
Atomic ships `openai/gpt-6-astra` and `openai-codex/gpt-6-astra`. Both accept text and image input, expose tool search and additional tools, and offer exactly `low`, `medium`, `high`, `xhigh`, and `max` reasoning. `off`, `minimal`, and Codex's client-side `ultra` orchestration preset are not API reasoning levels and do not appear in Atomic's selector.
|
|
229
|
-
|
|
230
|
-
The built-in OpenAI and Codex entries use a 272,000-token default input/context limit and a 128,000-token maximum output. OpenAI documents a 1,050,000-token API maximum, but requests above 272,000 aggregate input tokens enter the long-context price tier for the whole request. Override `contextWindow` only when the larger window and its price are intentional.
|
|
231
|
-
|
|
232
|
-
| Aggregate input | Input | Cached input | Cache write | Output |
|
|
233
|
-
| --- | ---: | ---: | ---: | ---: |
|
|
234
|
-
| Up to 272,000 | $10 | $1 | $12.50 | $50 |
|
|
235
|
-
| Above 272,000 | $20 | $2 | $25 | $75 |
|
|
236
|
-
|
|
237
|
-
Rates are per million tokens. `openai/gpt-6-astra-fast` and `openai-codex/gpt-6-astra-fast` are derived canonical choices that keep these base catalog rates; the OpenAI adapters apply Fast's 2x multiplier at request time. The Codex fast choice sends upstream ID `gpt-6-astra` with `service_tier: priority` while Atomic records `gpt-6-astra-fast`.
|
|
238
|
-
|
|
239
|
-
Amazon Bedrock exposes `openai.gpt-6-astra`, `global.openai.gpt-6-astra`, and `us.openai.gpt-6-astra` through the `amazon-bedrock` provider. These entries keep the same 272,000 input and 128,000 output limits, text and image input, and five reasoning levels; Atomic sends the selected effort as Bedrock's OpenAI `reasoning_effort` field. They do not get Fast or OpenAI tool-search metadata. Atomic sends each Bedrock ID unchanged and records all four price fields as zero because AWS had not published Astra pricing. Zero means unknown here, not free.
|
|
240
|
-
|
|
241
|
-
Atomic does not synthesize Azure OpenAI Astra entries. Live-provider catalogs remain authoritative: the current OpenRouter catalog publishes `openai/gpt-6-astra` and `openai/gpt-6-astra-pro`, while the Vercel AI Gateway publishes `openai/gpt-6-astra` and `openai/gpt-6-astra-fast`. Atomic imports those exact IDs and their request-wide long-context prices. Vercel owns its suffixed ID, so it remains route-less and does not gain Atomic's first-party fast-route behavior.
|
|
242
|
-
|
|
243
|
-
On OpenAI Responses, Astra uses the newer prompt-cache payload. `cacheRetention: "long"` sends `prompt_cache_options.ttl: "30m"` instead of the legacy `prompt_cache_retention: "24h"`; `none` sends explicit mode without a cache key, and `short` sends neither cache option. Earlier Responses models keep the 24-hour field for long retention.
|
|
158
|
+
Moved to [Model configuration reference](/models/reference#model-configuration).
|
|
244
159
|
|
|
245
160
|
### Sampling Parameters
|
|
246
161
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
```json
|
|
250
|
-
{
|
|
251
|
-
"id": "deepseek-v4-flash",
|
|
252
|
-
"samplingParams": {
|
|
253
|
-
"temperature": 1.0,
|
|
254
|
-
"top_p": 0.95,
|
|
255
|
-
"top_k": 0,
|
|
256
|
-
"min_p": 0
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
Only OpenAI-compatible APIs apply these values (`openai-completions`, `openai-responses`, and `azure-openai-responses`); other APIs ignore them. Per-request keys override model defaults and named request fields. In `modelOverrides`, `samplingParams` merges per key with the base model's values. Keys are provider-defined and remain unchanged; malformed `samplingParams` values are rejected while loading `models.json`.
|
|
162
|
+
Moved to [Model configuration reference](/models/reference#sampling-parameters).
|
|
262
163
|
|
|
263
|
-
For vLLM OpenAI-compatible models that share the reasoning and answer budgets, set `compat.supportsThinkingTokenBudget` to `true`. Atomic sends the opt-in `thinking_token_budget` value for an enabled thinking level and always leaves 1024 tokens for the final answer. Pi's defaults are 1024, 2048, 8192, and 16384 tokens for `minimal`, `low`, `medium`, and `high`; the `thinkingBudgets` settings override them. `xhigh` and `max` use the `high` budget, and Atomic omits the field when no positive budget remains after reserving answer space.
|
|
264
|
-
|
|
265
|
-
Model references resolve the complete, unmodified ID before Atomic interprets thinking suffixes or glob syntax. For example, if the catalog contains the literal ID `provider/literal[free]:high`, that complete model wins and `:high` remains part of its ID; it does not become a thinking-level suffix and `[free]` is not treated as a character class. Only when the complete ID is absent does Atomic parse a valid thinking suffix, try the stripped exact ID, then apply glob/fuzzy matching. This preserves literal provider IDs without changing ordinary `*`, `?`, bracket-glob, ambiguity, ordering, or deduplication behavior.
|
|
266
164
|
### Request-wide Cost Tiers
|
|
267
165
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
```json
|
|
271
|
-
{
|
|
272
|
-
"id": "long-context-model",
|
|
273
|
-
"cost": {
|
|
274
|
-
"input": 1,
|
|
275
|
-
"output": 2,
|
|
276
|
-
"cacheRead": 0.25,
|
|
277
|
-
"cacheWrite": 0.5,
|
|
278
|
-
"tiers": [
|
|
279
|
-
{
|
|
280
|
-
"inputTokensAbove": 272000,
|
|
281
|
-
"input": 2,
|
|
282
|
-
"output": 3,
|
|
283
|
-
"cacheRead": 0.5,
|
|
284
|
-
"cacheWrite": 1
|
|
285
|
-
}
|
|
286
|
-
]
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
Atomic chooses one rate set for the entire request. It calculates aggregate input as `input + cacheRead + cacheWrite`, selects only tiers whose threshold is **strictly exceeded**, and uses the matching tier with the highest `inputTokensAbove`. Exactly 272,000 aggregate input tokens in the example still use the base rates; 272,001 use every rate from the tier, including the tier's output rate.
|
|
292
|
-
|
|
293
|
-
For `modelOverrides`, `cost` is partial: any supplied scalar rate replaces that scalar while omitted scalar rates remain inherited. A scalar-only cost override also preserves inherited tiers. Supplying `tiers` replaces the whole inherited tier array; use `"tiers": []` to clear it explicitly. Every supplied replacement tier must still be complete.
|
|
294
|
-
|
|
295
|
-
```json
|
|
296
|
-
{
|
|
297
|
-
"providers": {
|
|
298
|
-
"openai": {
|
|
299
|
-
"modelOverrides": {
|
|
300
|
-
"gpt-5.6-sol": {
|
|
301
|
-
"cost": {
|
|
302
|
-
"input": 4,
|
|
303
|
-
"tiers": []
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
This override changes only the base input rate, retains the model's other base rates, and clears its inherited long-context tiers.
|
|
313
|
-
|
|
314
|
-
A constant thinking-token cap can go here too, but it will not follow `thinkingBudgets` or leave room for the answer. Prefer `compat.thinkingTokenBudgetField` (or the `supportsThinkingTokenBudget` alias) for that.
|
|
166
|
+
Moved to [Model configuration reference](/models/reference#request-wide-cost-tiers).
|
|
315
167
|
|
|
316
168
|
### Thinking Level Map
|
|
317
169
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
Values are tristate:
|
|
321
|
-
|
|
322
|
-
| Value | Meaning |
|
|
323
|
-
| ------- | ---------------------------------------------------------- |
|
|
324
|
-
| omitted | Level is supported and uses the provider's default mapping |
|
|
325
|
-
| string | Level is supported and this value is sent to the provider |
|
|
326
|
-
| `null` | Level is unsupported and hidden/skipped/clamped away |
|
|
327
|
-
|
|
328
|
-
Example for a model that only supports off, high, and max reasoning:
|
|
329
|
-
|
|
330
|
-
```json
|
|
331
|
-
{
|
|
332
|
-
"id": "deepseek-v4-pro",
|
|
333
|
-
"reasoning": true,
|
|
334
|
-
"thinkingLevelMap": {
|
|
335
|
-
"minimal": null,
|
|
336
|
-
"low": null,
|
|
337
|
-
"medium": null,
|
|
338
|
-
"high": "high",
|
|
339
|
-
"xhigh": null,
|
|
340
|
-
"max": "max"
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
Example for a model where thinking cannot be disabled:
|
|
346
|
-
|
|
347
|
-
```json
|
|
348
|
-
{
|
|
349
|
-
"id": "always-thinking-model",
|
|
350
|
-
"reasoning": true,
|
|
351
|
-
"thinkingLevelMap": {
|
|
352
|
-
"off": null
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
Migration: older configs that used `compat.reasoningEffortMap` should move that mapping to model-level `thinkingLevelMap`. Use `null` for levels that should not appear in the UI.
|
|
358
|
-
|
|
359
|
-
`/thinking` opens the thinking-level selector. Enter applies the level to the current session only. Persist (the selector's save action) writes `settings.modelThinkingLevels` for the active model instead of replacing the global `defaultThinkingLevel`. Settings → Default thinking level per model lists those overrides.
|
|
170
|
+
Moved to [Model configuration reference](/models/reference#thinking-level-map).
|
|
360
171
|
|
|
361
172
|
### Context Window
|
|
362
173
|
|
|
363
|
-
|
|
364
|
-
compaction thresholds, footer/stats, session replay, and RPC/SDK state.
|
|
365
|
-
|
|
366
|
-
```json
|
|
367
|
-
{
|
|
368
|
-
"id": "long-context-model",
|
|
369
|
-
"reasoning": true,
|
|
370
|
-
"contextWindow": 400000
|
|
371
|
-
}
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
Built-in models take their `contextWindow` from the bundled `pi-ai` catalog. To
|
|
375
|
-
change one, use `modelOverrides`:
|
|
376
|
-
|
|
377
|
-
```json
|
|
378
|
-
{
|
|
379
|
-
"providers": {
|
|
380
|
-
"github-copilot": {
|
|
381
|
-
"modelOverrides": {
|
|
382
|
-
"gpt-5.5": {
|
|
383
|
-
"contextWindow": 272000
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
To add a new model id under a built-in provider, define it in `models`:
|
|
392
|
-
|
|
393
|
-
```json
|
|
394
|
-
{
|
|
395
|
-
"providers": {
|
|
396
|
-
"github-copilot": {
|
|
397
|
-
"models": [
|
|
398
|
-
{
|
|
399
|
-
"id": "my-copilot-model",
|
|
400
|
-
"contextWindow": 400000
|
|
401
|
-
}
|
|
402
|
-
]
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
```
|
|
174
|
+
Moved to [Model configuration reference](/models/reference#context-window).
|
|
407
175
|
|
|
408
176
|
## Overriding Built-in Providers
|
|
409
177
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
```json
|
|
413
|
-
{
|
|
414
|
-
"providers": {
|
|
415
|
-
"anthropic": {
|
|
416
|
-
"baseUrl": "https://my-proxy.example.com/v1"
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
All built-in Anthropic models remain available. Existing OAuth or API key auth continues to work.
|
|
423
|
-
|
|
424
|
-
To merge custom models into a built-in provider, include the `models` array:
|
|
425
|
-
|
|
426
|
-
```json
|
|
427
|
-
{
|
|
428
|
-
"providers": {
|
|
429
|
-
"anthropic": {
|
|
430
|
-
"baseUrl": "https://my-proxy.example.com/v1",
|
|
431
|
-
"apiKey": "$ANTHROPIC_API_KEY",
|
|
432
|
-
"api": "anthropic-messages",
|
|
433
|
-
"models": [...]
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
Merge semantics:
|
|
440
|
-
- Built-in models are kept.
|
|
441
|
-
- Custom models are upserted by `id` within the provider.
|
|
442
|
-
- If a custom model `id` matches a built-in model `id`, the custom model replaces that built-in model.
|
|
443
|
-
- If a custom model `id` is new, it is added alongside built-in models.
|
|
178
|
+
Moved to [Model configuration reference](/models/reference#overriding-built-in-providers).
|
|
444
179
|
|
|
445
180
|
## Per-model Overrides
|
|
446
181
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
```json
|
|
450
|
-
{
|
|
451
|
-
"providers": {
|
|
452
|
-
"openrouter": {
|
|
453
|
-
"modelOverrides": {
|
|
454
|
-
"anthropic/claude-sonnet-4": {
|
|
455
|
-
"name": "Claude Sonnet 4 (Bedrock Route)",
|
|
456
|
-
"compat": {
|
|
457
|
-
"openRouterRouting": {
|
|
458
|
-
"only": ["amazon-bedrock"]
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
`modelOverrides` supports these fields per model: `name`, `reasoning`, `thinkingLevelMap`, `input`, `cost` (partial scalar rates plus optional full tier-array replacement), `contextWindow`, `maxTokens`, `samplingParams` (merged per key), `headers`, `compat`.
|
|
469
|
-
|
|
470
|
-
Atomic reads one `models.json` from the active agent directory. It does not layer model overrides from `.pi` and `.atomic` files.
|
|
471
|
-
|
|
472
|
-
Within a single file, custom model definitions replace matching built-in entries after built-in overrides are applied. `modelOverrides` composes only with built-in and extension-registered models; it does not modify a same-ID custom model definition.
|
|
473
|
-
|
|
474
|
-
Behavior notes:
|
|
475
|
-
- Atomic retains the parsed override map even when an extension registers the matching provider/model after `models.json` is loaded.
|
|
476
|
-
- Model overrides come from the active agent directory's single `models.json`; no cross-file layering or merging is performed.
|
|
477
|
-
- For matching built-in and extension-registered models, the model definition is the base and `modelOverrides` wins configured fields. Extension-registered model headers are shallow-merged with override headers, with override headers winning duplicate names. A same-ID custom model replaces the built-in override result, including its complete header record.
|
|
478
|
-
- A scalar-only `cost` override preserves inherited tiers. Supplying `cost.tiers` replaces the complete tier array, including `[]` to clear it; omitted scalar cost fields remain inherited.
|
|
479
|
-
- Provider-level request headers remain a separate provider layer and are combined at request time.
|
|
480
|
-
- Unknown model IDs are ignored unless a matching model is subsequently registered by an extension.
|
|
481
|
-
- If `models` is also defined for a provider in `models.json`, those custom models are merged after built-in overrides. A custom model with the same `id` replaces the overridden built-in model entry.
|
|
182
|
+
Moved to [Model configuration reference](/models/reference#per-model-overrides).
|
|
482
183
|
|
|
483
184
|
## Derived Fast Model Variants
|
|
484
185
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
Two rules matter when you write `models.json`:
|
|
488
|
-
|
|
489
|
-
- **Your exact ID wins.** If a provider, a custom model in `models`, or an extension already defines that exact `<base>-fast` ID, Atomic keeps yours untouched, does not derive a duplicate, and prints a warning naming the model to rename or remove if you wanted the derived variant instead. A model you define is an ordinary model: the `-fast` suffix alone never gives it fast routing behavior.
|
|
490
|
-
- **`modelOverrides` applies to derived variants.** A derived entry is a real catalog model, so `modelOverrides["gpt-5.6-sol-fast"]` customizes it exactly like any other model, and its routing metadata survives the override. Overriding the *base* model still flows through to the derived entry by inheritance; a fast-specific override wins over that inherited value.
|
|
491
|
-
|
|
492
|
-
A derived variant inherits the base model's `cost`. The provider adapter applies the fast-tier multiplier at request time, so do not pre-multiply cost in an override.
|
|
186
|
+
Moved to [Model configuration reference](/models/reference#derived-fast-model-variants).
|
|
493
187
|
|
|
494
188
|
## Anthropic Messages Compatibility
|
|
495
189
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
By default, Atomic sends per-tool `eager_input_streaming: true`. If a proxy or Anthropic-compatible backend rejects that field, set `supportsEagerToolInputStreaming` to `false`. Atomic will omit `tools[].eager_input_streaming` and send the legacy `fine-grained-tool-streaming-2025-05-14` beta header for tool-enabled requests instead.
|
|
499
|
-
|
|
500
|
-
```json
|
|
501
|
-
{
|
|
502
|
-
"providers": {
|
|
503
|
-
"anthropic-proxy": {
|
|
504
|
-
"baseUrl": "https://proxy.example.com",
|
|
505
|
-
"api": "anthropic-messages",
|
|
506
|
-
"apiKey": "$ANTHROPIC_PROXY_KEY",
|
|
507
|
-
"compat": {
|
|
508
|
-
"supportsEagerToolInputStreaming": false,
|
|
509
|
-
"supportsLongCacheRetention": true
|
|
510
|
-
},
|
|
511
|
-
"models": [
|
|
512
|
-
{
|
|
513
|
-
"id": "claude-opus-4-8",
|
|
514
|
-
"reasoning": true,
|
|
515
|
-
"input": ["text", "image"]
|
|
516
|
-
}
|
|
517
|
-
]
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
```
|
|
522
|
-
|
|
523
|
-
| Field | Description |
|
|
524
|
-
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
525
|
-
| `supportsEagerToolInputStreaming` | Whether the provider accepts per-tool `eager_input_streaming`. Default: `true`. Set to `false` to omit that field and use the legacy fine-grained tool streaming beta header on tool-enabled requests. |
|
|
526
|
-
| `supportsLongCacheRetention` | Whether the provider accepts Anthropic long cache retention (`cache_control.ttl: "1h"`) when cache retention is `long`. Default: `true`. |
|
|
527
|
-
| `delegatesThinkingModelBinding` | Whether the API decides for itself which thinking blocks the target model may read, dropping the rest. Default: `false`. See [Preserved thinking and model switches](#preserved-thinking-and-model-switches). |
|
|
528
|
-
| `enforcesPreservedThinkingBinding` | Whether the model rejects a thinking block replayed behind a changed conversation prefix. Default: `false`. When `true`, Atomic sends the `thinking-binding-controls-2026-08-01` beta header and `prefix_mismatch_behavior: "drop_block"`. |
|
|
529
|
-
| `supportsMidConvoEffort` | Whether the exact Claude model transport supports per-turn effort system messages. Atomic persists native effort levels and sends `drop_block` when enabled. Default: `false`. |
|
|
530
|
-
| `supportsForcedToolChoice` | Whether the model accepts forced tool use (`tool_choice` `any` or a named tool). Default: `true`. When `false`, Atomic rejects a forced choice with an error rather than sending a request the model refuses. `auto` and `none` are never altered. |
|
|
531
|
-
|
|
532
|
-
`supportsMidConvoEffort` and `enforcesPreservedThinkingBinding` compose rather than replace one another. The former is restricted to exact provider/model transports that accept effort-only system messages and adds the two per-turn-effort betas. It also enables `drop_block`, because historical effort changes can invalidate a signed prefix. The latter remains a separate Atomic compatibility flag for transports that enforce preserved-thinking prefixes but do not accept effort-only messages. Do not enable `supportsMidConvoEffort` for an API that merely imitates the Messages shape.
|
|
533
|
-
|
|
534
|
-
`supportsForcedToolChoice` and `supportsTemperature` also exist on the Amazon Bedrock and OpenAI-compatible completions `compat` objects, with the same meanings and the same `true` defaults. Unlike the two preserved-thinking flags, which describe Anthropic's first-party endpoint, these describe the **model**, so Atomic applies them to every mirror that reaches it rather than only to `provider: "anthropic"`.
|
|
535
|
-
|
|
536
|
-
On the completions adapter, `supportsTemperature: false` also strips `temperature`, `top_p`, and `top_k` out of `samplingParams`. That merge is documented as last-wins so its keys override the named request fields, which means it would otherwise reopen exactly the parameters the model rejects. The strip runs after the merge, so it also covers a model-level `samplingParams` default, and it removes only those three keys — every other custom key you pass still overrides as before.
|
|
190
|
+
Moved to [Model configuration reference](/models/reference#anthropic-messages-compatibility).
|
|
537
191
|
|
|
538
192
|
### Forced tool use on Claude Fable 5.1
|
|
539
193
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
Atomic's own agent loop only ever asks for `auto` or `none`, so no interactive session can reach this. It is reachable through the `@bastani/pi-ai` library's Anthropic, Bedrock, and OpenAI-completions entry points, which accept the wider tool-choice shape. For a model marked `supportsForcedToolChoice: false`, all three **fail the request with an error naming the model and the remedy**, before the round trip. That matters most on a gateway: OpenRouter drops parameters a model does not support, so an unguarded forced choice would vanish silently and return a plausible answer that ignored the instruction.
|
|
543
|
-
|
|
544
|
-
Atomic deliberately does not substitute `auto` on your behalf. Asking the model to call a specific tool and asking it to decide for itself are different requests, and silently swapping one for the other would discard an instruction you gave explicitly. If the substitution is what you want, make it yourself — branch on `compat.supportsForcedToolChoice` to decide. Every other model passes forced choices through unchanged, and `auto` and `none` are never altered on any model.
|
|
545
|
-
|
|
546
|
-
On the OpenAI-completions path the tool-choice union is wider than Anthropic's, and four of its members force a call: `"required"`, `{"type": "function", ...}`, `{"type": "custom", ...}`, and `{"type": "allowed_tools", "allowed_tools": {"mode": "required", ...}}`. All four are rejected. `allowed_tools` with `"mode": "auto"` is **not** rejected: OpenAI documents that mode as letting the model pick from the allowed tools *and generate a message*, so it narrows the candidate set rather than forcing a call, and it reaches the provider unchanged.
|
|
547
|
-
|
|
548
|
-
Two scoping details are worth knowing. **Claude Fable 5 is not restricted** — Anthropic names Fable 5.1 and Mythos 5.1 as the exceptions to forced tool use working, and OpenRouter's own metadata agrees, so the guard is version-scoped rather than family-scoped. That is the opposite of `supportsTemperature`, which Anthropic's sampling-parameter sentence applies to both Fable generations. And a provider "latest" alias such as OpenRouter's `~anthropic/claude-fable-latest` is **not** covered: its id names no version, so no rule keyed on the id can stay true if the alias re-points at a model that accepts forced tool use. If you use such an alias and need a forced choice guarded, pin the versioned id instead.
|
|
194
|
+
Moved to [Model configuration reference](/models/reference#forced-tool-use-on-claude-fable-5-1).
|
|
549
195
|
|
|
550
196
|
### Preserved thinking and model switches
|
|
551
197
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
Two separate checks follow from that, and Atomic handles them differently.
|
|
555
|
-
|
|
556
|
-
**The model check is the API's job.** A block is readable by the model that produced it or a newer one. Claude Fable 5.1 reads every earlier Claude model's blocks; no earlier model reads Fable 5.1's. A block the target model cannot read is always dropped by the API before the prompt reaches the model, unbilled, and the request succeeds. For first-party Anthropic models, Atomic therefore replays signed thinking blocks unchanged when you switch models mid-conversation and lets the API adjudicate:
|
|
557
|
-
|
|
558
|
-
- **Switching up** to Claude Fable 5.1 from another Claude model keeps the conversation's reasoning, because Fable 5.1 is allowed to read it.
|
|
559
|
-
- **Switching down** from Claude Fable 5.1 to an earlier Claude model drops that reasoning server-side, and the earlier model reasons again from the visible messages.
|
|
560
|
-
|
|
561
|
-
In both directions the visible assistant text, tool calls, and tool results are preserved exactly, so the conversation stays coherent. Atomic no longer rewrites another Claude model's reasoning into visible assistant text on a switch: that both discarded reasoning the newer model was entitled to read and destabilized the prefix later blocks are bound to.
|
|
562
|
-
|
|
563
|
-
**The conversation check can fail the request, so Atomic opts out of failing.** On Claude Fable 5.1, replaying a thinking block behind a changed prefix returns a 400. Anthropic enforces this by default for organizations created on or after August 31, 2026, which is why a session could fail on a new account but not an older one. Atomic sends the `thinking-binding-controls-2026-08-01` beta header with `thinking.block_binding.prefix_mismatch_behavior: "drop_block"` for that model, so a changed system prompt, a tool that appeared or disappeared, or a model switch drops the affected thinking blocks and the turn still answers. The field is sent on every request for that model, including turns with no reasoning level: the header alone would leave `prefix_mismatch_behavior` at its `"error"` default, which is the failure being avoided. When the API reports drops, Atomic records them on the assistant message's `diagnostics` array as an `anthropic_input_transformations` entry with the count, reasons, and block paths.
|
|
564
|
-
|
|
565
|
-
**Compaction is handled structurally, not by `drop_block`.** Atomic's client-side `preserve_recent` compaction serializes the protected tail into a single boundary message rather than replaying it as structured assistant and tool-result messages, so no signed thinking block survives a boundary to be replayed behind it. Compaction therefore **intentionally resets the signed reasoning chain**: reasoning produced before a boundary is not carried across it, while the tail's text, tool calls, and tool results are preserved losslessly. This is exactly the first remedy Anthropic documents for keep-tail compaction — strip `thinking` and `redacted_thinking` from turns you carry across and keep `text` and `tool_use` — reached by Atomic's transcript design rather than by a stripping pass. `drop_block` covers live prefix mismatches *between* boundaries; it is not what makes compaction safe. See [Compaction](/compaction).
|
|
566
|
-
|
|
567
|
-
**Server-side fallback leaves a boundary marker in the turn.** Claude Fable 5.1 is generated with the fallback targets Anthropic publishes for it — Claude Opus 4.8 and Claude Opus 5 — so a classifier refusal can be retried server-side on the same stream. When the decline happens partway through a response, the API emits a `fallback` content block marking where one model's output gives way to the next, then the fallback model continues. Atomic keeps that marker in the assistant turn as a `fallback` content block, and re-attributes the message to the serving model so usage is costed at that model's rates rather than the requested model's.
|
|
568
|
-
|
|
569
|
-
On the next turn the marker's **position** is load-bearing: Anthropic validates the surrounding thinking blocks against it, and a request that echoes thinking from both sides of the boundary is rejected if the marker is missing or moved. Atomic therefore replays the marker exactly where it appeared, drops the declining model's `thinking`, `redacted_thinking`, and unexecuted client-side tool calls that precede it, and keeps all visible text plus everything after it. A turn with no fallback boundary is unaffected.
|
|
570
|
-
|
|
571
|
-
**Provider restriction.** Both behaviors are scoped to first-party Anthropic models on the `anthropic-messages` API, which is where Anthropic documents the signature adjudication. Claude on Amazon Bedrock, Google Vertex, and Anthropic-compatible proxies keep the previous behavior: their thinking blocks are not replayed across a model switch, and Atomic does not send the block-binding beta on those paths. This includes two mirrors that could look eligible — opencode zen and the Vercel AI Gateway both ride `anthropic-messages`, and neither receives either capability. If you run Claude Fable 5.1 through one of those providers on a new Anthropic-backed account, a prefix change can still surface as a provider error. Custom providers known to adjudicate signatures the same way can opt in with the two `compat` fields above.
|
|
198
|
+
Moved to [Model configuration reference](/models/reference#preserved-thinking-and-model-switches).
|
|
572
199
|
|
|
573
200
|
## OpenAI Compatibility
|
|
574
201
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
- Provider-level `compat` applies defaults to all models under that provider.
|
|
578
|
-
- Model-level `compat` overrides provider-level values for that model.
|
|
579
|
-
|
|
580
|
-
```json
|
|
581
|
-
{
|
|
582
|
-
"providers": {
|
|
583
|
-
"local-llm": {
|
|
584
|
-
"baseUrl": "http://localhost:8080/v1",
|
|
585
|
-
"api": "openai-completions",
|
|
586
|
-
"compat": {
|
|
587
|
-
"supportsUsageInStreaming": false,
|
|
588
|
-
"maxTokensField": "max_tokens"
|
|
589
|
-
},
|
|
590
|
-
"models": [...]
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
| Field | Description |
|
|
597
|
-
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
598
|
-
| `supportsStore` | Provider supports `store` field |
|
|
599
|
-
| `supportsDeveloperRole` | Use `developer` vs `system` role |
|
|
600
|
-
| `supportsReasoningEffort` | Support for `reasoning_effort` parameter |
|
|
601
|
-
| `supportsUsageInStreaming` | Supports `stream_options: { include_usage: true }` (default: `true`) |
|
|
602
|
-
| `supportsFinishReason` | Whether streamed responses include `finish_reason`. When `false`, Atomic infers `stop` or `toolUse` when the stream ends. Default: `true`. |
|
|
603
|
-
| `supportsThinkingTokenBudget` | Alias for `thinkingTokenBudgetField: "thinking_token_budget"` (vLLM). Prefer `thinkingTokenBudgetField`. Default: `false`. |
|
|
604
|
-
| `thinkingTokenBudgetField` | Top-level request field used to cap reasoning tokens from `thinkingBudgets`, clamped so at least 1024 tokens remain for the answer. `"thinking_token_budget"` (vLLM), `"thinking_budget"` (Qwen/DashScope/SGLang), `"thinking_budget_tokens"` (llama.cpp). Off by default; not set on the generated catalog. |
|
|
605
|
-
| `maxTokensField` | Use `max_completion_tokens` or `max_tokens` |
|
|
606
|
-
| `requiresToolResultName` | Include `name` on tool result messages |
|
|
607
|
-
| `requiresAssistantAfterToolResult` | Insert an assistant message before a user message after tool results |
|
|
608
|
-
| `requiresThinkingAsText` | Convert thinking blocks to plain text |
|
|
609
|
-
| `requiresReasoningContentOnAssistantMessages` | Include empty `reasoning_content` on all replayed assistant messages when reasoning is enabled |
|
|
610
|
-
| `thinkingFormat` | Use `reasoning_effort`, `openrouter`, `deepseek`, `together`, `zai`, `qwen`, `chat-template`, or `qwen-chat-template` thinking parameters |
|
|
611
|
-
| `chatTemplateKwargs` | `chat_template_kwargs` values for `thinkingFormat: "chat-template"`; use `{ "$var": "thinking.enabled" }`, `{ "$var": "thinking.effort" }`, or `{ "$var": "thinking.budget" }` for Atomic-controlled thinking values |
|
|
612
|
-
| `chatTemplateArgs` | `chat_template_args` values for `thinkingFormat: "baseten"`; use `{ "$var": "thinking.enabled" }`, `{ "$var": "thinking.effort" }`, or `{ "$var": "thinking.budget" }` for Atomic-controlled thinking values |
|
|
613
|
-
| `cacheControlFormat` | Use Anthropic-style `cache_control` markers on the system prompt, last tool definition, and last user/assistant text content. Currently only `anthropic` is supported. |
|
|
614
|
-
| `supportsStrictMode` | OpenAI-compatible strict JSON-schema function tools. This is not a general guarantee for every API. |
|
|
615
|
-
| `supportsStrictTools` | Anthropic/Bedrock strict-tool capability, normally generated from verified model metadata. |
|
|
616
|
-
| `supportsOpenAIGrammarTools` | Canonical Pi capability for OpenAI Lark/regex custom tools. Keep false unless the endpoint passes custom tools through unchanged. |
|
|
617
|
-
| `supportsGrammarTools` | Atomic compatibility alias for `supportsOpenAIGrammarTools`; the canonical field wins if both disagree. |
|
|
618
|
-
| `supportsLongCacheRetention` | Whether the provider accepts long cache retention when cache retention is `long`: `prompt_cache_options.ttl: "30m"` for GPT-5.6+ Responses models, `prompt_cache_retention: "24h"` for earlier OpenAI models, or `cache_control.ttl: "1h"` when `cacheControlFormat` is `anthropic`. Default: `true`. |
|
|
619
|
-
| `vllmPriority` | vLLM scheduler priority sent as the top-level `priority` request field. Lower values are handled earlier and the server default is `0`, so it only takes effect when vLLM runs with `--scheduling-policy priority`. Off by default; not set on the generated catalog. |
|
|
620
|
-
| `openRouterRouting` | OpenRouter provider routing preferences. This object is sent as-is in the `provider` field of the [OpenRouter API request](https://openrouter.ai/docs/guides/routing/provider-selection). |
|
|
621
|
-
| `vercelGatewayRouting` | Vercel AI Gateway routing config for provider selection (`only`, `order`) |
|
|
202
|
+
Moved to [Model configuration reference](/models/reference#openai-compatibility).
|
|
622
203
|
|
|
623
204
|
### Constrained tool sampling
|
|
624
205
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
Strict JSON-schema support currently includes OpenAI, Anthropic, capable Bedrock Converse models, Mistral, and Gemini 3 through Google/Vertex. Earlier Gemini models cannot enforce required parameters: `prefer` falls back and `require` fails. OpenAI grammar tools are limited to capable GPT-5+ models on endpoints known to preserve custom tools; gateways such as OpenRouter may normalize and break them.
|
|
206
|
+
Moved to [Model configuration reference](/models/reference#constrained-tool-sampling).
|
|
628
207
|
|
|
629
208
|
### Catalog freshness and precedence
|
|
630
209
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
Claude Opus 5 is present in the generated Anthropic and Amazon Bedrock catalogs. Its metadata enables adaptive thinking, including `xhigh` where advertised. Bedrock uses its generated inference-profile ID, prompt-caching and strict-tool metadata, and preserves provider/AWS validation errors. Custom entries must reproduce those capabilities honestly rather than copying a display name alone.
|
|
634
|
-
`openrouter` uses `reasoning: { effort }`. `together` uses `reasoning: { enabled }` and also `reasoning_effort` when `supportsReasoningEffort` is enabled. `qwen` uses top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that require `chat_template_kwargs.enable_thinking` and `preserve_thinking`. Use `chat-template` for vLLM/Hugging Face chat templates that need configurable `chat_template_kwargs`, such as `chatTemplateKwargs: { "thinking": { "$var": "thinking.enabled" } }` for DeepSeek V3.x templates. Use `thinkingFormat: "baseten"` with `chatTemplateArgs` for providers that expose toggle controls through `chat_template_args` and optionally support top-level `reasoning_effort`.
|
|
635
|
-
|
|
636
|
-
`thinkingTokenBudgetField` is independent of `thinkingFormat`. Do not enable it on the generated Qwen catalog: those models already send `reasoning_effort`, and DashScope rejects `thinking_budget` together with `reasoning_effort`.
|
|
637
|
-
|
|
638
|
-
`cacheControlFormat: "anthropic"` is for OpenAI-compatible providers that expose Anthropic-style prompt caching through `cache_control` markers on text content and tool definitions.
|
|
639
|
-
|
|
640
|
-
Example:
|
|
210
|
+
Moved to [Model configuration reference](/models/reference#catalog-freshness-and-precedence).
|
|
641
211
|
|
|
642
|
-
|
|
643
|
-
{
|
|
644
|
-
"providers": {
|
|
645
|
-
"openrouter": {
|
|
646
|
-
"baseUrl": "https://openrouter.ai/api/v1",
|
|
647
|
-
"apiKey": "$OPENROUTER_API_KEY",
|
|
648
|
-
"api": "openai-completions",
|
|
649
|
-
"models": [
|
|
650
|
-
{
|
|
651
|
-
"id": "openrouter/anthropic/claude-3.5-sonnet",
|
|
652
|
-
"name": "OpenRouter Claude 3.5 Sonnet",
|
|
653
|
-
"compat": {
|
|
654
|
-
"openRouterRouting": {
|
|
655
|
-
"allow_fallbacks": true,
|
|
656
|
-
"require_parameters": false,
|
|
657
|
-
"data_collection": "deny",
|
|
658
|
-
"zdr": true,
|
|
659
|
-
"enforce_distillable_text": false,
|
|
660
|
-
"order": ["anthropic", "amazon-bedrock", "google-vertex"],
|
|
661
|
-
"only": ["anthropic", "amazon-bedrock"],
|
|
662
|
-
"ignore": ["gmicloud", "friendli"],
|
|
663
|
-
"quantizations": ["fp16", "bf16"],
|
|
664
|
-
"sort": {
|
|
665
|
-
"by": "price",
|
|
666
|
-
"partition": "model"
|
|
667
|
-
},
|
|
668
|
-
"max_price": {
|
|
669
|
-
"prompt": 10,
|
|
670
|
-
"completion": 20
|
|
671
|
-
},
|
|
672
|
-
"preferred_min_throughput": {
|
|
673
|
-
"p50": 100,
|
|
674
|
-
"p90": 50
|
|
675
|
-
},
|
|
676
|
-
"preferred_max_latency": {
|
|
677
|
-
"p50": 1,
|
|
678
|
-
"p90": 3,
|
|
679
|
-
"p99": 5
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
]
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
```
|
|
689
|
-
|
|
690
|
-
Vercel AI Gateway example:
|
|
212
|
+
## GPT-6-Astra Built-in Models
|
|
691
213
|
|
|
692
|
-
|
|
693
|
-
{
|
|
694
|
-
"providers": {
|
|
695
|
-
"vercel-ai-gateway": {
|
|
696
|
-
"baseUrl": "https://ai-gateway.vercel.sh/v1",
|
|
697
|
-
"apiKey": "$AI_GATEWAY_API_KEY",
|
|
698
|
-
"api": "openai-completions",
|
|
699
|
-
"models": [
|
|
700
|
-
{
|
|
701
|
-
"id": "moonshotai/kimi-k2.5",
|
|
702
|
-
"name": "Kimi K2.5 (Fireworks via Vercel)",
|
|
703
|
-
"reasoning": true,
|
|
704
|
-
"input": ["text", "image"],
|
|
705
|
-
"cost": { "input": 0.6, "output": 3, "cacheRead": 0, "cacheWrite": 0 },
|
|
706
|
-
"contextWindow": 262144,
|
|
707
|
-
"maxTokens": 262144,
|
|
708
|
-
"compat": {
|
|
709
|
-
"vercelGatewayRouting": {
|
|
710
|
-
"only": ["fireworks", "novita"],
|
|
711
|
-
"order": ["fireworks", "novita"]
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
]
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
```
|
|
214
|
+
Moved to [Model configuration reference](/models/reference#gpt-6-astra-built-in-models).
|