Skip to content

Feishu command approval card buttons fail with error code 200340 #10251

@stephenlzc

Description

@stephenlzc

Bug Description

When using Hermes Agent with the Feishu (Lark) gateway, the interactive card for command approval (⚠️ Command Approval Required) is displayed correctly. However, clicking any of the action buttons—Allow Once, Session, Always, or Deny—always results in a Feishu error:

Something went wrong. Please try again later
code: 200340

The agent thread remains blocked waiting for approval, and the command is never executed or rejected.

Steps to Reproduce

  1. Connect Hermes Agent to a Feishu bot via hermes gateway start.
  2. Send a message that triggers a dangerous command (e.g., rm -rf /tmp/test).
  3. The bot replies with an interactive approval card.
  4. Click any button on the card.
  5. Observe the Feishu client error code: 200340.

Root Cause Analysis

In gateway/platforms/feishu.py, the method _handle_approval_card_action() builds a P2CardActionTriggerResponse and attaches a CallBackCard to update the card UI after the user clicks a button:

https://github.com/NousResearch/hermes-agent/blob/main/gateway/platforms/feishu.py#L1909-L1913

card = CallBackCard()
card.type = "raw"
card.data = self._build_resolved_approval_card(choice=choice, user_name=user_name)

The problem is that _build_resolved_approval_card() returns a Python dict, but the Feishu API expects card.data to be a JSON string (a serialized card object). When the Lark SDK serializes the response, the dict becomes a nested JSON object:

{"card": {"type": "raw", "data": {"config": ...}}}

Feishu rejects this format and returns error 200340 (invalid request body / card action response format error).

Expected Behavior

Clicking an approval button should update the card to show the resolved state (e.g., "✅ Allowed once by ") and unblock the waiting agent thread.

Suggested Fix

Serialize the card dict to a JSON string before assigning it to card.data:

card = CallBackCard()
card.type = "raw"
card.data = json.dumps(
    self._build_resolved_approval_card(choice=choice, user_name=user_name),
    ensure_ascii=False,
)

This matches how outgoing interactive cards are already handled in send_exec_approval(), where the card is serialized with json.dumps(card, ensure_ascii=False) before sending.

Environment

  • Hermes Agent version: main branch (latest as of 2026-04-15)
  • Platform: Feishu (Lark)
  • File: gateway/platforms/feishu.py
  • Methods: _handle_approval_card_action(), _build_resolved_approval_card()

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/gatewayGateway runner, session dispatch, deliveryplatform/feishuFeishu / Lark adaptertype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions