DeepSeek Harness plugin

dsh-feishu-gateway

DeepSeek Harness-native Feishu (Lark) gateway: chat with the DSH agent from Feishu via long connection, with persistent sessions, /new, Markdown replies, and proactive push.

Jump to install

Source facts

Repository
kriskwok/dsh-feishu-gateway
Latest update
Aug 18, 2026
Category
Remote & Mobile
GitHub stars
2
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/kriskwok/dsh-feishu-gateway
Plugin: dsh-feishu-gateway
Author: kriskwok

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer4 files
README.mdSource · read only
README language

dsh-feishu-gateway

![npm version](https://www.npmjs.com/package/@kriskwok/dsh-feishu-gateway) ![License: MIT](LICENSE) ![GitHub stars](https://github.com/kriskwok/dsh-feishu-gateway)

English | 中文

Chat with your DeepSeek Harness (DSH) agent from Feishu (Lark).

A DSH plugin bundle that mounts a Feishu long-connection listener; every Feishu message is routed to a stable DSH session (resumed via the agents service, so multi-turn chats stay in the same session), and the agent's answer is replied as a Markdown-rich post message. It also supports /new to start a fresh session, a native Typing reaction while the answer is being produced, live streaming progress cards for long tasks, click-to-answer cards for permission approvals and the model's ask_user_question tool, and proactive push.

Features

  • 💬 Full conversation — Feishu private chat / group @bot → DSH agent → reply
  • 🔁 Persistent sessions — each Feishu conversation maps to one DSH session

(agents.resume / agents.create); /new (or "另起会话" / "新会话" / "重新开始" / "换个话题") starts a fresh one

  • ⌨️ Native Typing indicator — while the agent works, the bot adds a

Typing reaction to your message (like hermes-agent's Feishu gateway); it stays until the answer is done, and is swapped for a CrossMark reaction on failure. No more "thinking…" hint text by default.

  • 🎞 Streaming progress — long tasks report continuously: a live interactive

card streams the agent's thinking, tool calls, and answer draft as they happen (reporting.mode: 'stream', default). Set reporting.mode: 'final' to only receive the final result.

  • 🃏 Click-to-answer cards — permission approvals (approval/request, e.g.

sandbox escalation) and the model's ask_user_question tool render as Feishu interactive cards: click ✅ 允许一次 / 🚫 拒绝 or an option button to answer. The click response instantly replaces the card with a decided state (buttons removed, result shown) plus a toast confirmation.

  • ✍️ Markdown replies — plain rich-text (post) messages with the md

tag: bold, inline code, lists and links render natively, no cards needed

  • 🧩 Web-only interactive fences degrade gracefully — model-emitted

dsh-ui interactive UI fences (e.g. from dsh-genui) only render in the Web UI; on Feishu they are auto-downgraded to a one-line readable hint (title extracted, "view in Web UI"), never a raw JSON code block

  • 🤖 Full agent capability — the DSH agent runs with its own model and

tools (bash, files, subagents…), fully autonomous

  • 📨 Proactive push — optional admin HTTP API (/api/push) to push text /

Markdown / cards to any user or group

  • 🔌 No public network required — Feishu long connection, no webhook URL
  • 🗂 Persistence — Feishu↔DSH session mapping survives restarts

Requirements

  • DeepSeek Harness installed and built (dsh CLI), with DEEPSEEK_API_KEY

configured (the agent's model is used as-is)

  • A Feishu open-platform self-built app with the bot capability enabled

(see below)

Feishu app setup

1. Feishu Open Platform → create a self-built app. 2. Enable the bot capability. 3. Grant permissions: im:message, im:message:send_as_bot (+ im:message:send_as_bot:readonly to read content). Publish a version. 4. Under Events & callbacks, choose long connection and subscribe to im.message.receive_v1 (no public URL needed). The same long connection also delivers card button clicks (card.action.trigger, used by the approval / Q&A cards) — no webhook URL required. 5. In Feishu, search the app name and add the bot as a contact.

> The Typing reaction indicator and card buttons need the bot to be able to > interact with messages in the chat (im:message). If the reaction API is > denied, the gateway automatically falls back to the hintText message.

Installation (as a DSH plugin)

Prerequisite: this package is published on npm and dsh is on your PATH.

The recommended setup mounts the gateway into the web profile: it runs in the same process as the DSH Web UI, so starting the Web UI also starts the Feishu gateway, and both share the same DSH agent. A standalone profile is also supported (see "Alternative" at the end).

Option 1 (recommended): mount into the web profile

The web profile is DSH's default GUI profile (dsh --profile web).

1. Edit ~/.dsh/profiles/web/package.json to add the dependency and bundle:

{
  "name": "dsh-profile-web",
  "private": true,
  "dependencies": {
    "@kriskwok/dsh-feishu-gateway": "^0.2.0"
  },
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "@kriskwok/dsh-feishu-gateway"
      ]
    }
  }
}

2. Install dependencies in the web profile directory:

cd ~/.dsh/profiles/web && pnpm install

3. Edit ~/.dsh/profiles/web/cordis.patch.yml and fill in your Feishu app credentials:

- id: feishu-gateway
  config:
    feishu:
      appId: cli_xxxxxxxxxxxxxxxx
      appSecret: xxxxxxxxxxxxxxxxxxxxxxxx
    http:
      port: 3100      # optional admin API
      token: your-token

4. Start (or restart) the web profile:

dsh --profile web

> You can also use the one-shot script from this repository: > ./scripts/create-profile.sh (mounts into the web profile by default; > --standalone creates a standalone feishu profile instead).

Alternative: standalone feishu profile

To run the gateway without the Web UI, use a standalone profile:

mkdir -p ~/.dsh/profiles/feishu && cd ~/.dsh/profiles/feishu

cat > package.json <<'EOF'
{
  "name": "dsh-profile-feishu",
  "private": true,
  "dependencies": {
    "@kriskwok/dsh-feishu-gateway": "^0.2.0"
  },
  "dsh": {
    "profile": {
      "bundles": ["@deepseek-ai/dsh-base", "@kriskwok/dsh-feishu-gateway"]
    }
  }
}
EOF

cat > pnpm-workspace.yaml <<'EOF'
packages:
  - .
nodeLinker: hoisted
autoInstallPeers: false
EOF

pnpm install
# then create ~/.dsh/profiles/feishu/cordis.patch.yml with your app credentials
dsh --profile feishu

Configuration

All settings live in the feishu-gateway namespace (profile patch row or ~/.dsh/settings.yaml):

FieldDefaultDescription
feishu.appIdFeishu app id (required)
feishu.appSecretFeishu app secret (required)
feishu.domainfeishufeishu (CN) or lark (international)
feishu.botOpenId``Optional; @-detection works without it
feishu.replyModeatGroup policy: at or all
workspace~/Documents/DSH-WorkspaceAgent working directory (the session is also auto-attached to the matching DSH Workspace, so it groups under that Workspace in the Web UI instead of "Ungrouped")
hintText爸爸,我正在努力处理中……Fallback "processing" text (only when the Typing reaction is disabled/unavailable)
reporting.modestreamstream = live streaming progress card; final = only the final answer
reporting.typingReactiontrueShow the native Feishu Typing reaction while working
reporting.showReasoningtrueStream the model's reasoning in the card
reporting.showToolCallstrueStream tool-call activity in the card
reporting.patchIntervalMs1100Min interval between card patches; Feishu limits single-message updates to ~1/s (error 230020), and the stream backs off adaptively on failure
reporting.maxBodyChars900Max rendered card body length
reporting.failureReactionCrossMarkReaction added on failure (after removing Typing)
reporting.cardTitleStreaming🤖 DSH 处理中…Custom title of the streaming card while working (yellow header)
reporting.cardTitleDone🤖 DSH 处理完成Custom title of the streaming card when complete (green header)
interactions.approvalCardstrueAnswer permission approvals with clickable cards
interactions.userQuestionsCardstrueAnswer ask_user_question with clickable cards
interactions.approvalCardDisposeupdateAfter an approval-card click: update instantly replaces the card with a decided state (buttons removed, result shown) + toast; recall recalls the card message (falls back to update when recall fails — note Feishu leaves a "撤回了一条消息" placeholder)
newSessionPatterns/new + Chinese phrasesRegexes that reset the session
sessionsFiledata/dsh-feishu-sessions.jsonSession mapping persistence
http.port0Admin API port (0 disables)
http.token``Admin API bearer token

> Q&A cards in the web profile: ask_user_question answers go through the > single ctx.userQuestions provider slot. The gateway never claims that slot > (stealing it makes the Web UI's apiProxy host fail to start with > DUPLICATE_PROVIDER); it wraps service.ask at the service boundary > instead: sessions owned by a Feishu conversation are answered with Feishu > cards, while every other session continues through the registered UI > provider. Permission-approval cards work from Feishu in every setup. In a > standalone feishu profile, both ask_user_question and approvals are > answered from Feishu cards.

Session coexistence & self-healing

  • Preset composition (tools!) — in preset-roster deployments (e.g. the web

profile), Feishu agents are composed from the deployment's agent preset (meta.agentPreset + preset mount), so the model gets its tools instead of treating tool calls as plain text.

  • Web UI coexistence — sessions have a single live owner. When the Web UI

opens a session, the Feishu side takes over the running agent via agents.get() and drives the same session instead of failing with "while it is live" / "already exists"; both surfaces share one conversation.

  • Wedged-session self-heal — if a crashed process leaves a session

permanently conflicted ("already exists"), the gateway mints a fresh session id, re-points the Feishu conversation at it, and continues chatting.

Admin HTTP API (optional)

Enable by setting http.port. Endpoints:

  • GET /health — status
  • POST /api/push — proactive push

{ "receive_id": "ou_xxx", "receive_id_type": "open_id", "msg_type": "text", "content": "{\"text\":\"hi\"}" }

  • GET /api/sessions — Feishu↔DSH session mapping overview

Development

pnpm install
pnpm build     # tsc → lib/
pnpm test      # offline self-tests

> Note: @deepseek-ai/* packages are provided by the DSH host at runtime; for > local type-checking they are symlinked from your deepseek-harness checkout > (see the publish checklist).

License

MIT