Partager via


Contexte d’exécution

Le contexte d’exécution fournit un intergiciel avec accès aux informations relatives à l’environnement d’exécution actuel et à la demande. Cela permet des modèles tels que la configuration par session, le comportement spécifique à l’utilisateur et le comportement du middleware dynamique en fonction des conditions d’exécution.

En C#, le contexte d’exécution est généralement passé par le biais AgentRunOptions ou l’état de session personnalisé. Le middleware peut accéder aux propriétés de session et exécuter des options pour prendre des décisions d’exécution.

Conseil / Astuce

Pour plus d’informations sur la façon dont l’étendue d’intergiciel affecte l’accès au contexte d’exécution, consultez la page Agent vs Run Scope .

Le contexte d’exécution Python est divisé sur trois surfaces publiques :

  • session= pour l’état et l’historique des conversations.
  • function_invocation_kwargs= pour les valeurs que seuls les outils ou les intergiciels de fonction doivent voir.
  • client_kwargs= pour la configuration des intergiciels client ou des données spécifiques au client.

Utilisez la plus petite surface qui correspond aux données. Cela permet de conserver les entrées d’outils explicites et d’éviter la fuite de métadonnées client uniquement dans l’exécution de l’outil.

Conseil / Astuce

Traitez function_invocation_kwargs comme le remplacement de l’ancien modèle de passage arbitraire public **kwargs à agent.run() ou get_response().

Choisir le compartiment d’exécution approprié

Cas d’utilisation Surface d’API Accès à partir de
Partager l’état de conversation, les ID de session de service ou l’historique session= ctx.session, AgentContext.session
Transmettre des valeurs d’exécution uniquement aux outils ou intergiciels de fonction function_invocation_kwargs= FunctionInvocationContext.kwargs
Passer des valeurs d’exécution spécifiques au client ou à la configuration du middleware client client_kwargs= implémentations personnalisées get_response(..., client_kwargs=...)

Passer des valeurs d’exécution d’outil uniquement

from typing import Annotated

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


@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 = OpenAIResponsesClient().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)

Utilisez ctx.kwargs à l’intérieur de l’outil au lieu de déclarer une couverture **kwargs sur l’outil pouvant être appelé. Les outils hérités **kwargs fonctionnent toujours pour la compatibilité, mais seront supprimés avant la disponibilité générale.

Tout paramètre annoté comme FunctionInvocationContext étant traité comme le paramètre de contexte d’exécution injecté, quel que soit son nom et n’est pas exposé dans le schéma JSON affiché au modèle. Si vous fournissez un modèle de schéma/d’entrée explicite, un paramètre non annoté brut nommé ctx est également reconnu comme paramètre de contexte injecté.

Si la valeur est un état d’outil de longue durée ou une dépendance plutôt que des données par appel, conservez-la sur une instance de classe d’outil au lieu de la function_invocation_kwargstransmettre. Pour ce modèle, consultez Créer une classe avec plusieurs outils de fonction.

L’intergiciel de fonction reçoit le même contexte

L’intergiciel de fonction utilise le même FunctionInvocationContext objet que celui reçu par les outils. Cela signifie que le middleware peut inspecter context.arguments, context.kwargs, context.sessionet context.result.

from collections.abc import Awaitable, Callable

from agent_framework import FunctionInvocationContext
from agent_framework.openai import OpenAIResponsesClient


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 = OpenAIResponsesClient().as_agent(
    name="Notifier",
    instructions="Send email updates.",
    tools=[send_email],
    middleware=[enrich_tool_runtime_context],
)

Le contrat d’intergiciel utilise call_next() sans argument. Mutez context.kwargs avant de l’appeler, et l’outil sélectionné voit ces valeurs par le biais de son injecté FunctionInvocationContext.

Utiliser pour l’état session= du runtime partagé

from typing import Annotated

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


@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 = OpenAIResponsesClient().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"])

Passez la session explicitement avec session= et lisez-la à partir de ctx.session. L’accès à la session n’a plus besoin de voyager via les kwargs d’exécution.

Partager l’état de session avec des agents délégués

Lorsqu’un agent est exposé en tant qu’outil via as_tool(), les kwargs de fonction d’exécution transitent déjà par ctx.kwargs. Ajoutez propagate_session=True uniquement lorsque le sous-agent doit partager l’appelant AgentSession.

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


@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 = OpenAIResponsesClient()

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

Avec propagate_session=True, l’agent délégué voit le même ctx.session état que l’appelant. Laissez-le False isoler l’agent enfant dans sa propre session.

Clients et agents de conversation personnalisés

Si vous implémentez des méthodes publiques ou get_response() publiques run() personnalisées, ajoutez les compartiments d’exécution explicites à la signature.

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

Utiliser function_invocation_kwargs pour les flux d’appel d’outils et client_kwargs pour le comportement spécifique au client. La transmission de valeurs spécifiques au client directement par le biais d’un chemin public **kwargs est un chemin de compatibilité et doit être traitée comme déconseillée. De même, la définition de nouveaux outils avec une **kwargs compatibilité de migration uniquement consiste à consommer des données d’exécution via l’objet de contexte injecté à la place.

Prochaines étapes