Tillståndshantering med AG-UI

AG-UI definierar tillståndshändelser och begärandefält för delning av programtillstånd mellan en klient och en agentslutpunkt. Implementerings- och tillståndsmönster som stöds varierar beroende på MAF SDK.

Förutsättningar

Innan du börjar bör du se till att du förstår:

Vad är tillståndshantering?

AG-UI tillstånd kan ge:

  • Delat tillstånd: Både klient och server har en synkroniserad vy över programtillståndet
  • Klient- och serveruppdateringar: Program kan skicka tillstånd i begäranden och generera tillståndshändelser
  • Realtidsuppdateringar: Ändringar strömmas omedelbart med tillståndshändelser
  • Förutsägande uppdateringar: En SDK kan mappa förlopp för verktygsanrop till optimistiskt användargränssnittstillstånd
  • Strukturerade data: Tillståndet följer ett JSON-schema för validering

Användningsfall

Tillståndshantering är värdefullt för:

  • Generativt användargränssnitt: Skapa gränssnittskomponenter baserat på agentkontrollerat tillstånd
  • Formulärbyggnad: Agenten fyller i formulärfält när den samlar in information
  • Förloppsspårning: Visa realtidsförlopp för åtgärder i flera steg
  • Interaktiva instrumentpaneler: Visa data som uppdateras när agenten bearbetar dem
  • Samarbetsredigering: Flera användare ser konsekventa tillståndsuppdateringar

AG-UI-tillståndet är ett JSON-objekt som är synligt för klienten och kopplat till en körning. I .NET innehåller integreringen två explicita mekanismer:

  • Lässtatus som klienten tillhandahåller från den ursprungliga RunAgentInput.
  • Mappa valda verktygsanrop eller resultat till AG-UI-tillståndshändelser med AGUIStreamOptions.

Tillståndsmappning är valfri. Godtyckliga verktygsresultat omvandlas inte automatiskt till delat tillstånd.

Läs klienttillstånd

MapAGUIServer lagrar ursprunget RunAgentInputChatOptions. Om modellen behöver klientens aktuella tillstånd omger du basagenten med ett lättviktigt DelegatingAIAgent som hämtar tillståndet med TryGetRunAgentInput och lägger till det i modellens kontext:

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);

Den omslutande funktionen hanterar endast sökvägen för indata. Tillståndshändelseutsläpp förblir deklarativa genom AGUIStreamOptions, som visas i följande avsnitt. TryGetRunAgentInput läser indata som värdlagret lagras på ChatOptions.AdditionalProperties. Programkoden kommer inte åt ordlistan direkt.

Klienttillstånd är inte tillförlitlig indata i begäran. Verifiera dess form och värden innan du använder den i prompter, routning eller privilegierade åtgärder.

Generera en tillståndsögonblicksbild

Mappa ett verktygsresultat till STATE_SNAPSHOT när verktyget returnerar det fullständiga tillståndet:

using AGUI.Server;

AGUIStreamOptions streamOptions = new AGUIStreamOptions()
    .MapResultAsStateSnapshot("generate_recipe");

app.MapAGUIServer("/", agent).WithMetadata(streamOptions);

MapResultAsStateSnapshot kräver att värdet FunctionResultContent.Result är en JsonElement. Serialisera en POCO, ordlista eller samling till JsonElement i verktyget innan du returnerar den. Resultatet av generate_recipe blir sedan ögonblicksbilden och ersätter klientens aktuella delade tillstånd.

För andra resultattyper använder du MapResult med en anpassad mappare som konstruerar StateSnapshotEvent.

Generera tillståndsdelta

Mappa ett verktygsresultat till STATE_DELTA när det returnerar en RFC 6902 JSON-korrigering:

AGUIStreamOptions streamOptions = new AGUIStreamOptions()
    .MapResultAsStateSnapshot("create_plan")
    .MapResultAsStateDelta("update_plan_step");

app.MapAGUIServer("/", agent).WithMetadata(streamOptions);

Använd en ögonblicksbild för att initiera eller ersätta tillstånd och deltan för inkrementella ändringar.

MapResultAsStateDelta kräver också ett JsonElement resultat. Elementet måste innehålla en RFC 6902 JSON Patch-matris . Använd MapResult med en anpassad mappare om verktyget returnerar en annan representation.

Kartverktyget anropar till tillstånd

AGUIStreamOptions.MapCall kopplar en vald FunctionCallContent till ytterligare AG-UI-händelser som genereras efter de vanliga händelserna för verktygsanrop. Använd när tillståndet härleds från verktygsargument i stället för verktygsresultatet:

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);

Programmet äger mappningen och tillståndsformen. MapCall härleder inte tillstånd från godtyckliga verktygsargument eller undertrycker normal verktygskörning. Inkrementella uppdateringar kräver att den underliggande modellklienten exponerar strömmade verktygsanropsargument och programmet för att konfigurera motsvarande argumentextrahering.

Ta emot tillstånd i en .NET-klient

AG-UI .NET-klienten exponerar händelser i tillståndsprotokollet via 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;
    }
}

Klienten ansvarar för att behålla och tillämpa delat tillstånd och sedan skicka det aktuella tillståndet på senare begäranden när programmet kräver det.

Nästa steg

Definiera tillståndsmodeller

Definiera först Pydantiska modeller för din tillståndsstruktur. Detta säkerställer typsäkerhet och validering:

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")

Tillståndsschema

Definiera ett tillståndsschema för att ange strukturen och typerna av ditt tillstånd:

state_schema = {
    "recipe": {"type": "object", "description": "The current recipe"},
}

Anmärkning

Tillståndsschemat använder ett enkelt format med type och valfritt description. Den faktiska strukturen definieras av dina pydantiska modeller.

Uppdateringar av förutsägande tillstånd

Argument från verktyg för förutsägande tillstånd strömmar till tillståndet när LLM genererar dem, vilket möjliggör optimistiska uppdateringar av användargränssnittet.

predict_state_config = {
    "recipe": {"tool": "update_recipe", "tool_argument": "recipe"},
}

Den här konfigurationen mappar tillståndsfältet recipe till recipe verktygets update_recipe argument. När agenten anropar verktyget strömmas argumenten till tillståndet i realtid när LLM genererar dem.

Uppdateringsverktyg för statusdefiniering

Skapa en verktygsfunktion som accepterar din pydantiska modell:

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

Verktygsfunktionens parameternamn (recipe) måste matcha tool_argument i din predict_state_config.

Skapa agenten med tillståndshantering

Här är en fullständig serverimplementering med tillståndshantering:

"""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)

Viktiga begrepp

  • Pydantiska modeller: Definiera strukturerat tillstånd med typsäkerhet och validering
  • Tillståndsschema: Enkelt format som anger tillståndsfälttyper
  • Konfiguration för prediktivt tillstånd: Kartlägger tillståndsfält till verktygsargument för uppdateringar i realtid
  • Tillståndsinmatning: Aktuellt tillstånd matas automatiskt in som systemmeddelanden för att ge kontext
  • Fullständiga uppdateringar: Verktyg måste skriva hela tillståndet, inte bara delta
  • Bekräftelsestrategi: Anpassa godkännandemeddelanden för din domän (recept, dokument, uppgiftsplanering osv.)

Förstå tillståndshändelser

Tillståndsögonblickshändelse

En fullständig ögonblicksbild av det aktuella tillståndet som genereras när verktyget är klart:

{
    "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"
            ]
        }
    }
}

Tillståndsdeltahändelse

Inkrementella tillståndsuppdateringar med JSON Patch-format som genereras som verktygsargument i LLM-dataströmmar.

{
    "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"]
            }
        }
    ]
}

Anmärkning

Tillståndsdeltahändelser strömmas i realtid när LLM genererar verktygsargumenten, vilket ger optimistiska uppdateringar av användargränssnittet. Den slutliga tillståndsögonblicksbilden genereras när verktyget slutför körningen.

Kundimplementering

Paketet agent_framework_ag_ui tillhandahåller AGUIChatClient anslutning till AG-UI servrar, vilket ger Python-klientupplevelsen paritet med .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())

Viktiga fördelar

Tillhandahåller AGUIChatClient :

  • Förenklad anslutning: Automatisk hantering av HTTP/SSE-kommunikation
  • Trådhantering: Inbyggd tråd-ID-spårning för konversationskontinuitet
  • Agentintegrering: Fungerar sömlöst med Agent för välbekanta API
  • Tillståndshantering: Automatisk parsning av tillståndshändelser från servern
  • Paritet med .NET: Konsekvent upplevelse mellan olika språk

Tip

Använd AGUIChatClient med Agent för att få full nytta av agentramverkets funktioner som konversationshistorik, verktygskörning och stöd för mellanprogram.

Bekräftar förutsagt tillstånd

Ställ in require_confirmation=TrueAgentFrameworkAgent när förutsagda tillståndsändringar bör vänta på klientbekräftelse innan de tillämpas:

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,
)

Anpassa bekräftelsekopian i ditt AG-UI klientgränssnitt när du återger bekräftelsehändelsen.

Exempelinteraktion

När servern och klienten körs:

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

:state Använd kommandot för att visa det aktuella tillståndet när som helst under konversationen.

Prediktiva tillståndsuppdateringar i praktiken

När du använder prediktiva tillståndsuppdateringar med predict_state_config, tar klienten emot STATE_DELTA händelser när LLM genererar verktygsargument i realtid innan verktyget körs:

// 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

Detta gör det möjligt för klienten att visa optimistiska uppdateringar av användargränssnittet i realtid när agenten tänker, vilket ger omedelbar feedback till användarna.

Tillstånd med Human-in-the-Loop

Du kan kombinera tillståndshantering med arbetsflöden för godkännande genom att ange 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
)

När aktiverad:

  1. Tillståndsuppdateringar strömmar när agenten genererar verktygsargument (förutsägande uppdateringar via STATE_DELTA händelser)
  2. Agenten pausar innan verktyget körs med ett tool_call avbrott i RUN_FINISHED.outcome.interrupts
  3. Om det godkänns körs verktyget och det slutliga tillståndet genereras (via STATE_SNAPSHOT händelse)
  4. Om de avvisas ignoreras ändringarna av prediktivt tillstånd

Avancerade tillståndsmönster

Komplext tillstånd med flera fält

Du kan hantera flera tillståndsfält med olika verktyg:

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"},
    },
)

Använda jokerteckenverktygsargument

När ett verktyg returnerar komplexa kapslade data använder du "*" för att mappa alla verktygsargument för att ange:

@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": "*"}
}

Detta mappar hela verktygsanropet (alla argument) till tillståndsfältet document .

Metodtips

Använda pydantiska modeller

Definiera strukturerade modeller för typsäkerhet:

class Recipe(BaseModel):
    """Use Pydantic models for structured, validated state."""
    title: str
    skill_level: SkillLevel
    ingredients: list[Ingredient]
    instructions: list[str]

Fördelar:

  • Typsäkerhet: Automatisk validering av datatyper
  • Dokumentation: Fältbeskrivningar fungerar som dokumentation
  • IDE-stöd: Automatisk slutförande och typkontroll
  • Serialisering: Automatisk JSON-konvertering

Slutför tillståndsuppdateringar

Skriv alltid hela tillståndet, inte bara 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."

Detta säkerställer tillståndskonsekvens och korrekta prediktiva uppdateringar.

Matcha parameternamn

Se till att verktygets parameternamn matchar tool_argument konfigurationen:

# 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
}

Ange kontext i instruktioner

Ta med tydliga instruktioner om tillståndshantering:

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
    """,
    ...
)

Anpassa bekräftelsegränssnittet

Anpassa meddelanden om godkännande och tillståndsbekräftelse i din AG-UI-klient när du återger bekräftelsehändelser från servern.

Nästa steg

Nu har du lärt dig alla grundläggande AG-UI funktioner! Härnäst kan du:

Ytterligare resurser

Go AG-UI-tillståndshantering kan implementeras med mellanprogram som emitterar strukturerade message.DataContent-uppdateringar tillsammans med vanliga textuppdateringar.

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

Se exemplet för AG-UI-tillståndshantering för ett fullständigt körbart exempel.