Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Os agentes do Microsoft Foundry dão suporte à chamada de função, que permite estender agentes com recursos personalizados. Defina uma função com seu nome, parâmetros e descrição, e o agente pode solicitar que seu aplicativo a chame. Seu aplicativo executa a função e retorna a saída. Em seguida, o agente usa o resultado para continuar a conversa com dados precisos e em tempo real de seus sistemas.
Importante
Execuções expiram 10 minutos após a criação. Envie os resultados da ferramenta antes que expirem.
Você pode executar agentes com ferramentas de função no portal do Microsoft Foundry. No entanto, o portal não dá suporte à adição, remoção ou atualização de definições de função em um agente. Use o SDK ou a API REST para configurar ferramentas de função.
Suporte de uso
✔️ (GA) indica disponibilidade geral, ✔️ (versão prévia) indica visualização pública e um traço (-) indica que o recurso não está disponível.
| Suporte ao Microsoft Foundry | SDK do Python | SDK do C# | SDK do JavaScript | Java SDK | API REST | Configuração básica do agente | Configuração do agente padrão |
|---|---|---|---|---|---|---|---|
| ✔️ | ✔️ (Versão prévia) | ✔️ (Versão prévia) | ✔️ (Versão prévia) | - | ✔️ (GA) | ✔️ | ✔️ |
Observação
Atualmente, o SDK do Java não dá suporte à chamada de função com as novas APIs do agente (azure-ai-projects pacote). O suporte a Java está disponível apenas para as APIs de agente clássico. Para exemplos de chamada de função Java com agentes clássicos, consulte a documentação do agente clássico.
Pré-requisitos
Antes de começar, verifique se você tem:
Um projeto do Foundry e um modelo implantado.
O pacote do SDK de pré-lançamento mais recente para seu idioma:
- Python:
azure-ai-projects>=2.0.0b4 - .NET:
Azure.AI.Projects.OpenAI(pré-lançamento) - TypeScript:
@azure/ai-projects(beta mais recente)
Para obter as etapas de instalação e autenticação, consulte o início rápido.
- Python:
Variáveis de ambiente
Cada idioma usa nomes de variáveis de ambiente diferentes. Use um conjunto de forma consistente.
| Linguagem | Endpoint do projeto | Nome da implantação do modelo |
|---|---|---|
| Python | FOUNDRY_PROJECT_ENDPOINT |
FOUNDRY_MODEL_DEPLOYMENT_NAME |
| C# | FOUNDRY_PROJECT_ENDPOINT |
FOUNDRY_MODEL_DEPLOYMENT_NAME |
| TypeScript | FOUNDRY_PROJECT_ENDPOINT |
FOUNDRY_MODEL_DEPLOYMENT_NAME |
| API REST | FOUNDRY_PROJECT_ENDPOINT |
(campo use o corpo da solicitação) |
Dica
Se você usar DefaultAzureCredential, entre usando az login antes de executar os exemplos.
Verificação rápida
Se você não tiver certeza de que sua autenticação e ponto de extremidade tenham sido configurados corretamente, primeiro execute o trecho a seguir.
import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from dotenv import load_dotenv
load_dotenv()
with (
DefaultAzureCredential() as credential,
AIProjectClient(endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"], credential=credential) as project_client,
):
print("Connected to project.")
Criar um agente com ferramentas de função
A chamada de função segue este padrão:
- Definir ferramentas de função — Descreva o nome, os parâmetros e a finalidade de cada função.
- Criar um agente – registre o agente com suas definições de função.
- Enviar um prompt – o agente analisa o prompt e solicita chamadas de função, se necessário.
- Executar e retornar – seu aplicativo executa a função e envia a saída de volta para o agente.
- Obter a resposta final – o agente usa a saída da função para concluir sua resposta.
Observação
Você precisa do pacote de pré-lançamento mais recente. Para obter mais informações, confira o Início Rápido.
Use o exemplo de código a seguir para criar um agente, manipular uma chamada de função e retornar a saída da ferramenta para o agente.
import os
import json
from dotenv import load_dotenv
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import PromptAgentDefinition, Tool, FunctionTool
from azure.identity import DefaultAzureCredential
from openai.types.responses.response_input_param import FunctionCallOutput, ResponseInputParam
load_dotenv()
def get_horoscope(sign: str) -> str:
"""Generate a horoscope for the given astrological sign."""
return f"{sign}: Next Tuesday you will befriend a baby otter."
endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
with (
DefaultAzureCredential() as credential,
AIProjectClient(endpoint=endpoint, credential=credential) as project_client,
project_client.get_openai_client() as openai_client,
):
# Define a function tool for the model to use
func_tool = FunctionTool(
name="get_horoscope",
parameters={
"type": "object",
"properties": {
"sign": {
"type": "string",
"description": "An astrological sign like Taurus or Aquarius",
},
},
"required": ["sign"],
"additionalProperties": False,
},
description="Get today's horoscope for an astrological sign.",
strict=True,
)
tools: list[Tool] = [func_tool]
agent = project_client.agents.create_version(
agent_name="MyAgent",
definition=PromptAgentDefinition(
model=os.environ["FOUNDRY_MODEL_DEPLOYMENT_NAME"],
instructions="You are a helpful assistant that can use function tools.",
tools=tools,
),
)
# Prompt the model with tools defined
response = openai_client.responses.create(
input="What is my horoscope? I am an Aquarius.",
extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
)
print(f"Response output: {response.output_text}")
input_list: ResponseInputParam = []
# Process function calls
for item in response.output:
if item.type == "function_call":
if item.name == "get_horoscope":
# Execute the function logic for get_horoscope
horoscope = get_horoscope(**json.loads(item.arguments))
# Provide function call results to the model
input_list.append(
FunctionCallOutput(
type="function_call_output",
call_id=item.call_id,
output=json.dumps({"horoscope": horoscope}),
)
)
print("Final input:")
print(input_list)
response = openai_client.responses.create(
input=input_list,
previous_response_id=response.id,
extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
)
print(f"Agent response: {response.output_text}")
print("\nCleaning up...")
project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
print("Agent deleted")
Resultado esperado
O seguinte exemplo mostra a saída esperada:
Response output:
Final input:
[FunctionCallOutput(type='function_call_output', call_id='call_abc123', output='{"horoscope": "Aquarius: Next Tuesday you will befriend a baby otter."}')]
Usar agentes com exemplo de funções
Neste exemplo, você usa funções locais com agentes. Use as funções para fornecer ao Agente informações específicas em resposta a uma pergunta do usuário. O código neste exemplo é síncrono. Para obter um exemplo assíncrono, consulte o exemplo de código de exemplo no SDK do Azure para repositório .NET no GitHub.
class FunctionCallingDemo
{
// Define three functions:
// 1. GetUserFavoriteCity always returns "Seattle, WA".
// 2. GetCityNickname handles only "Seattle, WA"
// and throws an exception for other city names.
// 3. GetWeatherAtLocation returns the weather in Seattle, WA.
/// Example of a function that defines no parameters but
/// returns the user's favorite city.
private static string GetUserFavoriteCity() => "Seattle, WA";
/// <summary>
/// Example of a function with a single required parameter
/// </summary>
/// <param name="location">The location to get nickname for.</param>
/// <returns>The city nickname.</returns>
/// <exception cref="NotImplementedException"></exception>
private static string GetCityNickname(string location) => location switch
{
"Seattle, WA" => "The Emerald City",
_ => throw new NotImplementedException(),
};
/// <summary>
/// Example of a function with one required and one optional, enum parameter
/// </summary>
/// <param name="location">Get weather for location.</param>
/// <param name="temperatureUnit">"c" or "f"</param>
/// <returns>The weather in selected location.</returns>
/// <exception cref="NotImplementedException"></exception>
public static string GetWeatherAtLocation(string location, string temperatureUnit = "f") => location switch
{
"Seattle, WA" => temperatureUnit == "f" ? "70f" : "21c",
_ => throw new NotImplementedException()
};
// For each function, create FunctionTool, which defines the function name, description, and parameters.
public static readonly FunctionTool getUserFavoriteCityTool = ResponseTool.CreateFunctionTool(
functionName: "getUserFavoriteCity",
functionDescription: "Gets the user's favorite city.",
functionParameters: BinaryData.FromString("{}"),
strictModeEnabled: false
);
public static readonly FunctionTool getCityNicknameTool = ResponseTool.CreateFunctionTool(
functionName: "getCityNickname",
functionDescription: "Gets the nickname of a city, e.g. 'LA' for 'Los Angeles, CA'.",
functionParameters: BinaryData.FromObjectAsJson(
new
{
Type = "object",
Properties = new
{
Location = new
{
Type = "string",
Description = "The city and state, e.g. San Francisco, CA",
},
},
Required = new[] { "location" },
},
new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }
),
strictModeEnabled: false
);
private static readonly FunctionTool getCurrentWeatherAtLocationTool = ResponseTool.CreateFunctionTool(
functionName: "getCurrentWeatherAtLocation",
functionDescription: "Gets the current weather at a provided location.",
functionParameters: BinaryData.FromObjectAsJson(
new
{
Type = "object",
Properties = new
{
Location = new
{
Type = "string",
Description = "The city and state, e.g. San Francisco, CA",
},
Unit = new
{
Type = "string",
Enum = new[] { "c", "f" },
},
},
Required = new[] { "location" },
},
new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }
),
strictModeEnabled: false
);
// Create the method GetResolvedToolOutput.
// It runs the preceding functions and wraps the output in a ResponseItem object.
private static FunctionCallOutputResponseItem GetResolvedToolOutput(FunctionCallResponseItem item)
{
if (item.FunctionName == getUserFavoriteCityTool.FunctionName)
{
return ResponseItem.CreateFunctionCallOutputItem(item.CallId, GetUserFavoriteCity());
}
using JsonDocument argumentsJson = JsonDocument.Parse(item.FunctionArguments);
if (item.FunctionName == getCityNicknameTool.FunctionName)
{
string locationArgument = argumentsJson.RootElement.GetProperty("location").GetString();
return ResponseItem.CreateFunctionCallOutputItem(item.CallId, GetCityNickname(locationArgument));
}
if (item.FunctionName == getCurrentWeatherAtLocationTool.FunctionName)
{
string locationArgument = argumentsJson.RootElement.GetProperty("location").GetString();
if (argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unitElement))
{
string unitArgument = unitElement.GetString();
return ResponseItem.CreateFunctionCallOutputItem(item.CallId, GetWeatherAtLocation(locationArgument, unitArgument));
}
return ResponseItem.CreateFunctionCallOutputItem(item.CallId, GetWeatherAtLocation(locationArgument));
}
return null;
}
public static void Main()
{
// Create project client and read the environment variables that will be used in the next steps.
var projectEndpoint = System.Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT");
var modelDeploymentName = System.Environment.GetEnvironmentVariable("FOUNDRY_MODEL_DEPLOYMENT_NAME");
AIProjectClient projectClient = new(endpoint: new Uri(projectEndpoint), tokenProvider: new DefaultAzureCredential());
// Create an agent version with the defined functions as tools.
PromptAgentDefinition agentDefinition = new(model: modelDeploymentName)
{
Instructions = "You are a weather bot. Use the provided functions to help answer questions. "
+ "Customize your responses to the user's preferences as much as possible and use friendly "
+ "nicknames for cities whenever possible.",
Tools = { getUserFavoriteCityTool, getCityNicknameTool, getCurrentWeatherAtLocationTool }
};
AgentVersion agentVersion = projectClient.Agents.CreateAgentVersion(
agentName: "myAgent",
options: new(agentDefinition));
// If the local function call is required, the response item is of type FunctionCallResponseItem.
// It contains the function name needed by the Agent. In this case, use the helper method
// GetResolvedToolOutput to get the FunctionCallOutputResponseItem with the function call result.
// To provide the right answer, supply all the response items to the CreateResponse call.
// At the end, output the function's response.
ResponsesClient responseClient = projectClient.OpenAI.GetProjectResponsesClientForAgent(agentVersion.Name);
ResponseItem request = ResponseItem.CreateUserMessageItem("What's the weather like in my favorite city?");
var inputItems = new List<ResponseItem> { request };
string previousResponseId = null;
bool functionCalled = false;
ResponseResult response;
do
{
response = responseClient.CreateResponse(
previousResponseId: previousResponseId,
inputItems: inputItems);
previousResponseId = response.Id;
inputItems.Clear();
functionCalled = false;
foreach (ResponseItem responseItem in response.OutputItems)
{
inputItems.Add(responseItem);
if (responseItem is FunctionCallResponseItem functionToolCall)
{
Console.WriteLine($"Calling {functionToolCall.FunctionName}...");
inputItems.Add(GetResolvedToolOutput(functionToolCall));
functionCalled = true;
}
}
} while (functionCalled);
Console.WriteLine(response.GetOutputText());
// Remove all the resources created in this sample.
projectClient.Agents.DeleteAgentVersion(agentName: agentVersion.Name, agentVersion: agentVersion.Version);
}
}
Resultado esperado
O seguinte exemplo mostra a saída esperada:
Calling getUserFavoriteCity...
Calling getCityNickname...
Calling getCurrentWeatherAtLocation...
Your favorite city, Seattle, WA, is also known as The Emerald City. The current weather there is 70f.
Há duas maneiras de usar a chamada de função no Serviço do Foundry Agent.
- Crie um
response. Quando você precisar que o agente chame funções novamente, crie outraresponse. - Crie um
conversatione, em seguida, crie vários itens de conversa. Cada item de conversa corresponde a umresponse.
Defina as seguintes variáveis de ambiente antes de executar os exemplos:
export AGENT_TOKEN=$(az account get-access-token --scope "https://ai.azure.com/.default" --query accessToken -o tsv)
Defina uma função para o agente chamar
Comece definindo uma função para seu agente chamar. Quando você cria uma função para um agente chamar, descreva sua estrutura e todos os parâmetros necessários em um docstring. Para obter funções de exemplo, consulte os outros idiomas do SDK.
Criar um agente
curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/agents?api-version=v1" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AGENT_TOKEN" \
-d '{
"name": "<AGENT_NAME>-function-calling",
"description": "Agent with function calling",
"definition": {
"kind": "prompt",
"model": "<MODEL_DEPLOYMENT>",
"instructions": "You are a helpful agent.",
"tools": [
{
"type": "function",
"name": "getCurrentWeather",
"description": "Get the current weather in a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "The city and state e.g. San Francisco, CA"},
"unit": {"type": "string", "enum": ["c", "f"]}
},
"required": ["location"]
}
}
]
}
}'
Criar uma conversa
curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/conversations" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AGENT_TOKEN" \
-d '{
"items": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "What'\''s the weather in Dar es Salaam, Tanzania?"
}
]
}
]
}'
Salve a ID da conversa retornada (conv_xyz...) para a próxima etapa.
Criar uma resposta
Substitua <CONVERSATION_ID> pela ID da etapa anterior.
curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/responses" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AGENT_TOKEN" \
-d '{
"agent": {"type": "agent_reference", "name": "<AGENT_NAME>-function-calling"},
"conversation": "<CONVERSATION_ID>",
"input": []
}'
Resultado esperado
A resposta contém um item de chamada de função que você precisa processar:
{
"output": [
{
"type": "function_call",
"call_id": "call_xyz789",
"name": "getCurrentWeather",
"arguments": "{\"location\": \"Dar es Salaam, Tanzania\", \"unit\": \"c\"}"
}
]
}
Depois de processar a chamada de função e retornar a saída ao agente, a resposta final apresenta as informações meteorológicas em linguagem natural.
Use o exemplo de código a seguir para criar um agente com ferramentas de função, manipular chamadas de função do modelo e fornecer resultados de função para obter a resposta final.
import { DefaultAzureCredential } from "@azure/identity";
import { AIProjectClient } from "@azure/ai-projects";
import "dotenv/config";
const projectEndpoint = process.env["FOUNDRY_PROJECT_ENDPOINT"] || "<project endpoint>";
const deploymentName = process.env["FOUNDRY_MODEL_DEPLOYMENT_NAME"] || "<model deployment name>";
/**
* Define a function tool for the model to use
*/
const funcTool = {
type: "function" as const,
name: "get_horoscope",
description: "Get today's horoscope for an astrological sign.",
strict: true,
parameters: {
type: "object",
properties: {
sign: {
type: "string",
description: "An astrological sign like Taurus or Aquarius",
},
},
required: ["sign"],
additionalProperties: false,
},
};
/**
* Generate a horoscope for the given astrological sign.
*/
function getHoroscope(sign: string): string {
return `${sign}: Next Tuesday you will befriend a baby otter.`;
}
export async function main(): Promise<void> {
// Create AI Project client
const project = new AIProjectClient(projectEndpoint, new DefaultAzureCredential());
const openAIClient = await project.getOpenAIClient();
// Create agent with function tools
console.log("Creating agent with function tools...");
const agent = await project.agents.createVersion("function-tool-agent", {
kind: "prompt",
model: deploymentName,
instructions: "You are a helpful assistant that can use function tools.",
tools: [funcTool],
});
console.log(`Agent created (id: ${agent.id}, name: ${agent.name}, version: ${agent.version})`);
// Prompt the model with tools defined
console.log("\nGenerating initial response...");
const response = await openAIClient.responses.create(
{
input: [
{
type: "message",
role: "user",
content: "What is my horoscope? I am an Aquarius.",
},
],
},
{
body: { agent: { name: agent.name, type: "agent_reference" } },
},
);
console.log(`Response output: ${response.output_text}`);
// Process function calls
const inputList: Array<{
type: "function_call_output";
call_id: string;
output: string;
}> = [];
for (const item of response.output) {
if (item.type === "function_call") {
if (item.name === "get_horoscope") {
// Parse the function arguments
const args = JSON.parse(item.arguments);
// Execute the function logic for get_horoscope
const horoscope = getHoroscope(args.sign);
// Provide function call results to the model
inputList.push({
type: "function_call_output",
call_id: item.call_id,
output: JSON.stringify({ horoscope }),
});
}
}
}
console.log("\nFinal input:");
console.log(JSON.stringify(inputList, null, 2));
// Submit function results to get final response
const finalResponse = await openAIClient.responses.create(
{
input: inputList,
previous_response_id: response.id,
},
{
body: { agent: { name: agent.name, type: "agent_reference" } },
},
);
// The model should be able to give a response!
console.log("\nFinal output:");
console.log(finalResponse.output_text);
// Clean up
console.log("\nCleaning up resources...");
await project.agents.deleteVersion(agent.name, agent.version);
console.log("Agent deleted");
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});
Resultado esperado
O seguinte exemplo mostra a saída esperada:
Creating agent with function tools...
Agent created (id: <agent-id>, name: function-tool-agent, version: <version>)
Generating initial response...
Response output:
Final input:
[
{
"type": "function_call_output",
"call_id": "call_abc123",
"output": "{\"horoscope\":\"Aquarius: Next Tuesday you will befriend a baby otter.\"}"
}
]
Final output:
Your horoscope for Aquarius: Next Tuesday you will befriend a baby otter.
Cleaning up resources...
Agent deleted
Verificar se a chamada de função funciona
Utilize estas verificações para confirmar se a chamada de função está funcionando:
- Sua primeira resposta contém um item de saída com
typedefinido comofunction_call. - Seu aplicativo executa a função solicitada usando os argumentos retornados.
- Seu aplicativo envia uma resposta de acompanhamento que inclui um
function_call_outputitem e faz referência à resposta anterior e o agente retorna uma resposta de linguagem natural.
Se você usar o rastreamento no Microsoft Foundry, confirme se a invocação da ferramenta ocorreu. Para obter diretrizes sobre como validar a invocação de ferramentas e controlar o uso de ferramentas, consulte As práticas recomendadas para usar ferramentas no Serviço do Microsoft Foundry Agent.
Considerações sobre segurança e dados
- Trate argumentos de ferramenta e saídas de ferramenta como entrada não confiável. Valide e sanifique os valores antes de usá-los.
- Não passe segredos (chaves de API, tokens, cadeias de conexão) na saída da ferramenta. Retornar somente os dados de que o modelo precisa.
- Aplicar o princípio de privilégios mínimos à identidade usada por
DefaultAzureCredential. - Evite efeitos colaterais, a menos que você os pretenda explicitamente. Por exemplo, restrinja as ferramentas de função a operações seguras ou exija confirmação explícita do usuário para ações que alterem dados.
- Para operações de execução prolongada, retorne um status imediatamente e implemente a sondagem. A expiração de execução de 10 minutos se aplica ao tempo total decorrido, não à execução de função individual.
Resolução de problemas
| Questão | Causa provável | Resolução |
|---|---|---|
| O agente retorna a chamada de função, mas não fornece uma resposta final. | A saída da ferramenta não foi retornada ao modelo. | Execute a função, em seguida, chame responses.create com a saída da ferramenta e previous_response_id para continuar. |
| Nenhuma chamada de função ocorre. | A função não está na definição do agente ou possui um nome inadequado. | Verifique se a ferramenta funcional foi adicionada ao agente. Use nomes e descrições de parâmetros claros e descritivos. |
| Os argumentos não são JSON válidos. | Incompatibilidade de esquema ou alucinação de modelo. | Verifique se o esquema JSON usa tipos corretos e propriedades necessárias. Trate erros de parsing de forma elegante em seu aplicativo. |
| Campos obrigatórios estão faltando. | O esquema não impõe as propriedades necessárias. | Adicione "required": [...] matriz ao esquema de parâmetros. Definir strict: true para uma validação mais rigorosa. |
| Os resultados da ferramenta falham devido à expiração. | Execução expirada (limite de 10 minutos). | Retorne prontamente as saídas da ferramenta. Para operações lentas, retorne um status e faça uma consulta separada. |
| Função chamada com parâmetros incorretos. | Descrição da função ambígua. | Melhore o campo description da função. Adicione descrições de parâmetro detalhadas com exemplos. |
| Várias chamadas de função em uma resposta. | O modelo determinou várias funções necessárias. | Manipule cada chamada de função na matriz de saída. Retornar todos os resultados em uma única responses.create chamada. |
| Função não visível no portal do Foundry. | O portal não executa chamadas de função. | Testar a chamada de função por meio do SDK ou da API REST. O portal mostra agentes, mas não invoca funções. |
Limpar os recursos
Ao concluir o teste, exclua os recursos criados para evitar custos contínuos.
Exclua o agente:
curl -X DELETE "$FOUNDRY_PROJECT_ENDPOINT/agents/<AGENT_NAME>-function-calling?api-version=v1" \
-H "Authorization: Bearer $AGENT_TOKEN"
Exclua a conversa:
curl -X DELETE "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/conversations/<CONVERSATION_ID>" \
-H "Authorization: Bearer $AGENT_TOKEN"