feat: support codex runner in reviewer container
- Build both agent-runner and codex-runner into container image - Select runner path based on group.agentType at docker exec time - Update README to role-centric overview, generic MoA references - Add MoA reference opinions guidance to arbiter prompt
This commit is contained in:
26
README.md
26
README.md
@@ -14,13 +14,15 @@ Tribunal arbiter system inspired by multi-agent consensus architectures.
|
||||
|
||||
## Overview
|
||||
|
||||
A single unified service (`ejclaw`) manages three Discord bots in one process:
|
||||
A single unified service (`ejclaw`) runs a **Tribunal** of three roles:
|
||||
|
||||
- **Codex-main** (`@codex`) — Owner agent. Handles user requests, writes code.
|
||||
- **Claude** (`@claude`) — Reviewer agent. Critically reviews owner's work, verifies design direction.
|
||||
- **Codex-review** (`@codex-review`) — Arbiter agent. Summoned on-demand to break deadlocks between owner and reviewer.
|
||||
| Role | Purpose | Default |
|
||||
|------|---------|---------|
|
||||
| **Owner** | Handles user requests, writes code | Codex (`@codex`) |
|
||||
| **Reviewer** | Critically reviews owner's work, verifies design direction | Claude Code (`@claude`) |
|
||||
| **Arbiter** | On-demand deadlock breaker between owner and reviewer | Codex (`@codex-review`) |
|
||||
|
||||
All agent types and models are independently configurable per role via `.env`.
|
||||
Each role's agent type and model are independently configurable via `.env` (`OWNER_AGENT_TYPE`, `REVIEWER_AGENT_TYPE`, `ARBITER_AGENT_TYPE`, `*_MODEL`). Three Discord bots provide the identity layer — which bot speaks is determined by the active role, not hardcoded.
|
||||
|
||||
## Room Assignment Model
|
||||
|
||||
@@ -60,22 +62,22 @@ User message
|
||||
|
||||
### Mixture of Agents (MoA)
|
||||
|
||||
When enabled, the arbiter collects opinions from external models (Kimi, GLM, etc.) before rendering its verdict:
|
||||
When enabled, the arbiter collects opinions from configurable external reference models before rendering its verdict:
|
||||
|
||||
```
|
||||
Deadlock detected → MoA reference queries (Kimi + GLM, parallel)
|
||||
Deadlock detected → MoA reference queries (parallel, configurable via MOA_REF_MODELS)
|
||||
→ Opinions injected into arbiter's prompt
|
||||
→ SDK arbiter (subscription-based) aggregates all perspectives
|
||||
→ Arbiter aggregates all perspectives
|
||||
→ Final verdict: PROCEED / REVISE / RESET / ESCALATE
|
||||
```
|
||||
|
||||
No extra SDK processes. External references use lightweight API calls (Anthropic-compatible).
|
||||
No extra SDK processes. External references use lightweight OpenAI/Anthropic-compatible API calls.
|
||||
|
||||
## Features
|
||||
|
||||
- **Tribunal 3-agent system** — Owner/reviewer/arbiter with on-demand deadlock resolution
|
||||
- **Discord-independent communication** — Agent-to-agent data flows directly via DB, Discord is display-only
|
||||
- **Mixture of Agents** — External model opinions (Kimi, GLM) enrich arbiter verdicts
|
||||
- **Mixture of Agents** — Configurable external reference models enrich arbiter verdicts
|
||||
- **Per-role model selection** — `OWNER_MODEL`, `REVIEWER_MODEL`, `ARBITER_MODEL` + effort + fallback toggle
|
||||
- **Container-isolated reviewer** — Persistent Docker container with read-only source mount
|
||||
- **Global failover** — Account-level Claude failure → all channels switch to codex, auto-recovers
|
||||
@@ -107,8 +109,8 @@ Discord ──► SQLite (WAL) ──► GroupQueue ──┬──► Owner (ho
|
||||
├──► Arbiter (on-demand, fresh session each time)
|
||||
│ │
|
||||
│ ┌───┴─── MoA (if enabled) ───┐
|
||||
│ │ Kimi API ──► opinion │
|
||||
│ │ GLM API ──► opinion │
|
||||
│ │ Ref model A ──► opinion │
|
||||
│ │ Ref model B ──► opinion │
|
||||
│ │ → injected into prompt │
|
||||
│ └────────────────────────────┘
|
||||
│ │
|
||||
|
||||
@@ -52,18 +52,24 @@ RUN curl -fsSL https://bun.sh/install | bash
|
||||
# Create app directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy host's agent-runner (same code, same SDK version)
|
||||
COPY runners/agent-runner/package*.json ./
|
||||
RUN bun install
|
||||
COPY runners/agent-runner/ ./
|
||||
RUN bun run build
|
||||
# Copy agent-runner (Claude Code)
|
||||
COPY runners/agent-runner/package*.json ./agent/
|
||||
RUN bun install --cwd ./agent
|
||||
COPY runners/agent-runner/ ./agent/
|
||||
RUN bun run --cwd ./agent build
|
||||
|
||||
# Copy codex-runner
|
||||
COPY runners/codex-runner/package*.json ./codex/
|
||||
RUN bun install --cwd ./codex
|
||||
COPY runners/codex-runner/ ./codex/
|
||||
RUN bun run --cwd ./codex build
|
||||
|
||||
# Create workspace directories
|
||||
RUN mkdir -p /workspace/project /workspace/group /workspace/global \
|
||||
/workspace/ipc/messages /workspace/ipc/input
|
||||
|
||||
# Create entrypoint script
|
||||
RUN printf '#!/bin/bash\nset -e\ncat > /tmp/input.json\nbun /app/dist/index.js < /tmp/input.json\n' \
|
||||
# Entrypoint (fallback — persistent containers use docker exec with explicit runner path)
|
||||
RUN printf '#!/bin/bash\nset -e\ncat > /tmp/input.json\nbun /app/agent/dist/index.js < /tmp/input.json\n' \
|
||||
> /app/entrypoint.sh && chmod +x /app/entrypoint.sh
|
||||
|
||||
# Set ownership to node user (non-root)
|
||||
|
||||
@@ -22,6 +22,15 @@ You have been summoned because the owner and reviewer reached a deadlock after m
|
||||
- The situation cannot be resolved without user input, regardless of technical agreement
|
||||
- The same NEEDS_CONTEXT or BLOCKED is repeated after a prior PROCEED — this means your PROCEED did not resolve the issue
|
||||
|
||||
## MoA (Mixture of Agents) Reference Opinions
|
||||
|
||||
You may receive reference opinions from external models appended to your prompt. When present:
|
||||
|
||||
- **Cite them explicitly** in your verdict — e.g., "Reference model A agrees that...", "Reference model B raises a concern about..."
|
||||
- **Cross-reference** their opinions against the owner/reviewer conversation and code evidence
|
||||
- **Resolve conflicts** — if reference opinions disagree with each other or with owner/reviewer, state which view you adopt and why
|
||||
- Do NOT blindly follow reference opinions — they are inputs to your judgment, not authorities
|
||||
|
||||
## Rules
|
||||
|
||||
- Base your verdict on evidence (code, test output, logs), not on who said what first
|
||||
|
||||
@@ -484,7 +484,11 @@ export async function runReviewerContainer(args: {
|
||||
}
|
||||
}
|
||||
}
|
||||
execArgs.push(containerName, 'bun', '/app/dist/index.js');
|
||||
const isCodexAgent = (group.agentType || 'claude-code') === 'codex';
|
||||
const runnerPath = isCodexAgent
|
||||
? '/app/codex/dist/index.js'
|
||||
: '/app/agent/dist/index.js';
|
||||
execArgs.push(containerName, 'bun', runnerPath);
|
||||
|
||||
return new Promise<AgentOutput>((resolve) => {
|
||||
const proc = spawn(CONTAINER_RUNTIME_BIN, execArgs, {
|
||||
|
||||
Reference in New Issue
Block a user