Kontext modulu runtime

Kontext modulu runtime poskytuje middleware s přístupem k informacím o aktuálním spouštěcím prostředí a požadavku. To umožňuje vzory, jako je konfigurace relace, chování specifické pro uživatele a dynamické chování middlewaru na základě podmínek za běhu.

V jazyce C# kontext modulu runtime prochází třemi hlavními plochami:

  • AgentRunOptions.AdditionalProperties pro metadata klíč-hodnota pro spuštění, která middleware a nástroje mohou číst.
  • FunctionInvocationContext pro kontrolu a úpravu argumentů volání nástroje uvnitř middlewaru vyvolání funkce.
  • AgentSession.StateBag pro sdílený stav, který přetrvává napříč běhy v rámci konverzace.

Použijte nejužší povrch, který se vejde. Metadata pro jednotlivé spuštění patří do AdditionalProperties, trvalý stav konverzace patří do relace StateBaga manipulace s argumenty nástroje patří do middlewaru vyvolání funkce.

Návod

Informace o tom, jak rozsah middlewaru ovlivňuje přístup k kontextu modulu runtime, najdete na stránce Agent vs. Spustit obor .

Volba vhodné plochy modulu runtime

Případ použití Plocha rozhraní API Přístup z
Sdílení stavu konverzace nebo dat napříč spuštěními AgentSession.StateBag session.StateBag ve spuštění middlewaru AIAgent.CurrentRunContext?.Session v nástrojích
Předání metadat pro jednotlivé spuštění middlewaru nebo nástrojům AgentRunOptions.AdditionalProperties options.AdditionalProperties ve spuštění middlewaru AIAgent.CurrentRunContext?.RunOptions v nástrojích
Kontrola nebo úprava argumentů volání nástroje v middlewaru FunctionInvocationContext Zpětné volání middlewaru funkce

Předání hodnot pro jednotlivé spuštění prostřednictvím AgentRunOptions

AgentRunOptions Používá AdditionalProperties se k připojení dat klíč-hodnota pro jednotlivé spuštění. Middleware vyvolání funkce může tyto hodnoty předat do argumentů nástroje.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

[Description("Send an email to the specified address.")]
static string SendEmail(
    [Description("Recipient email address.")] string address,
    [Description("User ID of the sender.")] string userId,
    [Description("Tenant name.")] string tenant = "default")
{
    return $"Queued email for {address} from {userId} ({tenant})";
}

// Function invocation middleware that injects per-run values into tool arguments
async ValueTask<object?> InjectRunContext(
    AIAgent agent,
    FunctionInvocationContext context,
    Func<FunctionInvocationContext, CancellationToken, ValueTask<object?>> next,
    CancellationToken cancellationToken)
{
    var runOptions = AIAgent.CurrentRunContext?.RunOptions;
    if (runOptions?.AdditionalProperties is { } props)
    {
        if (props.TryGetValue("user_id", out var userId))
        {
            context.Arguments["userId"] = userId;
        }

        if (props.TryGetValue("tenant", out var tenant))
        {
            context.Arguments["tenant"] = tenant;
        }
    }

    return await next(context, cancellationToken);
}

AIAgent baseAgent = new AIProjectClient(
    new Uri("<your-foundry-project-endpoint>"),
    new DefaultAzureCredential())
        .AsAIAgent(
            model: "gpt-4o-mini",
            instructions: "Send email updates.",
            tools: [AIFunctionFactory.Create(SendEmail)]);

var agent = baseAgent
    .AsBuilder()
        .Use(InjectRunContext)
    .Build();

var response = await agent.RunAsync(
    "Email the launch update to finance@example.com",
    options: new AgentRunOptions
    {
        AdditionalProperties = new AdditionalPropertiesDictionary
        {
            ["user_id"] = "user-123",
            ["tenant"] = "contoso",
        }
    });

Console.WriteLine(response);

Výstraha

DefaultAzureCredential je vhodný pro vývoj, ale vyžaduje pečlivé zvážení v produkčním prostředí. V produkčním prostředí zvažte použití konkrétních přihlašovacích údajů (např ManagedIdentityCredential. ) k zabránění problémům s latencí, neúmyslnému testování přihlašovacích údajů a potenciálním bezpečnostním rizikům z náhradních mechanismů.

Middleware čte hodnoty AgentRunOptions.AdditionalProperties pro jednotlivé spuštění z okolí AIAgent.CurrentRunContext a vloží je do nástroje FunctionInvocationContext.Arguments před spuštěním nástroje.

Middleware vyvolání funkce přijímá kontext.

Middleware vyvolání funkce používá FunctionInvocationContext ke kontrole nebo úpravě argumentů nástroje, zachycení výsledků nebo přeskočení provádění nástrojů úplně.

using System;
using System.Threading;
using System.Threading.Tasks;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

async ValueTask<object?> EnrichToolContext(
    AIAgent agent,
    FunctionInvocationContext context,
    Func<FunctionInvocationContext, CancellationToken, ValueTask<object?>> next,
    CancellationToken cancellationToken)
{
    if (!context.Arguments.ContainsKey("tenant"))
    {
        context.Arguments["tenant"] = "contoso";
    }

    if (!context.Arguments.ContainsKey("requestSource"))
    {
        context.Arguments["requestSource"] = "middleware";
    }

    return await next(context, cancellationToken);
}

AIAgent baseAgent = new AIProjectClient(
    new Uri("<your-foundry-project-endpoint>"),
    new DefaultAzureCredential())
        .AsAIAgent(
            model: "gpt-4o-mini",
            instructions: "Send email updates.",
            tools: [AIFunctionFactory.Create(SendEmail)]);

var agent = baseAgent
    .AsBuilder()
        .Use(EnrichToolContext)
    .Build();

Middleware obdrží kontext vyvolání funkce a volání next pro pokračování kanálu. Před voláním nextztlumte context.Arguments a nástroj zobrazí aktualizované hodnoty.

Použití AgentSession.StateBag pro sdílený stav modulu runtime

using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

[Description("Store the specified topic in session state.")]
static string RememberTopic(
    [Description("Topic to remember.")] string topic)
{
    var session = AIAgent.CurrentRunContext?.Session;
    if (session is null)
    {
        return "No session available.";
    }

    session.StateBag.SetValue("topic", topic);
    return $"Stored '{topic}' in session state.";
}

AIAgent agent = new AIProjectClient(
    new Uri("<your-foundry-project-endpoint>"),
    new DefaultAzureCredential())
        .AsAIAgent(
            model: "gpt-4o-mini",
            instructions: "Remember important topics.",
            tools: [AIFunctionFactory.Create(RememberTopic)]);

var session = await agent.CreateSessionAsync();
await agent.RunAsync("Remember that the budget review is on Friday.", session: session);
Console.WriteLine(session.StateBag.GetValue<string>("topic"));

Předat relaci explicitně session: a přistupovat k ní z nástrojů prostřednictvím AIAgent.CurrentRunContext?.Session. Poskytuje StateBag typově bezpečné úložiště bezpečné pro přístup z více vláken, které se udržuje napříč běhy ve stejné relaci.

Sdílení stavu relace napříč middlewarem a nástroji

Spuštění middlewaru může číst a zapisovat relace StateBaga všechny změny jsou viditelné pro vyvolání middlewaru a nástrojů spuštěných ve stejném požadavku.

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

// Run middleware that stamps the session with request metadata
async Task<AgentResponse> StampRequestMetadata(
    IEnumerable<ChatMessage> messages,
    AgentSession? session,
    AgentRunOptions? options,
    AIAgent innerAgent,
    CancellationToken cancellationToken)
{
    if (session is not null && options?.AdditionalProperties is { } props)
    {
        if (props.TryGetValue("request_id", out var requestId))
        {
            session.StateBag.SetValue("requestId", requestId?.ToString());
        }
    }

    return await innerAgent.RunAsync(messages, session, options, cancellationToken);
}

AIAgent baseAgent = new AIProjectClient(
    new Uri("<your-foundry-project-endpoint>"),
    new DefaultAzureCredential())
        .AsAIAgent(
            model: "gpt-4o-mini",
            instructions: "You are a helpful assistant.");

var agent = baseAgent
    .AsBuilder()
        .Use(runFunc: StampRequestMetadata, runStreamingFunc: null)
    .Build();

var session = await agent.CreateSessionAsync();
await agent.RunAsync(
    "Hello!",
    session: session,
    options: new AgentRunOptions
    {
        AdditionalProperties = new AdditionalPropertiesDictionary
        {
            ["request_id"] = "req-abc-123",
        }
    });

Console.WriteLine(session.StateBag.GetValue<string>("requestId"));

Spuštění middlewaru přijme relaci přímo jako parametr. Používejte StateBag.SetValue a GetValue pro typově bezpečný přístup. Všechny hodnoty uložené během fáze middlewaru spuštění jsou k dispozici nástrojům a funkci vyvolání middlewaru prostřednictvím AIAgent.CurrentRunContext?.Session.

Kontext modulu runtime Pythonu je rozdělený mezi tři veřejné plochy:

  • session= pro stav konverzace a historii.
  • function_invocation_kwargs= pro hodnoty, které by měly vidět pouze nástroje nebo middleware funkcí.
  • client_kwargs= pro konfiguraci middlewaru specifického pro chat klienta nebo klienta.

Použijte nejmenší povrch, který odpovídá datům. Díky tomu jsou vstupy nástrojů explicitní a zabraňuje úniku metadat pouze klienta do provádění nástrojů.

Návod

Považovat function_invocation_kwargs za náhradu za starý vzor předávání libovolných veřejných **kwargs nebo agent.run()get_response().

Volba správného kontejneru modulu runtime

Případ použití Plocha rozhraní API Přístup z
Sdílení stavu konverzace, ID relací služby nebo historie session= ctx.session, AgentContext.session
Předání hodnot modulu runtime pouze nástrojům nebo middlewaru funkcí function_invocation_kwargs= FunctionInvocationContext.kwargs
Předání hodnot modulu runtime specifických pro klienta nebo konfigurace middlewaru klienta client_kwargs= vlastní get_response(..., client_kwargs=...) implementace

Předání hodnot modulu runtime jen pro nástroj

from typing import Annotated

from agent_framework import FunctionInvocationContext, tool
from agent_framework.openai import OpenAIChatClient


@tool(approval_mode="never_require")
def send_email(
    address: Annotated[str, "Recipient email address."],
    ctx: FunctionInvocationContext,
) -> str:
    user_id = ctx.kwargs["user_id"]
    tenant = ctx.kwargs.get("tenant", "default")
    return f"Queued email for {address} from {user_id} ({tenant})"


agent = OpenAIChatClient().as_agent(
    name="Notifier",
    instructions="Send email updates.",
    tools=[send_email],
)

response = await agent.run(
    "Email the launch update to finance@example.com",
    function_invocation_kwargs={
        "user_id": "user-123",
        "tenant": "contoso",
    },
)

print(response.text)

Používejte ctx.kwargs uvnitř nástroje místo deklarování deky **kwargs na volatelném nástroji. Starší **kwargs nástroje stále fungují kvůli kompatibilitě, ale před ga se odeberou.

Jakýkoli parametr, který FunctionInvocationContext je označený jako vložený kontextový parametr modulu runtime bez ohledu na jeho název, a není vystavený ve schématu JSON zobrazeném modelu. Pokud zadáte explicitní model schématu nebo vstupu, je jako vložený kontextový parametr rozpoznán také prostý neoznačený ctx parametr.

Pokud je hodnota dlouhodobý stav nástroje nebo závislost místo dat pro vyvolání, nechejte ji na instanci function_invocation_kwargstřídy nástroje místo předávání . Tento vzor najdete v tématu Vytvoření třídy s více nástroji funkcí.

Middleware funkce přijímá stejný kontext.

Middleware funkce používá stejný FunctionInvocationContext objekt, který nástroje přijímají. To znamená, že middleware může kontrolovat context.arguments, context.kwargs, context.sessiona context.result.

from collections.abc import Awaitable, Callable

from agent_framework import FunctionInvocationContext
from agent_framework.openai import OpenAIChatClient


async def enrich_tool_runtime_context(
    context: FunctionInvocationContext,
    call_next: Callable[[], Awaitable[None]],
) -> None:
    context.kwargs.setdefault("tenant", "contoso")
    context.kwargs.setdefault("request_source", "middleware")
    await call_next()


agent = OpenAIChatClient().as_agent(
    name="Notifier",
    instructions="Send email updates.",
    tools=[send_email],
    middleware=[enrich_tool_runtime_context],
)

Kontrakt middlewaru používá call_next() bez argumentů. Před voláním ztlumte context.kwargs a vybraný nástroj tyto hodnoty zobrazí prostřednictvím injektáže FunctionInvocationContext.

Použití session= pro sdílený stav modulu runtime

from typing import Annotated

from agent_framework import FunctionInvocationContext, tool
from agent_framework.openai import OpenAIChatClient


@tool(approval_mode="never_require")
def remember_topic(
    topic: Annotated[str, "Topic to remember."],
    ctx: FunctionInvocationContext,
) -> str:
    if ctx.session is None:
        return "No session available."

    ctx.session.state["topic"] = topic
    return f"Stored {topic!r} in session state."


agent = OpenAIChatClient().as_agent(
    name="MemoryAgent",
    instructions="Remember important topics.",
    tools=[remember_topic],
)

session = agent.create_session()
await agent.run("Remember that the budget review is on Friday.", session=session)
print(session.state["topic"])

Předat relaci explicitně session= a číst z ctx.session. Přístup k relacím už nemusí procházet moduly runtime kwargs.

Sdílení stavu relace s delegovanými agenty

Když je agent vystaven jako nástroj prostřednictvím as_tool(), funkce runtime kwargs již prochází ctx.kwargs. Přidat propagate_session=True pouze tehdy, když má sub-agent sdílet volajícího AgentSession.

from agent_framework import FunctionInvocationContext, tool
from agent_framework.openai import OpenAIChatClient


@tool(description="Store findings for later steps.")
def store_findings(findings: str, ctx: FunctionInvocationContext) -> None:
    if ctx.session is not None:
        ctx.session.state["findings"] = findings


client = OpenAIChatClient()

research_agent = client.as_agent(
    name="ResearchAgent",
    instructions="Research the topic and store findings.",
    tools=[store_findings],
)

research_tool = research_agent.as_tool(
    name="research",
    description="Research a topic and store findings.",
    arg_name="query",
    propagate_session=True,
)

U propagate_session=Truedelegovaného agenta se zobrazí stejný ctx.session stav jako volající. False Ponechte ho tak, aby izoloval podřízeného agenta ve vlastní relaci.

Vlastní chatovací klienti a agenti

Pokud implementujete vlastní veřejné run() nebo get_response() metody, přidejte do podpisu explicitní kontejnery modulu runtime.

from collections.abc import Mapping, Sequence
from typing import Any

from agent_framework import ChatOptions, Message


async def get_response(
    self,
    messages: Sequence[Message],
    *,
    options: ChatOptions[Any] | None = None,
    function_invocation_kwargs: Mapping[str, Any] | None = None,
    client_kwargs: Mapping[str, Any] | None = None,
    **kwargs: Any,
):
    ...

Používá se function_invocation_kwargs pro toky volání nástrojů a client_kwargs pro chování specifické pro klienta. Předávání hodnot specifických pro klienta přímo prostřednictvím veřejného **kwargs je pouze cesta kompatibility a měla by se považovat za zastaralá. Stejně tak definování nových nástrojů s kompatibilitou pouze s **kwargs migrací – místo toho spotřebovávají data modulu runtime prostřednictvím vloženého objektu kontextu.

Další kroky

poskytovatelé