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
4 changes: 2 additions & 2 deletions plugins/memory/honcho/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion plugins/memory/honcho/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
6 changes: 3 additions & 3 deletions plugins/memory/honcho/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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")
Expand Down
2 changes: 1 addition & 1 deletion plugins/memory/honcho/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions scripts/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
15 changes: 15 additions & 0 deletions tests/honcho_plugin/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down
2 changes: 1 addition & 1 deletion tests/honcho_plugin/test_empty_profile_hint.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions tests/honcho_plugin/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
# ---------------------------------------------------------------------------
Expand Down
6 changes: 3 additions & 3 deletions website/docs/user-guide/features/honcho.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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.

Expand Down
4 changes: 2 additions & 2 deletions website/docs/user-guide/features/memory-providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.<profile>` 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

Expand Down Expand Up @@ -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.
Expand Down