Skip to content

fix(honcho): stop clipping honcho_reasoning tool results to the injection budget - #59471

Closed
vizi0uz wants to merge 1 commit into
NousResearch:mainfrom
vizi0uz:fix/honcho-reasoning-tool-truncation
Closed

vizi0uz wants to merge 1 commit into
NousResearch:mainfrom
vizi0uz:fix/honcho-reasoning-tool-truncation

Conversation

@vizi0uz

@vizi0uz vizi0uz commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

honcho_reasoning tool results longer than dialecticMaxChars (default 600) were silently
truncated mid-word with a trailing " …", even though the model deliberately spent a turn asking
Honcho for a full synthesized answer. This scopes that char cap to the auto-injection path it was
designed for, so explicit tool calls return Honcho's complete answer.

dialecticMaxChars is documented as the budget for the dialectic supplement auto-injected into the
system prompt every turn
— a small always-on guardrail. But HonchoSessionManager.dialectic_query()
applied it unconditionally, and that one method is shared by both the auto-injection path
(background prefetch → _run_dialectic_depth()) and the honcho_reasoning tool handler. So the tool
path inherited a budget meant only for recurring injection. The truncation is purely client-side —
Honcho returns the full answer (verified by replaying the same query with a direct HTTP call to the
backend chat endpoint).

Skipping the cap on the tool path is safe, not unbounded: the auto-injection path already has its own
token-based budget (contextTokens, enforced in prefetch() via _truncate_to_budget()), and tool
results are already bounded server-side by Honcho's dialectic MAX_OUTPUT_TOKENS — consistent with
sibling tools (honcho_search, honcho_context) which don't post-clip either.

Related Issue

Fixes #59469

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • plugins/memory/honcho/session.py: add apply_injection_cap: bool = True to dialectic_query(); the dialecticMaxChars truncation now runs only when it's True. Default preserves current behavior for all existing callers.
  • plugins/memory/honcho/__init__.py: the honcho_reasoning tool handler passes apply_injection_cap=False.
  • plugins/memory/honcho/client.py: clarify the dialectic_max_chars field comment (injection-only).
  • tests/honcho_plugin/test_session.py: new TestDialecticInjectionCap (injection path still truncates with " …"; tool path returns the full answer); updated the existing honcho_reasoning dispatch assertion for the new kwarg.

Fully backward compatible — the parameter defaults to True, so auto-injection is unchanged and no config migration is needed.

How to Test

uv run --extra dev --extra messaging python -m pytest \
  tests/honcho_plugin/test_session.py::TestDialecticInjectionCap \
  tests/honcho_plugin/test_session.py -q

Manual: with a peer whose memory yields a >600-char synthesized answer, call honcho_reasoning
(e.g. "Summarize known facts about this peer and communication preferences."). Before: the result
ends in " …", cut mid-word. After: the full answer is returned.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(honcho): …)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix
  • I've run the honcho test slice and all tests pass (130 passed, 1 pre-existing skip)
  • I've added tests for my changes
  • I've tested on my platform: Windows 11 (self-hosted Honcho backend)

Documentation & Housekeeping

  • I've updated relevant docstrings/comments (dialectic_query docstring, dialectic_max_chars comment)
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A (no new config key)
  • I've considered cross-platform impact — scripts/check-windows-footguns.py reports no footguns
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A (tool contract unchanged; it now just returns the full result)

Screenshots / Logs

N/A — behavior is text truncation; see How to Test for before/after.

Note for existing users

Anyone who bumped dialecticMaxChars in honcho.json as a workaround for truncated honcho_reasoning
answers can revert it to the default 600 after this lands — the cap no longer affects tool results.

Open question for maintainers

The auto-injection path now has two overlapping budgets: char-based dialecticMaxChars (always-on
default guardrail) and token-based contextTokens (opt-in, enforced at the injection layer). This PR
keeps both and only fixes the mis-scoped tool-path clip. If you'd prefer the injection budget
consolidated onto a single token-based control, happy to follow up — larger change, out of scope here.

…tion budget

dialecticMaxChars (default 600) is documented as the budget for the dialectic
supplement auto-injected into the system prompt every turn — a small recurring
cost that is correct to bound tightly. But dialectic_query() applied that cap
unconditionally, so explicit honcho_reasoning tool calls — where the model
deliberately spends a turn asking for a synthesized answer — were silently
truncated mid-word to 600 chars with a trailing " …", no error surfaced. The
full answer is returned by Honcho server-side; the clip happens client-side.

The auto-injection path already has its own token-based budget (contextTokens,
enforced in prefetch() via _truncate_to_budget), so the char cap's real job is a
cheap always-on guardrail for that recurring injection. Explicit tool results
are already bounded server-side by Honcho's dialectic MAX_OUTPUT_TOKENS and don't
need the injection cap — sibling tools (honcho_search, honcho_context) don't
post-clip their results either.

Add apply_injection_cap (default True, preserving current behavior) to
dialectic_query(); the honcho_reasoning tool handler passes False so it returns
Honcho's full synthesized answer. Auto-injection is unchanged. Tests cover both
the capped injection path and the uncapped tool path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@teknium1

Copy link
Copy Markdown
Collaborator

Thanks for the focused regression fix. The premise is live on current main: plugins/memory/honcho/session.py:658-660 clips every dialectic_query() result, while plugins/memory/honcho/__init__.py:1358-1362 routes explicit honcho_reasoning calls through that same method.

The proposed defaulted apply_injection_cap keeps the existing auto-injection path (plugins/memory/honcho/__init__.py:1072-1076) capped while letting the explicit tool handler opt out. A current-tree call-site scan found those as the two production callers, and the PR adds coverage for both the default capped result and the uncapped explicit result.

The PR base is an ancestor of current main; only plugins/memory/honcho/cli.py changed under the Honcho plugin since then, so salvage should be mechanical.

Automated hermes-sweeper review.

@teknium1 teknium1 added the sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users label Jul 15, 2026
@teknium1

Copy link
Copy Markdown
Collaborator

Merged via #62290 (commit 8d1c96f) — your honcho_reasoning clipping fix landed on main with authorship preserved via rebase-merge. Fixes #59469. Thanks @vizi0uz!

@teknium1 teknium1 closed this Jul 16, 2026
@teknium1 teknium1 added the area/memory Memory subsystem: store, providers, sync, background reviews label Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/memory Memory subsystem: store, providers, sync, background reviews comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users tool/memory Memory tool and memory providers type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: honcho_reasoning results silently truncated to dialecticMaxChars (system-prompt injection budget wrongly applied to explicit tool results)

3 participants