Chuyển tới nội dung chính

Thời gian chạy công cụ

Công cụ Hermes là các chức năng tự đăng ký được nhóm thành các bộ công cụ và được thực thi thông qua hệ thống đăng ký/điều phối trung tâm.

Các tập tin chính:

`tools/registry.py

`model_tools.py

`toolsets.py

`tools/terminal_tool.py

`tools/environments/* ``##Mô hình đăng ký công cụ

Mỗi mô-đun công cụ gọi registry.register(...) tại thời điểm nhập.

model_tools.py ` chịu trách nhiệm nhập/khám phá các mô-đun công cụ và xây dựng danh sách lược đồ được mô hình sử dụng.

registry.register() hoạt động như thế nào

Mọi tệp công cụ trong tools/ đều gọi registry.register() ở cấp mô-đun để tự khai báo. Chữ ký hàm là:

registry.register(
name="terminal", # Unique tool name (used in API schemas)
toolset="terminal", # Toolset this tool belongs to
schema=\{...}, # OpenAI function-calling schema (description, parameters)
handler=handle_terminal, # The function that executes when the tool is called
check_fn=check_terminal, # Optional: returns True/False for availability
requires_env=["SOME_VAR"], # Optional: env vars needed (for UI display)
is_async=False, # Whether the handler is an async coroutine
description="Run commands", # Human-readable description
emoji="💻", # Emoji for spinner/progress display
)

`
``Mỗi cuộc gọi tạo ra một
`ToolEntry
` được lưu trữ trong lệnh
`ToolRegistry._tools
` đơn lẻ được khóa theo tên công cụ. Nếu xung đột tên xảy ra giữa các bộ công cụ, một cảnh báo sẽ được ghi lại và việc đăng ký sau sẽ thắng.

### Khám phá:
`discover_builtin_tools()
``Khi
`model_tools.py
` được nhập, nó gọi
`discover_builtin_tools()
` từ
`tools/registry.py

. Hàm này quét mọi tệp
`tools/*.py
` bằng cách sử dụng phân tích cú pháp AST để tìm các mô-đun chứa lệnh gọi
`registry.register()
` cấp cao nhất, sau đó nhập chúng:

`Python

# tools/registry.py (simplified)
def discover_builtin_tools(tools_dir=None):
tools_path = Path(tools_dir) if tools_dir else Path(__file__).parent
for path in sorted(tools_path.glob("*.py")):
if path.name in \{"__init__.py", "registry.py", "MCP_tool.py"}:
Continue
if _module_registers_tools(path): # AST check for top-level registry.register()
importlib.import_module(f"tools.\{path.stem}")

`
``Tính năng tự động phát hiện này có nghĩa là các tệp công cụ mới được chọn tự động - không cần duy trì danh sách thủ công. Kiểm tra AST chỉ khớp với các lệnh gọi
`registry.register()
` cấp cao nhất (không phải các lệnh gọi bên trong các hàm), vì vậy các mô-đun trợ giúp trong
`tools/
` không được nhập.

Mỗi lần nhập sẽ kích hoạt các lệnh gọi
`registry.register()
` của mô-đun. Lỗi trong các công cụ tùy chọn (ví dụ: thiếu
`fal_CLIent
` để tạo hình ảnh) được phát hiện và ghi lại — chúng không ngăn các công cụ khác tải.

Sau khi khám phá công cụ cốt lõi, các công cụ MCP và công cụ plugin cũng được khám phá:
1. **Công cụ MCP**
`tools.MCP_tool.discover_MCP_tools()
` đọc cấu hình máy chủ MCP và đăng ký các công cụ từ máy chủ bên ngoài.
2. **Công cụ plugin**
`Hermes_CLI.plugins.discover_plugins()
` tải các plugin người dùng/dự án/pip có thể đăng ký các công cụ bổ sung.

## Kiểm tra tính khả dụng của công cụ (
`check_fn

)

Mỗi công cụ có thể tùy chọn cung cấp
`check_fn

- một lệnh gọi có thể trả về
`True
` khi công cụ này khả dụng và
`False
` nếu không. Kiểm tra điển hình bao gồm:
- **Có khóa API** — ví dụ:
`lambda: bool(os.environ.get("SERP_API_KEY"))
` dành cho tìm kiếm trên web
- **Dịch vụ đang chạy** — ví dụ: kiểm tra xem máy chủ Honcho đã được định cấu hình chưa
- **Đã cài đặt nhị phân** — ví dụ: xác minh
`playwright
` có sẵn cho các công cụ trình duyệt

Khi
`registry.get_definitions()
` xây dựng danh sách lược đồ cho mô hình, nó sẽ chạy
`check_fn()
` của từng công cụ:

``` python

# Simplified from registry.py
if entry.check_fn:
try:
available = bool(entry.check_fn())
except Exception:
available = False # Exceptions = unavailable
if not available:
Continue # Skip this tool entirely

`
``Các hành vi chính:
- Kết quả kiểm tra được **được lưu vào bộ nhớ đệm cho mỗi cuộc gọi** — nếu nhiều công cụ dùng chung
`check_fn
` thì nó chỉ chạy một lần.
- Các ngoại lệ trong
`check_fn()
` được coi là "không khả dụng" (không an toàn).
- Phương pháp
`is_toolset_available()
` kiểm tra xem
`check_fn
` của bộ công cụ có vượt qua hay không, được sử dụng để hiển thị giao diện người dùng và độ phân giải của bộ công cụ.

## Độ phân giải của bộ công cụ

Bộ công cụ được đặt tên là các gói công cụ. Hermes giải quyết chúng thông qua:
- danh sách bộ công cụ được bật/tắt rõ ràng
- cài đặt trước nền tảng (
`Hermes-CLI

,
`Hermes-Telegram

, v.v.)
- bộ công cụ MCP động
- các bộ mục đích đặc biệt được quản lý như
`Hermes-ACP

### Công cụ lọc
`get_tool_definitions()
` như thế nào

Điểm vào chính là
`model_tools.get_tool_definitions(enabled_toolsets, disabled_toolsets, quiet_mode)

:
1. **Nếu
`enabled_toolsets
` được cung cấp** — chỉ bao gồm các công cụ từ các bộ công cụ đó. Mỗi tên bộ công cụ được phân giải thông qua
`resolve_toolset()

, mở rộng các bộ công cụ tổng hợp thành các tên công cụ riêng lẻ.
2. **Nếu
`disabled_toolsets
` được cung cấp** — hãy bắt đầu với TẤT CẢ các bộ công cụ, sau đó trừ đi những bộ công cụ bị vô hiệu hóa.
3. **Nếu không** — bao gồm tất cả các bộ công cụ đã biết.
4. **Lọc sổ đăng ký** — bộ tên công cụ đã giải quyết được chuyển tới
`registry.get_definitions()

, áp dụng tính năng lọc
`check_fn
` và trả về các lược đồ định dạng OpenAI.
5. **Vá lược đồ động** — sau khi lọc, các lược đồ
`execute_code
` và
`browser_navigate
` được điều chỉnh linh hoạt để chỉ các công cụ tham chiếu thực sự đã vượt qua quá trình lọc (ngăn ảo giác mô hình về các công cụ không khả dụng).

### Tên bộ công cụ kế thừa

Tên bộ công cụ cũ có hậu tố
`_tools
` (ví dụ:
`web_tools

,
`terminal_tools

) được ánh xạ tới tên công cụ hiện đại của chúng thông qua
`_LEGACY_TOOLSET_MAP
` để tương thích ngược.

## Công văn

Trong thời gian chạy, các công cụ được gửi đi thông qua sổ đăng ký trung tâm, với các ngoại lệ vòng lặp tác nhân đối với một số công cụ cấp tác nhân như xử lý bộ nhớ/việc cần làm/tìm kiếm phiên.### Luồng điều phối: model tool_call → thực thi trình xử lý

Khi mô hình trả về
`tool_call

, quy trình là:

`
Model response with tool_call

run_agent.py agent loop

model_tools.handle_function_call(name, args, task_id, user_task)

[Agent-loop tools?] → handled directly by agent loop (todo, memory, session_search, delegate_task)

[Plugin pre-hook] → invoke_hook("pre_tool_call", ...)

registry.dispatch(name, args, **kwargs)

Look up ToolEntry by name

[Async handler?] → bridge via _run_async()
[Sync handler?] → call directly

Return result string (or JSON error)

[Plugin post-hook] → invoke_hook("post_tool_call", ...)

`

### Lỗi gói

Tất cả việc thực thi công cụ đều được gói gọn trong việc xử lý lỗi ở hai cấp độ:
1. **
`registry.dispatch()

** — bắt bất kỳ ngoại lệ nào từ trình xử lý và trả về

\{"error": "Tool execution failed: ExceptionType: message"}
` dưới dạng JSON.
2. **
`handle_function_call()

** — gói toàn bộ công văn trong lần thử phụ/ngoại trừ việc trả về

\{"error": "Error executing tool_name: message"}

.

Điều này đảm bảo mô hình luôn nhận được chuỗi JSON đúng định dạng, không bao giờ có ngoại lệ chưa được xử lý.

### Công cụ vòng lặp tác nhân

Bốn công cụ bị chặn trước khi gửi đăng ký vì chúng cần trạng thái cấp tác nhân (TodoStore, MemoryStore, v.v.):
-
`todo

- theo dõi kế hoạch/nhiệm vụ
-
`memory

- ghi bộ nhớ liên tục
-
`session_search
` — thu hồi giữa các phiên
-
`delegate_task

- tạo ra các phiên tác nhân phụ

Lược đồ của các công cụ này vẫn được đăng ký trong sổ đăng ký (dành cho
`get_tool_definitions

), nhưng trình xử lý của chúng trả về lỗi sơ khai nếu việc gửi đi bằng cách nào đó đến trực tiếp với chúng.

### Cầu nối không đồng bộ

Khi trình xử lý công cụ không đồng bộ,
`_run_async()
` sẽ kết nối nó với đường dẫn điều phối đồng bộ hóa:
- **Đường dẫn CLI (không có vòng lặp đang chạy)** — sử dụng vòng lặp sự kiện liên tục để duy trì hoạt động của các máy khách không đồng bộ được lưu trong bộ nhớ đệm
- **Đường dẫn cổng (vòng lặp đang chạy)** — tạo ra một luồng dùng một lần với
`asyncio.run()

- **Luồng công nhân (công cụ song song)** — sử dụng các vòng lặp liên tục trên mỗi luồng được lưu trữ trong bộ nhớ cục bộ của luồng

## Luồng phê duyệt DANGEROUS_PATTERNS

Công cụ đầu cuối tích hợp hệ thống phê duyệt lệnh nguy hiểm được xác định trong
`tools/approval.py

:
1. **Phát hiện mẫu**
`DANGEROUS_PATTERNS
` là danh sách các bộ dữ liệu

(regex, description)
` bao gồm các hoạt động phá hoại:
- Xóa đệ quy (
`rm -rf

)
- Định dạng hệ thống tập tin (
`mkfs

,
`dd

)
- Hoạt động phá hoại SQL (
`DROP TABLE

,
`DELETE FROM
` không có
`WHERE

)
- Ghi đè cấu hình hệ thống (

> /etc/

)
- Thao tác dịch vụ (
`systemctl stop

)
- Thực thi mã từ xa (
`curl | sh

)
- Fork bom, xử lý tiêu diệt, v.v.
2. **Phát hiện** — trước khi thực hiện bất kỳ lệnh đầu cuối nào,
`detect_dangerous_command(command)
` sẽ kiểm tra tất cả các mẫu.
3. **Lời nhắc phê duyệt** — nếu tìm thấy kết quả phù hợp:
- **Chế độ CLI** — lời nhắc tương tác yêu cầu người dùng phê duyệt, từ chối hoặc cho phép vĩnh viễn
- **Chế độ cổng** — lệnh gọi lại phê duyệt không đồng bộ sẽ gửi yêu cầu đến nền tảng nhắn tin
- **Phê duyệt thông minh** — tùy chọn, LLM phụ trợ có thể tự động phê duyệt các lệnh có rủi ro thấp khớp với các mẫu (ví dụ:
`rm -rf node_modules/
` an toàn nhưng khớp với "xóa đệ quy")
4. **Trạng thái phiên** — phê duyệt được theo dõi mỗi phiên. Khi bạn phê duyệt "xóa đệ quy" cho một phiên, các lệnh
`rm -rf
` tiếp theo sẽ không được nhắc lại.
5. **Danh sách cho phép vĩnh viễn** — tùy chọn "cho phép vĩnh viễn" ghi mẫu vào
`command_allowlist
` của
`command_allowlist

, tồn tại qua các phiên.

## Môi trường đầu cuối/thời gian chạy

Hệ thống đầu cuối hỗ trợ nhiều phụ trợ:
- địa phương
- Docker
- sss
- điểm kỳ dị
- phương thức
- daytona
- vercel_sandbox

Nó cũng hỗ trợ:
- ghi đè cwd trên mỗi tác vụ
- quản lý quá trình nền
- Chế độ PTY
- gọi lại phê duyệt cho các lệnh nguy hiểm

## Đồng thời

Lệnh gọi công cụ có thể thực hiện tuần tự hoặc đồng thời tùy thuộc vào yêu cầu tương tác và kết hợp công cụ.

## Tài liệu liên quan
- [Toolsets Reference](../reference/toolsets-reference.md)
- [Built-in Tools Reference](../reference/tools-reference.md)
- [Agent Loop Internals](./agent-loop.md)
- [ACP Internals](./ACP-internals.md)