Nội bộ vòng lặp đại lý
Công cụ điều phối cốt lõi là lớp
AIAgent của
run_agent.py — một tệp lớn (15k+ dòng) xử lý mọi thứ từ lắp ráp nhanh chóng đến gửi công cụ đến chuyển đổi dự phòng của nhà cung cấp.
Trách nhiệm cốt lõi``AIAgent
` chịu trách nhiệm:
-
Lắp ráp các lược đồ công cụ và nhắc nhở hệ thống hiệu quả thông qua `prompt_builder.py
-
Chọn đúng chế độ nhà cung cấp/API (chat_completions, Codex_responses, Anthropic_messages)
-
Thực hiện cuộc gọi mô hình bị gián đoạn với hỗ trợ hủy
-
Thực hiện các lệnh gọi công cụ (tuần tự hoặc đồng thời thông qua nhóm luồng)
-
Duy trì lịch sử hội thoại ở định dạng tin nhắn OpenAI
-
Xử lý việc nén, thử lại và chuyển đổi mô hình dự phòng
-
Theo dõi ngân sách lặp lại giữa các đại lý cha và con
-
Xóa bộ nhớ liên tục trước khi bối cảnh bị mất
Hai điểm vào
# Simple interface — returns final response string
response = agent.chat("Fix the bug in main.py")
# Full interface — returns dict with messages, metadata, usage stats
result = agent.run_conversation(
user_message="Fix the bug in main.py",
system_message=None, # auto-built if omitted
conversation_history=None, # auto-loaded from session if omitted
task_id="task_abc123"
)
`
```chat()
` là một trình bao bọc mỏng xung quanh
`run_conversation()
` giúp trích xuất trường
`final_response
` từ lệnh kết quả.
## Chế độ API
Hermes hỗ trợ ba chế độ thực thi API, được giải quyết từ việc lựa chọn nhà cung cấp, đối số rõ ràng và chẩn đoán URL cơ sở:
| Chế độ API | Được sử dụng cho | Loại khách hàng |
|----------|----------|-------------|
|
`chat_completions
` | Điểm cuối tương thích với OpenAI (OpenRouter, tùy chỉnh, hầu hết các nhà cung cấp) |
OpenAI.OpenAI
` |
|
`Codex_responses
` | OpenAI Codex / API phản hồi |
OpenAI.OpenAI
` với định dạng Phản hồi |
|
`Anthropic_messages
` | API thông điệp nhân loại bản địa |
Anthropic.Anthropic
` qua bộ chuyển đổi |
Chế độ này xác định cách định dạng thông báo, cách cấu trúc lệnh gọi công cụ, cách phân tích cú pháp phản hồi và cách hoạt động của bộ nhớ đệm/truyền phát. Cả ba đều hội tụ về cùng một định dạng thông báo nội bộ (các lệnh
`role
/
`content
/
`tool_calls
` theo phong cách OpenAI) trước và sau lệnh gọi API.
**Thứ tự phân giải chế độ:**
1. Đối số hàm tạo
`API_mode
` rõ ràng (mức độ ưu tiên cao nhất)
2. Phát hiện dành riêng cho nhà cung cấp (ví dụ: nhà cung cấp
`Anthropic
` →
`Anthropic_messages
)
3. Chẩn đoán URL cơ sở (ví dụ:
`API.Anthropic.com
` →
`Anthropic_messages
)
4. Mặc định:
`chat_completions
## Xoay vòng đời
Mỗi lần lặp của vòng lặp tác nhân tuân theo trình tự sau:
``` text
run_conversation()
1. Generate task_id if not provided
2. Append user message to conversation history
3. Build or reuse cached system prompt (prompt_builder.py)
4. Check if preflight compression is needed (>50% context)
5. Build API messages from conversation history
- chat_completions: OpenAI format as-is
- Codex_responses: convert to Responses API input items
- Anthropic_messages: convert via Anthropic_adapter.py
6. Inject ephemeral prompt layers (budget warnings, context pressure)
7. Apply prompt caching markers if on Anthropic
8. Make interruptible API call (_interruptible_API_call)
9. Parse response:
- If tool_calls: execute them, append results, loop back to step 5
- If text response: persist session, flush memory if needed, return
`
### Định dạng tin nhắn
Tất cả các tin nhắn đều sử dụng định dạng tương thích với OpenAI trong nội bộ:
``` python
\{"role": "system", "content": "..."}
\{"role": "user", "content": "..."}
\{"role": "assistant", "content": "...", "tool_calls": [...]}
\{"role": "tool", "tool_call_id": "...", "content": "..."}
`
``Nội dung lý luận (từ các mô hình hỗ trợ tư duy mở rộng) được lưu trữ trong
`assistant_msg["reasoning"]
` và được hiển thị tùy chọn qua
`reasoning_callback
.
### Quy tắc luân phiên tin nhắn
Vòng lặp tác nhân thực thi việc luân phiên vai trò thông báo nghiêm ngặt:
- Sau hệ thống có thông báo:
`User → Assistant → User → Assistant → ...
`
- Trong quá trình gọi công cụ:
`Assistant (with tool_calls) → Tool → Tool → ... → Assistant
- **Không bao giờ** hai tin nhắn trợ lý liên tiếp
- **Không bao giờ** hai tin nhắn của người dùng liên tiếp
- **Chỉ** Vai trò
`tool
` có thể có các mục liên tiếp (kết quả công cụ song song)
Nhà cung cấp xác thực các trình tự này và sẽ từ chối các lịch sử không đúng định dạng.
## Lệnh gọi API bị gián đoạn
Các yêu cầu API được gói trong
`_interruptible_API_call()
` chạy lệnh gọi HTTP thực tế trong luồng nền trong khi theo dõi sự kiện gián đoạn:
``` text
┌────────────────────────────────────────────────────┐
│ Main thread API thread │
│ │
│ wait on: HTTP POST │
│ - response ready ───▶ to provider │
│ - interrupt event │
│ - timeout │
└────────────────────────────────────────────────────┘
`
``Khi bị gián đoạn (người dùng gửi tin nhắn mới, lệnh
/stop
` hoặc tín hiệu):
- Chuỗi API bị hủy (phản hồi bị loại bỏ)
- Tác nhân có thể xử lý đầu vào mới hoặc tắt sạch
- Không có phản hồi một phần nào được đưa vào lịch sử hội thoại
## Thực thi công cụ
### Tuần tự và Đồng thời
Khi mô hình trả về các lệnh gọi công cụ:
- **Cuộc gọi công cụ đơn** → được thực thi trực tiếp trong luồng chính
- **Nhiều lệnh gọi công cụ** → được thực thi đồng thời thông qua
`ThreadPoolExecutor
- Ngoại lệ: các công cụ được đánh dấu là tương tác (ví dụ:
`clarify
) buộc thực thi tuần tự
- Kết quả được chèn lại theo thứ tự gọi công cụ ban đầu bất kể thứ tự hoàn thành
### Luồng thực thi
``` text
for each tool_call in response.tool_calls:
1. Resolve handler from tools/registry.py
2. Fire pre_tool_call plugin hook
3. Check if dangerous command (tools/approval.py)
- If dangerous: invoke approval_callback, wait for user
4. Execute handler with args + task_id
5. Fire post_tool_call plugin hook
6. Append \{"role": "tool", "content": result} to history
`
### Công cụ cấp đại lý
Một số công cụ bị
`run_agent.py
` chặn *trước khi* đạt đến
`handle_function_call()
:
| Công cụ | Tại sao bị chặn |
|------|----------------------|
|
`todo
` | Đọc/ghi trạng thái tác vụ cục bộ của tác nhân |
|
`memory
` | Ghi vào các tập tin bộ nhớ liên tục có giới hạn ký tự |
|
`session_search
` | Truy vấn lịch sử phiên thông qua phiên DB của đại lý |
|
`delegate_task
` | Sinh ra (các) tác nhân phụ với bối cảnh biệt lập |
Những công cụ này trực tiếp sửa đổi trạng thái tác nhân và trả về kết quả của công cụ tổng hợp mà không cần thông qua sổ đăng ký.
## Bề mặt gọi lại
`AIAgent
` hỗ trợ các lệnh gọi lại dành riêng cho nền tảng cho phép tiến trình theo thời gian thực trong tích hợp CLI, cổng và ACP:
| Gọi lại | Khi bị sa thải | Được sử dụng bởi |
|----------|-------------|----------|
|
`tool_progress_callback
` | Trước/sau mỗi lần thực hiện công cụ | CLI spinner, thông báo tiến trình cổng |
|
`thinking_callback
` | Khi người mẫu bắt đầu/ngưng suy nghĩ | Chỉ báo CLI "suy nghĩ..." |
|
`reasoning_callback
` | Khi mô hình trả về nội dung suy luận | Hiển thị lý luận CLI, khối lý luận cổng |
|
`clarify_callback
` | Khi công cụ
`clarify
` được gọi | Lời nhắc đầu vào CLI, thông báo tương tác cổng |
|
`step_callback
` | Sau mỗi lượt đại lý hoàn thành | Theo dõi bước cổng, tiến trình ACP |
|
`stream_delta_callback
` | Mỗi mã thông báo phát trực tuyến (khi được bật) | Hiển thị phát trực tuyến CLI |
|
`tool_gen_callback
` | Khi lệnh gọi công cụ được phân tích cú pháp từ luồng | Xem trước công cụ CLI trong spinner |
|
`status_callback
` | Thay đổi trạng thái (suy nghĩ, thực thi, v.v.) | Cập nhật trạng thái ACP |
## Hành vi ngân sách và dự phòng
### Ngân sách lặp lại
Tác nhân theo dõi các lần lặp qua
`IterationBudget
:
- Mặc định: 90 lần lặp (có thể định cấu hình qua
`agent.max_turns
)
- Mỗi đại lý có ngân sách riêng. Các đại lý phụ có ngân sách độc lập được giới hạn ở mức
`delegation.max_iterations
` (mặc định là 50) — tổng số lần lặp lại giữa các đại lý chính và các đại lý phụ có thể vượt quá giới hạn của đại lý phụ
- Khi đạt 100%, đại lý dừng và trả về bản tóm tắt công việc đã thực hiện
### Mô hình dự phòng
Khi mô hình chính bị lỗi (giới hạn tốc độ 429, lỗi máy chủ 5xx, lỗi xác thực 401/403):
1. Kiểm tra danh sách
`fallback_providers
` trong config
2. Thử từng phương án dự phòng theo thứ tự
3. Khi thành công, hãy tiếp tục cuộc trò chuyện với nhà cung cấp mới
4. Vào ngày 401/403, hãy thử làm mới thông tin xác thực trước khi vượt qua
Hệ thống dự phòng cũng bao gồm các tác vụ phụ trợ một cách độc lập — mỗi tác vụ trực quan, nén và trích xuất web đều có chuỗi dự phòng riêng có thể định cấu hình thông qua phần cấu hình
`auxiliary.*
.
## Nén và kiên trì
### Khi quá trình nén được kích hoạt
- **Preflight** (trước lệnh gọi API): Nếu cuộc hội thoại vượt quá 50% cửa sổ ngữ cảnh của mô hình
- **Tự động nén cổng**: Nếu cuộc trò chuyện vượt quá 85% (tích cực hơn, chạy giữa các lượt)
### Điều gì xảy ra trong quá trình nén
1. Bộ nhớ được xóa vào đĩa trước (ngăn ngừa mất dữ liệu)
2. Các lượt hội thoại giữa được tóm tắt thành một bản tóm tắt ngắn gọn
3. N tin nhắn cuối cùng được giữ nguyên (
`compression.protect_last_n
, mặc định: 20)
4. Các cặp thông báo cuộc gọi/kết quả công cụ được giữ cùng nhau (không bao giờ tách rời)
5. ID dòng phiên mới được tạo (nén tạo ra phiên "con")
### Sự kiên trì của phiên
Sau mỗi lượt:
- Tin nhắn được lưu vào kho phiên (SQLite via
`Hermes_state.py
)
- Các thay đổi về bộ nhớ được chuyển thành
`MEMORY.md
` /
`USER.md
- Phiên có thể được tiếp tục sau thông qua
/resume
` hoặc
`Hermes chat --resume
## Tệp nguồn chính
| Tập tin | Mục đích |
|------|----------|
|
`run_agent.py
` | Lớp AIAgent — vòng lặp tác nhân hoàn chỉnh |
|
`agent/prompt_builder.py
` | Hệ thống nhắc nhở từ trí nhớ, kỹ năng, ngữ cảnh, tính cách |
|
`agent/context_engine.py
` | ContextEngine ABC — quản lý bối cảnh có thể cắm được |
|
`agent/context_compressor.py
` | Công cụ mặc định - thuật toán tóm tắt mất dữ liệu |
|
`agent/prompt_caching.py
` | Dấu hiệu bộ nhớ đệm nhanh chóng của con người và số liệu bộ nhớ đệm |
|
`agent/auxiliary_CLIent.py
` | Ứng dụng khách LLM phụ trợ cho các nhiệm vụ phụ (tầm nhìn, tóm tắt) |
|
`model_tools.py
` | Bộ sưu tập lược đồ công cụ, công văn
`handle_function_call()
` |
## Tài liệu liên quan
- [Provider Runtime Resolution](./provider-runtime.md)
- [Prompt Assembly](./prompt-assembly.md)
- [Context Compression & Prompt Caching](./context-compression-and-caching.md)
- [Tools Runtime](./tools-runtime.md)
- [Architecture Overview](./architecture.md)