메모리 제공자 플러그인
anchor alias
메모리 제공자 플러그인 구축
메모리 제공자 플러그인은 내장된 MEMORY.md 및 USER.md를 넘어서 Hermes Agent에 지속적인 세션 간 지식을 제공합니다. 이 가이드에서는 빌드 방법을 다룹니다.
메모리 제공자는 두 가지 제공자 플러그인 유형 중 하나입니다. 다른 하나는 내장된 컨텍스트 압축기를 대체하는 컨텍스트 엔진 플러그인입니다. 둘 다 동일한 패턴을 따릅니다: 단일 선택, 구성 기반, hermes plugins을 통해 관리됩니다.
디렉토리 구조
각 메모리 제공자는 plugins/memory/<name>/에 있습니다.
plugins/memory/my-provider/
├── __init__.py # MemoryProvider implementation + register() entry point
├── plugin.yaml # Metadata (name, description, hooks)
└── README.md # Setup instructions, config reference, tools
메모리 제공자 ABC
플러그인은 agent/memory_provider.py의 MemoryProvider 추상 기본 클래스를 구현합니다.
from agent.memory_provider import MemoryProvider
class MyMemoryProvider(MemoryProvider):
@property
def name(self) -> str:
return "my-provider"
def is_available(self) -> bool:
"""Check if this provider can activate. NO network calls."""
return bool(os.environ.get("MY_API_KEY"))
def initialize(self, session_id: str, **kwargs) -> None:
"""Called once at agent startup.
kwargs always includes:
hermes_home (str): Active HERMES_HOME path. Use for storage.
"""
self._api_key = os.environ.get("MY_API_KEY", "")
self._session_id = session_id
#... implement remaining methods
필수 방법
핵심 수명주기
| 방법 | 부름을 받았을 때 | 구현해야 합니까? |
|---|---|---|
name (속성) | 항상 | 예 |
is_available() | 에이전트 초기화, 활성화 전 | 예 - 네트워크 호출 없음 |
initialize(session_id, **kwargs) | 에이전트 시작 | 예 |
get_tool_schemas() | 초기화 후 도구 주입을 위해 | 예 |
handle_tool_call(name, args) | 에이전트이 도구를 사용하는 경우 | 예(도구가 있는 경우) |
구성
| 방법 | 목적 | 구현해야 합니까? |
|---|---|---|
get_config_schema() | hermes memory setup에 대한 구성 필드 선언 | 예 |
save_config(values, hermes_home) | 기본 위치에 비밀이 아닌 구성 쓰기 | 예(env-var 전용이 아닌 경우) |
옵션 후크
| 방법 | 부름을 받았을 때 | 사용 사례 |
|---|---|---|
system_prompt_block() | 시스템 프롬프트 조립 | 정적 제공자 정보 |
prefetch(query) | 각 API 호출 전 | 회상된 컨텍스트 반환 |
queue_prefetch(query) | 매 턴마다 | 다음 차례를 위해 예열 |
sync_turn(user, assistant) | 각 턴이 완료되면 | 대화 지속 |
on_session_end(messages) | 대화가 종료됩니다 | 최종 추출/플러시 |
on_pre_compress(messages) | 컨텍스트 압축 전 | 삭제하기 전에 통찰력을 저장하세요 |
on_memory_write(action, target, content) | 내장 메모리 쓰기 | 백엔드에 미러링 |
shutdown() | 프로세스 종료 | 연결 정리 |
구성 스키마
get_config_schema()은 hermes memory setup에서 사용하는 필드 설명자 목록을 반환합니다.
def get_config_schema(self):
return [
{
"key": "api_key",
"description": "My Provider API key",
"secret": True, # → written to.env
"required": True,
"env_var": "MY_API_KEY", # explicit env var name
"url": "https://my-provider.com/keys", # where to get it
},
{
"key": "region",
"description": "Server region",
"default": "us-east",
"choices": ["us-east", "eu-west", "ap-south"],
},
{
"key": "project",
"description": "Project identifier",
"default": "hermes",
},
]
``secret: True` 및 `env_var`이 있는 필드는 `.env`로 이동합니다. 비밀이 아닌 필드는 `save_config()`로 전달됩니다.
:::tip[Minimal vs Full Schema]
`get_config_schema()`의 모든 필드는 `hermes memory setup` 중에 프롬프트됩니다. 옵션이 많은 공급자는 스키마를 최소화해야 합니다. 즉, 사용자가 **반드시** 구성해야 하는 필드(API 키, 필수 자격 증명)만 포함해야 합니다. 설정 중에 옵션 설정을 모두 묻는 대신 구성 파일 참조(예: `$HERMES_HOME/myprovider.json`)에 옵션 설정을 문서화하세요. 이렇게 하면 고급 구성을 계속 지원하면서 설정 마법사의 속도가 빨라집니다. 예를 보려면 Supermemory 공급자를 참조하세요. API 키만 묻는 메시지가 표시됩니다. 다른 모든 옵션은 `supermemory.json`에 있습니다.
:::
## 구성 저장 \{#save-config}
```python
def save_config(self, values: dict, hermes_home: str) -> None:
"""Write non-secret config to your native location."""
import json
from pathlib import Path
config_path = Path(hermes_home) / "my-provider.json"
config_path.write_text(json.dumps(values, indent=2))
env-var-only 공급자의 경우 기본 no-op를 그대로 둡니다.
플러그인 진입점
def register(ctx) -> None:
"""Called by the memory plugin discovery system."""
ctx.register_memory_provider(MyMemoryProvider())
플러그인.yaml
name: my-provider
version: 1.0.0
description: "Short description of what this provider does."
hooks:
- on_session_end # list hooks you implement
스레딩 계약
sync_turn() 비차단이어야 합니다. 백엔드에 지연 시간(API 호출, LLM 처리)이 있는 경우 데몬 스레드에서 작업을 실행합니다.
def sync_turn(self, user_content, assistant_content):
def _sync():
try:
self._api.ingest(user_content, assistant_content)
except Exception as e:
logger.warning("Sync failed: %s", e)
if self._sync_thread and self._sync_thread.is_alive():
self._sync_thread.join(timeout=5.0)
self._sync_thread = threading.Thread(target=_sync, daemon=True)
self._sync_thread.start()
프로필 격리
모든 저장소 경로는 반드시 하드코딩된 ~/.hermes이 아닌 initialize()의 hermes_home kwarg를 사용해야 합니다.
# CORRECT — profile-scoped
from hermes_constants import get_hermes_home
data_dir = get_hermes_home() / "my-provider"
# WRONG — shared across all profiles
data_dir = Path("~/.hermes/my-provider").expanduser()
테스트
실제 SQLite 공급자를 사용한 전체 테스트 패턴은 tests/agent/test_memory_plugin_e2e.py을 참조하세요.
from agent.memory_manager import MemoryManager
mgr = MemoryManager()
mgr.add_provider(my_provider)
mgr.initialize_all(session_id="test-1", platform="cli")
# Test tool routing
result = mgr.handle_tool_call("my_tool", {"action": "add", "content": "test"})
# Test lifecycle
mgr.sync_all("user msg", "assistant msg")
mgr.on_session_end()
mgr.shutdown_all()
CLI 명령 추가
메모리 공급자 플러그인은 자체 CLI 하위 명령 트리(예: hermes my-provider status, hermes my-provider config)를 등록할 수 있습니다. 이는 규칙 기반 검색 시스템을 사용하므로 코어 파일을 변경할 필요가 없습니다.
작동 원리
- 플러그인 디렉터리에
cli.py파일을 추가하세요. - argparse 트리를 구축하는
register_cli(subparser)함수를 정의합니다. - 메모리 플러그인 시스템은 시작 시
discover_plugin_cli_commands()을 통해 이를 발견합니다. - 명령은
hermes <provider-name> <subcommand>아래에 표시됩니다.
활성 공급자 게이팅: CLI 명령은 공급자가 구성에서 활성 memory.provider인 경우에만 나타납니다. 사용자가 공급자를 구성하지 않은 경우 명령이 hermes --help에 표시되지 않습니다.
예
# plugins/memory/my-provider/cli.py
def my_command(args):
"""Handler dispatched by argparse."""
sub = getattr(args, "my_command", None)
if sub == "status":
print("Provider is active and connected.")
elif sub == "config":
print("Showing config...")
else:
print("Usage: hermes my-provider <status|config>")
def register_cli(subparser) -> None:
"""Build the hermes my-provider argparse tree.
Called by discover_plugin_cli_commands() at argparse setup time.
"""
subs = subparser.add_subparsers(dest="my_command")
subs.add_parser("status", help="Show provider status")
subs.add_parser("config", help="Show provider config")
subparser.set_defaults(func=my_command)
참조 구현
13개 하위 명령, 프로필 간 관리(--target-profile) 및 구성 읽기/쓰기가 포함된 전체 예는 plugins/memory/honcho/cli.py을 참조하세요.
CLI를 사용한 디렉터리 구조
plugins/memory/my-provider/
├── __init__.py # MemoryProvider implementation + register()
├── plugin.yaml # Metadata
├── cli.py # register_cli(subparser) — CLI commands
└── README.md # Setup instructions
단일 공급자 규칙
한 번에 하나 외부 메모리 공급자만 활성화할 수 있습니다. 사용자가 두 번째 등록을 시도하면 MemoryManager는 경고와 함께 이를 거부합니다. 이를 통해 도구 스키마 팽창 및 백엔드 충돌을 방지할 수 있습니다.