💡 Why toService ManagementIntermediate✨ AI-assisted

Why Service Teams Should Migrate Classic Foundry Agents Now

WittyTech Daily··4 min read
#microsoft foundry#agent migration#service retirement

Your classic Foundry agents have an expiry date. Microsoft Learn says Agents (classic) are deprecated and will be retired on March 31, 2027, with the generally available Microsoft Foundry Agent Service as the replacement. That is 171 days from today. If you need to migrate Foundry classic agents, run it like any service retirement: an inventory, an owner, a change record and a date.

Treat Foundry classic agents as a planned service retirement

An agent that triages tickets or drafts replies is a service component, even if someone built it in an afternoon. Retiring a component you never inventoried is how you learn about it from an angry user. So open a retirement entry before anyone opens an editor:

retirement: foundry-agents-classic
retires_on: 2027-03-31
cutover_target: 2027-02-15
agents:
  - name: <agent-name>
    project: <foundry-project>
    owner: <named-person>
    model_deployment: <deployment-name>
    tools: [<tool-types>]
    decision: migrate | replace | delete
    change_record: <ticket-id>

One named owner per agent ("the AI team" is not a person), one decision per agent, and a cutover date that leaves March as buffer. The February date is my suggestion, not Microsoft's.

Answer "it still works today" honestly

It does, and nobody should rewrite a working agent out of panic. But five months is shorter than it sounds once change windows and approvals are counted, and the migration guide contains parts that need real decisions:

  • Three tools don't carry over. Azure Functions has no equivalent in the new service, Connected Agents points to the A2A tool, and Deep Research points to the Deep Research model with the Web Search tool.
  • State doesn't move. The guide says its migration tool doesn't migrate past runs, threads or messages, and advises starting new conversations after cutover. Historical data stays reachable through the previous API until it's deprecated.
  • New work lands in one place. Microsoft says new features and model support are added only to the new agents.

The inventory also gives you a legitimate third option: some classic agents have no users, and deleting them is a perfectly good way to finish the migration.

Check the classic limits before you size the work

The classic quotas and limits page lists fixed limits worth recording per agent: 128 tools registered per agent, 100,000 messages per thread, 10,000 files per agent or thread, and 512 MB per file. Microsoft says these Agent Service limits can't be increased. An agent near 128 tools, or a thread near the message cap, deserves a look before cutover rather than after.

Rate limits work differently. The Agent Service doesn't set its own; rate limiting is applied at the model deployment, and exceeding it returns a 429. If the classic and new agents call the same deployment during a parallel run, they share one quota. That page covers the classic service, so confirm the new service's limits in the current docs before assuming the numbers match.

What the code change looks like

Per the guide, create_agent() becomes create_version(), threads become conversations, and runs become responses. Install the SDK first:

pip install "azure-ai-projects>=2.3.0"
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import CodeInterpreterTool, PromptAgentDefinition

project = AIProjectClient(
    endpoint="https://<resource-name>.services.ai.azure.com/api/projects/<project-name>",
    credential=DefaultAzureCredential(),
)
openai = project.get_openai_client()

# Was: client.agents.create_agent(model=..., name=..., instructions=..., tools=...)
agent = project.agents.create_version(
    agent_name="my-agent",
    definition=PromptAgentDefinition(
        model="gpt-4.1",
        instructions="You politely help with math questions.",
        tools=[CodeInterpreterTool()],
    ),
)

# Was: client.agents.threads.create(...)
conversation = openai.conversations.create(
    items=[{"type": "message", "role": "user", "content": "I need help with a math question."}],
    metadata={"agent": "my-agent"},
)

# Was: runs.create(...) plus a polling loop
response = openai.responses.create(
    input="Draw a graph for a line with a slope of 4 and y-intercept of 9.",
    conversation=conversation.id,
    extra_body={"agent_reference": {"name": "my-agent", "type": "agent_reference"}},
)

Agent creation stays on the project client. Conversations and responses go through the OpenAI client from get_openai_client(); calling conversations.create() on the project client raises an AttributeError, which the guide lists as a troubleshooting case.

Use the guide's own checks as the acceptance test in your change record: create_version() returns an id and a version, a conversation returns output items, and a second response in the same conversation remembers the first.

First step: list every classic agent in your tenant

Start with the Foundry resources you can read across subscriptions:

az extension add --name resource-graph
az graph query -q "resources | where type =~ 'microsoft.cognitiveservices/accounts' and kind =~ 'AIServices' | project name, resourceGroup, subscriptionId"

Projects live inside those resources. If you also have older hub-based projects, they won't appear in that query, so list them separately in the portal. Then list the classic agents in each project:

# pip install azure-ai-agents azure-identity
import os
from azure.identity import DefaultAzureCredential
from azure.ai.agents import AgentsClient

client = AgentsClient(
    endpoint=os.environ["PROJECT_ENDPOINT"],
    credential=DefaultAzureCredential(),
)

for agent in client.list_agents():
    tools = agent.tools or []
    print(agent.id, agent.name, agent.model, len(tools), sorted({t.type for t in tools}))

Point PROJECT_ENDPOINT at one project at a time. The output gives you the name, model and tool types to paste into the register, plus a tool count to compare against 128. Check any azure_function, connected agent or deep research tool first, because those are the ones without a straight swap.

For anyone running agents in production, a retirement you inventory in October is a scheduled change, and one you discover in March is an incident.

← More in Service Management