In lesson 2.4 you built reise-helfer in the portal. Now an application is supposed to call it. The same four NuGet packages as in lesson 2.3 (Azure.AI.Projects, Azure.AI.Projects.Agents, Azure.AI.Extensions.OpenAI, Azure.Identity), the same sign-in with az login and DefaultAzureCredential, the same project endpoint. Only the client is a different one. The code is not run against Azure; this is how Microsoft Learn shows it. An answer of the agent is therefore not printed anywhere. For the exam and for Python, the note from lesson 2.3 applies.
Part 1: create an agent version
Learn shows how to create an agent version in code in C#. The code is Learn's example "Create an agent". Only the project endpoint, the agent name and Nordlicht's deployment name are changed. Long lines are wrapped, nothing else is changed.
using Azure.Identity;
using Azure.AI.Projects;
using Azure.AI.Projects.Agents;
using Azure.AI.Extensions.OpenAI;
// Format: "https://resource_name.services.ai.azure.com/api/projects/project_name"
var foundryProjectEndpoint =
"https://foundry-nordlicht.services.ai.azure.com/api/projects/nordlicht-ki";
var foundryAgentName = "reise-helfer";
// Create project client to call Foundry API
AIProjectClient projectClient = new(
endpoint: new Uri(foundryProjectEndpoint),
tokenProvider: new DefaultAzureCredential());
// Create an agent with a model and instructions
ProjectsAgentDefinition agentDefinition =
new DeclarativeAgentDefinition("reise-chat") // supports all Foundry direct models
{
Instructions = "You are a helpful assistant that answers general questions",
};
ProjectsAgentVersion agent =
projectClient.AgentAdministrationClient.CreateAgentVersion(
foundryAgentName,
options: new(agentDefinition));
Console.WriteLine(
$"Agent created (id: {agent.Id}, name: {agent.Name}, version: {agent.Version})");
Line by line
AIProjectClientwith endpoint andDefaultAzureCredential: as in lesson 2.3.DeclarativeAgentDefinition("reise-chat"): the definition of a prompt agent. The parameter is the model, here the deployment name.Instructions: the instructions. At Learn there is a general sentence in English.AgentAdministrationClient.CreateAgentVersion(…): creates a new version of the agent with this name. If the agent does not exist yet, it comes into being with the first version, otherwise a version is added. That is what Learn's comment says: "Create the agent (or a new version, if it already exists)".Console.WriteLine: according to Learn, writes ID, name and version number to the console.
Careful at Nordlicht: Whoever starts the example unchanged creates a version with Learn's general instruction. By default the agent's address serves the latest version (lesson 2.4): Then the limits from the pilot's instructions no longer apply. For Nordlicht, the instructions from lesson 2.4 belong in this string. And: Learn's example creates a version at every start.
Part 2: holding a conversation
The second part of Learn's example is in the same file. It begins as above and additionally has using OpenAI.Responses; and the line #pragma warning disable OPENAI001 (as in lesson 2.3). After creating the version, this follows:
// Create a conversation for multi-turn chat
ProjectConversation conversation = projectClient.ProjectOpenAIClient
.GetProjectConversationsClient()
.CreateProjectConversation();
// Chat with the agent to answer questions
ProjectResponsesClient responsesClient =
projectClient.ProjectOpenAIClient.GetProjectResponsesClientForAgent(
defaultAgent: foundryAgentName,
defaultConversationId: conversation.Id);
ResponseResult response = responsesClient.CreateResponse(
"What is the size of France in square miles?");
Console.WriteLine(response.GetOutputText());
// Ask a follow-up question in the same conversation
response = responsesClient.CreateResponse("And what is the capital city?");
Console.WriteLine(response.GetOutputText());
The questions about France are Learn's sample questions. Made-up questions of your own about a hotel fit better; the second should refer to the first.
CreateProjectConversation(): creates a conversation, the history of a dialog.GetProjectResponsesClientForAgent(defaultAgent, defaultConversationId): a Responses client that is bound to the agent and to this conversation. In lesson 2.3 it was bound to a deployment.CreateResponse(…): asks the question. The call here is notasync; Learn shows the simple form in this example.- The follow-up "And what is the capital city?" does not name France. It works because the client uses the same conversation: According to Learn, the history is kept across the calls, and the answer to the follow-up shows this.
What a conversation holds on to
- Foundry appends questions and answers to the conversation when one is used (Learn on prompt agents). The service manages conversations, tool calls and the lifecycle of the agent.
- The history lies in the service. Whoever wants to use their own resources, for example Azure Cosmos DB for the conversation state, can set that up according to Learn ("Use your own resources").
- How long conversations are kept and how large a history may become is open: Learn does not name it on these pages.
For Nordlicht this means: A conversation can contain names and wishes of customers. Where it lies and for how long belongs to the data protection review before the pilot operation (lesson 1.1), not to the developers' discretion.
Cleaning up and reusing
Learn's C# example does not clean up. The TypeScript version of the same page deletes the conversation and the agent version at the end; for the corresponding C# methods the page names nothing, that is open. Deleting because of test leftovers still makes sense: Learn points out that earlier versions remain callable until they are deleted, even if the address points to a newer one. Whoever wants to remove unsafe configurations deletes the versions and checks that they are gone.
For reusing, Learn advises (lifecycle): Create an agent once, remember name and ID and use them in later runs. Do not create it anew at every start. If a request for a previously created agent returns "404 Not Found", it was deleted. Then you create it anew and do not endlessly try the same ID.
A test project that you want to remove entirely you delete through the resource group, as in lesson 2.1.
A person checks every answer
The code shows: The agent's answer sits as text in a variable. What happens with it is decided by the application. At Nordlicht it never writes the text directly to customers, but presents it as a draft: A person in customer service checks every answer before it goes out. No model decides on refunds, cancellations or contract questions. That is the pilot's limit from lesson 1.1, and no code in this lesson lifts it.
Summary table
| Task | Building block |
|---|---|
| create an agent version | AgentAdministrationClient.CreateAgentVersion |
| create a history | CreateProjectConversation |
| talk with agent and history | GetProjectResponsesClientForAgent |
| ask | CreateResponse, text with GetOutputText |
| sign-in | DefaultAzureCredential after az login |
Exercise 1
Nordlicht starts the program from parts 1 and 2 every morning for a test. After a week there are many versions of reise-helfer in the project. Answer:
- Why do they come into being?
- Which sentence in the example code causes it?
- What does Nordlicht change in the program?
Solution 1
- Every call of
CreateAgentVersioncreates a new version. According to Learn, every change of the configuration creates a new, immutable version. - The call
CreateAgentVersionat the beginning of the program. Learn's comment says it creates the agent "or a new version, if it already exists". - Creating is separated from chatting: The agent is created once (or built in the portal), after that the program uses only conversation and Responses client. Old test versions are deleted. How exactly to delete them in C# is open: The TypeScript version shows deleting, for C# the page names no call.