← Back to PRs

#21848: feat(feishu): improve agent card experience with single-card streaming and execution timeline

by songshikang0111 open 2026-02-20 13:04 View on GitHub →
gateway channel: feishu size: L
## Summary - Problem: Currently, Feishu cards do not display the agent’s tool invocation details by default (verboseDefault: off). However, when tool invocation details are enabled (verboseDefault: on/full), a large number of separate message cards are generated, which quickly clutter the chat window. To help users understand the agent’s execution progress during multi-tool tasks, reduce uncertainty and anxiety, and enable more intuitive debugging and timely interruption, while also preventing tool use messages from overwhelming the chat interface, I designed a new agent card rendering mode that balances both needs. - Why it matters: Professional users need real-time visibility into tool use progress, while casual users require a more user-friendly card format to improve overall experience. - What changed: - Added/used a dedicated Feishu agent-card renderer with serialized update pipeline to enforce single-card updates. - Added `cardRenderer` config (`default | agent`) under Feishu channel config/account config; `agent` activates aggregated timeline card behavior. - Implemented strict timeline handling for `tool/block/final` ordering, reasoning inclusion (timeline only), early collapse when final starts, duplicate-final suppression in collapsed timeline - Restored Chinese UX style details (status titles/icons/colors, `执行过程(Execution process)` panel behavior, tool line text format). <img width="659" height="285" alt="image" src="https://github.com/user-attachments/assets/03301771-2ca6-4308-9edb-98c74de6ff78" /> - What did NOT change (scope boundary): - Core verbose semantics (`on`/`full`) were not changed. - Core OpenClaw reply pipeline/contracts were not changed. - The existing Feishu plugin rendering modes (card, text, auto) were not changed. A separate toggle was added to enable the new rendering mode (disabled by default). ## Change Type (select all) - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Docs - [ ] Security hardening - [ ] Chore/infra ## Scope (select all touched areas) - [ ] Gateway / orchestration - [ ] Skills / tool execution - [ ] Auth / tokens - [ ] Memory / storage - [x] Integrations - [x] API / contracts - [x] UI / DX - [ ] CI/CD / infra ## Linked Issue/PR - Closes #TBD - Related #TBD ## User-visible / Behavior Changes - New Feishu config option: `cardRenderer: "default" | "agent"` (top-level and per-account). - In `renderMode=card` + `cardRenderer=agent`: - Replies are rendered/updated in a single card (serialized updates). - Timeline includes ordered `tool/reasoning/block` events. - `执行过程` panel appears only in final stage and is collapsed immediately when final starts. - No timeline panel is shown for plain direct replies with no trace content. - `🧭 New session: ...` is routed to timeline, removed from final body. - Tool line format: - with detail: `调用\`toolname\`工具: ...` - without detail: `调用\`toolname\`工具` ## Security Impact (required) - New permissions/capabilities? (`Yes/No`) No - Secrets/tokens handling changed? (`Yes/No`) No - New/changed network calls? (`Yes/No`) No - Command/tool execution surface changed? (`Yes/No`) No - Data access scope changed? (`Yes/No`) No - If any `Yes`, explain risk + mitigation: N/A ## Repro + Verification ### Environment - OS: Windows (PowerShell) - Runtime/container: Node 22.x / pnpm workspace - Model/provider: N/A (channel rendering path) - Integration/channel (if any): Feishu extension - Relevant config (redacted): - `channels.feishu.renderMode=card` - `channels.feishu.cardRenderer=agent` - `agents.defaults.verboseDefault=on|full` ### Steps 1. Enable Feishu `renderMode=card` and `cardRenderer=agent`. 2. Send a prompt that: - (a) calls tools and then outputs final response, - (b) outputs direct final response without tools, - (c) includes session-open system trace (`🧭 New session: ...`). 3. Observe live card updates and final collapsed timeline. ### Expected - Single card updates throughout. - Timeline ordered and compact. - No duplicate final text inside collapsed timeline. - No `执行过程` panel for plain direct replies without trace/tool/reasoning. - `🧭 New session: ...` appears in timeline, not final body. ### Actual - Implemented behavior matches expected in code path. ## Evidence Attach at least one: - [ ] Failing test/log before + passing after - [ ] Trace/log snippets - [x] Screenshot/recording - [ ] Perf numbers (if relevant) ## Human Verification (required) - Automated tests - Ran the following test suites locally using vitest: - reply-dispatcher.test.ts → ✅ 2 tests passed (0 failures) - channel.test.ts → ✅ 1 test passed (0 failures) - Verified scenarios: - Code-path verification for single-card serialization and first-card creation lock. - Timeline parsing/routing for tool/reasoning/block/system-trace. - Final-collapse timing and duplicate-final trimming logic. - Edge cases checked: - Tool line with/without detail. - No-tool direct response path (no timeline panel). - Reasoning lines mixed with block text. ## Compatibility / Migration - Backward compatible? (`Yes/No`) Yes - Config/env changes? (`Yes/No`) Yes (optional new config) - Migration needed? (`Yes/No`) No - If yes, exact upgrade steps: N/A ## Failure Recovery (if this breaks) - How to disable/revert this change quickly: - Set `channels.feishu.cardRenderer=default` (or remove it) to return to legacy flow. - Files/config to restore: - `extensions/feishu/src/reply-dispatcher.ts` - `extensions/feishu/src/agent-card.ts` - `extensions/feishu/src/config-schema.ts` - `extensions/feishu/src/channel.ts` - Known bad symptoms reviewers should watch for: - Multiple cards per single reply in `agent` mode. - `执行过程` appearing for plain no-tool replies. - Final content duplicated inside collapsed timeline. ## Risks and Mitigations - Risk: Timeline parsing from mixed streamed text can misclassify rare edge formats. - Mitigation: Keep tool classification primarily on dispatcher `info.kind`; regex parsing only for tool line extraction. - Risk: Serialized update queue may delay very high-frequency updates. - Mitigation: Batched update scheduler with throttle and latest-card overwrite behavior. - Risk: Config precedence confusion (top-level vs account-level `cardRenderer`/`streaming`). - Mitigation: Reuse existing account-merge behavior and document effective config in PR notes. <!-- greptile_comment --> <h3>Greptile Summary</h3> Introduces a new agent card renderer for Feishu channels that aggregates tool invocations and execution timeline into a single, updating card. The implementation adds `cardRenderer: "default" | "agent"` config option under Feishu channel settings, with the new agent mode providing real-time visibility into tool execution while preventing message spam. **Key changes:** - Added new `agent-card.ts` module with timeline tracking, duplicate suppression, and serialized card updates - Extended `reply-dispatcher.ts` to route messages to agent card renderer when `renderMode=card` and `cardRenderer=agent` - Added `cardRenderer` config option to schema with account-level override support - Implemented proper queuing to ensure single-card updates and prevent race conditions - Timeline includes tool calls, reasoning blocks, and system traces with Chinese UX labels - Execution process panel appears collapsed only when final content starts (not shown for plain replies) **Implementation quality:** - Proper async queue management with `enqueueOp` prevents race conditions - Backward compatible - disabled by default, requires explicit config - Clean separation from existing streaming card flow - Handles edge cases like duplicate final content, missing credentials, and empty timelines <h3>Confidence Score: 4/5</h3> - Safe to merge with low risk - well-isolated feature flag - The implementation is solid with proper error handling, backward compatibility, and clear separation of concerns. Score reflects one minor concern about empty timeline behavior and the CLAUDE.md symlink-to-regular-file conversion, but these are low-impact. - Check `extensions/feishu/src/agent-card.ts` line 257 for edge case handling of empty timelines <sub>Last reviewed commit: 682efa8</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs