Tools¶
ระบบ tool ช่วยให้เอเจนต์ทำ action นอกเหนือจากการสร้างข้อความได้ -- การคำนวณ, การค้นหา memory, การอ่านไฟล์ และการเรียกโมเดลย่อย Tool ใช้การออกแบบแบบ spec-driven พร้อม dispatch engine กลาง และรองรับรูปแบบ function-calling ของ OpenAI
สถาปัตยกรรม¶
Agent --> Engine (with tool defs) --> tool_calls response --> ToolExecutor --> Tool.execute()
^ |
| v
+------------------------------- ToolResult <--------------------------------------------+
BaseTool ABC¶
Tool ทั้งหมด implement abstract base class BaseTool
from abc import ABC, abstractmethod
from openjarvis.tools._stubs import ToolSpec
from openjarvis.core.types import ToolResult
class BaseTool(ABC):
tool_id: str
@property
@abstractmethod
def spec(self) -> ToolSpec:
"""Return the tool specification."""
@abstractmethod
def execute(self, **params) -> ToolResult:
"""Execute the tool with the given parameters."""
def to_openai_function(self) -> dict:
"""Convert to OpenAI function-calling format."""
Method to_openai_function() มีมาให้จาก base class และแปลง spec ของ tool
เป็นรูปแบบที่ API ที่เข้ากันได้กับ OpenAI คาดหวัง:
{
"type": "function",
"function": {
"name": "calculator",
"description": "Evaluate a mathematical expression safely.",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Math expression to evaluate"
}
},
"required": ["expression"]
}
}
}
ToolSpec¶
Dataclass ToolSpec อธิบาย interface และลักษณะของ tool
| ฟิลด์ | ชนิด | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
name |
str |
-- | Identifier ของ tool แบบไม่ซ้ำกัน |
description |
str |
-- | คำอธิบายที่มนุษย์อ่านได้ (ส่งให้โมเดล) |
parameters |
dict[str, Any] |
{} |
JSON Schema สำหรับพารามิเตอร์ของ tool |
category |
str |
"" |
หมวดหมู่ของ tool (เช่น math, memory, reasoning) |
cost_estimate |
float |
0.0 |
ต้นทุนโดยประมาณต่อการเรียกใช้ |
latency_estimate |
float |
0.0 |
Latency โดยประมาณต่อการเรียกใช้ |
requires_confirmation |
bool |
False |
Tool ต้องการการยืนยันจากผู้ใช้หรือไม่ |
metadata |
dict[str, Any] |
{} |
Metadata เพิ่มเติม |
ToolResult¶
Dataclass ToolResult เก็บผลลัพธ์ของการรัน tool
| ฟิลด์ | ชนิด | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
tool_name |
str |
-- | ชื่อของ tool ที่ถูกเรียก |
content |
str |
-- | ผลลัพธ์ของ tool (ข้อความ) |
success |
bool |
True |
การรันสำเร็จหรือไม่ |
usage |
dict[str, Any] |
{} |
การใช้ token (สำหรับ LLM tool) |
cost_usd |
float |
0.0 |
ต้นทุนจริงของการเรียกใช้ |
latency_seconds |
float |
0.0 |
Latency ของการรันที่วัดได้ |
metadata |
dict[str, Any] |
{} |
Metadata เพิ่มเติม |
ToolExecutor¶
ToolExecutor คือ dispatch engine กลางสำหรับการเรียก tool มันจัดการชุด
instance ของ tool, parse argument แบบ JSON, วัด latency ของการรัน และ
เผยแพร่ event บน event bus
from openjarvis.tools._stubs import ToolExecutor
executor = ToolExecutor(tools=[calculator, think_tool], bus=event_bus)
# Get OpenAI-format tool definitions
openai_tools = executor.get_openai_tools()
# Execute a tool call
from openjarvis.core.types import ToolCall
tc = ToolCall(id="call_1", name="calculator", arguments='{"expression": "2+2"}')
result = executor.execute(tc)
print(result.content) # "4"
ขั้นตอนการรัน¶
- Parse argument: สตริง JSON
argumentsจากToolCallถูก deserialize - เผยแพร่ event เริ่มต้น:
TOOL_CALL_STARTถูกส่งบน event bus พร้อมชื่อ tool และ argument - รัน: method
execute()ของ tool ถูกเรียกพร้อมพารามิเตอร์ที่ parse แล้ว - วัด latency: เวลาที่ใช้รันถูกบันทึกไว้ใน
result.latency_seconds - เผยแพร่ event จบ:
TOOL_CALL_ENDถูกส่งพร้อมสถานะความสำเร็จและ latency - คืนผลลัพธ์:
ToolResultถูกคืนให้ผู้เรียก
หากชื่อ tool ไม่รู้จัก จะคืน ToolResult พร้อม success=False หากการ parse
JSON ล้มเหลวหรือ tool สร้าง exception error จะถูกจับและคืนเป็น ToolResult
ที่ล้มเหลว
Method¶
| Method | คืนค่า | คำอธิบาย |
|---|---|---|
execute(tool_call) |
ToolResult |
Parse argument, dispatch, วัดผล, ส่ง event |
available_tools() |
list[ToolSpec] |
คืน spec สำหรับ tool ที่ลงทะเบียนไว้ทั้งหมด |
get_openai_tools() |
list[dict] |
คืน tool ในรูปแบบ function ของ OpenAI |
build_tool_descriptions()¶
ฟังก์ชัน build_tool_descriptions() เป็น แหล่งความจริงเดียว (single
source of truth) สำหรับการสร้างคำอธิบาย tool แบบเสริมข้อมูล ที่ใช้ใน
system prompt ของเอเจนต์ เอเจนต์แบบ text ทั้งหมด (NativeReActAgent,
NativeOpenHandsAgent, RLMAgent, OrchestratorAgent ในโหมด structured)
ใช้ฟังก์ชันนี้เพื่อสร้างส่วน tool ในรูปแบบ Markdown
พารามิเตอร์¶
| พารามิเตอร์ | ชนิด | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
tools |
list[BaseTool] |
-- | รายการ instance ของ tool ที่จะอธิบาย |
include_category |
bool |
True |
รวมบรรทัด Category: หรือไม่ |
include_cost |
bool |
False |
รวมบรรทัดประมาณต้นทุนและ latency หรือไม่ |
การใช้งาน¶
from openjarvis.tools._stubs import build_tool_descriptions
from openjarvis.tools.calculator import CalculatorTool
from openjarvis.tools.think import ThinkTool
tools = [CalculatorTool(), ThinkTool()]
desc = build_tool_descriptions(tools)
print(desc)
# ### calculator
# Evaluate a mathematical expression safely.
# Category: math
# Parameters:
# - expression (string, required): Math expression to evaluate
#
# ### think
# Reasoning scratchpad ...
เอเจนต์ที่ใช้ Builder นี้¶
- NativeReActAgent -- แทรกคำอธิบายเข้าไปใน system prompt ของ ReAct
- NativeOpenHandsAgent -- แทรกคำอธิบายเข้าไปใน system prompt ของ CodeAct
- RLMAgent -- เพิ่มหมวด
## Available Toolsเข้าไปใน system prompt ของ REPL - OrchestratorAgent (โหมด structured) -- ส่ง
tools=ให้build_system_prompt()ซึ่งมอบหมายให้ builder นี้
สรุป Tool ในตัว¶
Tool ในตัวทั้งหมดลงทะเบียนผ่าน @ToolRegistry.register() และใช้งานได้ด้วย
ชื่อ ทั้งจากเอเจนต์และ CLI
| หมวดหมู่ | Registry Key | คำอธิบาย |
|---|---|---|
| Reasoning | think |
พื้นที่ร่างความคิดต้นทุนศูนย์สำหรับ chain-of-thought |
| Math | calculator |
ตัวประเมินนิพจน์คณิตศาสตร์อย่างปลอดภัย (ast-based) |
| Code | code_interpreter |
รันโค้ด Python ใน subprocess แบบ sandboxed |
| Code | code_interpreter_docker |
รันโค้ด Python ใน Docker container แบบใช้แล้วทิ้ง |
| Code | repl |
Python REPL แบบต่อเนื่อง คงสถานะข้ามการเรียก |
| Search | web_search |
ค้นหาเว็บ คืนสรุปผลลัพธ์ |
| File I/O | file_read |
อ่านเนื้อหาไฟล์พร้อมการตรวจสอบความปลอดภัย |
| HTTP | http_request |
ส่งคำขอ HTTP พร้อมการป้องกัน SSRF |
| Memory | retrieval |
ค้นหา memory backend หาบริบทที่เกี่ยวข้อง |
| Memory | memory_store |
เก็บเนื้อหาลง memory backend |
| Memory | memory_retrieve |
ดึงเนื้อหาที่เกี่ยวข้องจาก memory backend |
| Memory | memory_search |
ค้นหาแบบ full-text ข้าม memory ที่เก็บไว้ |
| Memory | memory_index |
Index ไฟล์หรือไดเรกทอรีเข้า memory backend |
| Inference | llm |
มอบหมายคำถามย่อยให้ inference engine |
| Channel | channel_send |
ส่งข้อความผ่าน channel (Telegram, Discord ฯลฯ) |
| Channel | channel_list |
แสดงรายการ messaging channel ที่มี |
| Channel | channel_status |
ตรวจสอบสถานะการเชื่อมต่อของ messaging channel |
| Scheduler | schedule_task |
ตั้งเวลางานสำหรับรันในอนาคตหรือแบบเกิดซ้ำ |
| Scheduler | list_scheduled_tasks |
แสดงรายการงานที่ตั้งเวลาไว้ทั้งหมด |
| Scheduler | pause_scheduled_task |
หยุดงานที่ตั้งเวลาไว้ที่กำลัง active ชั่วคราว |
| Scheduler | resume_scheduled_task |
ดำเนินงานที่หยุดไว้ต่อ |
| Scheduler | cancel_scheduled_task |
ยกเลิกงานที่ตั้งเวลาไว้อย่างถาวร |
| Integration | mcp_adapter |
เชื่อมต่อไปยังเซิร์ฟเวอร์ MCP tool ภายนอก (ดู External MCP Servers) |
รายละเอียด Tool ในตัว¶
Calculator¶
Registry key: calculator | หมวดหมู่: math
ประเมินนิพจน์ทางคณิตศาสตร์อย่างปลอดภัยด้วยโมดูล ast ของ Python ไม่มีการ
รันโค้ดตามอำเภอใจ -- อนุญาตเฉพาะ operation ที่อยู่ใน whitelist เท่านั้น
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
expression |
string | ใช่ | นิพจน์คณิตศาสตร์ (เช่น "2+3*4", "sqrt(16)") |
Operation ที่รองรับ:
| หมวดหมู่ | Operation |
|---|---|
| เลขคณิต | +, -, *, /, // (หารปัดลง), % (mod), ** (ยกกำลัง) |
| ฟังก์ชัน | abs, round, min, max, sqrt, log, log10, log2 |
| ตรีโกณมิติ | sin, cos, tan |
| ปัดเศษ | ceil, floor |
| ค่าคงที่ | pi, e |
ตัวอย่าง:
from openjarvis.tools.calculator import CalculatorTool
calc = CalculatorTool()
result = calc.execute(expression="sqrt(144) + 3**2")
print(result.content) # "21.0"
print(result.success) # True
Think¶
Registry key: think | หมวดหมู่: reasoning
พื้นที่ร่างความคิดต้นทุนศูนย์ input จะถูก echo กลับมาเป็น output ทำให้โมเดล "คิดออกเสียง" ระหว่างลูปการเรียกใช้ tool ได้ สิ่งนี้เปิดใช้งาน chain-of-thought reasoning ภายในเวิร์กโฟลว์ของเอเจนต์
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
thought |
string | ใช่ | กระบวนการให้เหตุผลหรือความคิด |
ตัวอย่าง:
from openjarvis.tools.think import ThinkTool
think = ThinkTool()
result = think.execute(thought="Let me break this problem into steps...")
print(result.content) # "Let me break this problem into steps..."
print(result.success) # True
ต้นทุนและ Latency
Tool Think มีต้นทุนเป็นศูนย์และ latency เกือบเป็นศูนย์ เหมาะสำหรับการให้เหตุผลแบบมีโครงสร้างโดยไม่ใช้ทรัพยากรเพิ่มเติม
Retrieval¶
Registry key: retrieval | หมวดหมู่: memory
ค้นหา memory backend หาบริบทที่เกี่ยวข้อง และคืนผลลัพธ์ที่จัดรูปแบบพร้อมการ ระบุแหล่งที่มา
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
query |
string | ใช่ | คำค้นหา |
top_k |
integer | ไม่ | จำนวนผลลัพธ์ (ค่าเริ่มต้น: 5) |
พารามิเตอร์ของ Constructor:
| พารามิเตอร์ | ชนิด | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
backend |
MemoryBackend |
None |
Memory backend ที่จะค้นหา |
top_k |
int |
5 |
จำนวนผลลัพธ์เริ่มต้น |
ตัวอย่าง:
from openjarvis.tools.retrieval import RetrievalTool
from openjarvis.memory.sqlite import SQLiteMemory
backend = SQLiteMemory(db_path="./memory.db")
retrieval = RetrievalTool(backend=backend)
result = retrieval.execute(query="machine learning")
print(result.content) # Formatted context with source tags
LLM¶
Registry key: llm | หมวดหมู่: inference
มอบหมายคำถามย่อยให้ inference engine มีประโยชน์สำหรับการสรุป, คำถามย่อย หรือการสร้างผลลัพธ์แบบมีโครงสร้างภายในเวิร์กโฟลว์ของเอเจนต์
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
prompt |
string | ใช่ | Prompt ที่จะส่งไปยังโมเดล |
system |
string | ไม่ | System message เสริมสำหรับบริบท |
พารามิเตอร์ของ Constructor:
| พารามิเตอร์ | ชนิด | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
engine |
InferenceEngine |
None |
Inference engine ที่จะใช้ |
model |
str |
"" |
Identifier ของโมเดล |
ตัวอย่าง:
from openjarvis.tools.llm_tool import LLMTool
llm = LLMTool(engine=my_engine, model="qwen3:8b")
result = llm.execute(
prompt="Summarize: AI is transforming industries...",
system="You are a concise summarizer.",
)
print(result.content)
FileRead¶
Registry key: file_read | หมวดหมู่: filesystem
อ่านเนื้อหาไฟล์พร้อมการตรวจสอบความปลอดภัย รองรับการจำกัดไดเรกทอรี (เสริม), ขีดจำกัดขนาดไฟล์ (สูงสุด 1 MB) และการจำกัดจำนวนบรรทัด
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
path |
string | ใช่ | Path ของไฟล์ที่จะอ่าน |
max_lines |
integer | ไม่ | จำนวนบรรทัดสูงสุดที่จะคืน (ค่าเริ่มต้น: ทั้งหมด) |
พารามิเตอร์ของ Constructor:
| พารามิเตอร์ | ชนิด | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
allowed_dirs |
list[str] |
None |
จำกัดการเข้าถึงไฟล์เฉพาะไดเรกทอรีเหล่านี้ |
คุณสมบัติด้านความปลอดภัย:
- ตรวจสอบ path เทียบกับไดเรกทอรีที่อนุญาต (เมื่อตั้งค่าไว้)
- ขนาดไฟล์สูงสุด: 1 MB
- ต้องเป็น encoding UTF-8 (ปฏิเสธไฟล์ binary)
- ตรวจสอบการมีอยู่และประเภทไฟล์
ตัวอย่าง:
from openjarvis.tools.file_read import FileReadTool
reader = FileReadTool(allowed_dirs=["/home/user/projects"])
result = reader.execute(path="/home/user/projects/README.md", max_lines=50)
print(result.content)
print(result.metadata) # {"path": "/home/user/projects/README.md", "size_bytes": 1234}
WebSearch¶
Registry key: web_search | หมวดหมู่: search
ค้นหาเว็บและคืนสรุปผลลัพธ์ มีประโยชน์สำหรับคำถามที่ต้องการข้อมูลปัจจุบัน
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
query |
string | ใช่ | สตริงคำค้นหา |
CodeInterpreter¶
Registry key: code_interpreter | หมวดหมู่: code
รันโค้ด Python ใน sandbox และคืนผลลัพธ์ ใช้โดย NativeOpenHandsAgent
สำหรับการรันแบบ CodeAct
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
code |
string | ใช่ | โค้ด Python ที่จะรัน |
Scheduler Tools¶
Scheduler tools เปิด operation ของ TaskScheduler เป็น tool ที่ค้นพบได้ผ่าน
MCP ทำให้เอเจนต์สร้าง, จัดการ และตรวจสอบงานที่ตั้งเวลาไว้เชิงโปรแกรมได้
Scheduler tool ทั้งหมดอยู่ในหมวด scheduler และต้องมี instance ของ
TaskScheduler ตั้งค่าไว้ในระบบ
Dependency ของ Scheduler
Scheduler tool ทำงานได้เฉพาะเมื่อมี TaskScheduler ต่อสายเข้ากับระบบ (ผ่าน SystemBuilder) หากไม่มี scheduler ตั้งค่าไว้ การเรียก scheduler tool ทั้งหมดจะคืนผลลัพธ์ success=False พร้อมข้อความอธิบายว่า scheduler ไม่พร้อมใช้งาน
schedule_task¶
Registry key: schedule_task | หมวดหมู่: scheduler
ตั้งเวลางานใหม่สำหรับรันในอนาคตหรือแบบเกิดซ้ำ
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
prompt |
string | ใช่ | คำถามหรือ prompt ที่จะรันตามตารางเวลา |
schedule_type |
string | ใช่ | หนึ่งใน "cron", "interval" หรือ "once" |
schedule_value |
string | ใช่ | นิพจน์ cron, interval เป็นวินาที หรือ ISO 8601 datetime สำหรับรันครั้งเดียว |
agent |
string | ไม่ | เอเจนต์ที่จะใช้รัน (ค่าเริ่มต้น: "simple") |
tools |
string | ไม่ | ชื่อ tool สำหรับเอเจนต์ คั่นด้วยคอมมา (เช่น "calculator,think") |
ตัวอย่างประเภทตารางเวลา:
schedule_type |
schedule_value |
ความหมาย |
|---|---|---|
once |
"2026-03-01T09:00:00Z" |
รันครั้งเดียวที่เวลา UTC นั้น |
interval |
"3600" |
รันทุก 3600 วินาที (1 ชั่วโมง) |
cron |
"0 9 * * 1-5" |
รันที่ 09:00 UTC จันทร์–ศุกร์ |
คืนค่า: JSON ที่มี task_id, next_run (ISO 8601) และ status
ตัวอย่าง (ผ่านการเรียก tool ของเอเจนต์):
from openjarvis.scheduler.tools import ScheduleTaskTool
from openjarvis.scheduler.scheduler import TaskScheduler
from openjarvis.scheduler.store import SchedulerStore
store = SchedulerStore(db_path="~/.openjarvis/scheduler.db")
scheduler = TaskScheduler(store=store, system=jarvis_system)
scheduler.start()
tool = ScheduleTaskTool()
tool._scheduler = scheduler
result = tool.execute(
prompt="Summarize the daily news",
schedule_type="cron",
schedule_value="0 8 * * *",
agent="simple",
)
# result.content: '{"task_id": "a3f9b12c", "next_run": "2026-02-26T08:00:00+00:00", "status": "active"}'
list_scheduled_tasks¶
Registry key: list_scheduled_tasks | หมวดหมู่: scheduler
คืนงานที่ตั้งเวลาไว้ทั้งหมด กรองตามสถานะได้ตามต้องการ
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
status |
string | ไม่ | กรองตามสถานะ: "active", "paused", "completed", "cancelled" |
คืนค่า: JSON array ของ object งาน
pause_scheduled_task¶
Registry key: pause_scheduled_task | หมวดหมู่: scheduler
หยุดงานที่ตั้งเวลาไว้ที่กำลัง active ชั่วคราว งานยังคงอยู่และดำเนินต่อได้ ภายหลัง
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
task_id |
string | ใช่ | ID ของงานที่จะหยุด |
resume_scheduled_task¶
Registry key: resume_scheduled_task | หมวดหมู่: scheduler
ดำเนินงานที่หยุดไว้ต่อ เวลา next_run จะถูกคำนวณใหม่จากเวลาปัจจุบัน
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
task_id |
string | ใช่ | ID ของงานที่จะดำเนินต่อ |
cancel_scheduled_task¶
Registry key: cancel_scheduled_task | หมวดหมู่: scheduler
ยกเลิกงานอย่างถาวร (ตั้งสถานะเป็น "cancelled" และล้าง next_run) งานที่
ยกเลิกแล้วจะไม่รันอีก
พารามิเตอร์:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
task_id |
string | ใช่ | ID ของงานที่จะยกเลิก |
การลงทะเบียน Tool¶
Tool ลงทะเบียนผ่าน decorator @ToolRegistry.register() ทำให้ค้นพบได้ด้วยชื่อ
ตอน runtime
from openjarvis.core.registry import ToolRegistry
from openjarvis.tools._stubs import BaseTool, ToolSpec
from openjarvis.core.types import ToolResult
@ToolRegistry.register("my_tool")
class MyTool(BaseTool):
tool_id = "my_tool"
@property
def spec(self) -> ToolSpec:
return ToolSpec(
name="my_tool",
description="A custom tool that does something useful.",
parameters={
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The input to process.",
},
},
"required": ["input"],
},
category="custom",
)
def execute(self, **params) -> ToolResult:
value = params.get("input", "")
return ToolResult(
tool_name="my_tool",
content=f"Processed: {value}",
success=True,
)
หลังลงทะเบียนแล้ว ใช้ tool กับเอเจนต์ได้:
การใช้ Tool กับเอเจนต์¶
ผ่าน CLI¶
Tool ระบุเป็นรายการคั่นด้วยคอมมาผ่าน flag --tools ต้องเลือกเอเจนต์ (มักเป็น
orchestrator):
# Single tool
jarvis ask --agent orchestrator --tools calculator "What is 15% of 340?"
# Multiple tools
jarvis ask --agent orchestrator --tools calculator,think "Solve: 2x + 5 = 13"
# All available tools (list them)
jarvis ask --agent orchestrator --tools calculator,think,retrieval,file_read "..."
ผ่าน Python SDK¶
Tool ส่งเป็นรายการสตริงชื่อ:
from openjarvis import Jarvis
j = Jarvis()
# Use calculator and think tools
result = j.ask_full(
"What is the area of a circle with radius 7?",
agent="orchestrator",
tools=["calculator", "think"],
)
for tr in result["tool_results"]:
print(f" {tr['tool_name']}: {tr['content']} (success={tr['success']})")
j.close()
SDK จะสร้าง instance ของ tool พร้อม dependency ที่เหมาะสมให้โดยอัตโนมัติ
ตัวอย่างเช่น tool retrieval จะได้รับ memory backend ที่ตั้งค่าไว้ และ tool
llm จะได้รับ engine และโมเดลที่ใช้งานอยู่