Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Note
API:et för progressiv verktygsexponering (FunctionInvocationContext.add_tools / remove_tools) är för närvarande endast Python.
Den här sidan beskriver tre kompletterande tekniker för att styra vilka verktyg en modell kan anropa och i vilken ordning, allt inom en enda agentkörning, utan att kräva ett arbetsflöde:
- Progressiv verktygsexponering – lägg till eller ta bort verktyg vid körning inifrån ett verktyg eller funktionsmellanprogram, så att modellen bara ser verktyg som den är redo att använda.
- Mellanprograms-gating – använd funktionsmellanprogram för att validera anropsargument och returnera korrigerande feedback utan att köra den underliggande funktionen.
-
Tvingat första anrop — använd
tool_choiceför att kräva att modellen anropar ett specifikt verktyg innan några andra.
Note
Villkor för parordning, till exempel "anropa get_record alltid före update_record" kräver inte något arbetsflöde. Teknikerna på den här sidan hanterar det mönstret i en enda körning. Arbetsflöden är avsedda för verklig orkestrering i flera steg över flera körningar eller parallella grenar.
Gradvis exponering av verktyg
Med exponering av progressiva verktyg kan du starta en körning med en liten uppsättning verktyg och lägga till eller ta bort verktyg som svar på tidigare verktygsresultat, allt inom samma körning. Modellen ser bara den uppdaterade uppsättningen vid nästa iteration av funktionsanropsloopen. verktygsanrop som redan har begärts i batchen under flygning körs fortfarande innan ändringen börjar gälla.
API:et är experimentellt och lever vidare på FunctionInvocationContext:
| Medlem | Beskrivning |
|---|---|
ctx.tools |
Den aktuella, ändringsbara list av verktyg för den aktuella körningen.
None när funktionen anropas utanför en funktionsanropsloop. |
ctx.add_tools(tools) |
Lägg till ett eller flera verktyg. Anropsbara objekt omges av FunctionTool. Att lägga till samma objekt igen är en no-op; ett annat objekt med ett duplicerat namn genererar ValueError. Allt eller inget: om något verktyg i batchen skulle utlösa ett fel, läggs inga till. |
ctx.remove_tools(tools) |
Ta bort efter namn, verktygsobjekt eller anropsbart. Namn som inte finns i listan ignoreras tyst. |
Båda hjälparna genererar ExperimentalWarning första gången de anropas i en process (funktions-ID PROGRESSIVE_TOOLS). Om du anropar någon av hjälparna utanför en funktionsanropsloop genereras RuntimeError.
Important
Verktygslistan återställs till den ursprungliga uppsättningen vid varje nytt agent.run()-anrop, så alla spärrar återaktiveras automatiskt vid varje tur.
Note
Progressiv verktygsexponering gäller endast för standard-funktionsanropsloopen. Den är inte tillgänglig för CodeAct-providers (agent-framework-monty, agent-framework-hyperlight), där modellen ser en enda kodkörningsyta i stället för enskilda verktygsscheman. När du anropar add_tools eller remove_tools inifrån en CodeAct-sandbox-miljö genereras RuntimeError. Om du vill ändra verktygsuppsättningen för en CodeAct-agent använder du providerns egna add_tools / remove_tool / clear_tools metoder mellan körningarna.
Mönster för loader-tool
Registrera en liten uppsättning "loader"-verktyg i förväg och låt modellen hämta ytterligare verktyg på begäran. Detta håller det inledande schemat litet, vilket förbättrar noggrannheten för verktygsval och minskar kostnaderna.
import asyncio
import warnings
from typing import Annotated
from agent_framework import Agent, FunctionInvocationContext, tool
from agent_framework.openai import OpenAIChatClient
from pydantic import Field
warnings.filterwarnings("ignore", category=UserWarning) # suppress ExperimentalWarning for brevity
@tool(approval_mode="never_require")
def factorial(n: Annotated[int, Field(description="A non-negative integer.")]) -> str:
"""Compute the factorial of n."""
if n < 0:
return "Error: n must be a non-negative integer."
result = 1
for value in range(2, n + 1):
result *= value
return f"{n}! = {result}"
@tool(approval_mode="never_require")
def fibonacci(n: Annotated[int, Field(description="The 0-based index in the Fibonacci sequence.")]) -> str:
"""Compute the n-th Fibonacci number."""
if n < 0:
return "Error: n must be a non-negative integer."
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return f"fib({n}) = {a}"
# The ctx parameter is injected by the framework and is NOT visible to the model.
@tool(approval_mode="never_require")
def load_math_tools(ctx: FunctionInvocationContext) -> str:
"""Load additional math tools (factorial, fibonacci) so they can be used."""
ctx.add_tools([factorial, fibonacci])
return "Loaded math tools: factorial, fibonacci. You can now call them."
async def main() -> None:
agent = Agent(
client=OpenAIChatClient(),
name="MathAgent",
instructions=(
"You are a math assistant. "
"If you need math capabilities that are not yet available, call load_math_tools first."
),
tools=[load_math_tools], # agent starts with only the loader
)
print(await agent.run("What is 5 factorial?"))
asyncio.run(main())
Det fullständiga körbara exemplet är på python/samples/02-agents/tools/dynamic_tool_exposure.py.
Gating-mönster
Registrera endast läsverktyget inledningsvis. Läsverktyget lägger till skrivverktyget efter en lyckad hämtning, så modellen kan inte anropa skrivverktyget innan läsverktyget har körts.
from agent_framework import Agent, FunctionInvocationContext, tool
from agent_framework.openai import OpenAIChatClient
_last_fetched_id: str | None = None
@tool(approval_mode="never_require")
def get_record(record_id: str, ctx: FunctionInvocationContext) -> str:
"""Fetch a record. Unlocks update_record for the same record."""
global _last_fetched_id
_last_fetched_id = record_id
ctx.add_tools(update_record) # gate: expose the write tool now
return f"Record {record_id}: title='Example record', status='open'"
@tool(approval_mode="never_require")
def update_record(record_id: str, status: str) -> str:
"""Update the status of a record."""
return f"Updated record {record_id} to status '{status}'."
agent = Agent(
client=OpenAIChatClient(),
name="RecordAgent",
instructions="You help manage records. Fetch a record before updating it.",
tools=[get_record], # update_record is hidden until get_record runs
)
Eftersom ctx.tools återställs till [get_record] i början av varje körning, återaktiveras grinden automatiskt vid varje replikskifte.
Middleware-styrning
Funktionsmellanprogram kan granska argumenten för ett väntande verktygsanrop och avvisa det innan den underliggande funktionen körs genom att ange context.result utan att anropa call_next(). Strängen som tilldelats till context.result returneras till modellen som funktionsresultat, vilket ger den korrigerande feedback.
Detta är användbart för kontroller på argumentnivå som behöver information som inte är tillgänglig vid schemadefinitionstidpunkt, till exempel för att verifiera att en uppdatering riktar sig mot samma objekt som hämtades tidigare under körningen.
from collections.abc import Awaitable, Callable
from agent_framework import FunctionInvocationContext
_last_fetched_id: str | None = None
async def enforce_read_before_write(
context: FunctionInvocationContext,
call_next: Callable[[], Awaitable[None]],
) -> None:
"""Reject update_record calls that target a different record than the one fetched."""
if context.function.name == "update_record":
requested_id = context.arguments.get("record_id") if hasattr(context.arguments, "get") else None
if requested_id != _last_fetched_id:
# Set result without calling call_next — the function never executes.
context.result = (
f"Error: you must fetch record '{requested_id}' before updating it. "
f"Last fetched record was '{_last_fetched_id}'."
)
return
await call_next()
Lägg till mellanprogrammet i agenten:
agent = Agent(
client=OpenAIChatClient(),
name="RecordAgent",
instructions="Fetch a record before updating it.",
tools=[get_record, update_record],
middleware=[enforce_read_before_write],
)
Läs mer om mellanprogram för funktioner under Definiera mellanprogram och Åsidosättningar av resultat.
Tvinga fram ett verktygsanrop med tool_choice
Om du vill kräva att modellen anropar ett specifikt verktyg som sin första åtgärd skickar du tool_choice med läge "required" och en required_function_name. Ramverket återställs tool_choice automatiskt till None efter den första iterationen så att modellen är fri vid efterföljande iterationer.
result = await agent.run(
"Update record REC-42 to status 'in-progress'.",
tool_choice={"mode": "required", "required_function_name": "get_record"},
)
Fältet tool_choice accepterar en ToolMode diktering eller korthandssträngarna "auto", "required", eller "none":
from agent_framework import ToolMode
tool_choice: ToolMode = {"mode": "required", "required_function_name": "get_record"}
Semantik och varningar
| Behavior | Detail |
|---|---|
| Nästa iterationseffekt |
add_tools
/
remove_tools mutationer är synliga för modellen vid nästa loop iteration. Verktygsanrop som redan har skickats i den aktuella batchen slutförs ändå. |
| Batch under flygning | Om modellen begär flera verktyg i en batch körs alla innan den uppdaterade verktygslistan skickas tillbaka. |
| Duplicerade namn | Att lägga till exakt samma objekt igen är en no-op. Om du lägger till ett annat objekt vars namn matchar ett befintligt verktyg genereras ValueError. Hela batchen valideras innan något läggs till, så en dubblett mitt i en lista lämnar den aktiva listan oförändrad. |
| Fel utanför slingan | Anropar add_tools eller remove_tools när ctx.tools is None höjer RuntimeError. Detta inträffar när funktionen anropas direkt (till exempel via FunctionTool.invoke) i stället för via agentloopen. |
| Experimentellt status | Båda hjälpfunktionerna avger ExperimentalWarning vid det första anropet i varje process. Undertryck med warnings.filterwarnings("ignore", category=UserWarning) om så önskas. |
| Omfattning per körning | Den aktiva verktygslistan är en ny kopia som skapas från normalize_tools i början av varje agent.run()-anrop. Anroparens ursprungliga tools container är aldrig muterad. |
| CodeAct-uteslutning | Inte tillgängligt för agent-framework-monty eller agent-framework-hyperlight CodeAct-leverantörer. |