Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
As ferramentas frontend são declaradas e executadas pelo cliente AG-UI. O servidor recebe os seus esquemas para que o modelo os possa solicitar, mas não recebe as suas implementações.
Registar uma ferramenta de interface
Crie a ferramenta e entregue-a ao agente apoiado por AGUIChatClient:
using System.ComponentModel;
using AGUI.Client;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
[Description("Get the user's current location from the client device.")]
static string GetUserLocation() => "Amsterdam, Netherlands";
AITool locationTool = AIFunctionFactory.Create(
GetUserLocation,
name: "get_user_location");
using HttpClient httpClient = new() { BaseAddress = new Uri("http://localhost:8888") };
AGUIChatClient chatClient = new(new AGUIChatClientOptions(httpClient, "/"));
AIAgent agent = chatClient.AsAIAgent(tools: [locationTool]);
AGUIChatClient gere o fluxo de continuação:
- Envia a declaração da ferramenta frontend com o pedido de execução.
- Recebe do servidor a invocação de ferramenta do modelo.
- Executa a função de correspondência localmente.
- Envia o resultado de volta para o servidor.
- Continua a corrida e transmite a resposta final.
Tip
Consulte o exemplo de ferramentas frontend .NET para um cliente e servidor completos.
Warning
As declarações e resultados da ferramenta fornecidos por um cliente não confiável são entradas não confiáveis. Autorizar quais as ferramentas do cliente que podem influenciar a execução do agente do lado do servidor e validar os resultados antes de as utilizar para operações privilegiadas.
Para orientações gerais sobre criação de ferramentas, veja Usar ferramentas funcionais com um agente.
Passos seguintes
Este tutorial mostra como adicionar ferramentas de função de frontend aos seus clientes AG-UI. As ferramentas de front-end são funções que são executadas no lado do cliente, permitindo que o agente de IA interaja com o ambiente local do usuário, acesse dados específicos do cliente ou execute operações de interface do usuário.
Pré-requisitos
Antes de começar, certifique-se de ter concluído o tutorial de Introdução e de ter:
- Python 3.10 ou posterior
-
httpxinstalado para a funcionalidade do cliente HTTP - Compreensão básica da configuração do cliente AG-UI
- Serviço OpenAI do Azure configurado
O que são Frontend Tools?
As ferramentas de front-end são ferramentas de função que:
- São definidos e registados no cliente
- Executar no ambiente do cliente (não no servidor)
- Permitir que o agente de IA interaja com recursos específicos do cliente
- Fornecer resultados de volta ao servidor para que o agente incorpore nas respostas
Casos de uso comuns:
- Leitura de dados do sensor local
- Acesso ao armazenamento ou preferências do lado do cliente
- Executando operações da interface do usuário
- Interagindo com recursos específicos do dispositivo
Criando ferramentas de front-end
As ferramentas de front-end em Python são definidas de forma semelhante às ferramentas de back-end, mas são registradas com o cliente:
from typing import Annotated
from pydantic import BaseModel, Field
class SensorReading(BaseModel):
"""Sensor reading from client device."""
temperature: float
humidity: float
air_quality_index: int
def read_climate_sensors(
include_temperature: Annotated[bool, Field(description="Include temperature reading")] = True,
include_humidity: Annotated[bool, Field(description="Include humidity reading")] = True,
) -> SensorReading:
"""Read climate sensor data from the client device."""
# Simulate reading from local sensors
return SensorReading(
temperature=22.5 if include_temperature else 0.0,
humidity=45.0 if include_humidity else 0.0,
air_quality_index=75,
)
def change_background_color(color: Annotated[str, Field(description="Color name")] = "blue") -> str:
"""Change the console background color."""
# Simulate UI change
print(f"\n🎨 Background color changed to {color}")
return f"Background changed to {color}"
Criando um cliente AG-UI com ferramentas de front-end
Aqui está uma implementação completa do cliente com ferramentas de frontend:
"""AG-UI client with frontend tools."""
import asyncio
import json
import os
from typing import Annotated, AsyncIterator
import httpx
from pydantic import BaseModel, Field
class SensorReading(BaseModel):
"""Sensor reading from client device."""
temperature: float
humidity: float
air_quality_index: int
# Define frontend tools
def read_climate_sensors(
include_temperature: Annotated[bool, Field(description="Include temperature")] = True,
include_humidity: Annotated[bool, Field(description="Include humidity")] = True,
) -> SensorReading:
"""Read climate sensor data from the client device."""
return SensorReading(
temperature=22.5 if include_temperature else 0.0,
humidity=45.0 if include_humidity else 0.0,
air_quality_index=75,
)
def get_user_location() -> dict:
"""Get the user's current GPS location."""
# Simulate GPS reading
return {
"latitude": 52.3676,
"longitude": 4.9041,
"accuracy": 10.0,
"city": "Amsterdam",
}
# Tool registry maps tool names to functions
FRONTEND_TOOLS = {
"read_climate_sensors": read_climate_sensors,
"get_user_location": get_user_location,
}
class AGUIClientWithTools:
"""AG-UI client with frontend tool support."""
def __init__(self, server_url: str, tools: dict):
self.server_url = server_url
self.tools = tools
self.thread_id: str | None = None
async def send_message(self, message: str) -> AsyncIterator[dict]:
"""Send a message and handle streaming response with tool execution."""
# Prepare tool declarations for the server
tool_declarations = []
for name, func in self.tools.items():
tool_declarations.append({
"name": name,
"description": func.__doc__ or "",
# Add parameter schema from function signature
})
request_data = {
"messages": [
{"role": "system", "content": "You are a helpful assistant with access to client tools."},
{"role": "user", "content": message},
],
"tools": tool_declarations, # Send tool declarations to server
}
if self.thread_id:
request_data["thread_id"] = self.thread_id
async with httpx.AsyncClient(timeout=60.0) as client:
async with client.stream(
"POST",
self.server_url,
json=request_data,
headers={"Accept": "text/event-stream"},
) as response:
response.raise_for_status()
async for line in response.aiter_lines():
if line.startswith("data: "):
data = line[6:]
try:
event = json.loads(data)
# Tool calls arrive as TOOL_CALL_START/ARGS/END events
# and results are streamed back as TOOL_CALL_RESULT events.
yield event
# Capture thread_id
if event.get("type") == "RUN_STARTED" and not self.thread_id:
self.thread_id = event.get("threadId")
except json.JSONDecodeError:
continue
async def _handle_tool_call(self, event: dict, client: httpx.AsyncClient):
"""Execute frontend tool and send result back to server."""
tool_name = event.get("toolName")
tool_call_id = event.get("toolCallId")
arguments = event.get("arguments", {})
print(f"\n\033[95m[Client Tool Call: {tool_name}]\033[0m")
print(f" Arguments: {arguments}")
try:
# Execute the tool
tool_func = self.tools.get(tool_name)
if not tool_func:
raise ValueError(f"Unknown tool: {tool_name}")
result = tool_func(**arguments)
# Convert Pydantic models to dict
if hasattr(result, "model_dump"):
result = result.model_dump()
print(f"\033[94m[Client Tool Result: {result}]\033[0m")
# In current Python AG-UI, frontend tool declarations are sent with
# the run request. Tool-call lifecycle events are streamed back over SSE.
print(f"Tool result for {tool_call_id}: {result}")
except Exception as e:
print(f"\033[91m[Tool Error: {e}]\033[0m")
print(f"Tool error for {tool_call_id}: {e}")
async def main():
"""Main client loop with frontend tools."""
server_url = os.environ.get("AGUI_SERVER_URL", "http://127.0.0.1:8888/")
print(f"Connecting to AG-UI server at: {server_url}\n")
client = AGUIClientWithTools(server_url, FRONTEND_TOOLS)
try:
while True:
message = input("\nUser (:q or quit to exit): ")
if not message.strip():
continue
if message.lower() in (":q", "quit"):
break
print()
async for event in client.send_message(message):
event_type = event.get("type", "")
if event_type == "RUN_STARTED":
print(f"\033[93m[Run Started]\033[0m")
elif event_type == "TEXT_MESSAGE_CONTENT":
print(f"\033[96m{event.get('delta', '')}\033[0m", end="", flush=True)
elif event_type == "RUN_FINISHED":
print(f"\n\033[92m[Run Finished]\033[0m")
elif event_type == "RUN_ERROR":
error_msg = event.get("message", "Unknown error")
print(f"\n\033[91m[Error: {error_msg}]\033[0m")
print()
except KeyboardInterrupt:
print("\n\nExiting...")
except Exception as e:
print(f"\n\033[91mError: {e}\033[0m")
if __name__ == "__main__":
asyncio.run(main())
Como funcionam as ferramentas de front-end
Fluxo de protocolo
- Registro do cliente: O cliente envia declarações de ferramenta (nomes, descrições, parâmetros) para o servidor
- Orquestração de servidores: o agente de IA decide quando chamar ferramentas de frontend com base na solicitação do usuário
-
Eventos de Chamada de Ferramenta: O servidor transmite
TOOL_CALL_START,TOOL_CALL_ARGS, eTOOL_CALL_ENDeventos para o cliente - Execução do cliente: O cliente executa a ferramenta localmente
-
Eventos de Resultados: Os resultados das ferramentas são representados como
TOOL_CALL_RESULTeventos no stream - Processamento do agente: O servidor incorpora o resultado e continua a resposta
Principais Eventos
-
TOOL_CALL_START/TOOL_CALL_ARGS/TOOL_CALL_END: Pedidos do servidor e transmissão em fluxo dos detalhes das chamadas de ferramentas -
TOOL_CALL_RESULT: Evento de resultado da execução da ferramenta
Saída esperada
User (:q or quit to exit): What's the temperature reading from my sensors?
[Run Started]
[Client Tool Call: read_climate_sensors]
Arguments: {'include_temperature': True, 'include_humidity': True}
[Client Tool Result: {'temperature': 22.5, 'humidity': 45.0, 'air_quality_index': 75}]
Based on your sensor readings, the current temperature is 22.5°C and the
humidity is at 45%. These are comfortable conditions!
[Run Finished]
Configuração do servidor
O servidor AG-UI padrão do tutorial de Introdução suporta automaticamente ferramentas de front-end. Não são necessárias alterações no lado do servidor - ele lida com a orquestração de ferramentas automaticamente.
Melhores práticas
Segurança
def access_sensitive_data() -> str:
"""Access user's sensitive data."""
# Always check permissions first
if not has_permission():
return "Error: Permission denied"
try:
# Access data
return "Data retrieved"
except Exception as e:
# Don't expose internal errors
return "Unable to access data"
Tratamento de erros
def read_file(path: str) -> str:
"""Read a local file."""
try:
with open(path, "r") as f:
return f.read()
except FileNotFoundError:
return f"Error: File not found: {path}"
except PermissionError:
return f"Error: Permission denied: {path}"
except Exception as e:
return f"Error reading file: {str(e)}"
Operações assíncronas
async def capture_photo() -> str:
"""Capture a photo from device camera."""
# Simulate camera access
await asyncio.sleep(1)
return "photo_12345.jpg"
Troubleshooting
Ferramentas que não estão a ser acionadas
- Garantir que as declarações da ferramenta sejam enviadas ao servidor
- Verificar se as descrições das ferramentas indicam claramente a finalidade
- Verifique os logs do servidor para registro de ferramentas
Erros de execução
- Adicionar tratamento de erros abrangente
- Validar parâmetros antes de processar
- Devolva mensagens de erro amigáveis ao utilizador
- Registar erros para depuração
Problemas de tipos de dados
- Use modelos Pydantic para tipos complexos
- Converter modelos em ditados antes da serialização
- Lidar explicitamente com conversões de tipo
Próximas Etapas
- Renderização de ferramentas de back-end: combine com ferramentas do lado do servidor
Recursos adicionais
Os servidores Go AG-UI podem deixar as chamadas de ferramentas a cargo do frontend, desativando a chamada automática de funções no agente hospedado.
a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
Instructions: "You are a helpful assistant.",
Config: agent.Config{
Name: "AGUIAssistant",
DisableFuncAutoCall: true,
},
})
mux := http.NewServeMux()
mux.Handle("/", aguiprovider.NewJSONHTTPHandler(a, aguiprovider.HandlerConfig{}))
Tip
Veja o exemplo das ferramentas de front-end do AG-UI para um exemplo funcional completo.