100% private · no tracking · works offline100% client-side/no data leaves your browser/no accounts/works offline
GitHub Models shuts down for good on July 30, 2026 — this guide walks through finding every place your code depends on it and migrating to Azure AI Foundry, OpenRouter, a direct provider API, or a local model, with working code.
Free toolkit
85+ private dev tools
Everything runs in your browser. Zero tracking, no sign-up.
Browse toolsGitHub Models — the free playground and inference API for testing LLMs directly from a GitHub account — is being fully retired on July 30, 2026. If you've wired GitHub Models into a script, a GitHub Action, a side project, or (against better judgment) a production service, you have a hard deadline and two scheduled brownouts to deal with first: July 16 and July 23, 2026, when requests will intermittently fail before the final shutdown.
Most of what's been published about this so far is either a straight news recap or a "here are your options" overview that stops short of actual working code. This guide skips the news angle and goes straight to the mechanics: how to find every place your code depends on GitHub Models, how to migrate to each realistic replacement with working examples in Python and Node.js, how to update your GitHub Actions workflows, and how to cut over without an outage.
In this guide, we'll take a look at:
GitHub announced that GitHub Models — the playground, the model catalog, the inference API, and the bring-your-own-key (BYOK) endpoints — will be fully retired for all customers on July 30, 2026. This applies even to existing customers with active usage; there's no grandfathering.
Before the hard cutoff, GitHub is running two scheduled brownouts to let teams find out what breaks before it breaks for good:
If you're reading this after July 16, treat every failed request in your logs from that date onward as a preview of what's coming, not a transient blip.
Before picking a replacement, find every integration point. GitHub Models is easy to miss because it's often added quietly — a demo notebook, a GitHub Action step, an internal Slack bot.
Search your repositories for the telltale signs:
# The inference endpoint itself
grep -rn "models.github.ai" .
grep -rn "models.inference.ai.azure.com" . # older endpoint some repos still use
# The SDK patterns commonly used with it
grep -rn "GITHUB_TOKEN" --include="*.py" --include="*.ts" --include="*.js" .
grep -rn "azure-ai-inference\|ChatCompletionsClient" .
# GitHub Actions steps that call it
grep -rln "models.github.ai\|github-models" .github/workflows/
Check these places specifically:
actions/ai-inferenceKeep a running list — you'll migrate each one individually and want to check them off as you test.
GitHub Models exposes an OpenAI-compatible chat completions API. If your code uses the openai Python or Node SDK pointed at GitHub's endpoint, the actual migration is almost always three values: base URL, API key, and model name. The request/response shape stays the same.
Here's what a typical GitHub Models call looks like today:
# Before: GitHub Models
import os
from openai import OpenAI
client = OpenAI(
base_url="https://models.github.ai/inference",
api_key=os.environ["GITHUB_TOKEN"],
)
response = client.chat.completions.create(
model="openai/gpt-4o",
messages=[{"role": "user", "content": "Summarize this changelog entry."}],
)
print(response.choices[0].message.content)
The fix is to stop hardcoding those three values and pull them from configuration instead:
# After: provider-agnostic
import os
from openai import OpenAI
client = OpenAI(
base_url=os.environ["MODEL_BASE_URL"],
api_key=os.environ["MODEL_API_KEY"],
)
response = client.chat.completions.create(
model=os.environ["MODEL_NAME"],
messages=[{"role": "user", "content": "Summarize this changelog entry."}],
)
print(response.choices[0].message.content)
Now switching providers is an environment variable change, not a code change. The rest of this guide gives you the exact three values for each realistic replacement.
This is the path GitHub itself points to, and it makes sense if you're already on Microsoft infrastructure or want the closest thing to a drop-in replacement — GitHub Models ran on Azure AI infrastructure in the first place.
MODEL_BASE_URL=https://<your-resource-name>.services.ai.azure.com/models
MODEL_API_KEY=<your-azure-ai-foundry-key>
MODEL_NAME=gpt-4o
Create the resource once via the Azure CLI:
az cognitiveservices account create \
--name my-ai-foundry-resource \
--resource-group my-rg \
--kind AIServices \
--sku S0 \
--location eastus
If you don't want to be locked into one vendor's catalog again, OpenRouter puts dozens of models — including Claude, GPT, Gemini, and open-weight models — behind a single OpenAI-compatible endpoint.
MODEL_BASE_URL=https://openrouter.ai/api/v1
MODEL_API_KEY=<your-openrouter-key>
MODEL_NAME=anthropic/claude-sonnet-5
Swapping MODEL_NAME to openai/gpt-5.6 or google/gemini-3.2-pro requires no other code change — that portability is the main reason to pick this option over a single vendor.
If you only ever used one model family through GitHub Models, going direct removes a hop and usually gets you the newest model versions faster.
# Anthropic
MODEL_BASE_URL=https://api.anthropic.com/v1
MODEL_API_KEY=<your-anthropic-key>
MODEL_NAME=claude-sonnet-5
# OpenAI
MODEL_BASE_URL=https://api.openai.com/v1
MODEL_API_KEY=<your-openai-key>
MODEL_NAME=gpt-5.6
Note: Anthropic's native API uses a messages shape that's compatible with the OpenAI SDK's chat.completions.create call when you set the base URL as above, but for full feature access (extended thinking, tool use nuances) the native anthropic SDK is worth switching to instead of staying wrapped in the OpenAI client.
For CI jobs, internal tooling, or anything that doesn't need frontier-model quality, running an open-weight model locally removes the "another vendor retiring my endpoint" risk entirely.
# Start Ollama and pull a model once
ollama pull llama3.3
MODEL_BASE_URL=http://localhost:11434/v1
MODEL_API_KEY=ollama # any non-empty string; Ollama doesn't check it
MODEL_NAME=llama3.3
A small wrapper makes the provider swappable without touching call sites:
# model_client.py
import os
from openai import OpenAI
def get_client() -> OpenAI:
return OpenAI(
base_url=os.environ["MODEL_BASE_URL"],
api_key=os.environ["MODEL_API_KEY"],
)
def chat(prompt: str) -> str:
client = get_client()
response = client.chat.completions.create(
model=os.environ["MODEL_NAME"],
messages=[{"role": "user", "content": prompt}],
)
return response.choices[0].message.content
// modelClient.ts
import OpenAI from "openai";
const client = new OpenAI({
baseURL: process.env.MODEL_BASE_URL,
apiKey: process.env.MODEL_API_KEY,
});
export async function chat(prompt: string): Promise<string> {
const response = await client.chat.completions.create({
model: process.env.MODEL_NAME!,
messages: [{ role: "user", content: prompt }],
});
return response.choices[0].message.content ?? "";
}
Nothing above references GitHub Models by name — that's the point. The provider lives entirely in three environment variables, so migrating again in the future (or A/B testing two providers) doesn't touch application code.
If you used the actions/ai-inference action or curled the GitHub Models endpoint directly in a workflow, replace it with a plain HTTP call to your new provider, pulling the three values from repository or organization secrets:
# Before
- name: Summarize PR
uses: actions/ai-inference@v1
with:
model: openai/gpt-4o
prompt: "Summarize this pull request diff."
# After
- name: Summarize PR
env:
MODEL_BASE_URL: ${{ secrets.MODEL_BASE_URL }}
MODEL_API_KEY: ${{ secrets.MODEL_API_KEY }}
MODEL_NAME: ${{ secrets.MODEL_NAME }}
run: |
curl -sS "$MODEL_BASE_URL/chat/completions" \
-H "Authorization: Bearer $MODEL_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg model "$MODEL_NAME" --arg content "Summarize this pull request diff." \
'{model: $model, messages: [{role: "user", content: $content}]}')"
Store MODEL_BASE_URL, MODEL_API_KEY, and MODEL_NAME as repository or organization secrets/variables rather than hardcoding them, for the same reason as the application code above — you want to be able to change providers again without editing every workflow file.
GitHub Models had generous, simple free-tier limits. Every replacement here has its own rate-limit behavior, and none of them are identical, so add retry-with-backoff regardless of which provider you land on:
import time
from openai import OpenAI, RateLimitError, APIConnectionError
def chat_with_retry(client: OpenAI, model: str, prompt: str, max_retries: int = 5) -> str:
for attempt in range(max_retries):
try:
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
)
return response.choices[0].message.content
except (RateLimitError, APIConnectionError):
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt) # 1s, 2s, 4s, 8s, 16s
raise RuntimeError("unreachable")
If you're moving from a single free endpoint to a paid one, also add basic spend guardrails (a token budget per run, or a monthly cap in your provider's dashboard) before you cut traffic over — the failure mode changes from "request denied" to "unexpected bill."
Don't flip every call site over at once. A safe sequence:
import os
USE_NEW_PROVIDER = os.environ.get("USE_NEW_MODEL_PROVIDER", "false") == "true"
def get_active_client() -> OpenAI:
if USE_NEW_PROVIDER:
return OpenAI(base_url=os.environ["MODEL_BASE_URL"], api_key=os.environ["MODEL_API_KEY"])
return OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"])
GITHUB_TOKEN calls to the old endpoint will simply fail after July 30 anyway.GitHub Models was free, so every replacement is a real line-item change. Rough per-million-token pricing as of July 2026, using a mid-tier flagship model on each platform:
| Provider | Setup effort | Approx. input $/1M tokens | Approx. output $/1M tokens | Notes |
|---|---|---|---|---|
| Azure AI Foundry | Medium (Azure account + resource) | Varies by deployed model | Varies by deployed model | Closest to GitHub Models' original infra |
| OpenRouter | Low (single API key) | Varies by routed model | Varies by routed model | One key, many model families |
| Anthropic / OpenAI direct | Low | ~$2–$3 | ~$10–$15 | Fewer hops, latest models fastest |
| Ollama / LM Studio (local) | Medium (hardware-dependent) | $0 (compute cost only) | $0 (compute cost only) | No rate limits, lower quality ceiling |
Exact pricing changes often enough that you should check each provider's current pricing page before budgeting — treat the table above as a starting point for comparison shopping, not a quote.
Do I have to migrate before July 16? No, but treat July 16 and July 23 as free fire drills. Anything that breaks during a brownout will break permanently on July 30 — better to find it now.
Is there any grandfathering for existing paid or enterprise usage? No. GitHub's announcement explicitly states the retirement applies to everyone, including existing customers with active usage.
Will my code even need to change if I already use the openai SDK?
Usually just the base_url, api_key, and model values — see Step 2. The bigger risk is usually rate limits and pricing assumptions baked into your code, not the SDK calls themselves.
What about the Azure AI Inference SDK instead of the OpenAI SDK?
If your code already uses azure-ai-inference's ChatCompletionsClient rather than the OpenAI SDK, Azure AI Foundry is the least-friction target since the SDK already speaks its dialect — you'll mainly be updating the endpoint and credential, not the client library.
Can I just switch to GitHub Copilot instead? Only if your use case is "I want AI inside my IDE or PR workflow," which GitHub Copilot covers. It isn't a drop-in replacement for a general-purpose inference API called from arbitrary scripts or services — for that, you need one of the four options above.
GitHub Models is going away on a fixed date with no exceptions, and the two brownouts before that are a gift if you use them as forced testing windows rather than surprises. The actual migration is rarely a rewrite: isolate the base URL, API key, and model name behind configuration, pick a replacement that matches your actual usage pattern (Azure AI Foundry for the closest infrastructure match, OpenRouter for portability, a direct API for the newest models, or a local model for zero ongoing cost), and cut over through a canary and a feature flag rather than a big-bang deploy. Do it before July 23, and July 30 will be a non-event.
Comments
Sign in to join the discussion.
No comments yet. Be the first to share your thoughts.