Follow Discord
Sweep 22 Oct 2026 · 21:04Z Build v2.1.309 528 read Stable v2.1.308 Latest v2.1.308 Next v2.1.309 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-code

Claude apps gateway configuration changedclaude-apps-gateway-config

Nearest release: v2.1.289, published 9 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 4 Oct 2026 05:15 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 4 Oct 2026 05:37 UTC.

Upstream edited
Recorded here
Lines+31added
Lines−4removed
From line 780 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits60to this page, all time

#### Start sessions on a model the policy allows

The whole hunk

from line 780, old and new numbered
/
lines
from line 780
780780 - match: {}
781781 cli:
782782 availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]
783 # Make the Default option in /model resolve inside each policy's
784 # list. The eng-contractors policy inherits enforceAvailableModels.
785 enforceAvailableModels: true
783786```
784787 
785788A `match: {}` catch-all, conventionally listed last, is treated as a base layer. Every other policy inherits any key it doesn't set from the catch-all, so per-role entries only need to list what differs from the org default. The merge rules depend on the key type:
from line 791
788791* **Deny-lists and hook arrays**: `permissions.deny`, `permissions.ask`, `disabledMcpjsonServers`, `deniedMcpServers`, `blockedMarketplaces`, and every `hooks` event-type array. These take the union of base and policy, so an org-wide deny or audit hook can't be accidentally dropped by a per-role override.
789792* **Record-typed keys**: `env`, `modelOverrides`, and `skillOverrides`. These shallow-merge, so a per-role `env` block overrides keys it sets and inherits the rest from the base.
790793 
791`availableModels` is also enforced server-side at `/v1/messages`, so a denied model returns `400` regardless of what the client sends.
794`availableModels` is also enforced server-side at `/v1/messages`, so a denied model returns `400` regardless of what the client sends. An empty list denies every model. The check also covers the model a session starts on before the developer picks one, so [start sessions on a model the policy allows](#start-sessions-on-a-model-the-policy-allows).
792795 
793796The gateway validates the `model` value itself before it relays a request, so a malformed value never reaches an upstream. It rejects the request with a `400` in two cases:
794797 
from line 818
815818 * **Group membership**: changing a user's group membership changes which policy matches them. This takes effect on the next session re-mint, meaning the next silent refresh, bounded by `session.ttl_hours`.
816819</Note>
817820 
821#### Start sessions on a model the policy allows
822 
823If `availableModels` leaves out Claude Code's default model, sessions get `400` responses until the developer picks a listed model, for example with `/model`. In gateway sessions the default is the Opus model the `opus` alias resolves to, and `availableModels` on its own doesn't change it.
824 
825To fix this, set [`enforceAvailableModels: true`](/docs/en/model-config#enforce-the-allowlist-for-the-default-model) in the same `cli` block, then check which kind of entry the list has:
826 
827* **An alias such as `sonnet`, or a built-in ID such as `claude-sonnet-4-6`**: sessions start on one of those models, and the Default option in `/model` resolves to it
828* **No alias or built-in ID in the list**: sessions can keep starting on the built-in default, so also set [`model`](/docs/en/model-config#control-the-model-users-run-on) to one of the listed IDs in that policy's `cli` block
829 
830This policy lists one custom ID that [`models`](#models) defines, and starts sessions on that ID:
831 
832```yaml theme={null}
833managed:
834 policies:
835 - match: { groups: [restricted-projects] }
836 cli:
837 availableModels: [claude-opus-restricted]
838 enforceAvailableModels: true
839 model: claude-opus-restricted
840```
841 
818842#### Matcher values that stop the gateway at boot
819843 
820844At boot, the gateway checks the `match` block of every policy and the [`admin_groups`](#admin) list. Any of these values stops the gateway with an error that names the field:
from line 872
848872 cli:
849873 # Model access (also enforced server-side at /v1/messages)
850874 availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]
875 enforceAvailableModels: true # Default resolves inside the list
851876 
852877 # Permission policy
853878 permissions:
from line 988
963988 - match: { groups: [eng-contractors] }
964989 cli:
965990 availableModels: [claude-sonnet-4-6]
991 enforceAvailableModels: true
966992 desktop:
967993 isLocalDevMcpEnabled: false
968994 disableAutoUpdates: true
from line 1401
13751401 - match: { groups: [contractors] }
13761402 cli:
13771403 availableModels: [claude-haiku-4-5]
1378 # Constrain the Default picker option to availableModels instead of
1379 # the tier default, so contractors don't get a 400 on the default.
1380 enforceAvailableModels: true
13811404 # allow auto-approves these tools; it does not block the rest.
13821405 # Add deny rules to restrict tools.
13831406 permissions: { allow: [Read, Grep] }
from line 1407
13841407 - match: {}
13851408 cli:
13861409 availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]
1410 # Constrain the Default picker option to each policy's availableModels
1411 # instead of the built-in default, so no role gets a 400 on Default.
1412 # The contractors policy inherits this key.
1413 enforceAvailableModels: true
13871414 permissions:
13881415 allow: [Read, Grep, Bash, Edit]
13891416 deny: ["WebFetch"]
Feedback