Harness Academy
Tài liệu gốc 14 16 phútTiếng Việt + English
docs/en/s11-configuration-system.mdXem bản gốc
Ngôn ngữ bài đọc
Bản dịch tiếng Việt

Bản dịch đầy đủ theo đúng cấu trúc tài liệu; code, liên kết và định danh kỹ thuật được giữ nguyên.

s11: Hệ thống cấu hình

s00 > s01 > s02 > s03 > s04 > s05 > s06 > s07 > s08 > s09 > s10 > [ s11 ] > s12 > s13 > s14 > s15 > s16 > s17 > s18 > s19 > s20 > s21 > s22 > s23 > s24 > s25 > s26 > s27

Nếu cách duy nhất để điều chỉnh hành vi của hệ thống tổng đài viên là thay đổi mã thì đó không phải là một hệ thống thực sự có thể triển khai được.

Chương này giải quyết vấn đề gì

Bởi s10, bạn đã có một agent duy nhất có đầy đủ chức năng: vòng hội thoại, hệ thống công cụ, tính bền bỉ, bộ nhớ, kỹ năng, quyền và ủy quyền subagent.

Nhưng tất cả các tham số chi phối các cơ chế này -- sử dụng mô hình nào, gọi điểm cuối API nào, bật bộ công cụ nào, ngưỡng nén là gì, thông tin xác thực mà subagent sử dụng -- đều được mã hóa cứng hoặc nằm rải rác trên cơ sở mã.

Điều này tạo ra ba điểm đau thực sự:

1. Việc chuyển đổi mô hình yêu cầu thay đổi mã. Chuyển từ OpenRouter sang Anthropic hoặc từ Claude sang Gemini, không cần phải chạm vào một dòng Python nào.

2. Bí mật và cấu hình có cấu trúc được trộn lẫn với nhau. Khóa API không được xuất hiện trong tệp cấu hình YAML. Chúng cần được lưu trữ riêng, mã hóa riêng và không bao giờ được phạm phải một cách vô tình.

3. Cùng một người cần các bối cảnh runtime khác nhau. Một nhà phát triển có thể có một agent "viết mã" và một agent "viết", với các tính cách, bộ nhớ, bộ công cụ và thậm chí cả mô hình khác nhau. Nếu không có cách ly cấu hình, việc chuyển đổi ngữ cảnh có nghĩa là chỉnh sửa tệp theo cách thủ công.

Đây là vấn đề mà hệ thống cấu hình giải quyết:

Trích xuất "cách agent chạy" từ mã vào cấu hình bên ngoài có tính khai báo, có thể hợp nhất và có thể cô lập.

Nguồn cấu hình và mức độ ưu tiên

Thuật ngữ chính

HERMES_HOME là gì

Thư mục gốc cho toàn bộ hệ thống agent. Mặc định là ~/.hermes.

Tất cả cấu hình, bộ nhớ, phiên, kỹ năng và nhật ký đều nằm trong thư mục này. Nó là một root runtime hoàn toàn khép kín.

def get_hermes_home() -> Path:
    return Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))

Bằng cách thiết lập HERMES_HOME biến môi trường, bạn có thể trỏ toàn bộ hệ thống vào bất kỳ thư mục nào. Điều này đặc biệt hữu ích trong các tình huống Docker và Profile.

config.yaml là gì

Tệp cấu hình có cấu trúc. Tọa lạc tại HERMES_HOME/config.yaml. định dạng YAML.

Nó mô tả tất cả các tham số hành vi của agent: sử dụng mô hình nào, bật bộ công cụ nào, ngưỡng nén, chương trình phụ trợ đầu cuối, cấu hình subagent, v.v.

.env là gì

Tập tin bí mật. Tọa lạc tại HERMES_HOME/.env. Định dạng dotenv tiêu chuẩn.

Tất cả các khóa API, token và mật khẩu đều có ở đây -- không bao giờ có trong config.yaml. Quyền của tệp được đặt thành 0600 (chủ sở hữu chỉ đọc/ghi).

Hồ sơ là gì

Một thư mục HERMES_HOME bị cô lập hoàn toàn. Mỗi Hồ sơ có config.yaml, .env, bộ nhớ, phiên và kỹ năng độc lập riêng.

Ca sử dụng: cùng một người có thể có coder hồ sơ và một writer profile, với các tính cách, mô hình và cấu hình công cụ hoàn toàn khác nhau.

~/.hermes/                    <-- default profile
~/.hermes/profiles/coder/     <-- coder profile
~/.hermes/profiles/writer/    <-- writer profile

Chuyển đổi hồ sơ đơn giản có nghĩa là trỏ HERMES_HOME sang một thư mục khác.

Hợp nhất cấu hình là gì

Cấu hình hiệu quả cuối cùng không đến từ một nguồn duy nhất. Đó là kết quả của việc hợp nhất nhiều nguồn theo mức độ ưu tiên:

CLI arguments > environment variables > config.yaml > defaults

Mức độ ưu tiên cao hơn sẽ ghi đè mức độ ưu tiên thấp hơn. Điều này có nghĩa là bạn có thể đặt đường cơ sở trong config.yaml, sau đó tạm thời ghi đè một giá trị cụ thể thông qua các đối số CLI.

Mô hình tinh thần tối thiểu

DEFAULT_CONFIG in code (defaults)
  |
  | 1. Read config.yaml, deep merge
  v
Merged config dict
  |
  | 2. Read .env, load into environment variables
  v
Environment variables provide secrets
  |
  | 3. CLI arguments override
  v
Final runtime configuration
  |
  | 4. Expand ${VAR} references
  v
Passed to AIAgent.__init__()

Chỉ có một điểm mấu chốt:

Mã chứa đầy đủ các giá trị mặc định. Người dùng chỉ cần ghi đè các trường họ quan tâm. Các trường không bị ghi đè sẽ tự động sử dụng giá trị mặc định.

Cấu trúc dữ liệu chính

1. Cấu hình mặc định (DEFAULT_CONFIG)

Đây là từ điển mặc định hoàn chỉnh được xác định trong mã. Nó thiết lập giá trị mặc định cho mọi tùy chọn có thể định cấu hình:

DEFAULT_CONFIG = {
    "model": "",
    "providers": {},
    "fallback_providers": [],
    "credential_pool_strategies": {},
    "toolsets": ["hermes-cli"],

    "agent": {
        "max_turns": 90,
        "gateway_timeout": 1800,
        "tool_use_enforcement": "auto",
    },

    "terminal": {
        "backend": "local",
        "timeout": 180,
        "docker_image": "nikolaik/python-nodejs:python3.11-nodejs20",
        "persistent_shell": True,
    },

    "compression": {
        "enabled": True,
        "threshold": 0.50,
        "target_ratio": 0.20,
        "protect_last_n": 20,
    },

    "delegation": {
        "model": "",
        "provider": "",
        "base_url": "",
        "api_key": "",
        "max_iterations": 50,
        "reasoning_effort": "",
    },

    "memory": {
        "memory_enabled": True,
        "user_profile_enabled": True,
        "memory_char_limit": 2200,
        "user_char_limit": 1375,
    },

    "display": {
        "compact": False,
        "personality": "kawaii",
        "streaming": False,
        "show_cost": False,
    },

    "approvals": {
        "mode": "manual",
        "timeout": 60,
    },

    "command_allowlist": [],

    "tts": {
        "provider": "edge",
    },

    "auxiliary": {
        "vision":         {"provider": "auto", "model": ""},
        "web_extract":    {"provider": "auto", "model": ""},
        "compression":    {"provider": "auto", "model": ""},
        "session_search": {"provider": "auto", "model": ""},
        "approval":       {"provider": "auto", "model": ""},
    },

    "_config_version": 17,
}

Từ điển này phục vụ hai mục đích:

  1. Cung cấp giá trị mặc định -- Các trường không được người dùng định cấu hình sẽ tự động có giá trị
  2. Xác định lược đồ -- Mọi trường cấu hình hợp lệ đều có một vị trí ở đây

Lưu ý _config_version. Đây là số phiên bản được hệ thống di chuyển cấu hình sử dụng, sẽ được giải thích sau.

2. config.yaml của người dùng

Người dùng chỉ cần viết những phần họ quan tâm:

model: anthropic/claude-sonnet-4
toolsets:
  - hermes-cli
  - web
  - code-execution

agent:
  max_turns: 150

compression:
  threshold: 0.65

delegation:
  model: google/gemini-2.5-flash
  provider: openrouter

Người dùng đã không viết terminal, display, memory, v.v. -- những thứ đó tự động sử dụng giá trị mặc định từ DEFAULT_CONFIG.

3. tập tin .env

OPENROUTER_API_KEY=sk-or-v1-xxxxxxxxxxxx
ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxx
TELEGRAM_BOT_TOKEN=123456:ABC-DEF
TELEGRAM_ALLOWED_USERS=user1,user2

Các cặp khóa-giá trị thuần túy, không lồng nhau.

4. Cấu hình mô hình phụ trợ (phụ trợ)

agent Hermes không chỉ dựa vào một "mô hình chính". Nhiều tác vụ phụ trợ - phân tích tầm nhìn, trích xuất web, nén ngữ cảnh, tìm kiếm phiên, quyết định phê duyệt - có thể sử dụng các mô hình rẻ hơn, nhanh hơn:

auxiliary:
  vision:
    provider: openrouter
    model: google/gemini-2.5-flash
  compression:
    provider: openrouter
    model: google/gemini-2.5-flash
  approval:
    provider: openrouter
    model: google/gemini-2.5-flash

Mỗi tác vụ phụ trợ có thể định cấu hình độc lập nhà cung cấp, mô hình, base_url, api_key và thời gian chờ. Nếu không được cấu hình, mặc định "auto" chế độ cho phép hệ thống tự động chọn nhà cung cấp tốt nhất hiện có.

5. Cấu hình ủy quyền (delegation)

s10 đã đề cập rằng các agent phụ có thể sử dụng các mô hình và thông tin xác thực khác nhau. Cấu hình tồn tại ở đây:

delegation:
  model: google/gemini-2.5-flash     # Subagent uses a cheaper model
  provider: openrouter                # Subagent uses a different provider
  max_iterations: 50                  # Independent iteration limit per subagent
  reasoning_effort: medium            # Subagent reasoning intensity

Nếu model và provider được để trống, subagent sẽ kế thừa mô hình và thông tin đăng nhập của agent mẹ.

Thực hiện tối thiểu

Bước 1: Xác định mặc định và đường dẫn

import os
import yaml
from pathlib import Path

def get_hermes_home() -> Path:
    return Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))

def get_config_path() -> Path:
    return get_hermes_home() / "config.yaml"

def get_env_path() -> Path:
    return get_hermes_home() / ".env"

DEFAULT_CONFIG = {
    "model": "",
    "toolsets": ["hermes-cli"],
    "agent": {"max_turns": 90},
    "terminal": {"backend": "local", "timeout": 180},
    "compression": {"enabled": True, "threshold": 0.50},
    "delegation": {"model": "", "provider": ""},
}

Bước 2: Hợp nhất sâu

Đây là chức năng quan trọng nhất trong hệ thống cấu hình. Nếu người dùng chỉ ghi đè compression.threshold, các trường khác không được bị mất:

def _deep_merge(base: dict, override: dict) -> dict:
    """Recursive merge. override replaces base, but only for fields it declares."""
    result = base.copy()
    for key, value in override.items():
        if (
            key in result
            and isinstance(result[key], dict)
            and isinstance(value, dict)
        ):
            result[key] = _deep_merge(result[key], value)
        else:
            result[key] = value
    return result

Tại sao không chỉ sử dụng base.update(override)? Bởi vì update thay thế toàn bộ từ điển phụ:

# Wrong: using update
base = {"compression": {"enabled": True, "threshold": 0.50}}
override = {"compression": {"threshold": 0.65}}
base.update(override)
# base["compression"] = {"threshold": 0.65}  <-- enabled is gone!

# Correct: using _deep_merge
result = _deep_merge(base, override)
# result["compression"] = {"enabled": True, "threshold": 0.65}  <-- both preserved

Bước 3: Tải cấu hình

import copy

def load_config() -> dict:
    config = copy.deepcopy(DEFAULT_CONFIG)
    
    config_path = get_config_path()
    if config_path.exists():
        with open(config_path, encoding="utf-8") as f:
            user_config = yaml.safe_load(f) or {}
        config = _deep_merge(config, user_config)
    
    return config

copy.deepcopy là rất quan trọng -- bạn không được sửa đổi trực tiếp DEFAULT_CONFIG hoặc nhiều load_config() các cuộc gọi trong cùng một quy trình sẽ làm ô nhiễm lẫn nhau.

Bước 4: Tải .env

from dotenv import load_dotenv

def load_env():
    env_path = get_env_path()
    if env_path.exists():
        load_dotenv(dotenv_path=env_path, override=True)

override=True có nghĩa là các giá trị trong tệp .env sẽ ghi đè các biến môi trường shell hiện có. Đây là cố ý -- các giá trị mà người dùng viết vào ~/.hermes/.env là những giá trị có hiệu lực.

Bước 5: Mở rộng tham chiếu biến môi trường

config.yaml có thể tham chiếu các biến môi trường với ${VAR}:

delegation:
  api_key: "${OPENROUTER_API_KEY}"
import re

def _expand_env_vars(obj):
    if isinstance(obj, str):
        return re.sub(
            r"\${([^}]+)}",
            lambda m: os.environ.get(m.group(1), m.group(0)),
            obj,
        )
    if isinstance(obj, dict):
        return {k: _expand_env_vars(v) for k, v in obj.items()}
    if isinstance(obj, list):
        return [_expand_env_vars(item) for item in obj]
    return obj

Các tham chiếu chưa được giải quyết (khi biến môi trường không tồn tại) vẫn là ${VAR} thay vì trở thành chuỗi trống. Điều này cho phép người gọi phát hiện "giá trị này không được định cấu hình đúng cách".

Bước 6: Lưu cấu hình

def save_config(config: dict):
    config_path = get_config_path()
    config_path.parent.mkdir(parents=True, exist_ok=True)
    with open(config_path, "w", encoding="utf-8") as f:
        yaml.dump(config, f, default_flow_style=False, allow_unicode=True)
    os.chmod(config_path, 0o600)  # Owner read/write only

Đó là phiên bản tối thiểu. Sáu bước: xác định giá trị mặc định -> hợp nhất sâu -> tải YAML -> tải .env -> mở rộng tham chiếu -> lưu.

Lựa chọn thiết kế độc đáo của agent Hermes

1. Tách hai file: config.yaml và .env

Hầu hết các hệ thống đều sử dụng tất cả YAML hoặc tất cả .env. agent Hermes cố tình chia chúng thành hai tập tin:

  • config.yaml -- Cấu hình hành vi có cấu trúc (mô hình, bộ công cụ, ngưỡng, phần phụ trợ đầu cuối)
  • .env -- Bí mật (khóa API, token, mật khẩu)

Tại sao lại tách chúng ra?

  1. Bảo mật: Quyền của tệp .env được đặt thành 0600, người dùng khác không thể đọc được. config.yaml không chứa bí mật nào nên việc vô tình tiếp xúc sẽ không làm rò rỉ thông tin xác thực.
  2. Thân thiện với việc kiểm soát phiên bản: config.yaml có thể được kiểm tra một cách an toàn trong kiểm soát phiên bản (không có bí mật); .env đi vào .gitignore.
  3. Chia sẻ nhóm: Một nhóm có thể chia sẻ config.yaml (lựa chọn mô hình, cấu hình bộ công cụ) trong khi mỗi thành viên duy trì .env (khóa API riêng của họ).

2. Cách ly hồ sơ

Hồ sơ không chỉ là "hoán đổi tập tin cấu hình". Đó là "hoán đổi toàn bộ HERMES_HOME":

~/.hermes/profiles/coder/
+-- config.yaml       <-- independent configuration
+-- .env              <-- independent credentials
+-- SOUL.md           <-- independent persona
+-- memories/
|   +-- MEMORY.md     <-- independent memory
|   +-- USER.md       <-- independent user profile
+-- sessions/         <-- independent session history
+-- skills/           <-- independent skills
+-- logs/             <-- independent logs
+-- cron/             <-- independent scheduled tasks
+-- home/             <-- independent subprocess HOME (isolates git/ssh/npm config)
+-- workspace/        <-- independent working directory

Tạo hồ sơ:

hermes profile create coder          # Blank profile
hermes profile create coder --clone  # Copies config.yaml, .env, SOUL.md, MEMORY.md

Sử dụng hồ sơ:

hermes -p coder chat                 # Via the -p flag
hermes profile use coder             # Set as default

Bản chất của Hồ sơ là chỉ ra HERMES_HOME biến môi trường thành ~/.hermes/profiles/coder/. Sau đó tất cả mã -- get_hermes_home(), get_config_path(), get_env_path() -- tự động trỏ đến thư mục mới.

Không cần các nhánh có điều kiện. Khi thư mục thay đổi, toàn bộ thế giới sẽ thay đổi.

3. Di chuyển phiên bản cấu hình

Lược đồ cấu hình của agent Hermes phát triển theo thời gian. Phiên bản mới có thể thêm trường, đổi tên trường cũ hoặc di chuyển trường đến vị trí khác.

Hệ thống di chuyển theo dõi các phiên bản thông qua _config_version lĩnh vực:

# Which new environment variables each version introduced
ENV_VARS_BY_VERSION = {
    3: ["FIRECRAWL_API_KEY", "BROWSERBASE_API_KEY"],
    4: ["VOICE_TOOLS_OPENAI_KEY", "ELEVENLABS_API_KEY"],
    5: ["WHATSAPP_ENABLED", "SLACK_BOT_TOKEN"],
    10: ["TAVILY_API_KEY"],
}

Khi tải cấu hình, nếu tập tin _config_version thấp hơn phiên bản hiện tại trong mã, hệ thống sẽ:

  1. Thông báo cho người dùng về các biến môi trường tùy chọn mới
  2. Tự động di chuyển vị trí trường (ví dụ: max_turns đã chuyển từ cấp độ gốc sang agent.max_turns)
  3. Cập nhật _config_version đến phiên bản hiện tại
def _normalize_max_turns_config(config: dict) -> dict:
    """Migrate the old root-level max_turns to agent.max_turns."""
    config = dict(config)
    agent_config = dict(config.get("agent") or {})

    if "max_turns" in config and "max_turns" not in agent_config:
        agent_config["max_turns"] = config["max_turns"]

    config["agent"] = agent_config
    config.pop("max_turns", None)
    return config

Nguyên tắc thiết kế di chuyển là không mất dữ liệu: các tệp cấu hình cũ luôn hoạt động chính xác sau khi tải; một số trường chỉ được tự động di chuyển đến vị trí mới.

4. Bảo mật thư mục HERMES_HOME

Quyền được đặt tự động khi tạo thư mục và tệp:

def _secure_dir(path):
    os.chmod(path, 0o700)  # Owner access only

def _secure_file(path):
    os.chmod(path, 0o600)  # Owner read/write only

Trong chế độ được quản lý NixOS, các quyền được xử lý bởi tập lệnh kích hoạt hệ thống (0750 -- thành viên nhóm có thể đọc) và mã không chủ động đặt chúng.

5. Cấu hình mô hình dự phòng

s06 phục hồi lỗi được bảo hiểm. Hệ thống cấu hình cung cấp hỗ trợ khai báo cho chuyển đổi dự phòng:

# Primary model
model: anthropic/claude-sonnet-4

# Fallback model: auto-switch when the primary is unavailable
fallback_model:
  provider: openrouter
  model: anthropic/claude-sonnet-4

Điều kiện kích hoạt: giới hạn tốc độ (429), quá tải (529), lỗi dịch vụ (503), lỗi kết nối.

Điều này có nghĩa là logic chuyển đổi dự phòng từ s06 không cần mã hóa cứng bất kỳ thông tin mô hình nào -- nó chỉ đọc cấu hình.

Cách nó kết nối với vòng lặp chính

Cấu hình không có trong mã của vòng lặp lõi. Nó được tải trước khi vòng lặp bắt đầu và được truyền vào dưới dạng tham số.

Entry point (CLI or Gateway)
  |
  | 1. load_config()  -> read config.yaml + merge with defaults
  | 2. load_env()     -> read .env into environment variables
  v
Build AIAgent parameters
  |
  | config["model"]                -> model
  | config["agent"]["max_turns"]   -> max_iterations
  | config["terminal"]             -> environment configuration
  | os.getenv("OPENROUTER_API_KEY") -> api_key
  v
AIAgent(
    model=model,
    api_key=api_key,
    base_url=base_url,
    max_iterations=max_iterations,
    enabled_toolsets=toolsets,
    ...
)
  |
  v
Core loop runs (doesn't know where configuration came from)

Vòng lặp lõi không đọc trực tiếp config.yaml. Nó chỉ nhận được các tham số. Tất cả việc phân tích cú pháp và hợp nhất cấu hình được thực hiện ở lớp đầu vào.

Điều này có nghĩa là:

  • Vòng lặp lõi có thể được sử dụng lại bởi bất kỳ điểm vào nào (CLI, Gateway, kiểm tra)
  • Nguồn cấu hình có thể hoán đổi bất cứ lúc nào (chuyển từ YAML sang cơ sở dữ liệu không ảnh hưởng đến loop code)

Những sai lầm phổ biến nhất của người mới bắt đầu

1. Đưa khóa API vào config.yaml

Khóa API thuộc về .env, không phải config.yaml. config.yaml có thể nhận được git cam kết, chia sẻ hoặc in trong nhật ký. Tệp .env có 0600 bảo vệ quyền và ở dạng .gitignore theo mặc định.

Nếu config.yaml thực sự cần tham chiếu thông tin đăng nhập (ví dụ: api_key của cấu hình ủy quyền), hãy sử dụng ${VAR} tài liệu tham khảo:

delegation:
  api_key: "${DELEGATION_API_KEY}"

Chìa khóa thực tế nằm ở .env.

2. Thay đổi trực tiếp DEFAULT_CONFIG

load_config() phải copy.deepcopy(DEFAULT_CONFIG) trước khi sáp nhập. Nếu bạn thay đổi trực tiếp DEFAULT_CONFIG, lệnh gọi thứ hai tới load_config() trong cùng một quy trình sẽ đọc các giá trị mặc định bị ô nhiễm.

3. Sử dụng dict.update() thay vì deep merge

update() mất các trường lồng nhau. Người dùng chỉ cấu hình compression.threshold, nhưng compression.enabled biến mất. Bạn phải sử dụng đệ quy _deep_merge.

4. Chia sẻ .env giữa các Cấu hình

Mỗi Hồ sơ phải có .env riêng. Nếu nhiều cấu hình chia sẻ cùng một .env, việc chuyển đổi cấu hình có thể sử dụng khóa API sai hoặc thậm chí hiển thị khóa đặc quyền cao cho bối cảnh có đặc quyền thấp.

các --clone gắn cờ sao chép .env khi tạo hồ sơ; sau đó, hai bản sao độc lập.

5. Quên xử lý việc di chuyển cấu hình

Nếu hệ thống của bạn phát triển theo thời gian, tệp config.yaml của người dùng hiện tại có thể thiếu các trường mới. _deep_merge điền giá trị mặc định vào các trường bị thiếu, nhưng trường đổi tên hoặc chuyển vị trí yêu cầu chức năng di chuyển rõ ràng.

Phạm vi của chương này

Chương này trình bày cặn kẽ bốn điều:

  1. Tách hai tệp -- config.yaml giữ cấu hình có cấu trúc, .env giữ bí mật
  2. Hợp nhất sâu -- Người dùng chỉ ghi đè những gì họ quan tâm; mọi thứ khác sử dụng mặc định
  3. Cách ly hồ sơ -- Chuyển đổi HERMES_HOME sẽ chuyển đổi toàn bộ bối cảnh runtime
  4. Di chuyển phiên bản cấu hình -- Các tệp cấu hình cũ vẫn hoạt động chính xác trong các phiên bản mới

Các chủ đề bị trì hoãn:

  • Chi tiết cụ thể về chế độ được quản lý NixOS -> chủ đề triển khai
  • Chiến lược luân chuyển nhóm thông tin xác thực -> tối ưu hóa sản xuất
  • Luồng tương tác của trình hướng dẫn thiết lập -> chương CLI (s19)
  • Các trường cấu hình bộ điều hợp nền tảng -> Các chương Cổng (s12, s13)

Nếu người đọc có thể đạt được "việc thay đổi giá trị tệp cấu hình sẽ thay đổi hành vi của agent, việc thêm Cấu hình sẽ tách biệt bối cảnh runtime và các cấu hình cũ vẫn tồn tại khi nâng cấp mà không mất dữ liệu", thì chương này đã phục vụ mục đích của nó.

Sau chương này, bạn sẽ có thể trả lời

  • Tại sao phải chia khóa API và cấu hình cấu trúc thành hai file?
  • Đâu là sự khác biệt quan trọng giữa _deep_merge và dict.update()?
  • Bản chất của Hồ sơ là gì? Điều gì xảy ra về mặt kỹ thuật khi bạn chuyển đổi cấu hình?
  • Bốn mức độ ưu tiên của cấu hình là gì?
  • Mối quan hệ giữa hệ thống cấu hình và vòng lặp lõi là gì? Vòng lặp có biết cấu hình của nó đến từ YAML không?

Trong một câu: Hệ thống cấu hình của agent Hermes lưu trữ "tham số hành vi" trong config.yaml và "bí mật" trong .env, cả hai đều nằm trong thư mục HERMES_HOME. Nó sử dụng _deep_merge vì vậy người dùng chỉ khai báo sự khác biệt, Hồ sơ để chạy nhiều môi trường agent được cách ly hoàn toàn cho cùng một người và số phiên bản để di chuyển cấu hình cũ theo mã mới một cách dễ dàng.

Mục lục nguồn