Foundry Agent Service: build an agent, and move off the Assistants API
Build a prompt agent in Foundry Agent Service, then follow the migration path from the Azure OpenAI Assistants API: threads become conversations, runs become responses, a tool rewrites most of the code, and a few tools don't carry over.
AI & agentsFix a problem6 min read
Foundry Agent Service is where agents live in Microsoft Foundry now: a model, instructions and tools that Foundry runs for you, or your own code in a container that Foundry hosts. It replaced the Azure OpenAI Assistants API, whose sunset date, 26 August 2026, has passed. This guide builds a first agent the current way, then takes an existing Assistants API app through the migration, including the parts the migration tool can't do for you.
Three kinds of agent
| Prompt agent | Hosted agent | Responses API only | |
|---|---|---|---|
| What you write | Instructions, a model choice and tools, in the portal or SDK | Your own code with any framework (Agent Framework, LangGraph, the OpenAI Agents SDK and others), as a container or a zip | Calls from your own app; the agent's definition lives in your code |
| What Foundry runs | Everything | Your container, with a managed endpoint, scaling and its own identity | Nothing persistent; there's no agent resource |
| Compute to manage | None | Container compute, managed by Foundry | None |
| Best for | A fast start; production agents without custom orchestration | Agents that call into your own code or need custom orchestration | Agent logic that must ship and version with the app |
There's also a voice-based prompt agent for real-time spoken conversations, with several of its features in preview. Start declarative and move to a hosted agent when you need code; the model and tools stay the same.
Build a prompt agent
You need a Foundry project, a deployed model, the Foundry User role on the project, and the SDK: pip install "azure-ai-projects>=2.3.0" azure-identity, then az login. Everything goes through the project endpoint.
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import PromptAgentDefinition
project = AIProjectClient(
endpoint="https://<resource>.services.ai.azure.com/api/projects/<project>",
credential=DefaultAzureCredential(),
)
# The agent: a model and instructions, saved as version 1
project.agents.create_version(
agent_name="support-agent",
definition=PromptAgentDefinition(
model="gpt-5-mini", # your deployment name
instructions="You answer questions about our products, briefly.",
),
)
# Talk to it: a conversation keeps the context between turns
openai = project.get_openai_client(agent_name="support-agent")
conversation = openai.conversations.create()
first = openai.responses.create(conversation=conversation.id, input="What sizes does the jacket come in?")
print(first.output_text)
follow_up = openai.responses.create(conversation=conversation.id, input="And in blue?")
print(follow_up.output_text)
Two clients, on purpose: the project client creates and versions agents; the OpenAI client it hands you runs conversations and responses. Every create_version call makes a new version of the agent, which you can roll back to or compare. Tools, such as file search, code interpreter, web search, MCP servers and your own functions, go in the definition's tools list; a toolbox groups tools once and shares them across agents behind one endpoint.
In the portal the same takes a minute: Build > Agents > Create agent, name it, add instructions, and chat with it in the playground.
Move off the Assistants API
The Assistants API and the new agents differ in shape, not just in names:
| Before (Assistants API) | After (Foundry Agent Service) | What changes |
|---|---|---|
client.beta.assistants.create() | project.agents.create_version() with a PromptAgentDefinition | Agents are versioned, with a kind |
| Threads of messages | Conversations of items | Items include messages, tool calls and tool outputs |
| Messages | Items | Add them with conversations.items.create() |
| Runs, created and then polled | Responses, synchronous by default | No polling loop; tool-call loops are explicit |
| Assistants API endpoint | The project endpoint and the OpenAI v1 routes | One endpoint for models and agents |
Check the tools first. Most carry over, some don't: there's no Azure Functions tool in the new service, Connected agents are replaced by the agent-to-agent (A2A) tool, and Deep Research by a research model with the web search tool. Code interpreter, file search, function calling, Azure AI Search, OpenAPI, Bing grounding and MCP all exist in both.
Then run the migration tool. Microsoft's tool on GitHub rewrites the code constructs: agent definitions, thread and message creation, run creation. It doesn't move state: past threads, messages and runs stay where they are, readable through the old API while it lasts, and new conversations start fresh. The resource's region must support the Responses API; if agents don't appear in the new portal, that's why, and you need a resource in a supported region.
Verify by creating an agent and checking create_version() returns an id and a version; starting a conversation and getting output items back; and asking a follow-up in the same conversation to confirm it remembers. The errors you'll meet:
| Error | Cause | Fix |
|---|---|---|
'AIProjectClient' has no attribute 'conversations' | Conversations were called on the project client | Use project.get_openai_client() for conversations and responses |
create_agent() is removed | It went in SDK version 2.0 | create_version() with a PromptAgentDefinition |
404 or MethodNotAllowed from agent calls | Assistants API calls sent to the Responses endpoint | Rewrite the calls; don't just change the endpoint |
A model error from responses.create() | Wrong deployment name, or the model isn't in your region | Check Build > Models |
| Old threads missing | The tool doesn't migrate state | Start new conversations |
Run it safely
- Guardrails. An agent uses the guardrail assigned to it; if none is, it inherits its model's. An assigned guardrail replaces the model's entirely, including the new tool-call and tool-response intervention points, so assign one deliberately. Our guide on content filter errors covers what the controls do.
- Identity. Each agent can have its own Microsoft Entra identity for calling other services without shared secrets. Callers that only need to talk to an agent get the Foundry Agent Consumer role, scoped to the project or to that one agent, rather than Foundry User.
- Tracing and evaluation. Connect the project to Application Insights to see every model call and tool call an agent makes, run evaluations, and build datasets from real traces; stored completions, which some teams used for this, retire on 15 October 2026.
- Private networking. Prompt agents can run inside your virtual network; hosted agents can be attached to your own virtual network, with each session in an isolated sandbox.
- MCP servers. They extend an agent a long way and carry real risk: vet each server, limit the tools an agent may call, and add approvals where a call changes something.
- Publishing. Promote a version to a managed endpoint and share it through Microsoft Teams, Microsoft 365 Copilot or the Entra Agent Registry; publishing needs the Foundry Project Manager role on the resource.
Sources
- Agents in Microsoft Foundry, Microsoft Learn
- Quickstart: Get started with Microsoft Foundry SDK, Microsoft Learn
- Migrate to the new agents developer experience, Microsoft Learn
- Migrate from the Foundry (classic) portal, Microsoft Learn (the retirement dates)
- Guardrails and controls overview, Microsoft Learn
- Role-based access control for Microsoft Foundry, Microsoft Learn
Did this fix it?
Comments
No comments yet. Share what worked for you.
Sign in to comment. Comments show under a display name you choose, never your email.