Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Catatan
API eksposur alat progresif (FunctionInvocationContext.add_tools / remove_tools) saat ini hanya tersedia untuk Python.
Halaman ini mencakup tiga teknik pelengkap untuk mengontrol alat mana yang dapat dipanggil model dan dalam urutan apa, semuanya dalam satu agen berjalan, tanpa memerlukan alur kerja:
- Paparan alat progresif — menambahkan atau menghapus alat saat runtime dari dalam alat atau middleware fungsi, sehingga model hanya melihat alat yang siap digunakan.
- Middleware gating — gunakan middleware fungsi untuk memvalidasi argumen panggilan dan mengembalikan umpan balik korektif tanpa menjalankan fungsi yang mendasar.
-
Panggilan pertama paksa — gunakan
tool_choiceuntuk mengharuskan model memanggil alat tertentu sebelum yang lain.
Catatan
Batasan pengurutan berpasangan seperti "selalu panggil get_record sebelum update_record" tidak memerlukan alur kerja. Teknik pada halaman ini menangani pola tersebut di dalam satu eksekusi. Alur kerja digunakan untuk orkestrasi multilangkah yang benar-benar mencakup beberapa kali eksekusi atau cabang paralel.
Penampilan alat secara bertahap
Eksposur alat progresif memungkinkan Anda memulai eksekusi dengan sekumpulan alat kecil dan menambahkan atau menghapus alat sebagai respons terhadap hasil alat sebelumnya, semuanya dalam proses yang sama. Model hanya akan melihat kumpulan yang diperbarui pada iterasi berikutnya dari loop pemanggilan fungsi; pemanggilan tool yang sudah diminta dalam batch yang sedang diproses tetap akan dieksekusi sebelum perubahan tersebut berlaku.
API bersifat eksperimental dan hidup di FunctionInvocationContext:
| Anggota | Description |
|---|---|
ctx.tools |
list alat yang aktif dan dapat diubah untuk eksekusi saat ini.
None ketika fungsi dipanggil di luar perulangan pemanggilan fungsi. |
ctx.add_tools(tools) |
Tambahkan satu atau beberapa alat. Objek yang dapat dipanggil dibungkus dengan FunctionTool. Menambahkan kembali objek yang sama tidak menimbulkan efek apa pun; objek lain dengan nama duplikat akan menghasilkan ValueError. Semua atau tidak sama sekali: jika ada alat dalam batch yang akan muncul, tidak ada yang ditambahkan. |
ctx.remove_tools(tools) |
Hapus berdasarkan nama, objek alat, atau fungsi yang dapat dipanggil. Nama yang tidak ada dalam daftar diabaikan secara diam-diam. |
Kedua fungsi pembantu menghasilkan ExperimentalWarning saat pertama kali dipanggil dalam suatu proses (ID fitur PROGRESSIVE_TOOLS). Memanggil salah satu fungsi pembantu di luar loop pemanggilan fungsi akan menghasilkan RuntimeError.
Important
Daftar alat diatur ulang ke susunan awal pada setiap panggilan agent.run() baru, sehingga semua gate aktif kembali secara otomatis pada setiap giliran.
Catatan
Eksposur alat bertahap hanya berlaku pada loop pemanggilan fungsi standar. Hal ini tidak tersedia untuk penyedia CodeAct (agent-framework-monty, agent-framework-hyperlight), di mana model melihat satu antarmuka eksekusi kode, bukan skema perangkat individual. Memanggil add_tools atau remove_tools dari dalam sandbox CodeAct mengakibatkan RuntimeError. Untuk mengubah kumpulan alat untuk agen CodeAct, gunakan metode milik penyedia itu sendiri add_tools / remove_tool / clear_tools di antara setiap eksekusi.
Pola alat pemuat
Daftarkan sekumpulan kecil alat "loader" sejak awal dan biarkan model memuat alat tambahan sesuai permintaan. Ini menjaga skema awal tetap kecil, yang meningkatkan akurasi pemilihan alat dan mengurangi biaya.
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=FutureWarning) # 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())
Sampel lengkap yang dapat dijalankan adalah di python/samples/02-agents/tools/dynamic_tool_exposure.py.
Pola penyaringan
Daftarkan hanya alat pembaca terlebih dahulu. Tool baca menambahkan tool tulis setelah pengambilan data berhasil, sehingga model tidak dapat memanggil tool tulis sebelum tool baca dijalankan.
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
)
Karena ctx.tools diatur ulang ke [get_record] pada awal setiap kali dijalankan, gerbang diaktifkan kembali secara otomatis pada setiap giliran percakapan.
Pengendalian akses middleware
Middleware fungsi dapat memeriksa argumen panggilan alat yang masih tertunda dan menolaknya sebelum fungsi dasarnya dijalankan dengan menetapkan context.result tanpa memanggil call_next(). String yang ditetapkan untuk context.result dikembalikan ke model sebagai hasil fungsi, memberikan umpan balik korektif.
Ini berguna untuk pemeriksaan pada tingkat argumen yang memerlukan informasi yang tidak tersedia saat pendefinisian skema, misalnya memastikan bahwa pembaruan ditujukan ke item yang sama dengan yang diambil sebelumnya dalam proses eksekusi.
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()
Tambahkan middleware ke agen:
agent = Agent(
client=OpenAIChatClient(),
name="RecordAgent",
instructions="Fetch a record before updating it.",
tools=[get_record, update_record],
middleware=[enforce_read_before_write],
)
Untuk informasi lebih lanjut tentang middleware untuk fungsi, lihat Mendefinisikan Middleware dan Penggantian Hasil.
Memaksa pemanggilan alat dengan tool_choice
Untuk mengharuskan model memanggil alat tertentu sebagai tindakan pertamanya, teruskan tool_choice dengan mode "required" dan required_function_name. Kerangka kerja secara otomatis direset tool_choice ke None setelah iterasi pertama sehingga model bebas pada iterasi berikutnya.
result = await agent.run(
"Update record REC-42 to status 'in-progress'.",
options={"tool_choice": {"mode": "required", "required_function_name": "get_record"}},
)
Bidang tool_choice menerima ToolMode dict, atau bentuk singkat berupa string "auto", "required", atau "none":
from agent_framework import ToolMode
tool_choice: ToolMode = {"mode": "required", "required_function_name": "get_record"}
Semantik dan peringatan
| Behavior | Detail |
|---|---|
| Efek perulangan berikutnya |
add_tools
/
remove_tools mutasi terlihat oleh model pada iterasi perulangan berikutnya. Pemanggilan alat yang sudah dikirimkan dalam batch saat ini akan tetap selesai. |
| Batch yang sedang diproses | Jika model meminta beberapa alat dalam satu batch, semua jalankan sebelum daftar alat yang diperbarui dikirim kembali. |
| Nama duplikat | Menambahkan kembali objek yang sama persis adalah no-op. Menambahkan objek berbeda yang namanya cocok dengan alat yang ada akan menaikkan ValueError. Seluruh batch divalidasi sebelum penambahan apa pun dilakukan, sehingga jika ada entri duplikat di tengah daftar, daftar aktif tetap tidak berubah. |
| Kesalahan di luar loop | Memanggil add_tools atau remove_tools saat ctx.tools is None menaikkan RuntimeError. Ini terjadi ketika fungsi dipanggil secara langsung (misalnya melalui FunctionTool.invoke) daripada melalui perulangan agen. |
| Status eksperimental | Kedua fungsi pembantu menghasilkan ExperimentalWarning pada pemanggilan pertama di setiap proses. Sembunyikan dengan menggunakan warnings.filterwarnings("ignore", category=FutureWarning) jika diinginkan. |
| Cakupan per eksekusi | Daftar alat aktif adalah salinan baru yang dibuat dari normalize_tools saat awal setiap pemanggilan agent.run(). Wadah asli tools milik pemanggil tidak pernah diubah. |
| Pengecualian CodeAct | Tidak tersedia untuk agent-framework-monty atau agent-framework-hyperlight penyedia CodeAct. |
Catatan
API ketersediaan alat runtime yang tercakup di halaman ini saat ini hanya Python. Untuk pola tool Go, lihat Tool Fungsi dan Menggunakan tool fungsi dengan persetujuan human-in-the-loop.