dsh-telegram-bot
DiscoveredTelegram DM topics for DeepSeek Harness sessions: streaming, approvals, structured questions and session controls.
dsh-telegram-bot
Telegram bot for DeepSeek Harness, configured from the Harness Web UI.
Found a bug or have an idea? Open an issue.
The bot connects to Telegram, enforces the allowlists, and bridges DSH agent sessions to Telegram DM topics. The All topic stays global; every DSH session gets its own topic. The assistant answer is the first message and streams in place as text arrives; the current reasoning block and a rolling tool-call list update after it, then both transient messages are deleted when the answer is ready. Bot lifecycle notifications go to All.
Demo
▶️ First setup: https://youtu.be/QEeVucfBsWk
Install plugin → bot token → allowlist → /start → /sessions → a test prompt.
Enable Threaded mode
BotFather: Bot Settings → Threaded mode → Enable. Click the GIF to open it full size.
Features
- Settings → Telegram page in the Web UI.
- Bot token, stored through the credential seam and never written into the settings file. The credential reference is configurable with
tokenRef(defaultTELEGRAM_BOT_TOKEN). - Allowed users — Telegram user ids or
@usernames. - Allowed chats — Telegram chat ids or
@channelnames; empty means private chats only. - Enable bot toggle.
- Restart bot button — reapplies the saved settings and restarts long polling.
- Plugins page — the bundle page is informational and points to Settings → Telegram. The bundle switch above it is the plugin on/off control; turning it off unmounts the runtime and aborts polling.
- Agent bridge — an ordinary text message in a session topic starts a DSH agent turn in that session, with assistant text streamed back.
- DM topics —
/sessionsin All is the single place for DSH sessions: choose a workspace, then create a new session in it or open an existing one. The selected session continues in its own topic. Requires Threaded mode in @BotFather → Bot Settings. - All topic — Telegram's default topic and the management hub; lifecycle notifications are posted there.
- Thinking and tool calls — reasoning deltas and tool calls are mirrored into the topic, with independent Show model thinking / Show tool calls switches. Thinking is a 10-line rolling window; the tool-call message shows the last ten calls.
- Commands —
/start,/help,/sessions,/stop,/status,/current,/menu,/rename,/last,/restart,/id,/ping. - Approval prompts — when a tool asks for approval, the session topic gets a styled prompt with Deny and Allow inline buttons; the decision resolves the exact pending request.
- Structured questions —
ask_user_questionrequests render in the session topic with option buttons, multi-select, a custom-answer flow, and plan-review approve/decline choices. - Session controls — an inline 2×2 panel in each session topic: Model (Flash/Pro), Effort (off/low/high/max), Mode (permission preset), and Context (window, last request usage, and cache-hit percentage). Telegram reply keyboards are chat-wide, so the controls are a per-topic inline panel rather than a bottom keyboard.
- Recovery —
/last [n]shows the latest assistant answer(s) from the bound session, useful after switching between Web and Telegram./rename <name>changes the Telegram topic title;/restartrestarts the Telegram runtime;/menuopens the inline session controls. - Language — bot messages and the Telegram command menu default to English; a Settings selector switches them to Russian.
- Formatting — assistant Markdown (headings, bold, lists, code, links, tables) is converted to Telegram MarkdownV2. The same formatting is used for session previews and
/last. - Command hints — the runtime publishes the list with
setMyCommands, so Telegram shows the commands and descriptions when the user types/. The descriptions follow the selected Bot language; English is the default. - English and Russian page copy; Russian is registered as an optional language pack.
Install
From this checkout, run in the repository root:
npx @deepseek-ai/dsh plugin --profile web add .
After publishing to npm:
npx @deepseek-ai/dsh plugin --profile web add dsh-telegram-bot
dsh plugin add installs the package and selects its bundle in dsh.profile.bundles when the package declares dsh.bundle. Restart dsh web if the running profile does not pick the new bundle up through HMR.
Then open Settings → Telegram (or Plugins → Telegram Bot) in the Web UI.
Where it lives
DSH plugins are profile packages, not files inside the DeepSeek Harness checkout. A normal install resolves dsh-telegram-bot from npm into:
~/.dsh/profiles/web/node_modules/dsh-telegram-bot
A local development install can instead link this repository into the profile. Either way, users do not need to know or copy a local checkout path: dsh plugin --profile web add dsh-telegram-bot is enough.
Configure
| Field | Where it lives | Meaning |
|---|---|---|
| Bot token | credential store | Token from @BotFather; write-only from the page |
tokenRef | profile configuration | Credential/env name that holds the token; default TELEGRAM_BOT_TOKEN |
cwd | profile configuration | Working directory for Telegram-created DSH sessions; default process cwd |
agentPreset | profile configuration | Preset mounted for Telegram sessions when presets are available; default standard |
| Allowed users | profile configuration | Numeric Telegram user ids or @usernames; empty means nobody |
| Allowed chats | profile configuration | Numeric chat ids (groups are negative) or @channelnames; empty means private chats only |
| Show model thinking | profile configuration | Mirror reasoning deltas into a Thinking message |
| Show tool calls | profile configuration | Mirror tool names and arguments into the topic |
| Bot language | profile configuration | en (default) or ru for all Telegram bot messages |
| Enable bot | profile configuration | Whether the runtime polls Telegram while the profile runs |
| Restart | request field | Forces a fresh getMe + getUpdates cycle |
The token field reports only whether a token is configured. A token supplied by the process environment is reported as configured but cannot be overwritten from the page. Changing tokenRef points the runtime and the page at another credential; use it to run several bots from one host.
First run
- Create a bot with @BotFather and save its token in Settings → Telegram.
- In @BotFather open the bot's Bot Settings → Threaded mode and enable it (short GIF). Without this, private-chat topics cannot be created.
- Open the bot chat, tap the bot name and enable Topics. All is Telegram's default topic.
- Send
/startin All. With an empty user list the bot replies with your user id and chat id, plus the Threaded-mode reminder. - Add your user id to Allowed users and press Save (or Restart bot).
- In All send
/sessionsto create a new session or pick an existing DSH session. The dialog continues in its own topic.
The runtime starts only when Enable bot is on, a token is configured, and the profile process is running. It logs connection and polling diagnostics with the [telegram] prefix. Runtime state is at $DSH_HOME/telegram/status.json, and the topic → session mapping is at $DSH_HOME/telegram/state.json (neither contains the token).
Headless profile (no Web UI)
The bot does not need the Web server. A profile with dsh-base and this bundle polls Telegram on its own; the settings page simply is not available there.
mkdir -p ~/.dsh/profiles/tg
cd ~/.dsh/profiles/tg
~/.dsh/profiles/tg/package.json:
{
"name": "dsh-profile-tg",
"private": true,
"dependencies": { "dsh-telegram-bot": "^0.1.0" },
"dsh": {
"profile": {
"bundles": ["@deepseek-ai/dsh-base", "dsh-telegram-bot"]
}
}
}
~/.dsh/profiles/tg/cordis.patch.yml:
- id: telegram-bot
name: dsh-telegram-bot
config:
enabled: true
allowedUsers: ["<user-id>"]
allowedChats: ["<chat-id>"]
Install and run without Web:
cd ~/.dsh/profiles/tg
npm install
# Prefer the credential store; for a headless deployment the matching
# environment variable is the supported fallback.
printf 'TELEGRAM_BOT_TOKEN=%s\n' '<token>' >> ~/.dsh/.env
chmod 600 ~/.dsh/.env
npx @deepseek-ai/dsh --profile tg
No browser and no port are opened. Ctrl+C stops the process; $DSH_HOME/telegram/status.json shows the runtime state. Do not put the token in cordis.patch.yml.
Plugins page
The bundle detail page in Plugins is a short informational panel:
- it points to Settings → Telegram for token, access lists, language and display options;
- it lists the manual configuration files for headless setups;
- it does not duplicate the settings controls.
The bundle switch above the panel is the plugin on/off control. Settings → Telegram → Enable bot is a soft pause that keeps the plugin loaded but stops polling.
Security
- Approvals requested by Telegram-owned agents are answered in the session topic with Deny / Allow; unanswered prompts stay pending until the turn is cancelled or
/stopis used. - The token is a secret: it lives in the credential store, not in
cordis.patch.yml. - An empty user list answers only in private chats with the setup hint. Once the list is non-empty, unauthorized users are ignored.
- Group/channel chats require an explicit Allowed chats entry.
- A DSH plugin runs in-process with the Host. Install only packages whose source you trust.
- Do not run two pollers with the same bot token; Telegram answers
409 Conflictand one of them stops.
Develop
No build step is needed: index.js is the Host half and client.js is the browser bundle in the module-loader factory format.
Architecture
This is a transport plugin, not a tool plugin:
index.jsowns the Telegram runtime, topic routing and the bridge to existing DSH sessions;client.jsonly registers the Settings page and the Plugins-page note;- the plugin adds no model-facing tools, no system-prompt text and no new agent capabilities;
- it consumes existing services with
ctx.get, observes session and approval events withctx.on, and owns its polling lifetime withctx.effect; - Telegram commands such as
/sessionsand/lastare transport commands handled by the bot, not DSH tools exposed to the model.
That is why the model's toolset is unchanged after installing it: Telegram is another front door to the same DSH agent, not a second agent.
npm install
node --check client.js
node --check index.js
node -e "import('./index.js').then((m) => console.log(m.name, Object.keys(m)))"
Inspect the composed profile:
npx @deepseek-ai/dsh --profile web --dump-config
Publish and claim the name
dsh-telegram-bot is an unscoped npm name. Publishing the package is what claims it; no other registry or catalog is required for DSH installation.
npm login
npm whoami
npm publish --dry-run
npm publish
A Git URL or tarball also works for DSH (dsh plugin add github:you/dsh-telegram-bot), but the npm package name is the identity used by dsh plugin add, Plugin Manager, and npx. Use the same name for the GitHub repository and add the dsh-plugin topic for discovery.
Roadmap
- File attachments and voice input.
- Multiple chats and group/topic routing.
- Richer tool-result summaries.
License
MIT
Credits
Markdown to Telegram formatting uses telegramify-markdown (MIT).
Comments
Loading…
Similar plugins
by todayer
DeepSeek Harness Telegram bridge (bot) plugin, Hermes-style: per-topic sessions, DM topics, group gating, media, commands. Fork/extension of hi-wenw/dsh-telegram-channel.
★ 0
MIT
JavaScript
Aug 25, 2026
dsh plugin --profile web add dsh-telegram-channelTelegram remote control for DeepSeek Harness: list conversations with titles and workspaces, resume paused persisted sessions on demand (preset remount), turn-tracked reply relay, first-line reasoning
★ 0
dsh plugin --profile web add dsh-telegram-controlby Kevin66Z0
Remote-control DeepSeek Harness from Telegram: stream replies, one-tap keyboards, whitelist-secured, zero inbound ports.
★ 3
MIT
TypeScript
Sep 2, 2026
dsh plugin --profile web add @deepseek-ai/dsh-host-telegramby LosEcher
DSH bundle: thin Telegram bridge (long-poll Bot API, allowlist, per-chat agent sessions) for DeepSeek Harness
★ 0
↓ 201/wk
MIT
JavaScript
Oct 12, 2026
dsh plugin --profile web add dsh-channel-telegramby qschen86
DSH host plugin: Telegram notifications and reply-to-continue for sessions
★ 0
MIT
JavaScript
Sep 5, 2026
dsh plugin --profile web add dsh-telegram-bridgeby danilinao
Telegram remote for DeepSeek Harness — attach a live web session from your phone and answer its questions there, with a Russian UI. Russian fork of hi-wenw/dsh-telegram-channel (MIT).
★ 0
TypeScript
Oct 23, 2026
dsh plugin --profile web add dsh-telegram-channel-ru