Statusbeheer met AG-UI

AG-UI definieert status gebeurtenissen en aanvraagvelden voor het delen van de toepassingsstatus tussen een client en een agenteindpunt. De implementatie en ondersteunde statuspatronen variëren per MAF SDK.

Prerequisites

Voordat u begint, moet u het volgende begrijpen:

Wat is State Management?

AG-UI status kan het volgende bieden:

  • Gedeelde status: zowel client als server onderhouden een gesynchroniseerde weergave van de toepassingsstatus
  • Client- en serverupdates: toepassingen kunnen status verzenden in aanvragen en status gebeurtenissen verzenden
  • Realtime updates: wijzigingen worden onmiddellijk gestreamd met statusgebeurtenissen
  • Voorspellende updates: een SDK kan de voortgang van hulpprogramma-aanroepen toewijzen aan optimistische UI-status
  • Structured Data: State volgt een JSON-schema voor validatie

Gebruiksvoorbeelden

Staatbeheer is waardevol voor:

  • Generatieve gebruikersinterface: UI-onderdelen bouwen op basis van door agents beheerde status
  • Formulieropbouw: Agent vult formuliervelden in terwijl deze informatie verzamelt
  • Voortgang bijhouden: realtime voortgang van bewerkingen met meerdere stappen weergeven
  • Interactieve dashboards: gegevens weergeven die worden bijgewerkt wanneer de agent deze verwerkt
  • Gezamenlijke bewerking: meerdere gebruikers zien consistente statusupdates

AG-UI-toestand is JSON die zichtbaar is voor de client en gekoppeld is aan een uitvoering. In .NET biedt de integratie twee expliciete mechanismen:

  • Leesstatus aangeleverd door de client van de oorspronkelijke RunAgentInput.
  • Wijs geselecteerde toolaanroepen of resultaten toe aan AG-UI-statusgebeurtenissen met AGUIStreamOptions.

Toewijzing van statussen is optioneel. De resultaten van willekeurige hulpprogramma's worden niet automatisch gedeeld.

Clientstatus lezen

MapAGUIServer slaat de oorspronkelijke RunAgentInput op ChatOptions. Als het model de huidige status van de client nodig heeft, verpakt u de basisagent met een lichtgewicht DelegatingAIAgent waarmee de status TryGetRunAgentInput wordt hersteld en voegt u deze toe aan de modelcontext:

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

De wrapper verwerkt alleen het invoerpad. Statusgebeurtenisuitgifte blijft declaratief via AGUIStreamOptions, zoals wordt weergegeven in de volgende secties. TryGetRunAgentInput leest de invoer op die door de hostinglaag is opgeslagen ChatOptions.AdditionalProperties; toepassingscode heeft geen rechtstreeks toegang tot die woordenlijst.

Clientstatus is niet-vertrouwde aanvraaginvoer. Valideer de vorm en de waarden ervan voordat u het gebruikt in prompts, routering of geprivilegieerde bewerkingen.

Een momentopname van de status verzenden

Koppel een toolresultaat aan STATE_SNAPSHOT wanneer de tool de volledige status retourneert:

using AGUI.Server;

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

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

MapResultAsStateSnapshot vereist dat de waarde FunctionResultContent.Result een JsonElement is. Serialiseer een POCO, woordenlijst of verzameling in JsonElement het hulpprogramma voordat u deze retourneert. Het resultaat van generate_recipe wordt vervolgens de snapshot en vervangt de huidige gedeelde status van de client.

Gebruik voor andere resultaattypen MapResult met een aangepaste mapper die de StateSnapshotEvent opbouwt.

Statusdelta's verzenden

Wijs een hulpprogrammaresultaat toe aan STATE_DELTA wanneer deze een RFC 6902 JSON-patch retourneert:

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

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

Gebruik een momentopname om de status en delta's te initialiseren of te vervangen voor incrementele wijzigingen.

MapResultAsStateDelta vereist ook een JsonElement resultaat. Het element moet een RFC 6902 JSON Patch-matrix bevatten. Gebruik MapResult met een aangepaste mapper als het hulpprogramma een andere representatie teruggeeft.

Toolaanroepen toewijzen aan toestand

AGUIStreamOptions.MapCall koppelt een geselecteerd FunctionCallContent aan extra AG-UI-gebeurtenissen die worden gegenereerd na de normale toolaanroepgebeurtenissen. Gebruik deze wanneer de status is afgeleid van hulpprogrammaargumenten in plaats van het resultaat van het hulpprogramma:

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

De toepassing beheert de koppeling en de vorm van de status. MapCall leidt geen status af uit willekeurige toolargumenten en onderdrukt ook de normale uitvoering van tools niet. Incrementele updates vereisen dat de onderliggende modelclient gestreamde argumenten voor het aanroepen van hulpprogramma's beschikbaar maakt en de toepassing om de bijbehorende argumentextractie te configureren.

Status ontvangen in een .NET-client

De AG-UI .NET client geeft statusprotocol-gebeurtenissen weer viaChatResponseUpdate.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;
    }
}

De client is verantwoordelijk voor het behouden en toepassen van de gedeelde status en verzendt vervolgens de huidige status op latere aanvragen wanneer de toepassing dit vereist.

Volgende stappen 

Statusmodellen definiëren

Definieer eerst Pydantic-modellen voor uw statusstructuur. Dit zorgt voor de veiligheid en validatie van het type:

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

Definieer een statusschema om de structuur en typen van uw status op te geven:

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

Opmerking

Het statusschema maakt gebruik van een eenvoudige indeling met type en optioneel description. De werkelijke structuur wordt gedefinieerd door uw Pydantic-modellen.

Voorspellende statusupdates

Stream hulpprogramma-argumenten voor voorspellende statusupdates naar de status terwijl de LLM deze genereert, waardoor optimistische UI-updates mogelijk zijn.

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

Met deze configuratie wordt het recipe statusveld toegewezen aan het recipe argument van het update_recipe hulpprogramma. Wanneer de agent het hulpprogramma aanroept, worden de argumenten in realtime naar de status gestreamd terwijl de LLM deze genereert.

Definieer Hulpmiddel voor Het Bijwerken van de Toestand

Maak een hulpprogrammafunctie die uw Pydantic-model accepteert:

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

Belangrijk

De parameternaam (recipe) van de functie van het hulpprogramma moet overeenkomen met de tool_argument naam in uw predict_state_config.

De agent maken met State Management

Hier volgt een volledige server-implementatie met statusbeheer:

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

Belangrijkste concepten

  • Pydantic Models: Gestructureerde status definiëren met typeveiligheid en validatie
  • Statusschema: Eenvoudige indeling waarin statusveldtypen worden opgegeven
  • Voorspellende statusconfiguratie: Wijst statusvelden toe aan hulpprogrammaargumenten voor streaming-updates
  • Statusinjectie: de huidige status wordt automatisch geïnjecteerd als systeemberichten om context te bieden
  • Volledige updates: Hulpprogramma's moeten de volledige status schrijven, niet alleen delta's
  • Bevestigingsstrategie: Goedkeuringsberichten aanpassen voor uw domein (recept, document, taakplanning, enzovoort)

Toestandevenementen begrijpen

Momentopname van status gebeurtenis

Een volledige momentopname van de huidige status die wordt verzonden wanneer het hulpprogramma is voltooid:

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

Toestandsdelta-gebeurtenis

Incrementele statusupdates met de JSON Patch-indeling, verzonden als de hulpprogrammaargumenten voor LLM-streams:

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

Opmerking

Toestand delta-gebeurtenissen worden in realtime gestreamd terwijl de LLM de toolargumenten genereert, met optimistische gebruikersinterface-updates. De laatste momentopname van de status wordt verzonden wanneer het hulpprogramma de uitvoering voltooit.

Client-implementatie

Het agent_framework_ag_ui pakket biedt AGUIChatClient om verbinding te maken met AG-UI-servers, waardoor de Python-clientervaring gelijkwaardig wordt aan die van .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())

Belangrijkste voordelen

De AGUIChatClient biedt:

  • Vereenvoudigde verbinding: Automatische verwerking van HTTP/SSE-communicatie
  • Threadbeheer: ingebouwde thread-id-tracering voor gesprekscontinuïteit
  • Agentintegratie: werkt naadloos samen met Agent vertrouwde API
  • Statusafhandeling: Automatisch parseren van status gebeurtenissen van de server
  • Pariteit met .NET: Consistente ervaring in verschillende talen

Tip

Gebruik AGUIChatClient en Agent om ten volle te profiteren van de functies van het agent-framework, zoals gespreksgeschiedenis, uitvoering van hulpprogramma's en middleware-ondersteuning.

Voorspelde status bevestigen

require_confirmation=True Instellen AgentFrameworkAgent wanneer voorspelde statuswijzigingen moeten wachten op clientbevestiging voordat ze worden toegepast:

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

Pas de bevestigingstekst aan in de UI van uw AG-UI-client wanneer u het bevestigingsevent rendert.

Voorbeeldinteractie

Met de server en client in werking:

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

Gebruik de :state opdracht om de huidige status op elk gewenst moment tijdens het gesprek weer te geven.

Voorspellende statusupdates in actie

Wanneer u voorspellende statusupdates predict_state_config gebruikt, STATE_DELTAontvangt de client gebeurtenissen wanneer de LLM hulpprogrammaargumenten in realtime genereert voordat het hulpprogramma wordt uitgevoerd:

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

Hierdoor kan de client optimistische UI-updates in realtime laten zien terwijl de agent denkt, zodat de gebruiker onmiddellijk feedback kan geven.

State met Mens-in-the-Loop

U kunt statusbeheer combineren met goedkeuringswerkstromen door het volgende in te stellen 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
)

Wanneer deze functie is ingeschakeld:

  1. Statusupdates worden gestreamd terwijl de agent hulpprogrammaargumenten genereert (voorspellende updates via STATE_DELTA gebeurtenissen)
  2. Agent pauzeert voordat de tool wordt uitgevoerd met een tool_call interrupt in RUN_FINISHED.outcome.interrupts
  3. Indien goedgekeurd, wordt het hulpprogramma uitgevoerd en wordt de uiteindelijke status verzonden (via STATE_SNAPSHOT gebeurtenis)
  4. Als de voorspellingsstatus wordt afgewezen, worden de wijzigingen genegeerd.

Geavanceerde statuspatronen

Complexe status met meerdere velden

U kunt meerdere statusvelden beheren met verschillende hulpprogramma's:

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

Gebruik van argumenten voor wildcards

Wanneer een hulpprogramma complexe geneste gegevens retourneert, gebruikt u "*" om alle hulpprogrammaargumenten toe te wijzen aan de status.

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

Hiermee wordt de hele aanroep (alle argumenten) toegewezen aan het document statusveld.

Beste praktijken

Pydantic-modellen gebruiken

Gestructureerde modellen definiëren voor typeveiligheid:

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

Voordelen:

  • Typeveiligheid: Automatische validatie van gegevenstypen
  • Documentatie: Veldbeschrijvingen dienen als documentatie
  • IDE-ondersteuning: Automatische voltooiing en typecontrole
  • Serialisatie: Automatische JSON-conversie

Volledige statusupdates

Schrijf altijd de volledige status, niet alleen delta's:

@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."

Dit zorgt voor statusconsistentie en de juiste voorspellende updates.

Overeenkomende parameternamen

Zorg ervoor dat de namen van de parameters overeenkomen met de tool_argument configuratie:

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

Context opgeven in instructies

Neem duidelijke instructies over statusbeheer op:

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

Bevestigingsinterface aanpassen

Pas goedkeurings- en statusbevestigingsberichten aan in uw AG-UI-client wanneer bevestigingsgebeurtenissen van de server worden weergegeven.

Volgende stappen

U hebt nu alle kernfuncties AG-UI geleerd. Vervolgens kunt u het volgende doen:

Aanvullende bronnen

Go AG-UI statusbeheer kan worden geïmplementeerd met middleware die gestructureerde message.DataContent updates verzendt naast normale tekstupdates.

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

Zie het voorbeeld vanAG-UI statusbeheer voor een volledig voorbeeld dat kan worden uitgevoerd.