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

Thêm bộ điều hợp nền tảng

Hướng dẫn này bao gồm việc thêm nền tảng nhắn tin mới vào cổng Hermes. Bộ điều hợp nền tảng kết nối Hermes với dịch vụ nhắn tin bên ngoài (Telegram, Discord, WeCom, v.v.) để người dùng có thể tương tác với đại lý thông qua dịch vụ đó.

mẹo

Việc thêm bộ điều hợp nền tảng sẽ chạm vào hơn 20 tệp trên mã, cấu hình và tài liệu. Sử dụng hướng dẫn này làm danh sách kiểm tra — bản thân tệp bộ điều hợp thường chỉ chiếm 40% công việc.

Tổng quan về kiến trúc

User ↔ Messaging Platform ↔ Platform Adapter ↔ Gateway Runner ↔ AIAgent

Mọi bộ điều hợp đều mở rộng BasePlatformAdapter từ gateway/platforms/base.py và thực hiện:

  • connect() — Thiết lập kết nối (WebSocket, thăm dò ý kiến dài, máy chủ HTTP, v.v.)
  • disconnect() — Tắt máy sạch sẽ
  • send() — Gửi tin nhắn văn bản tới cuộc trò chuyện
  • send_typing() — Hiển thị chỉ báo gõ (tùy chọn)
  • get_chat_info() — Trả về siêu dữ liệu trò chuyện

Các tin nhắn gửi đến được bộ chuyển đổi nhận và chuyển tiếp qua self.handle_message(event), lớp cơ sở sẽ định tuyến đến trình chạy cổng.

Danh sách kiểm tra từng bước

1. Nền tảng Enum

Thêm nền tảng của bạn vào enum Platform trong gateway/config.py:

class Platform(str, Enum):
# ... existing platforms ...
NEWPLAT = "newplat"

2. Tệp điều hợp

Tạo gateway/platforms/newplat.py:

from gateway.config import Platform, PlatformConfig
from gateway.platforms.base import (
BasePlatformAdapter, MessageEvent, MessageType, SendResult,
)

def check_newplat_requirements() -> bool:
"""Return True if dependencies are available."""
return SOME_SDK_AVAILABLE

class NewPlatAdapter(BasePlatformAdapter):
def __init__(self, config: PlatformConfig):
super().__init__(config, Platform.NEWPLAT)
# Read config from config.extra dict
extra = config.extra or {}
self._API_key = extra.get("API_key") or os.getenv("NEWPLAT_API_KEY", "")

async def connect(self) -> bool:
# Set up connection, start polling/webhook
self._mark_connected()
return True

async def disconnect(self) -> None:
self._running = False
self._mark_disconnected()

async def send(self, chat_id, content, reply_to=None, metadata=None):
# Send message via platform API
return SendResult(success=True, message_id="...")

async def get_chat_info(self, chat_id):
return {"name": chat_id, "type": "dm"}

Đối với tin nhắn gửi đến, hãy tạo MessageEvent và gọi self.handle_message(event):

source = self.build_source(
chat_id=chat_id,
chat_name=name,
chat_type="dm", # or "group"
user_id=user_id,
user_name=user_name,
)
event = MessageEvent(
text=content,
message_type=MessageType.TEXT,
source=source,
message_id=msg_id,
)
await self.handle_message(event)

3. Cấu hình cổng (gateway/config.py)

Ba điểm tiếp xúc:

  1. get_connected_platforms() — Thêm kiểm tra thông tin xác thực cần thiết cho nền tảng của bạn
  2. load_gateway_config() — Thêm mục nhập bản đồ env mã thông báo: Platform.NEWPLAT: "NEWPLAT_TOKEN"
  3. _apply_env_overrides() — Ánh xạ tất cả các biến env NEWPLAT_* vào cấu hình

4. Chạy cổng (gateway/run.py)

Năm điểm tiếp xúc:

  1. _create_adapter() — Thêm nhánh elif platform == Platform.NEWPLAT:
  2. Bản đồ người dùng được phép _is_user_authoriZed()Platform.NEWPLAT: "NEWPLAT_ALLOWED_USERS"
  3. _is_user_authoriZed() cho phép_tất cả bản đồPlatform.NEWPLAT: "NEWPLAT_ALLOW_ALL_USERS"
  4. Kiểm tra sớm bộ dữ liệu _any_allowlist — Thêm "NEWPLAT_ALLOWED_USERS"
  5. Kiểm tra sớm bộ dữ liệu _allow_all — Thêm "NEWPLAT_ALLOW_ALL_USERS"
  6. Bộ đông lạnh _UPDATE_ALLOWED_PLATFORMS — Thêm Platform.NEWPLAT

5. Phân phối đa nền tảng

  1. gateway/platforms/webhook.py — Thêm "newplat" vào bộ dữ liệu loại phân phối
  2. cron/scheduler.py — Thêm vào bộ đông lạnh _KNOWN_DELIVERY_PLATFORMS và bản đồ nền tảng _deliver_result()

6. Tích hợp CLI

  1. Hermes_CLI/config.py — Thêm tất cả các biến thể NEWPLAT_* vào _EXTRA_ENV_KEYS
  2. Hermes_CLI/gateway.py — Thêm mục vào danh sách _PLATFORMS với khóa, nhãn, biểu tượng cảm xúc, token_var, setup_instructions và vars
  3. Hermes_CLI/platforms.py — Thêm mục nhập PlatformInfo có nhãn và default_toolset (được sử dụng bởi skills_configtools_config TUI)
  4. Hermes_CLI/setup.py — Thêm chức năng _setup_newplat() (có thể ủy quyền cho gateway.py) và thêm bộ dữ liệu vào danh sách nền tảng nhắn tin
  5. Hermes_CLI/status.py — Thêm mục phát hiện nền tảng: "NewPlat": ("NEWPLAT_TOKEN", "NEWPLAT_HOME_CHANNEL")
  6. Hermes_CLI/dump.py — Thêm "newplat": "NEWPLAT_TOKEN" vào lệnh phát hiện nền tảng

7. Công cụ

  1. tools/send_message_tool.py — Thêm "newplat": Platform.NEWPLAT vào bản đồ nền tảng
  2. tools/cronjob_tools.py — Thêm newplat vào chuỗi mô tả mục tiêu phân phối

8. Bộ công cụ

  1. toolsets.py — Thêm định nghĩa bộ công cụ "Hermes-newplat" với _Hermes_CORE_TOOLS
  2. toolsets.py — Thêm "Hermes-newplat" vào danh sách bao gồm "Hermes-gateway"

9. Tùy chọn: Gợi ý về nền tảng

agent/prompt_builder.py — Nếu nền tảng của bạn có các giới hạn hiển thị cụ thể (không đánh dấu, giới hạn độ dài tin nhắn, v.v.), hãy thêm mục nhập vào lệnh _PLATFORM_HINTS. Thao tác này sẽ đưa hướng dẫn dành riêng cho nền tảng vào lời nhắc của hệ thống:

_PLATFORM_HINTS = {
# ...
"newplat": (
"You are chatting via NewPlat. It supports markdown formatting "
"but has a 4000-character message limit."
),
}

Không phải tất cả các nền tảng đều cần gợi ý — chỉ thêm một gợi ý nếu hành vi của tổng đài viên sẽ khác.

10. Kiểm tra

Tạo tests/gateway/test_newplat.py bao gồm:

  • Xây dựng bộ chuyển đổi từ cấu hình
  • Xây dựng sự kiện tin nhắn
  • Phương thức gửi (giả lập API bên ngoài)
  • Các tính năng dành riêng cho nền tảng (mã hóa, định tuyến, v.v.)

11. Tài liệu| Tập tin | Thêm gì |

|------|-------------| | website/docs/user-guide/messaging/newplat.md | Trang thiết lập nền tảng đầy đủ | | website/docs/user-guide/messaging/index.md | Bảng so sánh nền tảng, sơ đồ kiến ​​trúc, bảng bộ công cụ, phần bảo mật, liên kết các bước tiếp theo | | website/docs/reference/environment-variables.md | Tất cả NEWPLAT_* env vars | | website/docs/reference/toolsets-reference.md | bộ công cụ Hermes-newplat | | website/docs/integrations/index.md | Liên kết nền tảng | | website/sidebars.ts | Mục nhập thanh bên cho trang tài liệu | | website/docs/developer-guide/architecture.md | Số lượng bộ điều hợp + danh sách | | website/docs/developer-guide/gateway-internals.md | Danh sách tập tin bộ điều hợp |

Kiểm tra tính chẵn lẻ

Trước khi đánh dấu PR nền tảng mới là hoàn chỉnh, hãy chạy kiểm tra tính chẵn lẻ đối với nền tảng đã được thiết lập:

# Find every .py file mentioning the reference platform
search_files "BlueBubbles" output_mode="files_only" file_glob="*.py"

# Find every .py file mentioning the new platform
search_files "newplat" output_mode="files_only" file_glob="*.py"

# Any file in the first set but not the second is a potential gap

Lặp lại cho các tệp .md.ts. Điều tra từng khoảng trống - đó là bảng liệt kê nền tảng (cần cập nhật) hay tham chiếu dành riêng cho nền tảng (bỏ qua)?

Các mẫu phổ biến

Bộ điều hợp thăm dò ý kiến ​​dài

Nếu bộ điều hợp của bạn sử dụng tính năng bỏ phiếu dài (như Telegram hoặc Weixin), hãy sử dụng tác vụ vòng lặp bỏ phiếu:

async def connect(self):
self._poll_task = asyncio.create_task(self._poll_loop())
self._mark_connected()

async def _poll_loop(self):
while self._running:
messages = await self._fetch_updates()
for msg in messages:
await self.handle_message(self._build_event(msg))

Bộ điều hợp gọi lại/Webhook

Nếu nền tảng đẩy tin nhắn đến điểm cuối của bạn (như Cuộc gọi lại WeCom), hãy chạy máy chủ HTTP:

async def connect(self):
self._app = web.Application()
self._app.router.add_post("/callback", self._handle_callback)
# ... start aiohttp server
self._mark_connected()

async def _handle_callback(self, request):
event = self._build_event(await request.text())
await self._message_queue.put(event)
return web.Response(text="success") # Acknowledge immediately

Đối với các nền tảng có thời hạn phản hồi chặt chẽ (ví dụ: giới hạn 5 giây của WeCom), hãy luôn xác nhận ngay lập tức và chủ động gửi phản hồi của tổng đài viên qua API sau đó. Phiên tổng đài viên kéo dài 3–30 phút — việc trả lời nội tuyến trong cửa sổ phản hồi gọi lại là không khả thi.

Khóa mã thông báo

Nếu bộ điều hợp giữ kết nối liên tục với thông tin xác thực duy nhất, hãy thêm khóa theo phạm vi để ngăn hai hồ sơ sử dụng cùng một thông tin xác thực:

from gateway.status import acquire_scoped_lock, release_scoped_lock

async def connect(self):
if not acquire_scoped_lock("newplat", self._token):
logger.error("Token already in use by another profile")
return False
# ... connect

async def disconnect(self):
release_scoped_lock("newplat", self._token)

Triển khai tham khảo

Bộ chuyển đổiMẫuĐộ phức tạpTài liệu tham khảo tốt cho
BlueBubbles.pyREST + webhookTrung bìnhTích hợp API REST đơn giản
weixin.pyThăm dò ý kiến ​​dài + CDNCaoXử lý phương tiện, mã hóa
WeCom_callback.pyGọi lại/webhookTrung bìnhMáy chủ HTTP, mật mã AES, đa ứng dụng
Telegram.pyThăm dò ý kiến ​​​​dài + API BotCaoBộ điều hợp đầy đủ tính năng với các nhóm, chủ đề