hermes - ✅(Solved) Fix Feishu gateway: tool progress bubbles truncate short outputs to tool name only [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#28598Fetched 2026-05-20 04:03:15
View on GitHub
Comments
0
Participants
1
Timeline
9
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×5labeled ×4

When display.platforms.feishu.tool_progress is enabled, tool progress bubbles on Feishu show a preview of the tool output. However, tools with short structured outputs (like fact_store returning {"fact_id": 136, "status": "added"}) get truncated to just the tool name:

  • ⚙️ fact_store... — shows nothing useful
  • vs 🧠 memory: "-memory: "some content"" — shows meaningful context

The same truncation length is applied uniformly, but short JSON outputs lose all information value while longer outputs still convey useful snippets.

Root Cause

When display.platforms.feishu.tool_progress is enabled, tool progress bubbles on Feishu show a preview of the tool output. However, tools with short structured outputs (like fact_store returning {"fact_id": 136, "status": "added"}) get truncated to just the tool name:

  • ⚙️ fact_store... — shows nothing useful
  • vs 🧠 memory: "-memory: "some content"" — shows meaningful context

The same truncation length is applied uniformly, but short JSON outputs lose all information value while longer outputs still convey useful snippets.

Fix Action

Fixed

PR fix notes

PR #28618: feat(display): add tool_progress previews for fact_store and fact_feedback

Description (problem / solution / changelog)

Problem

When tool_progress is enabled on the Feishu platform, tools like fact_store and fact_feedback show unhelpful progress bubbles — only the tool name (e.g. ⚙️ fact_store...) with no indication of what action is being performed or what data is involved.

This is because build_tool_preview() in agent/display.py had no handler for these tools, returning None which falls through to a generic tool-name-only display.

Solution

Add action-based preview generation for both tools in build_tool_preview():

fact_store — 6 actions:

ActionPreview formatExample
add+ "content..."+ "user prefers dark mode"
searchsearch: "query..."search: "deploy process"
probeprobe: entityprobe: alice
reasonreason: e1, e2, e3reason: alice, bob
updateupdate: #idupdate: #42
removeremove: #idremove: #7

fact_feedback — shows action + fact ID:

  • helpful: #136

Long content is truncated at 25-30 chars with ... suffix, matching the existing memory tool pattern.

Testing

  • Added 12 new unit tests covering all fact_store actions + fact_feedback + truncation
  • All 40 tests in test_display.py pass
  • No security impact (pure display logic)

Fixes #28598

Changed files

  • agent/display.py (modified, +24/-0)
  • tests/agent/test_display.py (modified, +48/-0)

PR #28719: feat(display): declarative tool-preview schema to eliminate per-tool hardcoding (#28621)

Description (problem / solution / changelog)

What does this PR do?

Adds a declarative tool-preview schema registry to agent/display.py so new tools — including plugin/third-party tools — can ship a one-line progress preview alongside their schema definition, instead of editing the hardcoded if-elif chain in build_tool_preview() every time.

Before, tools without a manual entry fell back to ⚙️ tool_name... on Feishu / Telegram bubbles and the CLI spinner. This is what prompted #28598 (fact_store / fact_feedback showing no useful context); #28621 generalises that observation: the if-elif chain is a structural oversight generator, and plugins have no path to preview support at all.

The new API is:

from agent.display import register_tool_preview

register_tool_preview(
    "fact_store",
    field="action",
    templates={
        "add":    '+ "{content:.30}"',
        "search": 'search: "{query:.25}"',
        "remove": "remove: #{fact_id}",
        "*":      "{action}",          # wildcard fallback
    },
    truncate=60,                        # per-tool cap
)

Design choices:

  • Backward compatible — registry is consulted before the legacy chain. Existing tools keep working; migration is incremental, no flag-day.
  • Plugin-friendly — plugins call register_tool_preview() at import time, next to their schema definition. No core code edit required.
  • Safe by default — missing keys render as "" (a partial tool call never crashes the spinner), string values are whitespace-collapsed, lists are joined with , , bad templates degrade to None + a warning log instead of raising.
  • Per-tool overridetruncate=N takes priority over the global _tool_preview_max_len, useful for plugins that know their content is naturally short.
  • Last-write-wins — plugins can override built-in previews if they need to.

Related Issue

Fixes #28621 Also closes #28598 (the user-visible bug that prompted this proposal — fact_store and fact_feedback now render meaningful previews).

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)

Changes Made

  • agent/display.py — adds register_tool_preview(), _unregister_tool_preview(), the _TOOL_PREVIEW_REGISTRY module-level dict, _SafePreviewArgs (a dict subclass that returns "" for missing keys and normalises values for str.format_map), and _render_registered_preview(). build_tool_preview() consults the registry first, applies the per-tool truncate (falling back to the global _tool_preview_max_len), and only then falls through to the existing hardcoded chain. Also hardens the legacy path against truthy non-dict args.
  • plugins/memory/holographic/__init__.py — registers preview templates for fact_store (10 actions, including add, search, probe, reason, update, remove, plus a * fallback) and fact_feedback (helpful / unhelpful / *). The registration sits right next to FACT_STORE_SCHEMA / FACT_FEEDBACK_SCHEMA so reviewers see UX + schema together.
  • tests/agent/test_display.py — adds TestRegisterToolPreview (15 unit tests covering single-template rendering, field dispatch with * fallback, missing-key safety, list-arg joining, per-field precision truncation, per-tool vs. global truncate precedence, whitespace collapsing, None"", bad-template fallback with log assertion, last-write-wins re-registration, registry-over-legacy priority, and rejection of malformed registrations) plus TestFactStorePluginPreview (7 smoke tests for the holographic plugin registrations) and one extra defensive test for truthy non-dict args.
  • website/docs/developer-guide/adding-tools.md — adds an "Optional: Tool Progress Previews" section showing the API and dispatch form, plus a checklist nudge so authors register a preview when relevant.

Memory and the other complex special cases (process, todo, send_message) are intentionally left on the legacy path in this PR — the issue's scope calls for 2–3 POC migrations with the rest deferred. memory in particular has a "<missing old_text>" sentinel that doesn't fit the minimal field/templates/truncate schema cleanly; if that's wanted, it should land in a follow-up PR (possibly extending the schema with an optional defaults mapping).

How to Test

# Full registry coverage + smoke tests for the plugin migration.
scripts/run_tests.sh tests/agent/test_display.py -q
# Expected: 55 passed (31 existing + 24 new).

# Manual: with the holographic-memory plugin enabled, watch a tool
# progress bubble while issuing a fact_store call from chat.
# Before this PR:  ⚙️ fact_store...
# After this PR:   ⚙️ fact_store + "user prefers tabs"

Checklist

Code

  • My commit messages follow Conventional Commits (feat(display):, feat(memory/holographic):, test(display)+docs:)
  • I searched for existing PRs — no duplicate
  • My PR contains only changes related to this feature
  • I've run scripts/run_tests.sh tests/agent/test_display.py -q (55 passed, 0 failed)
  • I've added tests for my changes (22 new tests covering the registry contract + plugin smoke tests)
  • I've tested on my platform: macOS 15.x (darwin 24.6.0)

Documentation & Housekeeping

  • I've updated relevant documentation (website/docs/developer-guide/adding-tools.md)
  • N/A — no config keys changed (cli-config.yaml.example)
  • N/A — no architecture / workflow change requiring CONTRIBUTING.md / AGENTS.md updates
  • I've considered cross-platform impact — pure Python, no platform-specific code paths
  • N/A — no tool description/schema changes (preview registration is additive metadata)

Changed files

  • agent/display.py (modified, +167/-0)
  • plugins/memory/holographic/__init__.py (modified, +35/-0)
  • tests/agent/test_display.py (modified, +209/-0)
  • website/docs/developer-guide/adding-tools.md (modified, +46/-0)
RAW_BUFFERClick to expand / collapse

Description

When display.platforms.feishu.tool_progress is enabled, tool progress bubbles on Feishu show a preview of the tool output. However, tools with short structured outputs (like fact_store returning {"fact_id": 136, "status": "added"}) get truncated to just the tool name:

  • ⚙️ fact_store... — shows nothing useful
  • vs 🧠 memory: "-memory: "some content"" — shows meaningful context

The same truncation length is applied uniformly, but short JSON outputs lose all information value while longer outputs still convey useful snippets.

Expected Behavior

Tool progress bubbles should show at minimum the tool name + a brief summary that is always informative, even for short outputs:

  • For tools returning JSON with "status" fields: show the status
  • For tools returning short results: show at least the first meaningful line or key-value pair
  • Consider a minimum display length that guarantees the bubble always shows something beyond the tool name

Current Behavior

fact_store calls display as ⚙️ fact_store... with zero context, indistinguishable from a pending/loading state.

Affected Tools

Any tool with compact JSON output: fact_store, fact_feedback, or similar structured-data tools.

Environment

  • Platform: Feishu
  • Gateway mode

Suggested Approach

Option A: Smart truncation — detect if output is JSON and extract status/summary fields for the preview Option B: Minimum preview length — guarantee at least N meaningful chars beyond the tool name Option C: Tool-specific display hints — allow tools to declare a progress_summary in their output for gateway display

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix Feishu gateway: tool progress bubbles truncate short outputs to tool name only [2 pull requests, 1 participants]