Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El contexto en tiempo de ejecución proporciona middleware con acceso a información sobre el entorno de ejecución actual y la solicitud. Esto permite patrones como la configuración por sesión, el comportamiento específico del usuario y el comportamiento de middleware dinámico en función de las condiciones del tiempo de ejecución.
En C#, el contexto en tiempo de ejecución fluye a través de tres superficies principales:
-
AgentRunOptions.AdditionalPropertiespara los metadatos de clave-valor por ejecución que pueden leer el middleware y las herramientas. -
FunctionInvocationContextpara inspeccionar y modificar argumentos de llamada de herramienta dentro del middleware de invocación de función. -
AgentSession.StateBagpara el estado compartido que persiste entre ejecuciones dentro de una conversación.
Utilice la superficie más estrecha que se ajuste. Los metadatos por ejecución pertenecen a AdditionalProperties, el estado de conversación persistente pertenece a la manipulación de argumentos de herramienta y de StateBagla sesión pertenece al middleware de invocación de funciones.
Sugerencia
Consulte la página Ámbito de ejecución frente al agente para obtener información sobre cómo el ámbito de middleware afecta al acceso al contexto en tiempo de ejecución.
Elección de la superficie en tiempo de ejecución adecuada
| Caso de uso | Superficie de API | Acceso desde |
|---|---|---|
| Compartir el estado o los datos de conversación entre ejecuciones | AgentSession.StateBag |
session.StateBag en ejecución de middleware, AIAgent.CurrentRunContext?.Session en herramientas |
| Pasar metadatos por ejecución a middleware o herramientas | AgentRunOptions.AdditionalProperties |
options.AdditionalProperties en ejecución de middleware, AIAgent.CurrentRunContext?.RunOptions en herramientas |
| Inspección o modificación de argumentos de llamada de herramienta en middleware | FunctionInvocationContext |
Devolución de llamada de middleware de invocación de función |
Pasar valores por ejecución a través de AgentRunOptions
Úselo AdditionalProperties para AgentRunOptions adjuntar datos de clave-valor por ejecución. El middleware de invocación de función puede reenviar estos valores a argumentos de herramienta.
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);
Advertencia
DefaultAzureCredential es conveniente para el desarrollo, pero requiere una consideración cuidadosa en producción. En producción, considere usar una credencial específica (por ejemplo, ManagedIdentityCredential) para evitar problemas de latencia, sondeos de credenciales no deseados y posibles riesgos de seguridad de los mecanismos de respaldo.
El middleware lee los valores por ejecución a AgentRunOptions.AdditionalProperties través del ambiente AIAgent.CurrentRunContext e los inserta en el elemento antes de FunctionInvocationContext.Arguments que se ejecute la herramienta.
El middleware de invocación de función recibe contexto
El middleware de invocación de funciones usa FunctionInvocationContext para inspeccionar o modificar argumentos de herramienta, interceptar resultados o omitir completamente la ejecución de la herramienta.
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();
El middleware recibe el contexto de invocación de función y llama next a para continuar con la canalización. Muta antes context.Arguments de llamar a nexty la herramienta ve los valores actualizados.
Uso AgentSession.StateBag para el estado de tiempo de ejecución compartido
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"));
Pase la sesión explícitamente con session: y acceda a ella desde herramientas a través AIAgent.CurrentRunContext?.Sessionde .
StateBag proporciona almacenamiento seguro para subprocesos y con seguridad de tipos que se conserva entre ejecuciones dentro de la misma sesión.
Uso compartido del estado de sesión entre middleware y herramientas
Ejecutar middleware puede leer y escribir la sesión StateBag, y los cambios son visibles para el middleware y las herramientas de invocación de funciones que se ejecutan en la misma solicitud.
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"));
Ejecutar middleware recibe la sesión directamente como parámetro. Use StateBag.SetValue y GetValue para el acceso seguro de tipos. Los valores almacenados durante la fase de middleware de ejecución están disponibles para herramientas y middleware de invocación de funciones a través de AIAgent.CurrentRunContext?.Session.
El contexto en tiempo de ejecución de Python se divide en tres superficies públicas:
-
session=para el estado y el historial de la conversación. -
function_invocation_kwargs=para los valores que solo deben ver las herramientas o el middleware de funciones. -
client_kwargs=para la configuración de middleware específica del cliente o datos específicos del cliente.
Use la superficie más pequeña que se ajuste a los datos. Esto mantiene las entradas de herramienta explícitas y evita la pérdida de metadatos solo de cliente en la ejecución de la herramienta.
Sugerencia
Trate function_invocation_kwargs como reemplazo del patrón antiguo de pasar público **kwargs arbitrario a agent.run() o get_response().
Elección del cubo de tiempo de ejecución adecuado
| Caso de uso | Superficie de API | Acceso desde |
|---|---|---|
| Compartir el estado de la conversación, los identificadores de sesión de servicio o el historial | session= |
ctx.session, AgentContext.session |
| Pasar valores en tiempo de ejecución solo necesitan herramientas o middleware de función | function_invocation_kwargs= |
FunctionInvocationContext.kwargs |
| Pasar valores de tiempo de ejecución específicos del cliente o configuración de middleware de cliente | client_kwargs= |
implementaciones personalizadas get_response(..., client_kwargs=...) |
Pasar valores en tiempo de ejecución de solo herramienta
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)
Use ctx.kwargs dentro de la herramienta en lugar de declarar manta **kwargs en la herramienta invocable. Las herramientas heredadas **kwargs siguen funcionando por compatibilidad, pero se quitarán antes de la disponibilidad general.
Cualquier parámetro anotado como FunctionInvocationContext se trata como el parámetro de contexto en tiempo de ejecución insertado, independientemente de su nombre, y no se expone en el esquema JSON mostrado al modelo. Si proporciona un modelo de entrada o esquema explícito, también se reconoce un parámetro sin anotar sin formato denominado ctx como el parámetro de contexto insertado.
Si el valor es de estado de herramienta de larga duración o una dependencia en lugar de datos por invocación, manténgalo en una instancia de clase de herramienta en lugar de pasarlo a través function_invocation_kwargsde . Para ese patrón, consulte Creación de una clase con varias herramientas de función.
El middleware de función recibe el mismo contexto
El middleware de función usa el mismo FunctionInvocationContext objeto que reciben las herramientas. Esto significa que el middleware puede inspeccionar context.arguments, context.kwargs, context.sessiony 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],
)
El contrato de middleware usa call_next() sin argumentos.
context.kwargs Muta antes de llamarlo y la herramienta seleccionada ve esos valores a través de su insertadoFunctionInvocationContext.
Uso session= para el estado de tiempo de ejecución compartido
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"])
Pase la sesión explícitamente con session= y léela desde ctx.session. El acceso a la sesión ya no necesita viajar a través de los kwargs en tiempo de ejecución.
Uso compartido del estado de sesión con agentes delegados
Cuando un agente se expone como una herramienta a través as_tool()de , la función en tiempo de ejecución kwargs ya fluye a través de ctx.kwargs. Agregue propagate_session=True solo cuando el subagente debe compartir el autor de AgentSessionla llamada.
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,
)
Con propagate_session=True, el agente delegado ve el mismo ctx.session estado que el autor de la llamada. Déjelo False para aislar el agente secundario en su propia sesión.
Clientes y agentes de chat personalizados
Si implementa métodos o run() públicos get_response() personalizados, agregue los cubos de tiempo de ejecución explícitos a la firma.
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,
):
...
Use function_invocation_kwargs para flujos de invocación de herramientas y client_kwargs para el comportamiento específico del cliente. Pasar valores específicos del cliente directamente a través de public **kwargs es solo una ruta de compatibilidad y debe tratarse como en desuso. Del mismo modo, la definición de nuevas herramientas con **kwargs es la compatibilidad de solo migración: consume datos en tiempo de ejecución a través del objeto de contexto insertado en su lugar.