Skip to content

fix(honcho): read peer cards from direct peer APIs#5137

Closed
robertvoy wants to merge 1 commit into
NousResearch:mainfrom
robertvoy:fix/honcho-profile-peer-card
Closed

fix(honcho): read peer cards from direct peer APIs#5137
robertvoy wants to merge 1 commit into
NousResearch:mainfrom
robertvoy:fix/honcho-profile-peer-card

Conversation

@robertvoy

Copy link
Copy Markdown

Bug Description

honcho_profile could return No profile facts available yet. even when hermes honcho status showed a populated peer card and honcho_context could synthesize stable facts.

Root Cause

The Honcho plugin was reading peer-card data through session.context(...). For per-session messaging flows, that session-scoped lookup could return an empty peer_card even when the underlying Honcho peer had a populated card.

Fix

  • fetch profile cards directly from the Honcho peer object via get_card() / card()
  • use peer-level context / representation lookups for search and prefetch paths that were relying on the same empty session-scoped data
  • normalize card payloads into a stable list-of-strings shape inside the session manager

How to Verify

  1. Configure Hermes with the Honcho memory provider and a populated Honcho peer card.
  2. Call honcho_profile in a messaging or CLI session.
  3. Confirm it returns the peer card facts instead of No profile facts available yet.

Test Plan

  • Added regression test for this bug
  • Existing targeted tests pass (pytest tests/honcho_plugin/test_session.py -q)
  • Manual verification of honcho_profile returning a populated peer card after restart

Risk Assessment

Low — the change only affects Honcho read paths for peer-card / representation retrieval, and it adds explicit regression coverage for the new behavior.

- fetch honcho_profile card data from peer.get_card()/peer.card()
- use peer-level context/representation lookups for search and prefetch
- add regression tests covering direct peer lookup behavior
@trevorgordon981

Copy link
Copy Markdown

Good diagnosis on the root cause — session.context() returning empty peer_card for per-session messaging flows is a real Honcho gotcha, and the peer-level API is the right escape hatch. Multi-layer fallbacks (get_cardcard_fetch_peer_card) and card normalization are clean.

But two semantic changes worth thinking about before merge:

1. Perspective-aware context is dropped.

Honcho's peer.context(target=...) takes a target arg that returns "the context for the target from this peer's perspective" (from peer.py docstring). The old session.context(peer_target=X, peer_perspective=Y) calls used that perspective explicitly:

Method Old perspective New perspective
get_prefetch_context (user) user-peer from assistant's POV user-peer's own context
get_prefetch_context (ai) assistant from user's POV assistant's own context
get_peer_card user from assistant's POV user's own card
search_context user from assistant's POV user's own context
get_ai_representation assistant from user's POV assistant's own context

The new code calls peer.context(search_query=...) without target=, getting each peer's "own" context rather than the other-peer-perspective view. Whether this matters depends on whether Honcho's "own representation" differs from "representation from another peer's POV" in practice — for single-user assistants with one user peer and one hermes peer, they might converge. For multi-user / multi-agent setups, the semantics diverge.

If the perspective was meaningful to the original design, preserve it by passing target=:

def _fetch_peer_context(self, peer_id: str, perspective_peer_id: str | None = None, search_query: str | None = None):
    peer = self._get_or_create_peer(peer_id)
    # perspective-aware: "context for `perspective_peer_id` from `peer_id`'s POV"
    ctx = peer.context(target=perspective_peer_id, search_query=search_query) if perspective_peer_id else peer.context(search_query=search_query)
    ...

And in get_prefetch_context:

user_ctx = self._fetch_peer_context(session.assistant_peer_id, perspective_peer_id=session.user_peer_id)
ai_ctx = self._fetch_peer_context(session.user_peer_id, perspective_peer_id=session.assistant_peer_id)

If the perspective wasn't load-bearing, at minimum add a comment in the PR explaining you verified that — someone digging into Honcho semantics later will wonder why the original code passed perspectives.

2. Token / conclusion limits dropped.

The old calls specified:

  • tokens=self._context_tokens (default lookups)
  • tokens=200 (for get_peer_card)
  • tokens=max_tokens (for search_context)

The new peer-level context() supports max_conclusions and search_top_k, which are conceptually similar bounds on the returned size. The new code doesn't use them, so returned representations/cards may be larger than the old flow expected. For search_context where a 800-token limit was specified, callers downstream may now get significantly more content.

Small fix:

ctx = peer.context(
    target=perspective_peer_id,
    search_query=search_query,
    max_conclusions=... # whatever maps to the old tokens limits
)

Minor:

  • _fetch_peer_context silently catches both peer.context() and peer.representation() failures at logger.debug level. If Honcho starts returning errors for some reason (auth issue, bad peer_id, API change), the user sees No profile facts available yet. with no obvious cause. Worth bumping at least the outer failure to logger.warning — if BOTH the primary and fallback path fail for a peer, that's actionable diagnostic info, not a debug-level event.

LGTM on the core fix (direct peer API is the right escape hatch for the session.context empty-card bug). Worth a round of clarification on the perspective change before merge.

@erosika

erosika commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

excellent catch! Appreciate the work on this. going to try and cherry pick your work into my PR to unify honcho fixes across the board

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the diagnosis and the clean fix, @robertvoy! This is an automated hermes-sweeper review.

The peer-level API read path this PR introduces has since been implemented on main as part of a larger Honcho context injection overhaul:

  • _fetch_peer_card(peer_id, *, target=None) — present at plugins/memory/honcho/session.py:830
  • _fetch_peer_context(..., target=None) — present at plugins/memory/honcho/session.py:848
  • _normalize_card() — present at plugins/memory/honcho/session.py:822
  • get_card / card fallback chain — present at lines 838–844
  • get_prefetch_context now passes target= on both peer lookups (lines 634, 642)

All of this was added in commit cc6e8941d (PR #10619feat(honcho): context injection overhaul, 5-tool surface, cost safety, session isolation, merged April 15 2026), which is a strict superset of the changes here. The perspective-aware target= semantics flagged by @trevorgordon981 were also addressed in that overhaul via _resolve_observer_target().

Closing as implemented on main.

@teknium1 teknium1 closed this Apr 27, 2026
@erosika

erosika commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

The retrieval-path fix this PR proposed (direct peer APIs via get_card() / peer.context()) actually landed separately in main as _fetch_peer_card / _fetch_peer_contextplugins/memory/honcho/session.py:855+. The get_peer_card method at line 1002 uses the direct-peer path.

What wasn't addressed was the user-visible side: honcho_profile returning a bare "No profile facts available yet." when the card is empty leaves no context for why, so the model often surfaces it to the user as if it were an error.

Picked up in #15381 as a small UX follow-up: added a hint field to the tool response that enumerates likely causes (observation disabled, peer still warming up, self-hosted < 3.x lacks peer cards) and suggests alternative tools (honcho_reasoning, honcho_search). 7 tests cover the hint paths.

Closing this as obsolete feels right — the architectural fix landed, and the UX gap is addressed separately.

erosika added a commit to erosika/hermes-agent that referenced this pull request Apr 27, 2026
Closed PR NousResearch#5137 addressed the retrieval path (peer cards via get_card()
instead of the session-scoped lookup that returned empty for per-session
messaging flows) — that architectural fix is already in main as
_fetch_peer_card / _fetch_peer_context.

What never got fixed is the user-visible side: honcho_profile returning
a flat 'No profile facts available yet.' leaves the model to guess at
why.  The model then often surfaces it to the user as a cryptic error.

Adds a diagnostic hint next to the existing 'result' message, enumerating
the likely causes in rough order of frequency:

  1. Observation disabled for this peer (user_observe_me/others off)
  2. Peer card hasn't accumulated yet (fresh peer / dialectic cadence
     hasn't fired enough turns — cards build over time)
  3. Generic fallback: self-hosted Honcho < 3.x lacks peer cards

The hint also suggests alternative tools (honcho_reasoning / honcho_search)
so the model can route around the empty card rather than giving up.

Schema description updated so the model knows the hint field exists and
that an empty card is NOT an error state.

7 tests cover the hint paths: warmup, observation-disabled for user + ai,
generic fallback, populated card still returns plain result (no hint),
alternative-tool suggestion present.
kshitijk4poor pushed a commit that referenced this pull request Apr 27, 2026
Closed PR #5137 addressed the retrieval path (peer cards via get_card()
instead of the session-scoped lookup that returned empty for per-session
messaging flows) — that architectural fix is already in main as
_fetch_peer_card / _fetch_peer_context.

What never got fixed is the user-visible side: honcho_profile returning
a flat 'No profile facts available yet.' leaves the model to guess at
why.  The model then often surfaces it to the user as a cryptic error.

Adds a diagnostic hint next to the existing 'result' message, enumerating
the likely causes in rough order of frequency:

  1. Observation disabled for this peer (user_observe_me/others off)
  2. Peer card hasn't accumulated yet (fresh peer / dialectic cadence
     hasn't fired enough turns — cards build over time)
  3. Generic fallback: self-hosted Honcho < 3.x lacks peer cards

The hint also suggests alternative tools (honcho_reasoning / honcho_search)
so the model can route around the empty card rather than giving up.

Schema description updated so the model knows the hint field exists and
that an empty card is NOT an error state.

7 tests cover the hint paths: warmup, observation-disabled for user + ai,
generic fallback, populated card still returns plain result (no hint),
alternative-tool suggestion present.
ulasbilgen pushed a commit to ulasbilgen/hermes-adhd-agent that referenced this pull request May 1, 2026
Closed PR NousResearch#5137 addressed the retrieval path (peer cards via get_card()
instead of the session-scoped lookup that returned empty for per-session
messaging flows) — that architectural fix is already in main as
_fetch_peer_card / _fetch_peer_context.

What never got fixed is the user-visible side: honcho_profile returning
a flat 'No profile facts available yet.' leaves the model to guess at
why.  The model then often surfaces it to the user as a cryptic error.

Adds a diagnostic hint next to the existing 'result' message, enumerating
the likely causes in rough order of frequency:

  1. Observation disabled for this peer (user_observe_me/others off)
  2. Peer card hasn't accumulated yet (fresh peer / dialectic cadence
     hasn't fired enough turns — cards build over time)
  3. Generic fallback: self-hosted Honcho < 3.x lacks peer cards

The hint also suggests alternative tools (honcho_reasoning / honcho_search)
so the model can route around the empty card rather than giving up.

Schema description updated so the model knows the hint field exists and
that an empty card is NOT an error state.

7 tests cover the hint paths: warmup, observation-disabled for user + ai,
generic fallback, populated card still returns plain result (no hint),
alternative-tool suggestion present.
donald131 pushed a commit to donald131/hermes-agent that referenced this pull request May 2, 2026
Closed PR NousResearch#5137 addressed the retrieval path (peer cards via get_card()
instead of the session-scoped lookup that returned empty for per-session
messaging flows) — that architectural fix is already in main as
_fetch_peer_card / _fetch_peer_context.

What never got fixed is the user-visible side: honcho_profile returning
a flat 'No profile facts available yet.' leaves the model to guess at
why.  The model then often surfaces it to the user as a cryptic error.

Adds a diagnostic hint next to the existing 'result' message, enumerating
the likely causes in rough order of frequency:

  1. Observation disabled for this peer (user_observe_me/others off)
  2. Peer card hasn't accumulated yet (fresh peer / dialectic cadence
     hasn't fired enough turns — cards build over time)
  3. Generic fallback: self-hosted Honcho < 3.x lacks peer cards

The hint also suggests alternative tools (honcho_reasoning / honcho_search)
so the model can route around the empty card rather than giving up.

Schema description updated so the model knows the hint field exists and
that an empty card is NOT an error state.

7 tests cover the hint paths: warmup, observation-disabled for user + ai,
generic fallback, populated card still returns plain result (no hint),
alternative-tool suggestion present.
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
Closed PR NousResearch#5137 addressed the retrieval path (peer cards via get_card()
instead of the session-scoped lookup that returned empty for per-session
messaging flows) — that architectural fix is already in main as
_fetch_peer_card / _fetch_peer_context.

What never got fixed is the user-visible side: honcho_profile returning
a flat 'No profile facts available yet.' leaves the model to guess at
why.  The model then often surfaces it to the user as a cryptic error.

Adds a diagnostic hint next to the existing 'result' message, enumerating
the likely causes in rough order of frequency:

  1. Observation disabled for this peer (user_observe_me/others off)
  2. Peer card hasn't accumulated yet (fresh peer / dialectic cadence
     hasn't fired enough turns — cards build over time)
  3. Generic fallback: self-hosted Honcho < 3.x lacks peer cards

The hint also suggests alternative tools (honcho_reasoning / honcho_search)
so the model can route around the empty card rather than giving up.

Schema description updated so the model knows the hint field exists and
that an empty card is NOT an error state.

7 tests cover the hint paths: warmup, observation-disabled for user + ai,
generic fallback, populated card still returns plain result (no hint),
alternative-tool suggestion present.
dannyJ848 pushed a commit to dannyJ848/hermes-agent that referenced this pull request May 17, 2026
Closed PR NousResearch#5137 addressed the retrieval path (peer cards via get_card()
instead of the session-scoped lookup that returned empty for per-session
messaging flows) — that architectural fix is already in main as
_fetch_peer_card / _fetch_peer_context.

What never got fixed is the user-visible side: honcho_profile returning
a flat 'No profile facts available yet.' leaves the model to guess at
why.  The model then often surfaces it to the user as a cryptic error.

Adds a diagnostic hint next to the existing 'result' message, enumerating
the likely causes in rough order of frequency:

  1. Observation disabled for this peer (user_observe_me/others off)
  2. Peer card hasn't accumulated yet (fresh peer / dialectic cadence
     hasn't fired enough turns — cards build over time)
  3. Generic fallback: self-hosted Honcho < 3.x lacks peer cards

The hint also suggests alternative tools (honcho_reasoning / honcho_search)
so the model can route around the empty card rather than giving up.

Schema description updated so the model knows the hint field exists and
that an empty card is NOT an error state.

7 tests cover the hint paths: warmup, observation-disabled for user + ai,
generic fallback, populated card still returns plain result (no hint),
alternative-tool suggestion present.
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
Closed PR NousResearch#5137 addressed the retrieval path (peer cards via get_card()
instead of the session-scoped lookup that returned empty for per-session
messaging flows) — that architectural fix is already in main as
_fetch_peer_card / _fetch_peer_context.

What never got fixed is the user-visible side: honcho_profile returning
a flat 'No profile facts available yet.' leaves the model to guess at
why.  The model then often surfaces it to the user as a cryptic error.

Adds a diagnostic hint next to the existing 'result' message, enumerating
the likely causes in rough order of frequency:

  1. Observation disabled for this peer (user_observe_me/others off)
  2. Peer card hasn't accumulated yet (fresh peer / dialectic cadence
     hasn't fired enough turns — cards build over time)
  3. Generic fallback: self-hosted Honcho < 3.x lacks peer cards

The hint also suggests alternative tools (honcho_reasoning / honcho_search)
so the model can route around the empty card rather than giving up.

Schema description updated so the model knows the hint field exists and
that an empty card is NOT an error state.

7 tests cover the hint paths: warmup, observation-disabled for user + ai,
generic fallback, populated card still returns plain result (no hint),
alternative-tool suggestion present.
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
Closed PR NousResearch#5137 addressed the retrieval path (peer cards via get_card()
instead of the session-scoped lookup that returned empty for per-session
messaging flows) — that architectural fix is already in main as
_fetch_peer_card / _fetch_peer_context.

What never got fixed is the user-visible side: honcho_profile returning
a flat 'No profile facts available yet.' leaves the model to guess at
why.  The model then often surfaces it to the user as a cryptic error.

Adds a diagnostic hint next to the existing 'result' message, enumerating
the likely causes in rough order of frequency:

  1. Observation disabled for this peer (user_observe_me/others off)
  2. Peer card hasn't accumulated yet (fresh peer / dialectic cadence
     hasn't fired enough turns — cards build over time)
  3. Generic fallback: self-hosted Honcho < 3.x lacks peer cards

The hint also suggests alternative tools (honcho_reasoning / honcho_search)
so the model can route around the empty card rather than giving up.

Schema description updated so the model knows the hint field exists and
that an empty card is NOT an error state.

7 tests cover the hint paths: warmup, observation-disabled for user + ai,
generic fallback, populated card still returns plain result (no hint),
alternative-tool suggestion present.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants