Procedura per scrivere un agente in .NET che, per rispondere, chiama una funzione C# scritta da te. Il modello non conosce il magazzino: sa solo che esiste una funzione per leggerlo, e decide da sé quando chiamarla e con quale argomento.

È il seguito della guida Distribuire un modello su Microsoft Foundry e chiamarlo da .NET: lì il modello rispondeva e basta, qui usa uno strumento.

Occorre: un account Azure con una sottoscrizione attiva, .NET 10 e l'interfaccia a riga di comando di Azure sul computer. Durata: circa quindici minuti. Costo: si paga a consumo sui token; la distribuzione Global Standard non ha un canone fisso. Le prove di questa guida usano poche migliaia di token.

Il portale delle schermate è in inglese: i nomi dei comandi sono riportati come appaiono a schermo.

Preparare il modello

La creazione dal portale è descritta passo per passo nella guida su Foundry. Qui si fa tutto da riga di comando, dopo az login.

1. Crea il gruppo e la risorsa Foundry

az group create -n rg-guide-agent-01 -l swedencentral

az cognitiveservices account create \
  --name foundry-guide-agent-01 \
  --resource-group rg-guide-agent-01 \
  --kind AIServices --sku S0 --location swedencentral \
  --custom-domain foundry-guide-agent-01 --yes

--custom-domain dà alla risorsa un indirizzo suo, foundry-guide-agent-01.openai.azure.com, che è quello usato dal programma. Il nome deve essere unico in tutta Azure.

La risorsa Foundry appena creata

2. Distribuisci il modello

az cognitiveservices account deployment create \
  --name foundry-guide-agent-01 \
  --resource-group rg-guide-agent-01 \
  --deployment-name gpt-5-mini \
  --model-name gpt-5-mini --model-version 2025-08-07 --model-format OpenAI \
  --sku-name GlobalStandard --sku-capacity 10

3. Dai il permesso a te stesso

Il programma entra con la tua identità, senza chiavi. Serve un ruolo sulla risorsa:

ID=$(az ad signed-in-user show --query id -o tsv)
RISORSA=$(az cognitiveservices account show -n foundry-guide-agent-01 -g rg-guide-agent-01 --query id -o tsv)

az role assignment create --assignee-object-id $ID --assignee-principal-type User \
  --role "Cognitive Services OpenAI User" --scope $RISORSA

L'agente

4. Crea il progetto

dotnet new console -n agent-demo
cd agent-demo
dotnet add package Azure.Identity --version 1.21.0
dotnet add package Microsoft.Agents.AI.OpenAI --version 1.28.0

Microsoft.Agents.AI.OpenAI porta con sé il resto: il pacchetto OpenAI per parlare con il modello e Microsoft.Extensions.AI per descrivere gli strumenti.

5. Scrivi il codice

Sostituisce Program.cs:

using System.ClientModel.Primitives;
using System.ComponentModel;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI;
using OpenAI.Chat;

#pragma warning disable OPENAI001

const string endpoint = "https://foundry-guide-agent-01.openai.azure.com/openai/v1";
const string deployment = "gpt-5-mini";

BearerTokenPolicy tokenPolicy = new(
    new DefaultAzureCredential(),
    "https://cognitiveservices.azure.com/.default");

ChatClient chat = new(
    deployment,
    tokenPolicy,
    new OpenAIClientOptions { Endpoint = new Uri(endpoint) });

AIAgent agent = chat.AsAIAgent(
    instructions: "You answer questions about the shop stock. "
                + "Always use the GetStock tool: never guess quantities or prices.",
    name: "ShopAssistant",
    tools: [AIFunctionFactory.Create(Shop.GetStock)]);

string question = args.Length > 0
    ? string.Join(' ', args)
    : "How many monitors are left, and how much do two of them cost?";

Console.WriteLine($"Question: {question}\n");
AgentResponse answer = await agent.RunAsync(question);
Console.WriteLine($"\nAnswer: {answer.Text}");

static class Shop
{
    static readonly Dictionary<string, (int Stock, decimal Price)> Items =
        new(StringComparer.OrdinalIgnoreCase)
        {
            ["Keyboard"] = (12, 49.90m),
            ["Monitor"] = (3, 199.00m),
            ["Network cable"] = (40, 7.50m),
        };

    [Description("Returns how many pieces of an item are in stock and the price of one piece, in euro.")]
    public static string GetStock([Description("The item name, for example Monitor")] string item)
    {
        Console.WriteLine($"  [tool] GetStock(\"{item}\")");
        return Items.TryGetValue(item, out var i)
            ? $"{i.Stock} in stock, {i.Price:0.00} euro each"
            : $"No item called {item}";
    }
}

Le parti che contano:

  • AsAIAgent trasforma il client del modello in un agente, con le istruzioni e l'elenco degli strumenti.
  • AIFunctionFactory.Create(Shop.GetStock) descrive la funzione al modello: nome, parametri e soprattutto i testi di [Description]. Il modello non vede il codice, vede solo quelle descrizioni: è da lì che capisce a cosa serve la funzione e cosa passarle.
  • Quando il modello decide di usare lo strumento, è l'agente a chiamare GetStock sul tuo computer e a rimandargli il risultato. Il dizionario del magazzino non lascia mai il programma: al modello arriva solo la riga che la funzione restituisce.
  • La riga [tool] stampata dalla funzione serve a vedere quando e con cosa viene chiamata.

6. Esegui

dotnet run
Question: How many monitors are left, and how much do two of them cost?

  [tool] GetStock("Monitor")

Answer: There are 3 monitors left. At €199.00 each, two cost €398.00.

La domanda dice «monitors», al plurale; il modello ha chiamato la funzione con Monitor, come suggerito dalla descrizione del parametro, e ha fatto da sé il conto.

7. Due articoli nella stessa domanda

La domanda si passa come argomento:

dotnet run -- "I need one keyboard and two network cables. Are they in stock, and what is the total?"
  [tool] GetStock("Keyboard")
  [tool] GetStock("Network cable")

Answer: Yes — both are in stock.

- Keyboard: 12 in stock, €49.90 each.
- Network cable: 40 in stock, €7.50 each.

Total for 1 keyboard + 2 network cables = €49.90 + 2×€7.50 = €64.90.

Il modello ha chiamato la funzione due volte, una per articolo, e poi ha sommato.

8. Un articolo che non c'è

dotnet run -- "Do you have a mouse?"
  [tool] GetStock("Mouse")

Answer: I don't have an item called exactly "Mouse" in the stock database.

Il modello ha comunque chiesto alla funzione invece di inventare: è l'effetto della frase «never guess» nelle istruzioni.

Le risposte del modello cambiano un po' da un'esecuzione all'altra; le chiamate alla funzione e i numeri restano quelli.

Eliminare le risorse

9. Elimina il gruppo di risorse

Il gruppo contiene solo la risorsa Foundry, con la distribuzione dentro.

Il gruppo con la risorsa Foundry

az group delete -n rg-guide-agent-01 --yes

Nomi dei comandi, codice e risposte rilevati l'8 novembre 2026, regione Sweden Central, con .NET 10.0.401, Microsoft Agent Framework 1.28.0 e l'interfaccia a riga di comando di Azure 2.91.0.