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.
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:
No comments:
Post a Comment