Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,43 @@ everos
│ └── show [--root PATH] Show effective configuration
├── server
│ └── start [--host] [--port] [--root] [--reload] [--log-level] Start the HTTP API server (uvicorn)
└── cascade [--root PATH] Inspect / operate the md → LanceDB sync queue
├── status Queue / LSN summary
├── sync [PATH] Drain the queue now (optional PATH force-enqueues)
└── fix [--apply] List failed rows / re-enqueue retryable ones
├── cascade [--root PATH] Inspect / operate the md → LanceDB sync queue
│ ├── status Queue / LSN summary
│ ├── sync [PATH] Drain the queue now (optional PATH force-enqueues)
│ └── fix [--apply] List failed rows / re-enqueue retryable ones
└── integrations Install EverOS into third-party tools
├── install [hermes] [--source PATH] [--force]
└── uninstall [hermes] [--source PATH] [--force] [--yes]
```

Each subcommand lives in its own module under
[`entrypoints/cli/commands/`](../src/everos/entrypoints/cli/commands/) and is
registered in `cli/main.py`. The CLI is intentionally small — hot-path
business (`/add` `/flush` `/search` `/get`) is the **HTTP API**, not the
CLI; the CLI covers setup (`init`), running the server, and index ops
(`cascade`). There is no `reindex` command — rebuild by deleting
`<root>/.index/lancedb` and restarting, or run `everos cascade sync`.
CLI; the CLI covers setup (`init`), running the server, index ops
(`cascade`), and external-tool install (`integrations`). There is no
`reindex` command — rebuild by deleting `<root>/.index/lancedb` and
restarting, or run `everos cascade sync`.

## `everos integrations`

Install EverOS integrations into third-party tools. Currently ships the
Hermes Agent memory-provider plugin — see
[hermes-integration.md](hermes-integration.md) for the full walkthrough.

```bash
everos integrations install hermes [--source PATH] [--force]
everos integrations uninstall hermes [--source PATH] [--force] [--yes]
```

`install` symlinks the bundle at `integrations/hermes/` into
`$HERMES_HOME/plugins/everos/` so Hermes discovers it. The bundle source
resolves in this order: `EVEROS_HERMES_PLUGIN_SOURCE` env → `--source`
flag → repo-root walk-up from `everos.__file__` (covers editable/dev
installs). An existing symlink is replaced; a real directory requires
`--force`. `uninstall` removes the symlink only if it points at this
bundle (`--force` skips the ownership check; `--source` overrides the
expected path). `~/.everos` memory data is never touched.

## `everos server start`

Expand Down
180 changes: 180 additions & 0 deletions docs/hermes-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# Hermes Agent Integration

Wire [Hermes Agent](https://github.com/NousResearch/hermes-agent) to an
EverOS server as its long-term, cross-session memory backend — durable
markdown memory, semantic + lexical recall, and offline consolidation,
with no `hermes-agent` PR required.

The integration ships **inside the EverOS repo** as a Hermes
`MemoryProvider` plugin bundle at
[`integrations/hermes/`](../integrations/hermes/). The
`everos integrations install hermes` command symlinks the bundle into
`~/.hermes/plugins/everos/`; Hermes discovers user-installed plugins and
loads them via the `MemoryProvider` subclass-fallback path.

## Prerequisites

- An EverOS server you can reach (local or remote). See
[QUICKSTART](../QUICKSTART.md) for install + `everos server start`.
- Hermes Agent installed (`hermes` on your `PATH`).
- For **OSS mode** (local EverOS with self-supplied models): an
OpenAI-protocol LLM, embedding, and (optionally) rerank endpoint —
e.g. DeepInfra, OpenRouter, OpenAI, Together, or a local vLLM/Ollama
exposing the OpenAI shape.

## Install

```bash
# from the EverOS checkout (editable/dev install — the common case)
everos integrations install hermes

# or, for a non-editable install, point at the bundle explicitly:
everos integrations install hermes --source /path/to/EverOS/integrations/hermes

# activate it in Hermes
hermes config set memory.provider everos
```

Verify Hermes discovered the plugin:

```bash
hermes memory status
# → Provider: everos · Plugin: installed ✓ · Status: available ✓
# Installed plugins: … everos (local) ← active
```

Then configure it with `hermes memory setup` (select `everos`) or by
editing `$HERMES_HOME/everos.json` directly (see [Config](#config)).

## Modes

| Mode | When | Config |
|---|---|---|
| `platform` | A vendor-hosted / remote EverOS server | `api_url` only |
| `oss` (default) | EverOS runs locally with your own LLM / embedding / rerank | `api_url` + `~/.everos/everos.toml` (the setup wizard writes it) |

`hermes memory setup` walks you through either mode. In OSS mode the
wizard writes `~/.everos/everos.toml` with `[llm]`, `[embedding]`, and
`[rerank]` blocks (chmod 600) — see
[configuration.md](configuration.md) for the full key reference. When
`agent_track_enabled` is set, it also seeds `~/.everos/ome.toml` to turn
on the agent-track OME strategies (`extract_agent_case`,
`extract_agent_skill`, `trigger_skill_clustering`).

## Config

Behavioral settings live in `$HERMES_HOME/everos.json`. Secrets belong in
`$HERMES_HOME/.env` (e.g. `EVEROS_API_KEY`), not `everos.json`.

| Key | Default | Description |
|---|---|---|
| `api_url` | `http://127.0.0.1:8000` | EverOS server URL |
| `mode` | `oss` | `platform` or `oss` |
| `user_id` | `hermes-user` | EverOS user id to index your memories under. When unset, the gateway-native id (Telegram/Discord/Slack) flows through so the same human gets one merged store |
| `agent_id` | `hermes` | EverOS agent id (agent-track attribution) |
| `app_id` | `default` | EverOS app scope |
| `project_id` | `default` | EverOS project scope |
| `agent_track_enabled` | `false` | Also write/search the agent track (cases + skills) |
| `api_key` | — | CLI-only; read by the `hermes everos` subcommands. The provider itself does not authenticate (EverOS is loopback/no-auth by default) |

`app_id` / `project_id` must match `^[a-zA-Z0-9_.@+-]+$` (the server-side
`PathSafeId` charset) and reject `.` / `..`.

## How it works

### Write path (every turn → durable memory)

After each completed Hermes turn, `sync_turn` builds two `MessageItem`s
(user + assistant, Unix-ms timestamps) and `POST /api/v1/memory/add`s them
on a daemon thread. EverOS buffers them per `session_id`; its boundary
detector decides when a segment is done, then the extractor (an LLM)
writes an **Episode** to markdown synchronously —
`~/.everos/.../users/<user_id>/episodes/episode-<date>.md`. At session end,
`on_session_end` calls `POST /memory/flush` to force extraction of any
pending buffer.

Markdown is the source of truth; SQLite (state) and LanceDB
(vectors + BM25) are derived and rebuildable. See
[how-memory-works.md](how-memory-works.md).

### Recall path (every turn → relevant context injected)

Before each turn, `prefetch` fires a background `POST /memory/search`
(`include_profile=True`) and waits up to 1.5 s. The result — top episodes
(subject + truncated narrative) + nested atomic facts + a profile
one-liner, score-sorted — is injected into the agent's context for that
turn. If the server is slow, the result surfaces on the next turn
(mem0-style two-phase).

### Long-term, consolidating

Episodes persist across Hermes restarts and chats. The Offline Memory
Engine runs in the background: `extract_atomic_facts` (single-sentence
facts), `extract_user_profile` (an evolving `user.md`), and — opt-in,
weekly cron — `reflect_episodes`, which merges fragmented episodes about
the same topic into one narrative and soft-archives the originals. See
[reflection.md](reflection.md).

## Tools exposed to the agent

Beyond passive prefetch, the agent gets four tools:

| Tool | Maps to | Purpose |
|---|---|---|
| `everos_search` | `POST /memory/search` | Semantic + lexical hybrid recall |
| `everos_list` | `POST /memory/get` | Paginated browse of episodes / profile / cases / skills |
| `everos_add` | `POST /memory/add` + `/flush` | Buffer a fact and force extraction |
| `everos_flush` | `POST /memory/flush` | Force extraction of the current session buffer |

`everos_search` / `everos_list` take an `owner` (`user` | `agent`) to
select the user vs agent track, independent of `mode`.

## Hermes-side CLI

When `memory.provider` is `everos`, Hermes exposes `hermes everos …`:

```bash
hermes everos status # reachability + active config/scope + breaker state
hermes everos search "QUERY" [--top-k N] [--method hybrid|vector|keyword|agentic] [--owner user|agent]
hermes everos flush [--session-id ID]
hermes everos setup --mode oss --api-url ... --user-id ... # non-interactive everos.json writer
```

`hermes everos setup` only manages `everos.json`; for full OSS setup
(including `~/.everos/everos.toml`) use `hermes memory setup`.

## Resilience

A circuit breaker trips after 5 consecutive transient failures (server
down, LLM/embedding 503) and pauses calls for 120 s. A down EverOS server
never crashes Hermes or stalls the conversation — it degrades to built-in
`MEMORY.md`/`USER.md` until the server recovers. Client errors
(`INVALID_INPUT`, `NOT_FOUND`, …) do **not** trip the breaker.

## Troubleshooting

| Symptom | Likely cause / fix |
|---|---|
| `hermes memory status` shows `Status: not available` | `everos.json` missing or `api_url` empty — run `hermes memory setup` |
| `everos_search` returns 503 | The query-embedding step failed — check `~/.everos/everos.toml` `[embedding]` is reachable |
| Memories not appearing after `everos_add` | `everos_add` buffers + flushes; extraction runs on flush. If extraction fails, check the EverOS server logs and the `[llm]` config |
| Recall misses a just-written episode | LanceDB indexing is async (sub-second, up to ~10–15 s under load); retry, or `everos cascade sync` |
| `hermes everos …` command not found | The CLI is gated on `memory.provider == everos` — run `hermes config set memory.provider everos` |

## Uninstall

```bash
everos integrations uninstall hermes # removes the dev symlink
# revert the provider if you no longer use it:
hermes config set memory.provider ''
```

`~/.everos` (your actual memory data) is preserved.

## See also

- [Bundle README](../integrations/hermes/README.md) — full setup/config/tool reference
- [how-memory-works.md](how-memory-works.md) — the write→index→read pipeline
- [api.md](api.md) — the EverOS HTTP API v1 contract this plugin calls
- [configuration.md](configuration.md) — `everos.toml` / env-var reference
- [cli.md](cli.md) — the `everos` CLI, including `everos integrations`
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ before wiring it into a real workflow.
| Doc | Purpose |
|---|---|
| [everos-demo.md](everos-demo.md) | `everos demo` — local educational TUI to feel the memory lifecycle before configuring keys |
| [hermes-integration.md](hermes-integration.md) | Wire Hermes Agent to EverOS as a long-term memory backend — install, config, lifecycle, tools |

## Reference

Expand Down
148 changes: 148 additions & 0 deletions integrations/hermes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# EverOS Memory Provider

EverOS memory provider plugin for Hermes Agent. Supports both vendor-hosted EverOS servers (platform mode) and local self-hosted instances (OSS mode) with your own LLM / embedding / rerank endpoints. Server-side md-first memory extraction, hybrid search, and per-session flushing.

## Requirements

- An EverOS server running and reachable (e.g. `everos server start`).
- `httpx` (declared in `plugin.yaml`; Hermes installs it automatically).

## Install

From the EverOS checkout, symlink this bundle into Hermes' plugin directory:

```bash
everos integrations install hermes
```

This links `integrations/hermes/` to `$HERMES_HOME/plugins/everos` (default
`~/.hermes/plugins/everos`). To point at a non-default bundle source, set
`EVEROS_HERMES_PLUGIN_SOURCE=/path/to/bundle` or pass `--source PATH`. To
replace an existing real directory at the target, pass `--force`.

> The bundle ships in-repo (`integrations/hermes/`), not in the EverOS
> wheel. Wheel-only installs (no checkout) therefore need
> `--source PATH` (or `EVEROS_HERMES_PLUGIN_SOURCE`) pointing at a
> separate checkout of the bundle.

Then activate EverOS as the memory provider:

```bash
hermes memory setup # select "everos"
```

Or, non-interactively:

```bash
hermes everos setup --mode platform --api-url http://127.0.0.1:8000 --api-key sk-...
hermes config set memory.provider everos
```

> `hermes everos setup` only writes/merges `$HERMES_HOME/everos.json`. For a
> full OSS-mode setup (writing `~/.everos/everos.toml` + `ome.toml`), use
> `hermes memory setup` and select "everos".

To remove the bundle later:

```bash
everos integrations uninstall hermes
```

The `memory.provider` setting in Hermes config is left untouched — clear it
manually with `hermes config set memory.provider ''` if needed.

## Config

Behavioral settings live in `$HERMES_HOME/everos.json` (set them via
`hermes memory setup` or `hermes everos setup`). Only the secret
`EVEROS_API_KEY` belongs in `~/.hermes/.env`.

| Key | Default | Description |
|-----|---------|-------------|
| `mode` | `platform` | `platform` (vendor-hosted EverOS) or `oss` (self-hosted) |
| `api_url` | `http://127.0.0.1:8000` | EverOS API base URL |
| `api_key` | — | EverOS API key (CLI-only; secret — prefer `EVEROS_API_KEY` env). Read from `EVEROS_API_KEY` / `everos.json` ONLY by the `hermes everos` CLI subcommands (status/search/flush). The provider itself does not authenticate: EverOS is loopback/no-auth by default. `_config.load_config` does not load it. |
| `user_id` | `hermes-user` | User identifier (user-track scope) |
| `agent_id` | `hermes` | Agent identifier (agent-track scope; used when `--owner agent`) |
| `app_id` | `default` | EverOS app scope |
| `project_id` | `default` | EverOS project scope |
| `agent_track_enabled` | `false` | Enables the agent-track OME extractors (`extract_agent_case`, `extract_agent_skill`, `trigger_skill_clustering`) in `~/.everos/ome.toml`. OSS mode only. |
| `everos_root` | `~/.everos` | EverOS root directory (OSS mode; `null` in platform mode) |

The EverOS server itself is configured via `~/.everos/everos.toml`
(see `everos config show`). The plugin only needs to know how to reach it
and which scope to read/write.

Example `everos.json`:

```json
{
"mode": "platform",
"api_url": "http://127.0.0.1:8000",
"user_id": "hermes-user",
"agent_id": "hermes",
"app_id": "default",
"project_id": "default"
}
```

## CLI

When EverOS is the active memory provider, `hermes everos <subcommand>` is
available:

| Subcommand | Description |
|------------|-------------|
| `status` | Print reachability, active mode/user/scope, and circuit-breaker state |
| `search QUERY` | One-off search against the active config; prints JSON |
| `flush` | POST `/memory/flush` for the current session |
| `setup` | Non-interactive shortcut: write/merge `everos.json` |

```bash
hermes everos status
hermes everos search "the user's preferred editor" --top-k 5
hermes everos flush --session-id my-session
hermes everos setup --mode oss --api-url http://127.0.0.1:8000
```

## Tools

The provider exposes four agent-facing tools:

| Tool | Description |
|------|-------------|
| `everos_search` | Hybrid search by meaning; returns ranked episodes / profiles / agent cases / skills |
| `everos_list` | List stored memories (paginated, unranked) |
| `everos_add` | Buffer a fact (add_messages) then flush the session; extraction runs on flush |
| `everos_flush` | Flush the current session's buffered messages for extraction |

## Troubleshooting

### "EverOS temporarily unavailable"

The circuit breaker trips after 5 consecutive failures and pauses API calls
for 2 minutes. It resets automatically.

- Check the EverOS server is running: `everos server start` or `curl http://127.0.0.1:8000/health`.
- Check `api_url` in `$HERMES_HOME/everos.json` points at the right server.
- Run `hermes everos status` to see the breaker state and reachability.

### Server unreachable

```bash
curl http://127.0.0.1:8000/health
```

If this fails, start the EverOS server (`everos server start`) or fix
`api_url`. The plugin degrades gracefully — search returns no results and
writes are buffered until the breaker resets.

### Memories not appearing

- `everos_add` buffers the fact (`add_messages`) and immediately flushes the
session — extraction runs on flush. For full LLM-backed extraction use the
normal turn flow.
- Search uses hybrid matching — try broader queries.
- Confirm `user_id` / `agent_id` / `app_id` / `project_id` match between
sessions (`$HERMES_HOME/everos.json`).
- Run `hermes everos flush` to force extraction of buffered messages.
Loading