Skip to content

BotHarness Architecture & Data Flow

System context, modules, data flow and boundaries (living doc)

BotHarness is a plugin layer on top of DSH (DeepSeek Harness) that gives agents a persistent identity: PersonaBot — a persona with memory that spans sessions and can work concurrently. DeepSeekBot is its first app (sidebar roster + delegation + IM integration). The DSH core is not forked; IM channels come from the dsh-im base.

Status: M1 implemented (PR #13) · M2 memory MVP · M3 roster & delegation · M5 IM adapter · updated 2026-09-17

1 · System context

System contextmmdsvg

Two entry points (DSH Web roster/delegation, Feishu group IM), one PersonaBot brain.

2 · Modules & packages

Modules & packagesmmdsvg
Module Responsibility Status
plugin.ts Plugin entry: settings namespace + provide('botharness'); assembled by createCore() M1 ✅
bots/registry.ts PersonaBot lifecycle + atomic persistence; remove keeps memory by default, only purge clears it M1 ✅
state/bot-state.ts Five session states reported → PersonaBot aggregation; aggregate-changed / session-changed / session-removed M1 ✅
im/* Read-only dsh-im store (v1/v2/v3 compatible) + workspace→BotIdentity (IM binding helper) M1 ✅ (M5 wiring)
Memory (M2) front-matter, directory-tree injection, memory_* tools, visibility, git versioning M2
roster client main panel + sidebar.panellist; roster tree / detail / create; @delegation M3

3 · Boot & service exposure

Boot & service exposuremmdsvg

Everything goes through the Cordis service bus — no file polling.

4 · Creating a PersonaBot (data flow)

Creating a PersonaBot (data flow)mmdsvg

Validate → duplicate check (against valid records, not stuck on tombstone directories) → atomic write → memory directory.

5 · IM binding resolution (helper today, wired in M5)

IM binding resolution (helper today, wired in M5)mmdsvg

6 · State machine & events

State machine & eventsmmdsvg
Event Trigger Consumer
aggregate-changed aggregate state changed roster / avatars (M3+)
session-changed any session state change (even if aggregate holds) session detail
session-removed session ended / cleaned up tree refresh

7 · On-disk data

Ours (written by the registry):

$DSH_HOME/botharness/bots/<slug>/
├── bot.json   # machine metadata (atomic write)
└── memory/    # default memory dir; absolute path configurable
               # M2: PERSONA.md / MEMORY.md / topic files

dsh-im’s (read-only):

$DSH_HOME/integrations/dsh-feishu/
├── config.json      # bots[]
├── workspaces.json  # v3: workspaces/aliases/overrides
└── bots/<botId>/state.json  # conversation binding (M5)

8 · Communication & boundaries

Channel Direction Notes
Cordis service provide/inject core → client/im/third-party the botharness service; no global singleton
Tracker subscription states.on() core → client in-process events, not polling
DSH event bus ctx.on DSH/dsh-im → core M3 subscribes to agent/* to drive state
Feishu / Lark dsh-im ↔ open platform outbound long connection; no public ingress (webhook exception, see PRD)
dsh-im disk read-only only through the single im/ module; no fork / no patch
Secrets only in the DSH credentials service; zero plaintext in the repo

9 · How to maintain

  • This is a living architecture document: when modules, data flows, or boundaries change structurally, update this file (mermaid sources are inlined).
  • This page is synced to the docs site (apps/docs) by scripts/sync-docs.mjs; site address https://botharness.ai/dev/architecture.
  • Companions: platform spec docs/botharness.md · app PRD PRD.md · glossary CONTEXT.md · decisions docs/adr/.
Navigation

Type to search…

↑↓ navigate↵ selectEsc close