> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pullfrog.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Azure OpenAI

Route runs through your own Azure OpenAI resource. Inference bills to your Azure subscription, so Azure credits apply.

<Note>
  Azure is BYOK only. Pullfrog never proxies this traffic.
</Note>

## Setup

Pick **Azure OpenAI** in the model dropdown, then supply five values. Like Bedrock and Vertex it has no per-model variants — the model is whatever your deployment serves.

**Either** store all five in the console: **Model usage** on the Billing card, then **Azure OpenAI → Set up**. Pullfrog injects them at run time and you never touch `pullfrog.yml`.

**Or** put `AZURE_API_KEY` in a [GitHub Actions secret](https://github.com/settings/secrets/actions) and the rest in your workflow `env:`:

```yaml theme={null}
env:
  AZURE_RESOURCE_NAME: my-resource
  AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }}
  AZURE_DEPLOYMENT: my-deployment
  AZURE_CONTEXT: "400000"
  AZURE_MAX_OUTPUT: "128000"
```

| Env var               | Sensitive | Purpose                                                         |
| --------------------- | --------- | --------------------------------------------------------------- |
| `AZURE_RESOURCE_NAME` | no        | The `<name>` in `https://<name>.openai.azure.com`.              |
| `AZURE_API_KEY`       | **yes**   | A key for that resource. Store as a secret.                     |
| `AZURE_DEPLOYMENT`    | no        | Your deployment's name — see below, it is not the model's name. |
| `AZURE_CONTEXT`       | no        | Context window of the model behind the deployment, in tokens.   |
| `AZURE_MAX_OUTPUT`    | no        | Max completion tokens that model accepts.                       |

All five are required, and the two limits must parse as positive numbers — `128k` is rejected. Values in your workflow `env:` win over Pullfrog-stored ones.

One optional sixth:

| Env var                      | Purpose                                                                           |
| ---------------------------- | --------------------------------------------------------------------------------- |
| `AZURE_USE_CHAT_COMPLETIONS` | Set to `"true"` for a deployment that predates Azure's Responses API — see below. |

## Responses API, and when to switch

Requests go to your resource's **Responses** endpoint (`/openai/v1/responses`), which is what current Azure models speak. Deploy a GPT-5-family model (`gpt-5-nano`, `gpt-5-mini`, `gpt-5`) and it works as-is.

Older deployments — `gpt-4`, `gpt-35-turbo` — only speak Chat Completions and answer a Responses request with an error. Set `AZURE_USE_CHAT_COMPLETIONS: "true"` for those.

## The deployment name is not the model name

Azure routes on the **deployment** name. `AZURE_DEPLOYMENT` is the name given to the deployment in the portal, which defaults to the model's name but is often changed:

* Deployed `gpt-5`, kept the default name → `AZURE_DEPLOYMENT: gpt-5`
* Named it `prod-reasoning` → `AZURE_DEPLOYMENT: prod-reasoning`

Find it under **Deployments** in [Microsoft Foundry](https://ai.azure.com), or your resource's **Model deployments** in the Azure portal. A name that doesn't exist on the resource returns `404` at the first request.

## Why the token limits are required

A deployment name tells Pullfrog nothing about the model behind it, so there is no catalog entry to read limits from. Undeclared, they break two things at once:

* **Completions get capped at 32000 tokens**, which any model with a smaller cap rejects outright.
* **Auto-compaction switches off.** Compaction keys off the context limit, so a long session grows until Azure refuses it on context length.

Set `AZURE_CONTEXT` to the real window of whichever model your deployment serves. Understating it compacts earlier than necessary; overstating it defers compaction until Azure refuses the request.

## Reasoning effort

The [effort setting](/models#selecting-a-model) doesn't apply to Azure runs. Effort levels belong to a specific model, and a deployment name doesn't identify one — guessing wrong makes the run hang rather than fall back, so Pullfrog sends nothing and the model's own default applies.

## Which models you can use

Whichever OpenAI models your Azure OpenAI resource has deployed — the GPT family, the reasoning models, and so on. Pullfrog sends the request to your deployment and doesn't constrain which of them is behind it.

Non-OpenAI models on Azure — Anthropic, DeepSeek, Llama, Mistral, Phi — are [Foundry Models](https://learn.microsoft.com/en-us/azure/ai-foundry/foundry-models/), served from a Foundry resource at a different endpoint rather than from `https://<name>.openai.azure.com`. This integration can't reach them. Point [OpenAI-compatible endpoints](/openai-compatible) at your Foundry inference URL instead.

## Troubleshooting

**`404` from Azure**

`AZURE_RESOURCE_NAME` doesn't match your endpoint hostname, or `AZURE_DEPLOYMENT` isn't a deployment on that resource. Check the deployment name in the portal — the deployment's name, not the model's. A Foundry model is also a `404` here; see above.

**A Responses-API error, or `Unrecognized request argument`**

The deployment serves a model that predates the Responses API. Set `AZURE_USE_CHAT_COMPLETIONS: "true"`.

**`401` from Azure**

The key doesn't belong to that resource. Keys are per-resource.

**The run says configuration is missing**

The error names the values it couldn't find. Check they're stored in the console or mapped into your workflow `env:` — Actions only injects what the workflow file lists.

## Using an Entra ID token instead of a key

Pullfrog sends a static credential and can't refresh a Microsoft Entra ID token mid-run. If your organization forbids resource keys, front the resource with a gateway that does the token exchange and point [OpenAI-compatible endpoints](/openai-compatible) at the gateway.
