Removing a Copilot model from one team can leave every affected developer able to use it through another team. GitHub's October 19, 2026 release makes model policies available through generally available REST GET and PATCH endpoints at enterprise, enterprise-team, enterprise-app, and organization scopes. That gives administrators a way to collect and change policy at scale. It also makes a mistaken interpretation easy to automate.
Name the people and apps that should lose access before changing a policy. Save the governing settings, remove the intended grant, then check those accounts. A successful PATCH alone cannot close the change.
This is a procedure derived from GitHub's documentation, not a report of tenant testing. Use the coding-agent security baseline for controls beyond model selection.
Establish which policy mode governs the change#
GitHub supports organization-based model control and an opt-in enterprise teams preview. In teams mode, organization model settings stop applying. A user's grants are additive across their enterprise teams: one remaining team grant can preserve access. Agent apps have a separate enterprise model configuration in that mode. The administration guide documents these boundaries.
Put the current mode, affected users, and agent apps in the change ticket. Collect team membership through the enterprise-team membership API or an approved directory export. Keep its capture time; a policy snapshot without membership cannot explain overlapping grants.
The model default is already active. It is separate from the feature default taking effect October 22, as GitHub's default-availability reference explains. Turning off a default does not substitute for reviewing explicit grants. The feature-default checklist covers that separate cutover.
Choose credentials for the scope you are reading. The enterprise AI-controls reference distinguishes read and write permissions. GitHub App credentials use the corresponding Enterprise AI controls permission; classic tokens use read:enterprise for reads and admin:enterprise for writes.
Organization endpoints have different requirements: even GET requires organization Administration write permission for supported fine-grained credentials, according to the organization API reference. A script that only sends GET requests can still hold a powerful credential. Keep collection credentials out of the evidence files and use a separately controlled writer.
See how your AI systems hold up under real attacks
General Analysis maps AI applications and agents, red teams prompts, retrieval, tools, MCP servers, browser actions, permissions, and business workflows, then turns findings into evidence your team can reproduce and retest.
Capture a baseline that can expose the remaining grant#
Suppose a developer belongs to both Research and Engineering, and both teams grant a model delegated by the enterprise. Clearing Research's grant leaves the Engineering grant intact. That is the overlap your pilot needs to catch.
Collect both teams, the enterprise policy, and app policy before changing anything. This Bash example requires gh, jq, an approved authenticated GitHub CLI session, an enterprise slug, and the numeric IDs of all relevant teams. It sends GET requests only. Save it as snapshot.sh; invoke it with the enterprise slug followed by the team IDs.
Code source: illustrative collector using GitHub's enterprise AI-controls endpoints.
set -euo pipefail
umask 077
enterprise="${1:?Pass the enterprise slug, then team IDs}"
shift
if [ "$#" -eq 0 ]; then
echo "Include every team relevant to the affected users." >&2
exit 1
fi
output_dir="$(mktemp -d ./copilot-policy.XXXXXX)"
started_at="$(date -u +%FT%TZ)"
base="/enterprises/${enterprise}"
capture() {
gh api --method GET \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2026-03-10" "$1" |
jq -S '.models |= sort_by(.model_name)' > "$output_dir/$2"
}
capture "$base/copilot/model-policies" enterprise.json
capture "$base/copilot/apps/model-policies" apps.json
for team_id in "$@"; do
[[ "$team_id" =~ ^[0-9]+$ ]] || exit 1
capture "$base/teams/$team_id/copilot/model-policies" \
"team-${team_id}.json"
done
jq -n --arg enterprise "$enterprise" --arg start "$started_at" \
--arg end "$(date -u +%FT%TZ)" \
'{enterprise: $enterprise, startedAt: $start,
completedAt: $end}' > "$output_dir/complete.json"
printf '%s\n' "$output_dir"
Only a completed collection gets complete.json. A failed run can leave partial files; exclude it from the comparison. These sequential reads are not an atomic snapshot. Avoid concurrent policy edits during collection and retain the membership export alongside it.
The launch post uses team_slug in its path, while the endpoint reference specifies integer team_id. The example follows the endpoint reference. For GHE.com, configure gh for the documented dedicated API host before adapting the collector.
Run the collector again after the approved change. Compare the returned enterprise default and model states, each team's enterprise_policy_state and editable fields, and the app policy. An unexpected change outside the intended scope needs investigation before expanding the rollout.
Clear the grant without inventing a team deny#
The team update reference documents optional as clearing the stored team policy. Locked models cannot be changed there. For a reviewed model returned by GET, the request body has this shape; replace the placeholder before use.
Code source: GitHub's team policy update schema, adapted with a model-name placeholder.
{
"models": [
{
"model_name": "MODEL_NAME_FROM_GET",
"policy_state": "optional"
}
]
}
The API schema also lists disabled, while the administration guide describes teams as additive and offers no team-level deny. The sources do not establish that submitting disabled overrides another team's grant. Use the documented clearing operation for withdrawal and resolve an enterprise-wide prohibition at the enterprise policy level.
Keep API acceptance and user acceptance as separate checks. This proposed matrix describes expected outcomes from GitHub's additive model rules; it contains no measured results.
| Pilot case | Expected policy result | Evidence needed |
|---|---|---|
| Research grant cleared; Engineering still grants the model | Overlapping member retains access | Both team responses and current membership |
| Last team grant cleared; enterprise delegates the model | No grant from those teams remains | Every applicable team, baseline, and affected-account check |
| Enterprise explicitly disables the model | Teams cannot enable it | Enterprise response and user/app verification |
| User grants removed; app policy still enables the delegated model | App access needs its own review | App policy and an authorized app-level check |
Use a harmless prompt with approved test data to check each intended client and account. Record the model requested, whether the request was accepted, the client version, and the time. Inspect both an existing session and a new one where your workflow uses both; do not turn a fresh-session result into an immediate-cutoff guarantee for running work. Leave unresolved differences open with the affected scope and owner.
Preserve intent before preparing rollback#
An organization GET returns effective policies, including values determined by defaults. An organization PATCH writes explicit settings and applies its requested changes atomically. The organization reference does not make a sequence of writes across scopes one transaction.
Copying effective GET values into a later PATCH can turn inherited behavior into durable explicit choices. Save the administrator's intended settings and inheritance before the change. Build a minimal rollback for the fields you changed; do not blindly replay the response object.
Changing governance mode has another rollback cost. GitHub says leaving the enterprise teams preview restores the pre-migration policy state and discards enterprise-level model changes made during teams mode. Check that documented rollback behavior before using the mode toggle as incident remediation.
Close the change when the before-and-after policy record, membership evidence, and user/app observations support the intended withdrawal. Retain tool-operation restrictions through Copilot managed permissions: deciding which model is available does not decide which files, commands, or connected tools an agent may use.
Frequently asked questions
- Does setting a Copilot team model policy to optional revoke a user's access?
It clears that team's stored policy. A user can retain access through the enterprise baseline or another enterprise team. Check all applicable grants and verify the affected account before recording access as removed.
- Did enterprise teams mode become generally available with the API?
No. GitHub announced general availability of the model policy REST endpoints on October 19, 2026. Its administration guide still describes enterprise teams mode as an opt-in preview.
- Can I restore a model policy by sending the GET response back as PATCH?
Do not treat a GET response as a rollback payload. Organization GET responses contain effective settings, including defaults, while PATCH writes explicit choices. Preserve the original intent and prepare a scope-specific rollback.

