# Azure AI Foundry Agents

> Use when provisioning persistent tool-using AI agents on Azure AI Foundry. The Hub/Project/Connection Bicep pattern, per-service managed identity and RBAC including the two-role gotcha where Azure AI Developer alone is not enough, agent-as-code provisioned by a run-and-exit job, azd versus az deployment in CI, GitHub Actions to Azure authentication, and which PR-environment resources are cheap. Getting this wrong looks like a healthy deploy until the first agent-creation call.

- Skill: `konradcinkusz/azure-ai-foundry-agents` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add konradcinkusz/azure-ai-foundry-agents`
- Raw SKILL.md: https://api.skillmd.com/api/skills/konradcinkusz/azure-ai-foundry-agents/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: konradcinkusz (https://skillmd.com/u/konradcinkusz)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/konradcinkusz/azure-ai-foundry-agents

---


# Provisioning AI agents on Azure AI Foundry

**Read [`references/AZURE-AI-FOUNDRY-AGENTS.md`](references/AZURE-AI-FOUNDRY-AGENTS.md) before applying any of this.**
That file is the standard; everything below it is a summary to help you decide
whether this skill applies and to check your work afterwards.

## What this standard covers

- The model in one paragraph
- What "agent" means here
- Repository layout
- Bicep: Hub, Project, Connection
- RBAC: who needs what, and the gotchas
- Agent-as-code: definitions and the provisioner
- Managed identity per service
- Provisioning the infrastructure
- GitHub Actions → Azure authentication
- Ephemeral / PR environments: what's cheap and what isn't

## Failure modes

| Symptom | Cause |
|---|---|
| Agent creation fails with an authorization error, deploy otherwise looks healthy | Consuming service's identity has "Azure AI Developer" on the Project but not "Cognitive Services OpenAI Contributor" on the OpenAI account — both are required |
| Hub↔OpenAI connection works for chat completions but not for agent operations | Hub identity has "OpenAI User" only; assistants/write needs "OpenAI Contributor" too |
| Infrastructure deployment fails on its first run in a fresh subscription | `Microsoft.MachineLearningServices` resource provider not registered |
| Role assignment fails with "already exists" on re-run | `name` on the `roleAssignments` resource used `guid()` with a random seed instead of a deterministic `guid(scope, principal, role)` |
| In-flight conversations start failing immediately after a version bump | The accepted consequence of replace-and-delete (§6), made worse by a client that cached an `asst_...` id instead of resolving the active agent per request |
| The Foundry project slowly fills with unused agents | Provisioning deactivates tracking rows without deleting the agents behind them, and has no orphan-cleanup pass |
| Provisioning reports success but no agent exists | The job ran against an empty or unreadable `agents/` directory — it must fail on finding no definitions, and verify an active row before exiting 0 |
| Provisioning runs several times per deploy and races itself over the tracking table | Wired as a startup hosted service on a multi-replica API instead of a single run-and-exit job (§6) |
| The provisioning job's logs are empty in CI even though it ran | The process exited before the platform's log forwarder flushed — write the completion line to stdout, flush it, and pause briefly before returning |
| Every PR environment silently re-creates Azure OpenAI + model deployments | No shared-OpenAI parameter threaded through `infra/`; classification not decided up front |
| Foundry SDK calls fail with a malformed endpoint | Used `discoveryUrl` directly instead of stripping `/discovery` and rebuilding the `/agents/v1.0/...` path |
| GitHub Actions can authenticate to `dev` but not `prd` (or vice versa) | Environments share one App Registration/service principal instead of one per environment |

## Checklist

Per environment (subscription/resource-group pair):

- [ ] `Microsoft.MachineLearningServices` provider registered before the first deployment
- [ ] One Hub, one Project per environment; Project's `hubResourceId` set explicitly
- [ ] OpenAI account referenced as `existing`, not duplicated per module
- [ ] Hub and Project identities both hold OpenAI Contributor **and** OpenAI User on the OpenAI account
- [ ] Agents endpoint derived from `discoveryUrl` (strip `/discovery`, rebuild `/agents/v1.0/...`), not the raw discovery URL

Per service that creates or runs agents:

- [ ] Own user-assigned managed identity; no shared/service-principal-wide identity
- [ ] Identity holds OpenAI Contributor on the OpenAI account **and** Azure AI Developer on the Project
- [ ] Agent definitions live in-repo as versioned JSON, one file per agent
- [ ] Agents provisioned by a run-and-exit job whose exit code gates the deploy, not by a startup hosted service on the API's path
- [ ] Provisioning is idempotent by `version` and scoped by `slug` + logical agent environment, the latter separate from `ASPNETCORE_ENVIRONMENT`
- [ ] Replacement deletes the superseded agent, and a cleanup pass removes orphans left by earlier runs
- [ ] The job fails loudly when it finds no definitions or ends with no active agent for the environment
- [ ] Clients resolve the active agent per request instead of caching an `asst_...` id across turns
- [ ] Thread ids never reach the client; only an internal conversation id does

Per repository:

- [ ] GitHub Environment per Azure environment (`dev`, `prd`, …), each its own App Registration
- [ ] OIDC federated credentials, not a long-lived client secret, for any new setup
- [ ] `prd` environment has a required-reviewers protection rule
- [ ] `docs/…RESOURCE_CLASSIFICATION.md` states which resources are re-provisioned per PR/ephemeral environment and which are shared, with the cost reasoning written down
- [ ] Secrets never committed; connection string / endpoint delivered through the platform secret store, same discipline as [`FLY-IO-DEPLOYMENT.md §9`](https://github.com/konradcinkusz/architecture-standards/blob/main/docs/guides/FLY-IO-DEPLOYMENT.md#9-configuration-and-secrets)

---

Generated from [`docs/guides/AZURE-AI-FOUNDRY-AGENTS.md`](https://github.com/konradcinkusz/architecture-standards/blob/main/docs/guides/AZURE-AI-FOUNDRY-AGENTS.md) by `scripts/build-marketplace.mjs`. Do not edit this file: change the source document, or its entry in `catalog/marketplace.catalog.json`, and re-run the generator.

