feat(gateway): support [[reply_to]] directive for gateway platforms#783
feat(gateway): support [[reply_to]] directive for gateway platforms#783wangyuyan-agent wants to merge 3 commits into
Conversation
- Add quote_message_id field to GatewayReply protocol
- Override send_message_with_reply in GatewayAdapter (refactored via
send_gateway_reply helper to eliminate duplication)
- Feishu: use quote_message_id as reply target with fallback to plain
send on failure
- Update docs/feishu.md and docs/output-directives.md for Feishu support
When an agent outputs [[reply_to:message_id]], the gateway sends the
message as a native reply/quote on the platform. Feishu shows it with
the quote reference UI via POST /im/v1/messages/{id}/reply.
Tested: 274 core + 126 gateway tests pass. E2E verified on Feishu.
OpenAB PR ScreeningThis is auto-generated by the OpenAB project-screening flow for context collection and reviewer handoff.
Screening report## IntentPR #783 extends OpenAB gateway delivery so an agent can intentionally send a platform-native reply or quote from its output using The operator-visible problem is that gateway platforms currently cannot consistently preserve reply context chosen by the agent. On Feishu specifically, an agent response that should quote a prior message is sent as a normal message unless gateway delivery carries an explicit reply target. FeatFeature. The PR adds a gateway protocol field, It also updates docs and test constructions for the new field. Who It ServesPrimary beneficiaries:
Rewritten PromptImplement gateway support for the existing Add an optional Update the Feishu adapter so replies prefer Preserve backward compatibility: absent Merge PitchThis is worth advancing because it closes the gap between agent-controlled reply intent and gateway platform delivery. It keeps the directive model consistent across Discord and gateway-backed platforms while making Feishu the first concrete gateway implementation. Risk is moderate-low if the protocol field is truly optional and fallback behavior is well tested. The main reviewer concern will be semantic overlap: Best-Practice ComparisonOpenClaw principles relevant here:
Hermes Agent principles relevant here:
Overall, this PR aligns more with OpenClaw’s explicit delivery routing than with Hermes’ scheduled-run mechanics. Implementation OptionsConservative option: accept Balanced option: merge the protocol field plus Feishu support, but add shared gateway tests for schema compatibility and adapter-level tests for target precedence: Ambitious option: formalize gateway delivery intent as a richer enum or structured target object, such as plain message, reply/quote, thread reply, edit, or platform-specific action. Migrate Feishu and other adapters toward that model over time to reduce overloaded fields and make delivery behavior auditable. Comparison Table
RecommendationAdvance the balanced option. The PR’s core direction is sound: a dedicated optional Keep the broader delivery-intent redesign out of this PR. If reviewers agree the field naming and precedence rules are right, merge this as the first gateway implementation, then open follow-up work for additional adapters and a more formal gateway delivery contract if the pattern repeats. |
- src/gateway.rs: clean up pending map entry before returning error on WebSocket send failure (prevents slow memory leak) - gateway/src/adapters/feishu.rs: retry chunked messages with thread_id when quote_message_id causes all chunks to fail (prevents silent message loss) - Improve fallback warn logs with structured fields for debugging
|
FIXED ✅ — All findings resolved in commits Findings
What We Changed
|
…tant - Add doc comments distinguishing reply_to (routing) from quote_message_id (visual reply UI) in both core and gateway schema - Split timeout catch-all into distinct arms with warn-level logging for failure, channel closed, and timeout cases - Extract 5s timeout to GATEWAY_REPLY_TIMEOUT_SECS constant
CHC-Agent
left a comment
There was a problem hiding this comment.
All findings addressed. LGTM ✅
Two blocking issues (pending map leak + chunked message loss) and four non-blocking improvements resolved in c212e81 + 95f3912. Design is sound, backward compatibility preserved, fallback behavior consistent with Discord adapter.
Recommend merge.
|
CHANGES REQUESTED What This PR DoesExtends the gateway protocol to support agent-controlled reply-to ( How It WorksAdds Findings
Finding Details🟡 F1: Redundant
|
Summary
Extends the gateway protocol to support agent-controlled reply-to (#777). When an agent outputs
[[reply_to:message_id]], the gateway now sends the message as a native reply/quote on the platform. Feishu is the first gateway platform to implement this — showing the native quote reference UI.Builds on #777 (agent-controlled reply-to via
[[reply_to:message_id]]directive).Prior Art
replyToMode: "off"/"first"/"all"(config)DISCORD_REPLY_TO_MODEenv var[[reply_to:message_id]]directivequote_message_idprotocol fieldDesign Trade-offs
Why a new
quote_message_idfield?Existing
reply_tohas overloaded semantics (LINE event_id / edit message_id). A dedicated field is explicit and self-documenting.Why fallback on failure?
Discord's
send_message_with_replyfalls back to plain send on invalid message_id. We match this behavior — if Feishu Reply API fails, retry as plain send.Why refactor to
send_gateway_replyhelper?send_messageandsend_message_with_replydiffered by one field. Extracted a private helper to eliminate ~35 lines of duplication.Changes
src/gateway.rs: Addquote_message_idtoGatewayReply; refactorsend_message/send_message_with_replyviasend_gateway_replyhelpergateway/src/schema.rs: Addquote_message_idfieldgateway/src/adapters/feishu.rs:handle_replyusesquote_message_idas reply target with fallbackgateway/src/adapters/googlechat.rs+gateway/src/main.rs: Test constructionsdocs/feishu.md: Add Agent-Controlled Reply-To sectiondocs/output-directives.md: Update to include Feishu supportConfiguration
No new configuration. Uses existing
[[reply_to:message_id]]directive from #777.Testing
[[reply_to:om_xxx]]→ Feishu shows native quote reply UI ✅Backward Compatibility
quote_message_idusesskip_serializing_if = None(core) +#[serde(default)](gateway)Discussion
https://discord.com/channels/1491295327620169908/1500160821567684660