Saturday, September 19, 2026

Microsoft Agent Framework: Prompt Agents in Microsoft Foundry with .NET

In this post, let's have a look at prompt agents in Microsoft Foundry, and how we can create and run them with Microsoft Agent Framework.

Some time back I blogged about Getting Started with Microsoft Agent Framework 1.0.0 in .NET. There, the agent was created in code, it lived inside the process, and when the app stopped, so did the agent. Foundry was only providing the model. That's usually called an ephemeral agent.

A prompt agent is the other option and it's a Foundry feature rather than an Agent Framework one. The agent definition, that's the model, the instructions and the tool schemas, is stored in Foundry as a versioned resource. Your code doesn't own it anymore, it just runs it. It shows up in the Foundry portal, it has a playground, every update creates a new version, and any application can run it by name. Agent Framework is how we run it, which is the rest of this post.

One thing that stays the same is tools. Foundry stores only the tool schemas. Your application still executes the tools.

Setup

We need the following packages (latest as of today, it will change).
<PackageReference Include="Azure.AI.Projects.Agents" Version="3.0.0-beta.2" />
<PackageReference Include="Microsoft.Agents.AI.Foundry" Version="1.22.0-preview.260918.1" />

Creating the agent

The tools are the same three methods from the getting started post, plain C# methods with [Description] attributes.
// ResponseTool, used to declare the agent's function tools, is still experimental
#pragma warning disable OPENAI001

// Agent administration lives under the project, so this needs the project endpoint,
// not the resource one the earlier samples use
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT")!;
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL")!;
const string agentName = "weekend-planner-prompt";

// For local development, using AzureCliCredential
var credential = new AzureCliCredential();

AIProjectClient projectClient = new(new Uri(endpoint), credential);

AIFunction[] tools =
[
    AIFunctionFactory.Create(GetWeather, nameof(GetWeather)),
    AIFunctionFactory.Create(GetActivities, nameof(GetActivities)),
    AIFunctionFactory.Create(GetCurrentDate, nameof(GetCurrentDate))
];

// Foundry stores the tool schemas, this app executes the tools
DeclarativeAgentDefinition definition = new(deploymentName)
{
    Instructions = """
        You help users plan their weekends and choose the best activities for the given weather.
        If an activity would be unpleasant in weather, don't suggest it.
        Include date of the weekend in response.
        """
};

foreach (AIFunction tool in tools)
{
    definition.Tools.Add(ResponseTool.CreateFunctionTool(
        tool.Name,
        BinaryData.FromString(tool.JsonSchema.GetRawText()),
        strictModeEnabled: false,
        functionDescription: tool.Description));
}

// Create the agent in Foundry, every run creates a new version of it
ProjectsAgentVersion agentVersion = 
await projectClient.AgentAdministrationClient.CreateAgentVersionAsync( agentName, new ProjectsAgentVersionCreationOptions(definition)); Console.WriteLine($"[Agent] Created '{agentVersion.Name}' version '{agentVersion.Version}'.");
Two things to note here. The tool schema comes straight from AIFunction.JsonSchema, so the [Description] attributes we already write for Agent Framework are what ends up stored in Foundry. And ResponseTool is still experimental, so we need to suppress OPENAI001.

Creating and deleting an agent is the one part that isn't Agent Framework. Every path in the docs goes through AgentAdministrationClient from Azure.AI.Projects.Agents, and that's what we use here.

Once this is executed, we can see our Prompt Agent in Microsoft Foundry.
Prompt Agent

Running the agent in Foundry Playground

The agent is in the project now, with a playground, so that is the first thing to try. And it stops at the first tool call and asks you to enter function output as JSON.
Prompt Agent in Playground
That is the whole point of a prompt agent. Foundry has the tool schemas, it does not have the tools, so the playground has nothing to run and asks you to play the part of the application. Paste what our code would have returned, "2026-09-26" for GetCurrentDate, and it carries on and asks for the next one.

Which is a good reminder that the playground is just another client here. To get actual answers, something has to run the tools, and that is what we do next.

Running the agent

And this is the nice part. Running a prompt agent is exactly the same as running the in-code agent, we just hand over the agent version instead of a model and instructions.
string userInput = "What should I do this weekend in Auckland?";

// Run the version that was just created, the tools are passed in from here
AIAgent agent = projectClient.AsAIAgent(agentVersion, tools: [.. tools]);
AgentResponse response = await agent.RunAsync(userInput);

Console.WriteLine();
Console.WriteLine("--- Agent Response ---");
Console.WriteLine(response.ToString());
The instructions aren't in the run call anymore, they are in Foundry. The tools are, because Foundry only knows their schemas.
[Agent] Created 'weekend-planner-prompt' version '1'.
[Tool] Getting current date
[Tool] Getting weather for 'Auckland'.
[Tool] Getting activities for 'Auckland' on '2026-09-26'.
[Tool] Getting activities for 'Auckland' on '2026-09-27'.

--- Agent Response ---
Weekend in Auckland: Saturday 26 Sep 2026 - Sunday 27 Sep 2026.
Forecast: ~18C and rainy, so indoor plans will work better.
// Omitted for brevity

Running an agent someone else created

Because the agent is a resource now, we don't need to be the one who created it. We can ask Foundry for it by name and run the latest version.
// Or resolve an existing agent by name and run its latest version, no instructions needed here
ProjectsAgentRecord agentRecord = 
await projectClient.AgentAdministrationClient.GetAgentAsync(agentName); AIAgent latestAgent = projectClient.AsAIAgent(agentRecord, tools: [.. tools]);
There is no model, no instructions and no version pinned in this code. All it provides is the tool implementations and the input. Someone can update the instructions in the portal, and the next run picks them up without a code change or a deployment.

Finally, since every run of the sample creates a version, let's clean up after ourselves.
// Delete the agent, remove this to keep it in the project
await projectClient.AgentAdministrationClient.DeleteAgentAsync(agentName);

So which one to use

If the agent ships with your application and nothing else needs to call it, creating it in code is simpler, there is nothing to create, version or delete. If you want the agent to be a thing in its own right, something with versions, a playground, and other applications running it by name, then a prompt agent is what you want.

The complete sample is here.

More read:
   Microsoft Agent Framework: Microsoft Foundry

Hope this helps.

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment