Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
AG-UI definisce gli eventi di stato e i campi della richiesta per la condivisione dello stato dell'applicazione tra un client e un endpoint agente. L'implementazione e i modelli di stato supportati variano in base a MAF SDK.
Prerequisites
Prima di iniziare, assicurarsi di comprendere:
Che cos'è Gestione stato?
Lo stato di AG-UI può fornire:
- Stato condiviso: sia il client che il server mantengono una visualizzazione sincronizzata dello stato dell'applicazione
- Aggiornamenti client e server: le applicazioni possono inviare lo stato nelle richieste e generare eventi di stato
- Aggiornamenti in tempo reale: le modifiche vengono trasmessi immediatamente usando gli eventi di stato
- Aggiornamenti predittivi: un SDK può mappare lo stato delle chiamate degli strumenti allo stato ottimistico dell'interfaccia utente
- Structured Data: Lo stato segue uno schema JSON per la convalida
Casi d'uso
La gestione dello stato è utile per:
- Interfaccia utente generativa: creare componenti dell'interfaccia utente in base allo stato controllato dall'agente
- Compilazione modulo: Agent popola i campi modulo durante la raccolta di informazioni
- Monitoraggio dello stato d'avanzamento: mostra lo stato d'avanzamento in tempo reale delle operazioni su più fasi
- Dashboard interattivi: visualizzare i dati aggiornati durante l'elaborazione dell'agente
- Modifica collaborativa: più utenti visualizzano aggiornamenti coerenti dello stato
Lo stato AG-UI è un JSON visibile al client associato a un'esecuzione. In .NET l'integrazione fornisce due meccanismi espliciti:
- Stato di lettura fornito dal client dal
RunAgentInputdi origine. - Mappa le chiamate o i risultati dello strumento selezionati agli eventi di stato di AG-UI con
AGUIStreamOptions.
La mappatura dello stato deve essere attivata esplicitamente. I risultati degli strumenti arbitrari non diventano automaticamente uno stato condiviso.
Leggi lo stato del client
MapAGUIServer archivia l'oggetto di origine RunAgentInput in ChatOptions. Se il modello richiede lo stato corrente del client, racchiudi l'agente di base con un wrapper leggero DelegatingAIAgent che recupera lo stato con TryGetRunAgentInput e lo aggiunge al contesto del modello:
using System.Text.Json;
using AGUI.Abstractions;
using AGUI.Server;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
internal sealed class RecipeStateAgent(AIAgent innerAgent)
: DelegatingAIAgent(innerAgent)
{
protected override Task<AgentResponse> RunCoreAsync(
IEnumerable<ChatMessage> messages,
AgentSession? session = null,
AgentRunOptions? options = null,
CancellationToken cancellationToken = default) =>
RunCoreStreamingAsync(messages, session, options, cancellationToken)
.ToAgentResponseAsync(cancellationToken);
protected override IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
IEnumerable<ChatMessage> messages,
AgentSession? session = null,
AgentRunOptions? options = null,
CancellationToken cancellationToken = default)
{
if (options is ChatClientAgentRunOptions { ChatOptions: { } chatOptions } &&
chatOptions.TryGetRunAgentInput(out RunAgentInput? input) &&
input.State is { ValueKind: JsonValueKind.Object } state)
{
ChatMessage stateMessage = new(
ChatRole.System,
$"The user's current recipe state is:\n{state.GetRawText()}");
messages = [stateMessage, .. messages];
}
return InnerAgent.RunStreamingAsync(
messages,
session,
options,
cancellationToken);
}
}
AIAgent agent = new RecipeStateAgent(baseAgent);
Il wrapper gestisce solo il percorso di input. Le emissioni di eventi di stato rimangono dichiarative tramite AGUIStreamOptions, come illustrato nelle sezioni seguenti.
TryGetRunAgentInput legge l'input archiviato dal livello di hosting in ChatOptions.AdditionalProperties; il codice dell'applicazione non accede direttamente al dizionario.
Lo stato del client è un input non attendibile della richiesta. Convalida la sua forma e i suoi valori prima di usarla nei prompt, nel routing o in operazioni con privilegi.
Creare uno snapshot dello stato
Associare il risultato di uno strumento a STATE_SNAPSHOT quando lo strumento restituisce lo stato completo:
using AGUI.Server;
AGUIStreamOptions streamOptions = new AGUIStreamOptions()
.MapResultAsStateSnapshot("generate_recipe");
app.MapAGUIServer("/", agent).WithMetadata(streamOptions);
MapResultAsStateSnapshot richiede che il valore FunctionResultContent.Result sia un oggetto JsonElement. Serializzare un POCO, un dizionario o una raccolta in JsonElement nello strumento prima di restituirlo. Il risultato di generate_recipe diventa quindi lo snapshot e sostituisce lo stato condiviso corrente del client.
Per altri tipi di risultati, usare MapResult con un mapper personalizzato che costruisce il StateSnapshotEvent.
Generare delta di stato
Associare un risultato di uno strumento a STATE_DELTA quando restituisce una JSON Patch RFC 6902:
AGUIStreamOptions streamOptions = new AGUIStreamOptions()
.MapResultAsStateSnapshot("create_plan")
.MapResultAsStateDelta("update_plan_step");
app.MapAGUIServer("/", agent).WithMetadata(streamOptions);
Utilizzare uno snapshot per inizializzare o sostituire lo stato e i delta per gestire modifiche incrementali.
MapResultAsStateDelta richiede anche un JsonElement risultato. L'elemento deve contenere una matrice di patch JSON RFC 6902 . Usare MapResult con un mapper personalizzato se lo strumento restituisce un'altra rappresentazione.
Eseguire il mapping delle chiamate allo stato degli strumenti
AGUIStreamOptions.MapCall esegue il mapping di un oggetto selezionato FunctionCallContent a eventi aggiuntivi AG-UI generati dopo gli eventi di chiamata allo strumento normali. Usarlo quando lo stato deriva dagli argomenti dello strumento anziché dal risultato dello strumento:
AGUIStreamOptions streamOptions = new AGUIStreamOptions()
.MapCall("write_document", call =>
{
if (call.Arguments?.TryGetValue("document", out object? document) is not true)
{
return [];
}
JsonElement snapshot = JsonSerializer.SerializeToElement(new { document });
return [new StateSnapshotEvent { Snapshot = snapshot }];
});
app.MapAGUIServer("/", agent).WithMetadata(streamOptions);
L'applicazione è proprietaria del mapping e della forma dello stato.
MapCall non deduce lo stato da argomenti arbitrari dello strumento o elimina la normale esecuzione dello strumento. Gli aggiornamenti incrementali richiedono che il client del modello sottostante esponga gli argomenti delle chiamate agli strumenti in streaming e che l'applicazione configuri la corrispondente estrazione degli argomenti.
Ricevere lo stato in un client .NET
Il client AG-UI .NET espone gli eventi del protocollo di stato tramite ChatResponseUpdate.RawRepresentation:
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(messages, session))
{
if (update.AsChatResponseUpdate().RawRepresentation is StateSnapshotEvent snapshot)
{
JsonElement state = snapshot.Snapshot;
}
else if (update.AsChatResponseUpdate().RawRepresentation is StateDeltaEvent delta)
{
JsonElement changes = delta.Delta;
}
}
Il client è responsabile della conservazione e dell'applicazione dello stato condiviso, quindi dell'invio dello stato corrente alle richieste successive quando l'applicazione lo richiede.
Passaggi successivi
Definire i modelli di stato
Innanzitutto, definisci i modelli Pydantic per la struttura dello stato. In questo modo si garantisce la sicurezza e la convalida dei tipi:
from enum import Enum
from pydantic import BaseModel, Field
class SkillLevel(str, Enum):
"""The skill level required for the recipe."""
BEGINNER = "Beginner"
INTERMEDIATE = "Intermediate"
ADVANCED = "Advanced"
class CookingTime(str, Enum):
"""The cooking time of the recipe."""
FIVE_MIN = "5 min"
FIFTEEN_MIN = "15 min"
THIRTY_MIN = "30 min"
FORTY_FIVE_MIN = "45 min"
SIXTY_PLUS_MIN = "60+ min"
class Ingredient(BaseModel):
"""An ingredient with its details."""
icon: str = Field(..., description="Emoji icon representing the ingredient (e.g., 🥕)")
name: str = Field(..., description="Name of the ingredient")
amount: str = Field(..., description="Amount or quantity of the ingredient")
class Recipe(BaseModel):
"""A complete recipe."""
title: str = Field(..., description="The title of the recipe")
skill_level: SkillLevel = Field(..., description="The skill level required")
special_preferences: list[str] = Field(
default_factory=list, description="Dietary preferences (e.g., Vegetarian, Gluten-free)"
)
cooking_time: CookingTime = Field(..., description="The estimated cooking time")
ingredients: list[Ingredient] = Field(..., description="Complete list of ingredients")
instructions: list[str] = Field(..., description="Step-by-step cooking instructions")
Schema dello stato
Definire uno schema di stato per specificare la struttura e i tipi dello stato:
state_schema = {
"recipe": {"type": "object", "description": "The current recipe"},
}
Annotazioni
Lo schema dello stato usa un formato semplice con type e facoltativo description. La struttura effettiva è definita dai modelli Pydantic.
Aggiornamenti dello stato predittivo
Gli aggiornamenti dello stato predittivo trasmettono gli argomenti del tool allo stato man mano che l'LLM li genera, consentendo aggiornamenti ottimistici dell'interfaccia utente.
predict_state_config = {
"recipe": {"tool": "update_recipe", "tool_argument": "recipe"},
}
Questa configurazione mappa il campo di stato recipe all'argomento recipe dello strumento update_recipe. Quando l'agente chiama lo strumento, gli argomenti vengono trasmessi allo stato in tempo reale man mano che l'LLM li genera.
Definire lo strumento di aggiornamento dello stato
Creare una funzione dello strumento che accetta il modello Pydantic:
from agent_framework import tool
@tool
def update_recipe(recipe: Recipe) -> str:
"""Update the recipe with new or modified content.
You MUST write the complete recipe with ALL fields, even when changing only a few items.
When modifying an existing recipe, include ALL existing ingredients and instructions plus your changes.
NEVER delete existing data - only add or modify.
Args:
recipe: The complete recipe object with all details
Returns:
Confirmation that the recipe was updated
"""
return "Recipe updated."
Importante
Il nome del parametro della funzione strumento (recipe) deve corrispondere a tool_argument in predict_state_config.
Creare l'agente con Gestione stato
Ecco un'implementazione completa del server con la gestione dello stato:
"""AG-UI server with state management."""
from agent_framework import Agent
from agent_framework.openai import OpenAIChatCompletionClient
from agent_framework_ag_ui import (
AgentFrameworkAgent,
add_agent_framework_fastapi_endpoint,
)
from azure.identity import AzureCliCredential
from fastapi import FastAPI
# Create the chat agent with tools
agent = Agent(
name="recipe_agent",
instructions="""You are a helpful recipe assistant that creates and modifies recipes.
CRITICAL RULES:
1. You will receive the current recipe state in the system context
2. To update the recipe, you MUST use the update_recipe tool
3. When modifying a recipe, ALWAYS include ALL existing data plus your changes in the tool call
4. NEVER delete existing ingredients or instructions - only add or modify
5. After calling the tool, provide a brief conversational message (1-2 sentences)
When creating a NEW recipe:
- Provide all required fields: title, skill_level, cooking_time, ingredients, instructions
- Use actual emojis for ingredient icons (🥕 🧄 🧅 🍅 🌿 🍗 🥩 🧀)
- Leave special_preferences empty unless specified
- Message: "Here's your recipe!" or similar
When MODIFYING or IMPROVING an existing recipe:
- Include ALL existing ingredients + any new ones
- Include ALL existing instructions + any new/modified ones
- Update other fields as needed
- Message: Explain what you improved (e.g., "I upgraded the ingredients to premium quality")
- When asked to "improve", enhance with:
* Better ingredients (upgrade quality, add complementary flavors)
* More detailed instructions
* Professional techniques
* Adjust skill_level if complexity changes
* Add relevant special_preferences
Example improvements:
- Upgrade "chicken" → "organic free-range chicken breast"
- Add herbs: basil, oregano, thyme
- Add aromatics: garlic, shallots
- Add finishing touches: lemon zest, fresh parsley
- Make instructions more detailed and professional
""",
client=OpenAIChatCompletionClient(
model=deployment_name,
azure_endpoint=endpoint,
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
credential=AzureCliCredential(),
),
tools=[update_recipe],
)
# Wrap agent with state management
recipe_agent = AgentFrameworkAgent(
agent=agent,
name="RecipeAgent",
description="Creates and modifies recipes with streaming state updates",
state_schema={
"recipe": {"type": "object", "description": "The current recipe"},
},
predict_state_config={
"recipe": {"tool": "update_recipe", "tool_argument": "recipe"},
},
)
# Create FastAPI app
app = FastAPI(title="AG-UI Recipe Assistant")
add_agent_framework_fastapi_endpoint(app, recipe_agent, "/")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8888)
Concetti chiave
- Modelli Pydantic: definire lo stato strutturato con tipizzazione sicura e convalida dei tipi
- Schema dello stato: formato semplice che specifica i tipi di campo di stato
- Configurazione dello stato predittivo: esegue il mapping dei campi di stato agli argomenti dello strumento per gli aggiornamenti in streaming
- Inserimento dello stato: lo stato corrente viene inserito automaticamente come messaggi di sistema per fornire il contesto
- Aggiornamenti completi: gli strumenti devono scrivere lo stato completo, non solo i delta
- Strategia di conferma: personalizzare i messaggi di approvazione per il dominio (ricetta, documento, pianificazione delle attività e così via)
Comprendere gli eventi di stato
Evento snapshot dello stato
Una istantanea completa dello stato corrente, emessa quando lo strumento è completato:
{
"type": "STATE_SNAPSHOT",
"snapshot": {
"recipe": {
"title": "Classic Pasta Carbonara",
"skill_level": "Intermediate",
"special_preferences": ["Authentic Italian"],
"cooking_time": "30 min",
"ingredients": [
{"icon": "🍝", "name": "Spaghetti", "amount": "400g"},
{"icon": "🥓", "name": "Guanciale or bacon", "amount": "200g"},
{"icon": "🥚", "name": "Egg yolks", "amount": "4"},
{"icon": "🧀", "name": "Pecorino Romano", "amount": "100g grated"},
{"icon": "🧂", "name": "Black pepper", "amount": "To taste"}
],
"instructions": [
"Bring a large pot of salted water to boil",
"Cut guanciale into small strips and fry until crispy",
"Beat egg yolks with grated Pecorino and black pepper",
"Cook spaghetti until al dente",
"Reserve 1 cup pasta water, then drain pasta",
"Remove pan from heat, add hot pasta to guanciale",
"Quickly stir in egg mixture, adding pasta water to create creamy sauce",
"Serve immediately with extra Pecorino and black pepper"
]
}
}
}
Evento di Stato Delta
Aggiornamenti incrementali dello stato usando il formato JSON Patch, generati come argomenti per lo strumento di streaming LLM.
{
"type": "STATE_DELTA",
"delta": [
{
"op": "replace",
"path": "/recipe",
"value": {
"title": "Classic Pasta Carbonara",
"skill_level": "Intermediate",
"cooking_time": "30 min",
"ingredients": [
{"icon": "🍝", "name": "Spaghetti", "amount": "400g"}
],
"instructions": ["Bring a large pot of salted water to boil"]
}
}
]
}
Annotazioni
Il flusso di eventi degli stati delta avviene in tempo reale mentre il modello di linguaggio genera gli argomenti dello strumento, fornendo aggiornamenti ottimistici della UI. Lo snapshot dello stato finale viene generato al termine dell'esecuzione dello strumento.
Implementazione del client
Il agent_framework_ag_ui pacchetto consente AGUIChatClient di connettersi ai server AG-UI, portando l'esperienza client Python alla parità con .NET:
"""AG-UI client with state management."""
import asyncio
import json
import os
from typing import Any
from agent_framework import Agent, Message, Role
from agent_framework_ag_ui import AGUIChatClient
async def main():
"""Example client with state tracking."""
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")
# Create AG-UI chat client
chat_client = AGUIChatClient(endpoint=server_url)
# Wrap with Agent for convenient API
agent = Agent(
name="ClientAgent",
client=chat_client,
instructions="You are a helpful assistant.",
)
# Get a thread for conversation continuity
thread = agent.create_session()
# Track state locally
state: dict[str, Any] = {}
try:
while True:
message = input("\nUser (:q to quit, :state to show state): ")
if not message.strip():
continue
if message.lower() in (":q", "quit"):
break
if message.lower() == ":state":
print(f"\nCurrent state: {json.dumps(state, indent=2)}")
continue
print()
# Stream the agent response with state
async for update in agent.run(message, session=thread, stream=True):
# Handle text content
if update.text:
print(update.text, end="", flush=True)
# Handle state updates surfaced through AG-UI events.
for content in update.contents:
if content.type == "data" and getattr(content, "media_type", None) == "application/json":
print("\n[JSON state payload received]")
print(f"\n\nCurrent state: {json.dumps(state, indent=2)}")
print()
except KeyboardInterrupt:
print("\n\nExiting...")
if __name__ == "__main__":
# Install dependencies: pip install agent-framework-ag-ui --pre
asyncio.run(main())
Vantaggi principali
Fornisce AGUIChatClient :
- Connessione semplificata: gestione automatica delle comunicazioni HTTP/SSE
- Gestione thread: tracciamento dell'ID thread integrato per la continuità della conversazione
-
Integrazione dell'agente: funziona perfettamente con
Agentper un'API familiare - Gestione dello stato: analisi automatica degli eventi di stato dal server
- Parità con .NET: esperienza coerente tra i linguaggi
Tip
Usare AGUIChatClient con Agent per ottenere il massimo vantaggio delle funzionalità del framework agente, ad esempio la cronologia delle conversazioni, l'esecuzione degli strumenti e il supporto del middleware.
Conferma dello stato stimato
Impostare require_confirmation=True su AgentFrameworkAgent quando le modifiche dello stato stimate devono attendere la conferma del client prima di essere applicate:
recipe_agent = AgentFrameworkAgent(
agent=agent,
state_schema={"recipe": {"type": "object", "description": "The current recipe"}},
predict_state_config={"recipe": {"tool": "update_recipe", "tool_argument": "recipe"}},
require_confirmation=True,
)
Personalizza il testo di conferma nell'interfaccia utente del client AG-UI quando viene visualizzato l'evento di conferma.
Interazione di esempio
Con il server e il client in esecuzione:
User (:q to quit, :state to show state): I want to make a classic Italian pasta carbonara
[Run Started]
[Calling Tool: update_recipe]
[State Updated]
[State Updated]
[State Updated]
[Tool Result: Recipe updated.]
Here's your recipe!
[Run Finished]
============================================================
CURRENT STATE
============================================================
recipe:
title: Classic Pasta Carbonara
skill_level: Intermediate
special_preferences: ['Authentic Italian']
cooking_time: 30 min
ingredients:
- 🍝 Spaghetti: 400g
- 🥓 Guanciale or bacon: 200g
- 🥚 Egg yolks: 4
- 🧀 Pecorino Romano: 100g grated
- 🧂 Black pepper: To taste
instructions:
1. Bring a large pot of salted water to boil
2. Cut guanciale into small strips and fry until crispy
3. Beat egg yolks with grated Pecorino and black pepper
4. Cook spaghetti until al dente
5. Reserve 1 cup pasta water, then drain pasta
6. Remove pan from heat, add hot pasta to guanciale
7. Quickly stir in egg mixture, adding pasta water to create creamy sauce
8. Serve immediately with extra Pecorino and black pepper
============================================================
Tip
Usare il :state comando per visualizzare lo stato corrente in qualsiasi momento durante la conversazione.
Aggiornamenti predittivi dello stato in azione
Quando si usano gli aggiornamenti dello stato predittivo con predict_state_config, il client riceve STATE_DELTA eventi perché LLM genera argomenti dello strumento in tempo reale, prima che lo strumento venga eseguito:
// Agent starts generating tool call for update_recipe
// Client receives STATE_DELTA events as the recipe argument streams:
// First delta - partial recipe with title
{
"type": "STATE_DELTA",
"delta": [{"op": "replace", "path": "/recipe", "value": {"title": "Classic Pasta"}}]
}
// Second delta - title complete with more fields
{
"type": "STATE_DELTA",
"delta": [{"op": "replace", "path": "/recipe", "value": {
"title": "Classic Pasta Carbonara",
"skill_level": "Intermediate"
}}]
}
// Third delta - ingredients starting to appear
{
"type": "STATE_DELTA",
"delta": [{"op": "replace", "path": "/recipe", "value": {
"title": "Classic Pasta Carbonara",
"skill_level": "Intermediate",
"cooking_time": "30 min",
"ingredients": [
{"icon": "🍝", "name": "Spaghetti", "amount": "400g"}
]
}}]
}
// ... more deltas as the LLM generates the complete recipe
In questo modo il client può visualizzare gli aggiornamenti ottimistici dell'interfaccia utente in tempo reale man mano che l'agente sta pensando, fornendo feedback immediato agli utenti.
Stato con umano nel ciclo
È possibile combinare la gestione dello stato con i flussi di lavoro di approvazione impostando require_confirmation=True:
recipe_agent = AgentFrameworkAgent(
agent=agent,
state_schema={"recipe": {"type": "object", "description": "The current recipe"}},
predict_state_config={"recipe": {"tool": "update_recipe", "tool_argument": "recipe"}},
require_confirmation=True, # Require approval for state changes
)
Se abilitato/a:
- Flusso degli aggiornamenti di stato mentre l'agente genera gli argomenti dello strumento (aggiornamenti predittivi tramite gli eventi
STATE_DELTA) - L'agent si interrompe prima di eseguire lo strumento con un'
tool_callinterruzione inRUN_FINISHED.outcome.interrupts - Se approvato, lo strumento esegue e lo stato finale viene generato (tramite
STATE_SNAPSHOTevento) - Se rifiutata, le modifiche dello stato predittivo vengono rimosse
Modelli di stato avanzati
Stato complesso con più campi
È possibile gestire più campi di stato con diversi strumenti:
from pydantic import BaseModel
class TaskStep(BaseModel):
"""A single task step."""
description: str
status: str = "pending"
estimated_duration: str = "5 min"
@tool
def generate_task_steps(steps: list[TaskStep]) -> str:
"""Generate task steps for a given task."""
return f"Generated {len(steps)} steps."
@tool
def update_preferences(preferences: dict[str, Any]) -> str:
"""Update user preferences."""
return "Preferences updated."
# Configure with multiple state fields
agent_with_multiple_state = AgentFrameworkAgent(
agent=agent,
state_schema={
"steps": {"type": "array", "description": "List of task steps"},
"preferences": {"type": "object", "description": "User preferences"},
},
predict_state_config={
"steps": {"tool": "generate_task_steps", "tool_argument": "steps"},
"preferences": {"tool": "update_preferences", "tool_argument": "preferences"},
},
)
Uso degli argomenti dello strumento con caratteri jolly
Quando uno strumento restituisce dati complessi e annidati, utilizzare "*" per mappare tutti gli argomenti dello strumento allo stato:
@tool
def create_document(title: str, content: str, metadata: dict[str, Any]) -> str:
"""Create a document with title, content, and metadata."""
return "Document created."
# Map all tool arguments to document state
predict_state_config = {
"document": {"tool": "create_document", "tool_argument": "*"}
}
Esegue il mapping dell'intera chiamata dello strumento (tutti gli argomenti) al document campo di stato.
Migliori pratiche
Utilizzare modelli Pydantic
Definire modelli strutturati per la sicurezza dei tipi:
class Recipe(BaseModel):
"""Use Pydantic models for structured, validated state."""
title: str
skill_level: SkillLevel
ingredients: list[Ingredient]
instructions: list[str]
Vantaggi:
- Sicurezza dei tipi: convalida automatica dei tipi di dati
- Documentazione: Le descrizioni dei campi fungono da documentazione
- Supporto dell'IDE: completamento automatico e controllo del tipo
- Serializzazione: conversione JSON automatica
Aggiornamenti dello stato completi
Scrivere sempre lo stato completo anziché solo i delta.
@tool
def update_recipe(recipe: Recipe) -> str:
"""
You MUST write the complete recipe with ALL fields.
When modifying a recipe, include ALL existing ingredients and
instructions plus your changes. NEVER delete existing data.
"""
return "Recipe updated."
In questo modo si garantisce la coerenza dello stato e gli aggiornamenti predittivi appropriati.
Abbinare i nomi dei parametri
Verificare che i nomi dei parametri degli strumenti corrispondano alla tool_argument configurazione:
# Tool parameter name
def update_recipe(recipe: Recipe) -> str: # Parameter name: 'recipe'
...
# Must match in predict_state_config
predict_state_config = {
"recipe": {"tool": "update_recipe", "tool_argument": "recipe"} # Same name
}
Fornire contesto nelle istruzioni
Includere istruzioni chiare sulla gestione dello stato:
agent = Agent(
instructions="""
CRITICAL RULES:
1. You will receive the current recipe state in the system context
2. To update the recipe, you MUST use the update_recipe tool
3. When modifying a recipe, ALWAYS include ALL existing data plus your changes
4. NEVER delete existing ingredients or instructions - only add or modify
""",
...
)
Personalizzare l'interfaccia utente di conferma
Personalizzare i messaggi di approvazione e conferma dello stato nel client AG-UI durante il rendering degli eventi di conferma dal server.
Operazioni successive
A questo punto sono state apprese tutte le funzionalità di base AG-UI. A questo punto è possibile:
- Esplorare la documentazione di Agent Framework
- Creare un'applicazione completa che combina tutte le funzionalità di AG-UI
- Distribuire il servizio AG-UI nell'ambiente di produzione
Risorse aggiuntive
La gestione dello stato in Go AG-UI può essere implementata con middleware che emette aggiornamenti strutturati message.DataContent insieme ai normali aggiornamenti di testo.
stateSnapshotMiddleware := agent.MiddlewareFunc(func(next agent.RunFunc, ctx context.Context, messages []*message.Message, opts ...agent.Option) iter.Seq2[*agent.ResponseUpdate, error] {
return func(yield func(*agent.ResponseUpdate, error) bool) {
for update, err := range next(ctx, messages, opts...) {
if err != nil {
yield(nil, err)
return
}
if update != nil {
// Inspect update contents and yield DataContent snapshots as needed.
}
if !yield(update, nil) {
return
}
}
}
})
a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
Config: agent.Config{
Middlewares: []agent.Middleware{stateSnapshotMiddleware},
},
})
Tip
Vedere l'esempio di gestione dello statoAG-UI per un esempio eseguibile completo.