Files
EJClaw/docs/architecture.md

5.1 KiB

Architecture

Service Stack

Single unified service (ejclaw) manages all three Discord bots in one process:

  • ejclaw.service — Single unified process
  • Discord bots: DISCORD_OWNER_BOT_TOKEN (owner), DISCORD_REVIEWER_BOT_TOKEN (reviewer), DISCORD_ARBITER_BOT_TOKEN (arbiter)
  • Paired review: owner ↔ reviewer (agent types configurable per role)
  • Reviewer fallback: Claude exhaustion → codex-review auto-handoff
  • Shared dirs: store/, groups/, data/
  • SQLite WAL mode + busy_timeout=5000 for concurrent access

Data Flow

Discord ──► SQLite (WAL) ──► GroupQueue ──┬──► Owner (host process)
                                          │       │
                                          │       ▼ (auto-trigger)
                                          ├──► Reviewer (host process, read-only guarded)
                                          │       │
                                          │   Verdict routing
                                          │       ├─ DONE → change detection → finalize or re-review
                                          │       ├─ BLOCKED → Arbiter (if enabled) or User
                                          │       └─ Feedback → Owner (loop)
                                          │
                                          ├──► Arbiter (on-demand, fresh session each time)
                                          │       │
                                          │   ┌───┴─── MoA (if enabled) ───┐
                                          │   │ Ref model A ──► opinion    │
                                          │   │ Ref model B ──► opinion    │
                                          │   │ → injected into prompt     │
                                          │   └────────────────────────────┘
                                          │       │
                                          │   PROCEED/REVISE/RESET/ESCALATE
                                          │
                                     IPC polling ◄── follow-up messages
                                          │
                              ┌────────── Router ──────────┐
                              ▼                            ▼
                   paired_turn_outputs           Discord (display only)
                   (agent ↔ agent data)      (user observation, @mention)

Room Assignment Model

Per-room routing uses an explicit assignment model:

  • room_settings is the room-level source of truth (SSOT)
  • Each room stores:
    • room_mode: single or tribunal
    • owner_agent_type: codex or claude-code
  • Public room assignment uses assign_room
  • registered_groups remains as a materialized capability/read-model layer

Operationally:

  • single → one owner bot
  • tribunal → per-room owner + globally configured reviewer + optional arbiter

Tribunal is no longer inferred from "two bots registered on one room"; it is an explicit room setting.

Tribunal 3-Agent System

User message
  → Owner responds (implementation, answer, etc.)
    → Reviewer auto-triggered (critical review, design check)
      → Verdict:
          DONE              → Owner finalizes → Task completed → @user ✅
          DONE_WITH_CONCERNS → Owner addresses feedback → loop
          BLOCKED/NEEDS_CONTEXT
            ├─ Arbiter enabled → Arbiter judges → PROCEED/REVISE/RESET/ESCALATE
            └─ Arbiter disabled → Escalate to user → @user ⚠️
      → Owner BLOCKED/NEEDS_CONTEXT → Arbiter (same path as reviewer)
      → Deadlock (2+ round trips without progress)
          → Arbiter summoned → binding verdict → loop resumes

Verification Isolation

Reviewer and arbiter now run as host processes with role-scoped read-only guards and sandbox settings. Docker remains in use for verification profiles:

  • Scratch workspace copied before execution
  • Verification command run inside the container image
  • Isolated filesystem view for test/typecheck/build checks
  • Runtime image shared with host tooling and evidence inspection

Key Files

File Purpose
src/index.ts Orchestrator: state, message loop, agent invocation
src/agent-runner.ts Spawns agent processes, manages env/sessions/skills
src/verification.ts Verification execution using the container image
src/container-runtime.ts Shared Docker runtime helpers for verification
src/channels/discord.ts Discord channel (8s typing refresh, Whisper transcription)
src/ipc.ts IPC watcher and task processing
src/router.ts Message formatting and outbound routing
src/config.ts Trigger pattern, paths, intervals
src/task-scheduler.ts Runs scheduled tasks
src/db.ts SQLite operations
runners/agent-runner/ Claude Code runner (Agent SDK)
runners/codex-runner/ Codex runner (SDK, codex exec wrapper)
groups/{name}/CLAUDE.md Per-group memory (isolated)