Bagikan melalui


Konteks Runtime

Konteks runtime menyediakan middleware dengan akses ke informasi tentang lingkungan dan permintaan eksekusi saat ini. Ini memungkinkan pola seperti konfigurasi per sesi, perilaku khusus pengguna, dan perilaku middleware dinamis berdasarkan kondisi runtime.

Di C#, konteks runtime mengalir melalui tiga permukaan utama:

  • AgentRunOptions.AdditionalProperties untuk metadata nilai kunci per jalankan yang dapat dibaca middleware dan alat.
  • FunctionInvocationContext untuk memeriksa dan memodifikasi argumen panggilan alat di dalam middleware pemanggilan fungsi.
  • AgentSession.StateBag untuk status bersama yang bertahan di seluruh eksekusi dalam percakapan.

Gunakan permukaan tersempit yang pas. Metadata per-eksekusi termasuk dalam AdditionalProperties, status percakapan persisten termasuk dalam StateBagsesi , dan manipulasi argumen alat milik middleware pemanggilan fungsi.

Petunjuk / Saran

Lihat halaman Agen vs Jalankan Cakupan untuk informasi tentang bagaimana cakupan middleware memengaruhi akses ke konteks runtime.

Pilih permukaan runtime yang tepat

Skenario penggunaan Permukaan API Diakses dari
Berbagi status percakapan atau data di seluruh eksekusi AgentSession.StateBag session.StateBag dalam menjalankan middleware, AIAgent.CurrentRunContext?.Session dalam alat
Meneruskan metadata per-eksekusi ke middleware atau alat AgentRunOptions.AdditionalProperties options.AdditionalProperties dalam menjalankan middleware, AIAgent.CurrentRunContext?.RunOptions dalam alat
Memeriksa atau mengubah argumen panggilan alat di middleware FunctionInvocationContext Panggilan balik middleware pemanggilan fungsi

Meneruskan nilai per-eksekusi melalui AgentRunOptions

Gunakan AdditionalProperties aktif AgentRunOptions untuk melampirkan data nilai kunci per-eksekusi. Middleware pemanggilan fungsi dapat meneruskan nilai-nilai ini ke dalam argumen alat.

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

Peringatan

DefaultAzureCredential nyaman untuk pengembangan tetapi membutuhkan pertimbangan yang cermat dalam produksi. Dalam produksi, pertimbangkan untuk menggunakan kredensial tertentu (misalnya, ManagedIdentityCredential) untuk menghindari masalah latensi, pemeriksaan kredensial yang tidak diinginkan, dan potensi risiko keamanan dari mekanisme fallback.

Middleware membaca nilai per-eksekusi dari AgentRunOptions.AdditionalProperties melalui sekitar AIAgent.CurrentRunContext dan menyuntikkannya ke alat FunctionInvocationContext.Arguments sebelum alat dijalankan.

Middleware pemanggilan fungsi menerima konteks

Middleware pemanggilan fungsi menggunakan FunctionInvocationContext untuk memeriksa atau memodifikasi argumen alat, mencegat hasil, atau melewati eksekusi alat sepenuhnya.

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 menerima konteks pemanggilan fungsi dan panggilan next untuk melanjutkan alur. Bermutasi context.Arguments sebelum memanggil next, dan alat melihat nilai yang diperbarui.

Gunakan AgentSession.StateBag untuk status runtime bersama

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

Teruskan sesi secara eksplisit dengan session: dan akses dari alat melalui AIAgent.CurrentRunContext?.Session. menyediakan StateBag penyimpanan aman jenis dan aman utas yang bertahan di seluruh eksekusi dalam sesi yang sama.

Berbagi status sesi di seluruh middleware dan alat

Menjalankan middleware dapat membaca dan menulis sesi StateBag, dan perubahan apa pun terlihat oleh middleware pemanggilan fungsi dan alat yang dijalankan dalam permintaan yang sama.

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

Jalankan middleware menerima sesi secara langsung sebagai parameter. Gunakan StateBag.SetValue dan GetValue untuk akses jenis aman. Nilai apa pun yang disimpan selama fase middleware eksekusi tersedia untuk alat dan middleware pemanggilan fungsi melalui AIAgent.CurrentRunContext?.Session.

Konteks runtime Python dibagi di tiga permukaan publik:

  • session= untuk status percakapan dan riwayat.
  • function_invocation_kwargs= untuk nilai yang hanya akan dilihat alat atau middleware fungsi.
  • client_kwargs= untuk data khusus klien obrolan atau konfigurasi middleware klien.

Gunakan permukaan terkecil yang sesuai dengan data. Ini membuat input alat tetap eksplisit dan menghindari kebocoran metadata khusus klien ke dalam eksekusi alat.

Petunjuk / Saran

Perlakukan function_invocation_kwargs sebagai pengganti pola lama dari meneruskan publik **kwargs arbitrer ke agent.run() atau get_response().

Pilih wadah runtime yang tepat

Skenario penggunaan Permukaan API Diakses dari
Bagikan status percakapan, ID sesi layanan, atau riwayat session= ctx.session, AgentContext.session
Meneruskan nilai runtime hanya alat atau kebutuhan middleware fungsi function_invocation_kwargs= FunctionInvocationContext.kwargs
Meneruskan nilai runtime khusus klien atau konfigurasi middleware klien client_kwargs= implementasi kustom get_response(..., client_kwargs=...)

Meneruskan nilai runtime khusus alat

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)

Gunakan ctx.kwargs di dalam alat alih-alih mendeklarasikan selimut **kwargs pada alat yang dapat dipanggil. Alat warisan **kwargs masih berfungsi untuk kompatibilitas, tetapi akan dihapus sebelum GA.

Parameter apa pun yang dianotasi seperti FunctionInvocationContext yang diperlakukan sebagai parameter konteks runtime yang disuntikkan, terlepas dari namanya, dan tidak diekspos dalam skema JSON yang ditunjukkan ke model. Jika Anda memberikan model skema/input eksplisit, parameter tanpa anotasi biasa bernama ctx juga dikenali sebagai parameter konteks yang disuntikkan.

Jika nilainya adalah status alat berumur panjang atau dependensi daripada data per pemanggilan, simpan pada instans kelas alat alih-alih meneruskannya melalui function_invocation_kwargs. Untuk pola tersebut, lihat Membuat kelas dengan beberapa alat fungsi.

Middleware fungsi menerima konteks yang sama

Middleware fungsi menggunakan objek yang sama FunctionInvocationContext dengan yang diterima alat. Itu berarti middleware dapat memeriksa context.arguments, , context.kwargscontext.session, dan 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],
)

Kontrak middleware menggunakan call_next() tanpa argumen. Bermutasi context.kwargs sebelum memanggilnya, dan alat yang dipilih melihat nilai-nilai tersebut melalui yang disuntikkan FunctionInvocationContext.

Gunakan session= untuk status runtime bersama

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

Berikan sesi secara eksplisit dengan session= dan baca dari ctx.session. Akses sesi tidak perlu lagi melakukan perjalanan melalui kwarg runtime.

Berbagi status sesi dengan agen yang didelegasikan

Ketika agen diekspos sebagai alat melalui as_tool(), fungsi runtime kwargs sudah mengalir melalui ctx.kwargs. Tambahkan propagate_session=True hanya ketika sub-agen harus berbagi penelepon 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,
)

Dengan , agen yang didelegasikan melihat status yang sama propagate_session=True dengan ctx.sessionpemanggil. False Biarkan untuk mengisolasi agen anak dalam sesinya sendiri.

Klien dan agen obrolan kustom

Jika Anda menerapkan publik run() atau get_response() metode kustom, tambahkan wadah runtime eksplisit ke tanda tangan.

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

Gunakan function_invocation_kwargs untuk alur pemanggilan alat dan client_kwargs untuk perilaku khusus klien. Meneruskan nilai khusus klien secara langsung melalui publik **kwargs hanyalah jalur kompatibilitas dan harus diperlakukan sebagai tidak digunakan lagi. Demikian juga, menentukan alat baru dengan **kwargs adalah kompatibilitas khusus migrasi — gunakan data runtime melalui objek konteks yang disuntikkan sebagai gantinya.

Langkah selanjutnya