Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
AG-UI definiert Zustandsereignisse und Anforderungsfelder zum Teilen des Anwendungszustands zwischen einem Client und einem Agent-Endpunkt. Die Implementierungs- und unterstützten Zustandsmuster variieren je nach MAF SDK.
Voraussetzungen
Bevor Sie beginnen, stellen Sie sicher, dass Sie Folgendes verstehen:
Was ist Zustandsverwaltung?
AG-UI Status kann Folgendes bereitstellen:
- Freigegebener Zustand: Sowohl Client als auch Server verwalten eine synchronisierte Ansicht des Anwendungszustands
- Client- und Serverupdates: Anwendungen können in Anfragen Zustand senden und Zustandsereignisse auslösen.
- Echtzeitaktualisierungen: Änderungen werden sofort mithilfe von Zustandsereignissen gestreamt.
- Predictive Updates: Ein SDK kann den Fortschritt des Toolaufrufs dem optimistischen UI-Zustand zuordnen.
- Strukturierte Daten: State folgt einem JSON-Schema für die Validierung.
Anwendungsfälle
Die Zustandsverwaltung ist nützlich für:
- Generative UI: Erstellen von UI-Komponenten basierend auf dem vom Agent gesteuerten Zustand
- Formularerstellung: Der Agent füllt Formularfelder auf, während er Informationen sammelt.
- Fortschrittsverfolgung: Anzeigen des Echtzeitfortschritts von mehrstufigen Vorgängen
- Interaktive Dashboards: Anzeigen von Daten, die aktualisiert werden, während der Agent sie verarbeitet
- Gemeinsame Bearbeitung: Mehrere Benutzer sehen konsistente Statusaktualisierungen
Der AG-UI-Zustand ist clientseitig sichtbares JSON, das einem Lauf zugeordnet ist. In .NET bietet die Integration zwei explizite Mechanismen:
- Lesestatus, der vom Client vom ursprünglichen
RunAgentInputbereitgestellt wird. - Zuordnen ausgewählter Toolaufrufe oder Ergebnisse zu AG-UI Zustandsereignissen mit
AGUIStreamOptions.
Die Statuszuordnung ist optional. Beliebige Toolergebnisse werden nicht automatisch zu einem geteilten Zustand.
Clientstatus lesen
MapAGUIServer speichert das ursprüngliche RunAgentInput auf ChatOptions. Wenn das Modell den aktuellen Zustand des Clients benötigt, umhüllen Sie den Basis-Agenten mit einem leichtgewichtigen DelegatingAIAgent-Element, das den Zustand mit TryGetRunAgentInput wiederherstellt und ihn dem Modellkontext hinzufügt:
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);
Der Wrapper behandelt nur den Eingabepfad. Die Emission von Zustandsereignissen bleibt über AGUIStreamOptions deklarativ, wie in den folgenden Abschnitten gezeigt.
TryGetRunAgentInput liest die Eingabedaten, die die Hostingebene in ChatOptions.AdditionalProperties gespeichert hat; der Anwendungscode greift nicht direkt auf dieses Dictionary zu.
Der Client-Zustand ist eine nicht vertrauenswürdige Eingabe aus der Anfrage. Überprüfen Sie ihre Form und Werte, bevor Sie sie in Eingabeaufforderungen, Routing oder privilegierten Vorgängen verwenden.
Zustandsaufnahme ausgeben
Ordnen Sie ein Toolergebnis zu STATE_SNAPSHOT , wenn das Tool den vollständigen Zustand zurückgibt:
using AGUI.Server;
AGUIStreamOptions streamOptions = new AGUIStreamOptions()
.MapResultAsStateSnapshot("generate_recipe");
app.MapAGUIServer("/", agent).WithMetadata(streamOptions);
MapResultAsStateSnapshot erfordert, dass der FunctionResultContent.Result Wert ein JsonElement sein muss. Serialisieren Sie eine POCO, ein Wörterbuch oder eine Sammlung im Tool zu JsonElement, bevor Sie es zurückgeben. Das Ergebnis von generate_recipe wird dann zur Momentaufnahme und ersetzt den aktuellen gemeinsam genutzten Zustand des Clients.
Verwenden Sie für andere Ergebnistypen MapResult mit einem benutzerdefinierten Mapper, der die StateSnapshotEvent erstellt.
Zustandsdeltas ausgeben
Ordnen Sie das Ergebnis eines Tools STATE_DELTA zu, wenn es einen RFC 6902 JSON-Patch zurückgibt:
AGUIStreamOptions streamOptions = new AGUIStreamOptions()
.MapResultAsStateSnapshot("create_plan")
.MapResultAsStateDelta("update_plan_step");
app.MapAGUIServer("/", agent).WithMetadata(streamOptions);
Verwenden Sie eine Momentaufnahme, um Zustand und Deltas für inkrementelle Änderungen zu initialisieren oder zu ersetzen.
MapResultAsStateDelta erfordert auch ein JsonElement Ergebnis. Das Element muss ein Array vom Typ RFC 6902 JSON Patch enthalten. Verwenden Sie MapResult mit einem benutzerdefinierten Mapper, wenn das Tool eine andere Darstellung zurückgibt.
Zuordnen von Toolaufrufen zum Status
AGUIStreamOptions.MapCall ordnet einem ausgewählten FunctionCallContent zusätzliche AG-UI-Ereignisse zu, die nach den normalen Tool-Call-Ereignissen ausgegeben werden. Verwenden Sie ihn, wenn der Zustand von Toolargumenten abgeleitet wird, anstatt das Toolergebnis:
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);
Die Anwendung verwaltet die Zuordnung sowie die Struktur des Zustands.
MapCall leitet den Zustand nicht von beliebigen Toolargumenten ab oder unterdrückt die normale Toolausführung. Inkrementelle Updates setzen voraus, dass der zugrunde liegende Modell-Client gestreamte Tool-Aufrufargumente bereitstellt und die Anwendung die entsprechende Argumentextraktion konfiguriert.
Empfangen des Status in einem .NET-Client
Der AG-UI .NET-Client stellt Statusprotokollereignisse über ChatResponseUpdate.RawRepresentation bereit:
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;
}
}
Der Client ist dafür verantwortlich, den geteilten Zustand zu speichern und anzuwenden und ihn dann bei späteren Anforderungen zu senden, wenn die Anwendung dies erfordert.
Nächste Schritte
Definieren von Zustandsmodellen
Definieren Sie zuerst Pydantische Modelle für Ihre Zustandsstruktur. Dadurch wird die Typsicherheit und Validierung sichergestellt:
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")
Statusschema
Definieren Sie ein Statusschema, um die Struktur und die Typen Ihres Zustands anzugeben:
state_schema = {
"recipe": {"type": "object", "description": "The current recipe"},
}
Note
Das Zustandsschema verwendet ein einfaches Format mit type und optional description. Die tatsächliche Struktur wird durch Ihre pydantischen Modelle definiert.
Vorhersagende Statusaktualisierungen
Prädiktiver Status überträgt Argumente von Stream-Tool auf den Status, während LLM sie generiert, und ermöglicht damit optimistische UI-Aktualisierungen.
predict_state_config = {
"recipe": {"tool": "update_recipe", "tool_argument": "recipe"},
}
Diese Konfiguration ordnet das recipe Statusfeld dem recipe Argument des update_recipe Tools zu. Wenn der Agent das Tool aufruft, werden die Argumente in Echtzeit in den Zustand übertragen, während die LLM sie generiert.
Definieren des Statusaktualisierungstools
Erstellen Sie eine Toolfunktion, die Ihr Pydantisches Modell akzeptiert:
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."
Important
Der Parametername der Toolfunktion (recipe) muss mit dem tool_argument in Ihrer predict_state_configFunktion übereinstimmen.
Agent mit Statusverwaltung erstellen
Hier ist eine vollständige Serverimplementierung mit Statusverwaltung:
"""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)
Wichtige Konzepte
- Pydantische Modelle: Definieren eines strukturierten Zustands mit Typsicherheit und Validierung
- Statusschema: Einfaches Format, das Zustandsfeldtypen angibt
- Predictive State Config: Ordnet Zustandsfelder den Toolargumenten für Streaming-Updates zu
- Zustandseinfügung: Der aktuelle Zustand wird automatisch als Systemmeldungen eingefügt, um Kontext bereitzustellen.
- Vollständige Updates: Tools müssen den vollständigen Zustand schreiben, nicht nur Deltas
- Bestätigungsstrategie: Anpassen von Genehmigungsmeldungen für Ihre Domäne (Rezept, Dokument, Aufgabenplanung usw.)
Verstehen von Statusereignissen
State Snapshot-Ereignis
Eine vollständige Momentaufnahme des aktuellen Zustands, die beim Abschluss des Tools ausgegeben wird:
{
"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"
]
}
}
}
State Delta-Ereignis
Inkrementelle Zustandsaktualisierungen mithilfe des JSON-Patchformats, die als Argumente des LLM-Streams-Tools ausgegeben werden:
{
"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"]
}
}
]
}
Note
Zustandsdeltaereignisse werden in Echtzeit gestreamt, während das LLM die Toolargumente generiert und optimistische UI-Updates ermöglicht. Die Momentaufnahme des endgültigen Zustands wird ausgegeben, wenn das Tool die Ausführung abgeschlossen hat.
Clientimplementierung
Das agent_framework_ag_ui Paket stellt AGUIChatClient für die Verbindung mit AG-UI-Servern bereit, wodurch das Python-Client-Erlebnis dem von .NET angeglichen wird.
"""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())
Wichtige Vorteile
Dies AGUIChatClient bietet Folgendes:
- Vereinfachte Verbindung: Automatische Verarbeitung der HTTP/SSE-Kommunikation
- Threadverwaltung: Integrierte Thread-ID-Nachverfolgung für die Unterhaltungskontinuität
-
Agent-Integration: Funktioniert nahtlos mit
Agentder vertrauten API - Zustandsbehandlung: Automatische Analyse von Zustandsereignissen vom Server
- Parität mit .NET: Konsistente Erfahrung über verschiedene Sprachen hinweg
Tip
Verwenden Sie AGUIChatClient zusammen mit Agent, um die vollen Vorteile der Funktionen des Agent-Frameworks, wie Unterhaltungsverlauf, Toolausführung und Middleware-Unterstützung, zu nutzen.
Bestätigen des vorhergesagten Zustands
Legen Sie require_confirmation=True für AgentFrameworkAgent fest, wenn vorhergesagte Zustandsänderungen vor der Anwendung auf die Bestätigung durch den Client warten sollen:
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,
)
Passen Sie den Bestätigungstext in der Benutzeroberfläche Ihres AG-UI-Clients an, wenn das Bestätigungsereignis gerendert wird.
Beispielinteraktion
Wenn der Server und der Client ausgeführt werden:
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
Verwenden Sie den :state Befehl, um den aktuellen Zustand jederzeit während der Unterhaltung anzuzeigen.
Prädiktive Zustandsaktualisierungen in Aktion
Bei Verwendung von vorhersagebasierten Statusaktualisierungen mit predict_state_config empfängt der Client STATE_DELTA Ereignisse, da der LLM die Argumente für Werkzeuge in Echtzeit generiert, bevor das Tool ausgeführt wird.
// 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
Auf diese Weise kann der Client optimistische UI-Updates in Echtzeit anzeigen, während der Agent denkt und den Benutzern sofortiges Feedback gibt.
Zustand mit "Human-in-the-Loop"
Sie können die Zustandsverwaltung mit Genehmigungsworkflows kombinieren, indem Sie Folgendes festlegen 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
)
Wenn aktiviert:
- Statusaktualisierungsstream, wenn der Agent Toolargumente generiert (Predictive Updates via
STATE_DELTAEvents) - Der Agent pausiert vor der Ausführung des Tools mit einer
tool_callUnterbrechung inRUN_FINISHED.outcome.interrupts - Bei Genehmigung wird das Tool ausgeführt und der endgültige Zustand wird über ein
STATE_SNAPSHOT-Ereignis ausgegeben. - Wenn dies abgelehnt wird, werden die Änderungen des Vorhersagezustands verworfen.
Erweiterte Zustandsmuster
Komplexer Zustand mit mehreren Feldern
Sie können mehrere Statusfelder mit unterschiedlichen Tools verwalten:
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"},
},
)
Verwenden von Wildcard-Toolargumenten
Wenn ein Tool komplexe geschachtelte Daten zurückgibt, verwenden Sie "*", um alle Toolargumente dem Zustand zuzuordnen.
@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": "*"}
}
Dadurch wird der gesamte Toolaufruf (alle Argumente) dem document Statusfeld zugeordnet.
Bewährte Methoden
Pydantische Modelle verwenden
Definieren sie strukturierte Modelle für die Typsicherheit:
class Recipe(BaseModel):
"""Use Pydantic models for structured, validated state."""
title: str
skill_level: SkillLevel
ingredients: list[Ingredient]
instructions: list[str]
Vorteile:
- Typsicherheit: Automatische Validierung von Datentypen
- Dokumentation: Feldbeschreibungen dienen als Dokumentation
- IDE-Unterstützung: Automatische Vervollständigung und Typüberprüfung
- Serialisierung: Automatische JSON-Konvertierung
Statusaktualisierungen abschließen
Schreiben Sie immer den vollständigen Zustand auf, nicht nur die Delta-Werte.
@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."
Dadurch wird die Zustandskonsistenz und die richtigen Vorhersageupdates sichergestellt.
Parameternamen abgleichen
Stellen Sie sicher, dass die Toolparameternamen mit der Konfiguration übereinstimmen tool_argument :
# 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
}
Bereitstellen von Kontext in Anweisungen
Schließen Sie klare Anweisungen zur Zustandsverwaltung ein:
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
""",
...
)
Anpassen der Bestätigungs-UI
Passen Sie Genehmigungs- und Statusbestätigungsmeldungen in Ihrem AG-UI-Client beim Rendern von Bestätigungsereignissen vom Server an.
Nächste Schritte
Sie haben jetzt alle wichtigsten AG-UI Features gelernt! Als Nächstes haben Sie folgende Möglichkeiten:
- Erkunden der Agent Framework-Dokumentation
- Erstellen einer vollständigen Anwendung, die alle AG-UI Features kombiniert
- Bereitstellen Ihres AG-UI-Diensts in die Produktionsumgebung
Zusätzliche Ressourcen
Go AG-UI Zustandsverwaltung kann mit Middleware implementiert werden, die strukturierte message.DataContent Updates zusammen mit normalen Textaktualisierungen ausgibt.
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
Siehe das AG-UI-Beispiel zur Zustandsverwaltung für ein vollständig lauffähiges Beispiel.