All plugins

hermes-tag

Feishu platform override with per-chat Tier-0/Tier-1 context, standing work, and privacy lifecycle controls. Disclosure — replaces Hermes' bundled Feishu, Slack and DingTalk platform registrations with wrapped adapters; in chats listed in enabled_chats it stores every received group message (text and attachments, including from members who never talk to the bot) plus each @-mention question and reply in a plaintext SQLite file under the plugin's data directory (Tier-0 kept up to 24 h / 500 rows, Tier-1 memories with no time limit), answers /tag commands itself before Hermes' gateway admission (state-changing ones limited to the configured admins), and lets admins create Hermes cron jobs that post to the chat.

DanielLi202Platformv0.5.0Updated 1 hour ago

About

Feishu platform override with per-chat Tier-0/Tier-1 context, standing work, and privacy lifecycle controls. Disclosure — replaces Hermes' bundled Feishu, Slack and DingTalk platform registrations with wrapped adapters; in chats listed in enabled_chats it stores every received group message (text and attachments, including from members who never talk to the bot) plus each @-mention question and reply in a plaintext SQLite file under the plugin's data directory (Tier-0 kept up to 24 h / 500 rows, Tier-1 memories with no time limit), answers /tag commands itself before Hermes' gateway admission (state-changing ones limited to the configured admins), and lets admins create Hermes cron jobs that post to the chat.

Hermes Tag

Post the images, add your notes, let the thread run — then @ it. It already has everything that matters.

Use Hermes to bring Claude-Tag-style capability to your Feishu/Lark (and Slack). Drop a few images, add a note, let other people chime in — when you finally @-mention it, it pulls those images (the originals), your note, and the relevant replies — not just your last line, and never your whole history. Silent until mentioned; then it retrieves exactly the few messages that matter.

English · 中文

License: MIT Version: 0.5.0 hermes-agent: tested against v0.22.5 Python: 3.14

What it is

Hermes Tag is a Claude-Tag-style context-selection layer for Hermes on Feishu/Lark (and Slack). It overrides Hermes's built-in Feishu platform — it is not a new platform. Each enabled chat gets one shared agent identity, and it answers only when @-mentioned.

What it uniquely adds on top of Hermes's built-in channels:

  1. Late @, full context. You can scatter context before you ever invoke it — images, a note, other people's replies — and when you finally @-mention it, it reconstructs the right bounded evidence across time and media: the images' originals, your note, and the relevant discussion. Not just your trigger message; not the whole transcript.
  2. Per-chat memory, by design. Long-term memory is built only from @-mention interactions and stays scoped to that chat — one chat's memory never leaks into another, and never becomes your whole account history. There is no cross-channel "workspace memory"; that isolation is the privacy promise.
  3. Auditable, with redacted audit events. /tag admin audit returns redacted events (scope, time, counts — never message text); /tag admin clear|disable removes a chat's retained data. The enabled_chats allowlist is the only storage and processing boundary.

The ContextSelector chooses bounded evidence with focused_reply, thread, deictic_recent, and plain scopes instead of dumping the transcript. That means no full-history RAG and no ambient auto-answering.

Shipped now vs. roadmap. Shipped: bounded multimodal evidence, Tier-0/Tier-1 memory, per-chat isolation, admin lifecycle, and redacted audit — on Feishu/Lark and Slack. DingTalk is also supported, but with reduced capability: DingTalk bots only receive messages that @-mention them in groups (no equivalent of Feishu's im:message.group_msg), so ambient group context (Tier-0) isn't available there — see docs/dingtalk.md. Roadmap: deeper connector/source-binding parity. The Claude-Tag comparison is the goal we measure against, not a claim that every Claude-Tag feature already ships.

This repository, the Python/pip package, and the manifest name are all hermes-tag.

Security & Risk Warnings (Read Before Use)

  • The enabled_chats allowlist is the storage and processing boundary.

  • Tier-0 stores message text. Each message the bot receives in an enabled chat is kept as Tier-0 short-term context, including its text. On Feishu this happens only when granted_scopes includes im:message.group_msg; on Slack and DingTalk it always happens. Defaults: 500 rows per chat (tier0_max_count). Rows older than 24 hours (tier0_ttl_seconds) are deleted the next time a message is stored for that chat, so a quiet chat can keep them longer.

  • Tier-1 stores the question and the reply. Each @-mention turn writes a Tier-1 memory of the form question=<message text>; conclusion=<reply text>. Every turn in a DM counts as a mention. Once a chat passes tier1_max_count (100 by default), older memories are merged. Tier-1 has no time limit.

  • Both are kept in a plaintext SQLite file (declared encryption_posture: plaintext-db-on-local-disk), at <hermes home>/plugin-data/hermes-tag/<platform>-tag.sqlite3 or your db_path. Attachments on stored messages are copied into the sibling <sqlite file>.media directory. Media from quoted messages is downloaded through the bundled adapter into Hermes's media cache, one new file per download. The plugin deletes all of these files: after the turn, or on clear or eviction if they are kept as Tier-0 context.

  • On Feishu it makes these Feishu Open API calls of its own, with the bot's credentials:

    • application.v6.scope.list, once per process, to check whether the app really holds im:message.group_msg as granted_scopes claims;
    • im.v1.message.get plus message-resource downloads, for quoted messages;
    • a DM to each configured admin when that check finds a mismatch or an available upgrade.

    On Slack and DingTalk it makes no API calls of its own.

  • /tag standing confirm (admin-only) creates a Hermes cron job. The job runs on its schedule and posts to the chat until it is cancelled or paused.

  • /tag admin clear and /tag admin disable delete a chat's Tier-0, Tier-1 and media, and cancel the cron jobs behind its standing jobs. They do not reset the Hermes conversation; send /new for that.

  • Audit events (/tag admin audit) record startup, storage, admin, standing-job and lifecycle actions: ids, counts and fixed strings, never message text. They are kept after a clear. Rows written by earlier versions that held a context preview are scrubbed when the store opens.

Read SECURITY.md and docs/design/ before enabling a pilot chat.

Requirements / Compatibility

| Item | Requirement |
| --- | --- |
| hermes-agent | >=0.22.5 (tested: v0.22.5) |
| lark-oapi | 1.6.8 |
| Python | 3.14 |
| Required env | FEISHU_APP_ID + FEISHU_APP_SECRET |

Hermes enforces the manifest requirement requires_hermes: ">=0.22.5".

Quickstart (<60s)

Installing with an AI agent? Point it at llms.txt and AGENTS.md — those are written for agent-driven install/config. This README is for humans.

hermes plugins install DanielLi202/hermes-tag
plugins:
  enabled:
    - hermes-tag
platforms:
  feishu:
    require_mention: false   # so unmentioned group messages reach the adapter for Tier-0 context
    extra:
      feishu_tag:
        enabled: true
        enabled_chats: [oc_xxx_pilot_chat]
        bot_open_id: ou_xxx_bot_open_id
        granted_scopes: [im:message.group_msg]
        admins: [ou_xxx_admin_open_id]
        encryption_posture: plaintext-db-on-local-disk

bot_open_id and admins must be Feishu open_id values (ou_...). This plugin does not need contact:user.employee_id:readonly; it normalizes sender identity to open_id even when that scope is granted.

On first use, Hermes Tag live-verifies granted_scopes against the Feishu app and DMs configured admins if the config claims im:message.group_msg but the app does not actually hold it. That catches the silent failure mode where non-@ group messages are never delivered, so Tier-0 group context stays @-only.

Full onboarding + live verification: see after-install.md. Slack setup: see docs/slack-setup.md. DingTalk setup + capability limits: see docs/dingtalk.md. Hitting something that looks broken? Check docs/known-limits.md — it maps common symptoms to Feishu-platform / hermes-core limits this plugin can't fix.

Usage

In groups, /tag commands require @-mention.

  • /tag status -> admin-only; reports the adapter platform, capability flags (tier0_full_ingest / l2_context / tier1_at_memory), and current per-chat metrics.
  • /tag admin count -> returns retained-state counts such as tier0=... tier1=... standing_jobs=....
  • /tag admin clear|disable|audit -> clears plugin data, disables plugin storage for the chat, or returns redacted audit events.
  • /tag standing add <schedule> <timezone> <description> then /tag standing confirm
  • /tag standing list|cancel <id>|pause <id>|enable <id>

| Context scope | Meaning |
| --- | --- |
| focused_reply | Explicit reply -> narrow to that parent as evidence. |
| thread | Real thread without explicit reply -> narrow to that thread as evidence. |
| deictic_recent | "上面那张图" / "the image above" -> nearest recent media. |
| plain | Bounded recent text. |

| Memory tier | Behavior |
| --- | --- |
| Tier-0 | Short-term per-chat buffer, TTL/count evicted. |
| Tier-1 | Long-term, @-derived, consolidated, tombstoned on delete. |

Project Structure

  • src/hermes_tag/core.py — config, sqlite store, TagEngine, PlatformSeam.
  • src/hermes_tag/context.py — ContextSelector: the bounded-evidence selector.
  • src/hermes_tag/base.py — TagAdapterMixin: the platform-agnostic orchestration.
  • src/hermes_tag/platforms/feishu.py — Feishu binding: mention detection, media fetch/download, registration.
  • src/hermes_tag/platforms/slack.py — Slack binding: mention detection, media buffering, registration.
  • src/hermes_tag/platforms/dingtalk.py — DingTalk binding: is_in_at_list mention detection, registration (reduced capability — see docs/dingtalk.md).
  • src/hermes_tag/i18n.py — locale strings.
  • src/hermes_tag/adapter.py — back-compat re-export shim.

The platform-agnostic base plus a narrow seam means each platform is a thin add; the generic policy is written once for all of them.

Contributing · Changelog · License

README from the reviewed commit 75e1931; it updates when the author re-pins.