From e53b938911be6f91ce7c91b11910f778dbd3aaa5 Mon Sep 17 00:00:00 2001 From: lebedyncrs Date: Thu, 18 Jun 2026 01:25:55 +0200 Subject: [PATCH 1/3] fix(honcho): disable AI self-observation by default When ai_observe_me is true, Honcho absorbs user facts from the AI's own replies into the AI peer's self-representation. Default it off across the config chain so directional mode keeps AI observeOthers without observeMe. Co-authored-by: Cursor --- plugins/memory/honcho/__init__.py | 2 +- plugins/memory/honcho/client.py | 6 +++--- plugins/memory/honcho/session.py | 2 +- tests/honcho_plugin/test_client.py | 15 +++++++++++++++ tests/honcho_plugin/test_empty_profile_hint.py | 2 +- tests/honcho_plugin/test_session.py | 12 ++++++++++++ 6 files changed, 33 insertions(+), 6 deletions(-) diff --git a/plugins/memory/honcho/__init__.py b/plugins/memory/honcho/__init__.py index 3d130293377b..b73eadaf62a1 100644 --- a/plugins/memory/honcho/__init__.py +++ b/plugins/memory/honcho/__init__.py @@ -1164,7 +1164,7 @@ def _empty_profile_hint(self, peer: str) -> Dict[str, Any]: observe_me = bool(getattr(cfg, "user_observe_me", True)) observe_others = bool(getattr(cfg, "user_observe_others", True)) else: - observe_me = bool(getattr(cfg, "ai_observe_me", True)) + observe_me = bool(getattr(cfg, "ai_observe_me", False)) observe_others = bool(getattr(cfg, "ai_observe_others", True)) if not (observe_me or observe_others): reasons.append( diff --git a/plugins/memory/honcho/client.py b/plugins/memory/honcho/client.py index df8c839aa817..89f36ece3a43 100644 --- a/plugins/memory/honcho/client.py +++ b/plugins/memory/honcho/client.py @@ -248,7 +248,7 @@ def _normalize_observation_mode(val: str) -> str: _OBSERVATION_PRESETS = { "directional": { "user_observe_me": True, "user_observe_others": True, - "ai_observe_me": True, "ai_observe_others": True, + "ai_observe_me": False, "ai_observe_others": True, }, "unified": { "user_observe_me": True, "user_observe_others": False, @@ -366,7 +366,7 @@ class HonchoClientConfig: # Resolved from "observation" object in config, falling back to observation_mode preset. user_observe_me: bool = True user_observe_others: bool = True - ai_observe_me: bool = True + ai_observe_me: bool = False ai_observe_others: bool = True # Session resolution session_strategy: str = "per-directory" @@ -598,7 +598,7 @@ def from_global_config( # observationMode keep the old "unified" default so users # aren't silently switched to full bidirectional observation. # New installations (no host block, no credentials) get - # "directional" (all observations on) as the new default. + # "directional" (user self+other, AI other-only) as the new default. observation_mode=_normalize_observation_mode( host_block.get("observationMode") or raw.get("observationMode") diff --git a/plugins/memory/honcho/session.py b/plugins/memory/honcho/session.py index e83c714b51bb..4acb918b14cb 100644 --- a/plugins/memory/honcho/session.py +++ b/plugins/memory/honcho/session.py @@ -131,7 +131,7 @@ def __init__( # Per-peer observation booleans (granular, from config) self._user_observe_me: bool = config.user_observe_me if config else True self._user_observe_others: bool = config.user_observe_others if config else True - self._ai_observe_me: bool = config.ai_observe_me if config else True + self._ai_observe_me: bool = config.ai_observe_me if config else False self._ai_observe_others: bool = config.ai_observe_others if config else True self._message_max_chars: int = ( config.message_max_chars if config else 25000 diff --git a/tests/honcho_plugin/test_client.py b/tests/honcho_plugin/test_client.py index 7e956aa54c30..e2dab5ad771b 100644 --- a/tests/honcho_plugin/test_client.py +++ b/tests/honcho_plugin/test_client.py @@ -563,6 +563,21 @@ def test_new_config_defaults_to_directional(self, tmp_path): cfg_file.write_text(json.dumps({})) cfg = HonchoClientConfig.from_global_config(config_path=cfg_file) assert cfg.observation_mode == "directional" + assert cfg.ai_observe_me is False + assert cfg.ai_observe_others is True + + def test_directional_preset_disables_ai_self_observation(self, tmp_path): + """Directional mode: AI observes user but not its own messages.""" + cfg_file = tmp_path / "config.json" + cfg_file.write_text(json.dumps({ + "apiKey": "k", + "hosts": {"hermes": {"enabled": True, "observationMode": "directional"}}, + })) + cfg = HonchoClientConfig.from_global_config(config_path=cfg_file) + assert cfg.ai_observe_me is False + assert cfg.ai_observe_others is True + assert cfg.user_observe_me is True + assert cfg.user_observe_others is True def test_explicit_directional_respected(self, tmp_path): """Existing config with explicit observationMode → uses what's set.""" diff --git a/tests/honcho_plugin/test_empty_profile_hint.py b/tests/honcho_plugin/test_empty_profile_hint.py index c1128e4fba03..bf695abd25f5 100644 --- a/tests/honcho_plugin/test_empty_profile_hint.py +++ b/tests/honcho_plugin/test_empty_profile_hint.py @@ -20,7 +20,7 @@ def _make_provider(**cfg_overrides) -> HonchoMemoryProvider: # Defaults match HonchoClientConfig defaults cfg.user_observe_me = cfg_overrides.get("user_observe_me", True) cfg.user_observe_others = cfg_overrides.get("user_observe_others", True) - cfg.ai_observe_me = cfg_overrides.get("ai_observe_me", True) + cfg.ai_observe_me = cfg_overrides.get("ai_observe_me", False) cfg.ai_observe_others = cfg_overrides.get("ai_observe_others", True) cfg.message_max_chars = 25000 provider._config = cfg diff --git a/tests/honcho_plugin/test_session.py b/tests/honcho_plugin/test_session.py index e8dadf2f5763..a8923f562eb0 100644 --- a/tests/honcho_plugin/test_session.py +++ b/tests/honcho_plugin/test_session.py @@ -99,6 +99,18 @@ def test_clear_updates_timestamp(self): assert session.updated_at >= original +# --------------------------------------------------------------------------- +# HonchoSessionManager observation defaults +# --------------------------------------------------------------------------- + + +class TestObservationDefaults: + def test_ai_self_observation_off_without_config(self): + mgr = HonchoSessionManager() + assert mgr._ai_observe_me is False + assert mgr._ai_observe_others is True + + # --------------------------------------------------------------------------- # HonchoSessionManager._sanitize_id # --------------------------------------------------------------------------- From ab7333e5f4e16c48a391a1283c26a0df1b14d85d Mon Sep 17 00:00:00 2001 From: lebedyncrs Date: Thu, 18 Jun 2026 01:28:01 +0200 Subject: [PATCH 2/3] chore: map lebedyncrs in AUTHOR_MAP Required for Hermes contributor attribution CI on PRs from this checkout. Co-authored-by: Cursor --- scripts/release.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/release.py b/scripts/release.py index 2a74b3015075..f30b307f4aab 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -139,6 +139,8 @@ "prostoandrei9@gmail.com": "vladkvlchk", "116314616+ThyFriendlyFox@users.noreply.github.com": "ThyFriendlyFox", "liliangjya@gmail.com": "truenorth-lj", + "lebedyn.sergij@gmail.com": "lebedyncrs", + "7259302+lebedyncrs@users.noreply.github.com": "lebedyncrs", "16943149+nepenth@users.noreply.github.com": "nepenth", "ben.bartholomew@vectorize.io": "benfrank241", "74339271+SaguaroDev@users.noreply.github.com": "SaguaroDev", From a769004c3f152e6ff95b32bc6093622e6a29ba59 Mon Sep 17 00:00:00 2001 From: lebedyncrs Date: Thu, 18 Jun 2026 01:47:20 +0200 Subject: [PATCH 3/3] docs(honcho): update directional preset defaults in user-facing docs AI observeMe is off by default in directional mode; document the new semantics and use-case table in honcho.md and memory-providers.md. Co-authored-by: Cursor --- plugins/memory/honcho/README.md | 4 ++-- website/docs/user-guide/features/honcho.md | 6 +++--- website/docs/user-guide/features/memory-providers.md | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/memory/honcho/README.md b/plugins/memory/honcho/README.md index cb9b720bf56a..295159f75da4 100644 --- a/plugins/memory/honcho/README.md +++ b/plugins/memory/honcho/README.md @@ -287,11 +287,11 @@ Maps 1:1 to Honcho's per-peer `SessionPeerConfig`. When present, overrides `obse |-------|---------|-------------| | `user.observeMe` | `true` | User peer self-observation (Honcho builds user representation) | | `user.observeOthers` | `true` | User peer observes AI messages | -| `ai.observeMe` | `true` | AI peer self-observation (Honcho builds AI representation) | +| `ai.observeMe` | `false` | AI peer self-observation (Honcho builds AI representation). Off by default — when on, user facts echoed in AI replies can leak into AI self-representation | | `ai.observeOthers` | `true` | AI peer observes user messages (enables cross-peer dialectic) | Presets: -- `"directional"` (default): all four `true` +- `"directional"` (default): user both on; AI `observeMe=false`, `observeOthers=true` - `"unified"`: user `observeMe=true`, AI `observeOthers=true`, rest `false` ### Hardcoded Limits diff --git a/website/docs/user-guide/features/honcho.md b/website/docs/user-guide/features/honcho.md index 31d839138307..ada24e1caf62 100644 --- a/website/docs/user-guide/features/honcho.md +++ b/website/docs/user-guide/features/honcho.md @@ -194,7 +194,7 @@ Two peers × two toggles = four flags. `observationMode` is a shorthand preset: | Preset | User flags | AI flags | Semantics | |--------|-----------|----------|-----------| -| `"directional"` (default) | me: on, others: on | me: on, others: on | Full mutual observation. Enables cross-peer dialectic — "what does the AI know about the user, based on what the user said and the AI replied." | +| `"directional"` (default) | me: on, others: on | me: off, others: on | AI models the user from user messages; AI self-observation off so echoed user facts (e.g. *"you play tennis Tuesdays"*) don't land in AI self-representation. Cross-peer dialectic still works via `observeOthers`. | | `"unified"` | me: on, others: off | me: off, others: on | Shared-pool semantics — the AI observes the user's messages only, the user peer only self-models. Single-observer pool. | Override the preset with an explicit `observation` block for per-peer control: @@ -210,9 +210,9 @@ Common patterns: | Intent | Config | |--------|--------| -| Full observation (most users) | `"observationMode": "directional"` | +| Default (most users) — AI models user, not its own echoes | `"observationMode": "directional"` | +| Full mutual observation (all four on) | `"observation": { "user": {"observeMe": true, "observeOthers": true}, "ai": {"observeMe": true, "observeOthers": true} }` | | AI shouldn't re-model the user from its own replies | `"ai": {"observeMe": true, "observeOthers": false}` | -| Strong persona the AI peer shouldn't update from self-observation | `"ai": {"observeMe": false, "observeOthers": true}` | Server-side toggles set via the [Honcho dashboard](https://app.honcho.dev) win over local defaults — Hermes syncs them back at session init. diff --git a/website/docs/user-guide/features/memory-providers.md b/website/docs/user-guide/features/memory-providers.md index 476bd46696dd..ca75987af491 100644 --- a/website/docs/user-guide/features/memory-providers.md +++ b/website/docs/user-guide/features/memory-providers.md @@ -154,7 +154,7 @@ The mapping: | **Workspace** | Shared environment. All Hermes profiles under one workspace see the same user identity. | | **User peer** (`peerName`) | The human. Shared across profiles in the workspace. | | **AI peer** (`aiPeer`) | One per Hermes profile. Host key `hermes` → default; `hermes.` for others. | -| **Observation** | Per-peer toggles controlling what Honcho models from whose messages. `directional` (default, all four on) or `unified` (single-observer pool). | +| **Observation** | Per-peer toggles controlling what Honcho models from whose messages. `directional` (default: user both on, AI observes others only) or `unified` (single-observer pool). | ### New profile, fresh Honcho peer @@ -195,7 +195,7 @@ Each host block can override the observation config independently. Example: a co Presets via `observationMode`: -- **`"directional"`** (default) — all four flags on. Full mutual observation; enables cross-peer dialectic. +- **`"directional"`** (default) — user both on; AI `observeMe: false`, `observeOthers: true`. AI models the user from user messages without self-observation (avoids user facts echoed in AI replies landing in AI self-representation). - **`"unified"`** — user `observeMe: true`, AI `observeOthers: true`, rest false. Single-observer pool; AI models the user but not itself, user peer only self-models. Server-side toggles set via the [Honcho dashboard](https://app.honcho.dev) win over local defaults — synced back at session init.