Skip to content

Latest commit

Β 

History

32 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

DepartAI

Two AI coding agents β€” from different vendors β€” take turns on a shared task, critically reviewing each other until both agree the work is done.

CI Release License: MIT Go Backends

DepartAI is a free, open-source CLI that orchestrates two AI coding agents in a deterministic, sequential relay on a shared task. Each agent can use a different backend and model β€” e.g. Alpha on Claude Opus, Beta on OpenAI Codex β€” so two different model families catch each other's blind spots. Agents hand off context through a shared task log, review each other's work each turn, and stop only when both independently agree the task is complete and every acceptance criterion in a shared spec is checked.

Why this and not a bigger multi-model swarm? Deliberate focus. DepartAI is a single self-contained Go binary β€” no IDE or plugin lock-in β€” running a simple, predictable two-agent relay with a spec as the contract. Less ceremony, more determinism.

Bring your own backend. DepartAI drives the official claude and/or codex CLIs, so you use your own LLM subscription(s). At least one must be installed and authenticated β€” see Prerequisites.

How It Works

departai
  β”‚
  β”œβ”€β–Ί Interactive REPL with autocomplete
  β”‚
  β”œβ”€β–Ί User types a task prompt
  β”‚     β”‚
  β”‚     β”œβ”€β–Ί Spec pre-turns (collaborative): each agent contributes Goal +
  β”‚     β”‚   Acceptance Criteria + Files in scope to a shared spec.md before
  β”‚     β”‚   any code is written. Append-only β€” later agents can extend but
  β”‚     β”‚   not weaken what earlier ones defined.
  β”‚     β”‚
  β”‚     └─► Relay loop:
  β”‚
  β”‚         Turn 1 (Alpha):  Implements navigation + CTA β†’ marks criterion [x] β†’ Complete: no
  β”‚         Turn 2 (Beta):   Reviews Alpha, fixes missing OG image, marks criterion [x] β†’ Complete: no
  β”‚         Turn 3 (Alpha):  Reviews Beta, runs tests, all criteria checked β†’ Complete: yes
  β”‚         Turn 4 (Beta):   Reviews everything, made zero changes β†’ Complete: yes
  β”‚         └─► Consensus + spec satisfied β†’ task ends
  β”‚
  β”œβ”€β–Ί User types another prompt (same task context)
  β”‚     └─► Appended as directive, agents continue from where they left off
  β”‚     └─► /respec re-runs the pre-turn loop to integrate the directive into the spec
  β”‚
  └─► /new to start fresh, /resume to pick a previous task

Why sequential turns? Each agent gets a fresh context window. The task log is the handoff mechanism β€” each agent reads what was done and continues from there. This avoids context window exhaustion on large tasks.

Why two agents? They critically review each other's work. An agent can only say "Complete: yes" if (1) it made zero code changes during its turn β€” meaning it reviewed the other's work and found nothing wrong β€” AND (2) every Acceptance Criterion in the spec is checked off. This forces a real verification cycle anchored to a stable definition of done.

Installation

Homebrew (macOS)

brew install manurgdev/departai/departai

This installs the binary plus shell completions and the man page (man departai). On Linux, use go install or the pre-built binaries below.

Using go install

go install github.com/manurgdev/departai@latest

Requires Go 1.25+. The binary lands in $(go env GOPATH)/bin β€” make sure that's on your $PATH.

Pre-built binaries for macOS, Linux, and Windows are also attached to each GitHub release.

Build from source

git clone https://github.com/manurgdev/departai
cd departai
go build -o departai .
mv departai /usr/local/bin/departai   # or anywhere on $PATH

Prerequisites

At least one supported AI CLI must be installed and authenticated:

Claude Code CLI (default backend):

npm install -g @anthropic-ai/claude-code
claude --version

Codex CLI (alternative backend):

npm install -g @openai/codex
codex --version

You can switch backends with /config set backend codex or --backend codex.

First run: the very first time you launch departai with no config, it shows a short welcome, detects which backends are installed, and offers to write a starter ~/.departai/config.yml β€” defaulting to cross-vendor (Alpha β†’ Claude, Beta β†’ Codex) when both are available.

Check your version anytime:

departai --version            # departai vX.Y.Z (os/arch)
departai --version --verbose  # + commit, build date, Go toolchain

Shell completions

Homebrew installs completions automatically. With go install, generate them for your shell:

departai completion zsh  > ~/.zsh/completions/_departai      # zsh
departai completion bash > /etc/bash_completion.d/departai   # bash
departai completion fish > ~/.config/fish/completions/departai.fish  # fish

Usage

Interactive mode (default)

departai                         # uses current directory
departai --dir /path/to/project  # explicit project directory

The REPL shows a banner with current config and a prompt. Type / to see autocomplete suggestions for all commands:

  DepartAI β€” AI Agent Orchestrator

  Work dir     : /Users/you/projects/my-app
  Mode         : dev
  Max turns    : unlimited
  Max turn time: no limit
  Log window   : unlimited
  Retries      : 2

  Agents:
    Alpha : claude / opus
    Beta  : codex / gpt-5.3-codex

  Type a task to start, or /help for commands.

departai (dev)> Build a REST API with user authentication

Direct mode

Run a single task without the REPL:

departai "Build a REST API with user authentication"
departai --dir /path/to/project "Add unit tests"
departai --model opus "Migrate the database schema"
departai --max-turns 6 "Fix the failing CI pipeline"

Task Lifecycle

departai tracks an active task. The REPL prompt shows it:

departai>                                ← no active task
departai> Build an API                   ← creates new task, agents start working
departai [20260418-build-an-api]>        ← task is active, agents finished or paused
departai [20260418-build-an-api]> add auth middleware  ← adds directive to SAME task
departai [20260418-build-an-api]> /continue            ← resumes relay without new directive
departai [20260418-build-an-api]> /new                 ← deselects β†’ back to "departai>"
departai> /resume                        ← pick any previous task

Key concepts

  • New prompt with active task β€” appended as a "User Directive" to the task log. Agents read it and act on it. Turn counter resets for max-turns but task log turn numbers keep incrementing.
  • New prompt without active task β€” creates a new task from scratch.
  • /continue β€” resumes the active task's agent relay loop (no new directive).
  • /resume β€” shows a list of all previous tasks in the project, select one to make it active (does not run it β€” use /continue or type a prompt after).
  • /new β€” deselects the active task. Next prompt creates a fresh one.
  • ESC β€” press during a running turn to stop the agent immediately. The task stays active for /continue later.

Streaming TUI

While agents work, departai shows a bubbletea TUI (alt-screen) with:

  • Pinned header β€” turn number, agent name, model, elapsed time (always visible)
  • Live event stream β€” agent reasoning text + tool calls as they happen
  • Token-level text streaming (Claude backend) β€” text from the agent appears live, character by character, as the LLM generates it. Long generations (e.g. writing an updated spec.md) no longer surface as a silent gap.
  • In-flight indicators β€” each tool call shows a spinner and a (running Xs) timer while the block is open, so you can tell when an agent is actively working on something vs. when a step has settled.
  • Spinner + total elapsed in the footer
  • Auto-continue β€” when a turn finishes, a 5-second countdown starts. Press any key to enter review mode, or wait to auto-continue to the next turn.

In review mode (after a turn finishes, press any key during countdown):

  • ↑/↓ or j/k β€” navigate between tool calls
  • Enter or Space β€” expand/collapse a tool call (shows diff for Edit operations)
  • q or Esc β€” continue to next turn

After the TUI exits, a compact summary is printed to the terminal so the turn activity persists in scroll-back history.

Interactive Commands

All commands use the / prefix with hierarchical autocomplete.

Command Description
/help Show all available commands
/dev Switch to development mode (code-focused)
/ask Switch to ask mode (research / Q&A)
/config Show current configuration
/config set <key> <value> Set a config value (validates models, prompts to save)
/config save Save config to project .departai/config.yml
/config save global Save config to ~/.departai/config.yml
/model Show global + per-agent models
/model <name> Set global model (validated)
/model alpha [<name>] Show/set Agent Alpha's model (validated)
/model beta [<name>] Show/set Agent Beta's model (validated)
/model <agent> unset Clear an agent's override (inherits global)
/continue Continue the active task's relay loop
/respec One-shot: force a fresh spec pre-turn before the next prompt or /continue (re-evaluates the spec to incorporate new directives or current state)
/resume Select a previous task from a list
/new Deselect active task (next prompt = new task)
/exit, /quit Exit departai

exit and quit also work without /. Press Ctrl+D on an empty line to exit. Ctrl+C cancels the current line without exiting (standard terminal UX).

The REPL supports multi-line input β€” long prompts wrap automatically to fit the terminal width and the editor grows vertically as you type. The prompt prefix is shown only on the first line; continuation lines align under the input column.

  • Shift+Enter inserts a newline (multi-line input). Works in modern terminals that distinguish Shift+Enter from Enter via the kitty keyboard protocol: kitty, iTerm2 (with "Report modifiers using CSI u" enabled), alacritty, ghostty, WezTerm.
  • Alt+Enter is the universal fallback for terminals that send Shift+Enter as a plain \r (Terminal.app default, older terminals).
  • Enter submits the current input.

Pasting large multi-line texts works as expected β€” bracketed paste is enabled, so the entire paste is treated as a single insert (newlines inside don't submit early).

Up/Down arrows navigate command history when the cursor is at the first/last line of the input; otherwise they move the cursor between lines. Command history persists across sessions in ~/.departai/history.txt.

Config keys for /config set

Key Example Description
model /config set model opus Global model for both agents (validated)
model.alpha /config set model.alpha opus Override for Agent Alpha (validated)
model.beta /config set model.beta sonnet Override for Agent Beta (validated)
backend /config set backend codex Default backend (claude or codex)
backend.alpha /config set backend.alpha claude Override backend for Agent Alpha
backend.beta /config set backend.beta codex Override backend for Agent Beta
max-turns /config set max-turns 20 Max turns per run (0 = unlimited)
max-turn-duration /config set max-turn-duration 15m Per-turn wall-clock budget (Go duration format, e.g. 15m, 1h30m); empty = no limit
log-window /config set log-window 6 Inject only the last N turns into each prompt (0 = full log). Reduces token cost on long tasks
max-retries /config set max-retries 2 Retries per turn on a transient backend failure (0 disables)
mode /config set mode ask Active mode: dev (default) or ask
instructions /config set instructions ./rules.md Custom instructions file
blocked-commands /config set blocked-commands "WebFetch,rm -rf" Comma-separated list of tools/patterns agents must NOT use (soft enforcement)

Model validation

Every model change is validated against the backend before being accepted (~1-2s). Invalid names are rejected and the previous value is kept.

Persistence

After any config change, a menu asks where to save: Project (default), Global, or Session only. Ctrl+C on the menu = Session only.

CLI Flags

Flag Default Description
--dir current directory Working directory where agents operate
--model (backend default) Global model (validated on startup)
--backend claude Agent backend: claude or codex
--instructions built-in Path to custom agent protocol markdown file
--max-turns unlimited (0) Max turns per run; 0 = no limit
--max-turn-duration no limit Per-turn wall-clock budget (e.g. 15m, 1h30m); empty = no limit
--log-window unlimited (0) Inject only the last N turns into each prompt; 0 = full log
--max-retries 2 Retries per turn on a transient backend failure (rate limit, 5xx, network blip); 0 disables
--version β€” Print version and exit (add --verbose for full build info)
--verbose false More detailed output (e.g. full build info with --version)

Configuration

YAML config files loaded in layers (later wins):

  1. Built-in defaults
  2. ~/.departai/config.yml β€” user-global
  3. <project>/.departai/config.yml β€” project-level
  4. CLI flags
  5. Interactive /config set commands
# .departai/config.yml

agent_backend: claude           # default backend: "claude" or "codex"
backend_alpha: claude           # per-agent backend overrides (optional)
backend_beta: codex             # Alpha uses Claude, Beta uses Codex

max_turns: 0                    # turn-count cap per run (0 = unlimited)
max_turn_duration: 15m          # per-turn wall-clock budget (Go duration; empty = no limit)
log_window: 6                   # inject only the last N turns into prompts (0 = full log)
max_retries: 2                  # retries per turn on a transient backend failure (0 = disabled)

model: opus                     # default model (alias or full name; depends on the backend)
model_alpha: opus               # per-agent model overrides (optional)
model_beta: gpt-5.3-codex       # each agent can use its backend's models

# instructions_file: ./my-instructions.md
# blocked_commands:
#   - WebFetch
#   - "rm -rf"

Modes β€” /dev and /ask

departai supports two modes:

  • /dev (default) β€” coding tasks. Agents critically review each other, edit code, run tests, and only declare consensus when both made zero changes and verified the work.
  • /ask β€” research / Q&A / analysis tasks. Agents discuss, gather evidence, cite sources, and produce a written answer. They can edit code if the question demands it, but the default output is analysis, not edits.

Switch from the REPL:

departai (dev)> /ask
  βœ“ Mode set to ask

departai (ask)>

Or set explicitly:

# .departai/config.yml
mode: ask

The active mode is always visible:

  • In the banner: Mode : ask
  • In the REPL prompt: departai (ask)> or departai (ask) [task-id]>
  • In /config output

Each mode has its own built-in agent protocol. The dev mode emphasises code-edit cycles + tests; the ask mode emphasises evidence-based reasoning, citing sources, and answering precisely. Both share the same two-agent relay and consensus rule.

Definition of Done β€” the spec

Every task gets a spec.md file alongside the task log. It is the stable contract both agents work from: Goal, Acceptance Criteria, Files in scope, Open questions, Decisions log. The orchestrator only declares the task complete when every Acceptance Criterion is checked off β€” no amount of agent enthusiasm overrides this.

How the spec is populated

When a task is created, spec.md starts in Status: DRAFT. Before any code is written, the orchestrator runs a spec pre-turn for each agent in sequence:

Spec Pre-turn 1/2 (Alpha):  Drafts initial Goal + Acceptance Criteria + Files in scope
                            from the user's prompt. Sets Status to ACTIVE.
Spec Pre-turn 2/2 (Beta):   Reviews Alpha's draft, ADDS missing criteria/files,
                            moves ambiguities to Open questions. Append-only β€”
                            cannot remove or weaken what Alpha defined.

Both agents read the user's prompt and contribute their best version. The cross-vendor diversity catches blind spots in the spec itself, not just in the code.

After the pre-turn loop, the regular relay starts with the spec as anchor. Every turn:

  • Reads the spec at the top of the prompt
  • Marks - [ ] β†’ - [x] on Acceptance Criteria as work is verified
  • Appends rationale to Decisions log when making non-obvious choices
  • Escalates ambiguities to Open questions rather than guessing
  • Cannot remove or weaken existing criteria β€” the contract is append-only

/respec β€” re-evaluate the spec

When you add a new directive to an active task that meaningfully changes scope, the spec needs to be updated to reflect it. Type /respec before your prompt:

departai (dev) [task-id]> /respec
  βœ“ Spec re-evaluation queued
    Next prompt (or /continue) will run the spec pre-turns first.

departai (dev) [task-id]> tambiΓ©n aΓ±ade login con OAuth
  β†’ Spec Pre-turn 1/2 (Alpha)   ← integrates the directive into the spec
  β†’ Spec Pre-turn 2/2 (Beta)    ← reviews and extends if needed
  β†’ Turn N (relay normal con spec actualizado)

/respec is one-shot β€” it consumes itself after the next prompt or /continue. It applies append-only rules: agents add criteria for the new directive but cannot remove existing ones. If a directive contradicts an existing criterion, the conflict goes to Open questions for the relay to resolve.

If you forget /respec and just type the directive, the relay still incorporates it (agents read User Directives in the task log), but the spec criteria stay as they were β€” agents may or may not extend them. /respec makes the spec update explicit and verifiable.

Spec-aware completion

The relay stops only when ALL of:

  1. The last two consecutive turns both report **Complete**: yes
  2. The spec Status is ACTIVE (not DRAFT)
  3. Every Acceptance Criterion is checked - [x]

If agents declare Complete: yes while criteria are unchecked, the orchestrator overrides them and continues the relay with a warning. The spec is the source of truth.

Security β€” restricting commands

Agents run with full permissions and can use any tool the backend exposes (filesystem, shell, web, MCPs, etc.). For sensitive projects you can configure a blocklist of commands or tools that agents must NOT use.

# .departai/config.yml
blocked_commands:
  - WebFetch              # block a whole tool
  - WebSearch
  - "rm -rf"              # block a shell pattern
  - "git push --force"

Or from the REPL:

departai> /config set blocked-commands "WebFetch,rm -rf,git push --force"
  βœ“ blocked-commands set to 3 commands

When the blocklist is non-empty, departai injects a "Forbidden Commands" section into every turn's prompt instructing agents to refuse and stop if the task seems to require any of them. The second agent's review pass catches violations in the first agent's work.

This is soft enforcement. The agent reads the instruction and is expected to comply. It is not a sandbox or syscall-level restriction. For hard isolation, run departai inside a container or use the host OS's permission system.

Global + project blocklists are union-merged: a project cannot un-block what's blocked globally. The merged list shows up in the banner as Blocked : N command(s) and in /config output.

Reliability Features

Long-running autonomous relays can fail in subtle ways: an agent stalls, two agents disagree forever, a task quietly drifts off-scope, the prompt grows linearly forever as the log accumulates. departai includes opt-in safeguards for each.

Per-turn time budget

Set max_turn_duration (or --max-turn-duration) and the orchestrator forcibly cancels a turn that exceeds the budget:

max_turn_duration: 15m

When set, the prompt for every turn includes a Time budget section telling the agent how long it has, instructing it to checkpoint progress to the task log every 3-5 substantial actions, and to stop gathering context at ~80% of the budget so it can write its turn summary.

If the deadline fires anyway, the orchestrator:

  • Kills the agent process via context cancellation
  • Appends a synthetic turn entry to the task log marking the timeout
  • Continues the relay with the next agent (whose budget is fresh)

The next agent reads the timeout note plus whatever the killed agent had time to write, and picks up from there. Time pressure alone is never a reason for an agent to escalate to the human β€” it just means the next agent gets a fresh budget.

Blocked on β€” escalating to the human

Agents can pause the relay when they hit a decision the human must make. They add an optional field to their turn summary:

**Complete**: no
**Blocked on**: The OAuth flow needs to know whether to use PKCE or implicit
flow. Acceptance criterion is ambiguous β€” need human decision.

The orchestrator detects the field and surfaces the question:

🚧 Agent Beta is blocked
   The OAuth flow needs to know whether to use PKCE or implicit flow.
   Acceptance criterion is ambiguous β€” need human decision.

Type a directive to unblock, or /continue to tell agents to decide themselves.

Three responses:

  • Type a prompt β€” appended as a User Directive that resolves the question, relay continues
  • /continue β€” relay continues without new info; the next agent sees the previous block and the protocol's anti-loop rule says "if the human did not respond, decide yourselves"
  • /new β€” abandon

The protocol explicitly forbids using Blocked on for time pressure or technical workarounds. Reserved for genuine human-intent decisions.

Scope warnings

The spec's Files in scope section names the files agents should be touching. If a turn modifies files outside that list β€” and doesn't add them to scope with a Decisions log entry β€” the next agent's prompt receives a warning:

## Scope warning

The previous turn (Turn 4, Agent Beta) modified files NOT listed in `Files in scope`:
- /unrelated/config.go

Either:
- Justify the change in **Decisions log** AND add the file to `Files in scope`, or
- Revert the off-scope change.

Soft enforcement (no syscall blocking), consistent with blocked_commands. The next agent reviews the off-scope change and either legitimises it (adds to scope + justification) or reverts.

Limitation: file-modification tracking relies on Claude's per-tool stream events (Edit, Write, MultiEdit, NotebookEdit). Codex only exposes Bash with the raw command β€” modifications inside bash (cat >, sed -i, etc.) are not captured. Detection works when at least one agent is Claude; degrades to no-op when both are Codex.

Oscillation detection

Two agents can disagree forever β€” Alpha fixes X, Beta breaks X, Alpha fixes again, ad infinitum. The orchestrator watches for this pattern: if the last 4 turns all touch β‰₯50% the same files (Jaccard overlap) AND no new Acceptance Criteria have been checked, it injects a warning:

## Possible oscillation detected

The last 4 turns have all touched mostly the same files (foo.go, bar.go) without
any new Acceptance Criteria being checked off.

Step back and identify the root cause:
- Are you and the previous agent disagreeing on the same point?
- Is there a misunderstanding of the spec?
- Is the criterion underspecified?

Take ONE decisive action this turn β€” or, if there's genuine disagreement that
needs human input, set **Blocked on** with the specifics.

If no progress within the next couple of turns, the orchestrator will stop the
relay and return control to the human.

If the pattern persists for 2 more turns (6 total), the orchestrator stops the relay and surfaces the situation:

πŸŒ€ Oscillation detected β€” relay stopped
   Last 6 turns kept touching: foo.go, bar.go
   Without new Acceptance Criteria being checked.

Type a directive to break the loop, or /continue to retry one more cycle.

/continue resets the detection β€” the relay gets a fresh K-turn window to escape. If it loops again, stops again. The same Codex limitation applies: oscillation detection works when at least one agent is Claude.

Log windowing

For very long tasks the task log can grow to hundreds of turns. Injecting the entire log into every prompt is expensive and pushes recent context away from the agent's focus. Set log_window (or --log-window) to inject only the last N turns:

log_window: 6

What's preserved regardless of windowing:

  • The task header and ## Original Task
  • All ## User Directive blocks (directives may add requirements)
  • The last N ## Turn entries
  • An omission marker (> _Turns 1–14 omitted to keep context bounded β€” full history in task-log.md._) just before the kept turns

The full log on disk is never trimmed β€” the windowing only affects what's injected into each agent's prompt. The spec acts as the long-term anchor: Decisions log, Open questions, and checked criteria preserve the durable state.

Default is 0 (no windowing) for backward compatibility. Enable on long-running projects.

Transient-error retry

Backend CLIs occasionally fail transiently β€” rate limits (429/529), 5xx, or network blips. Instead of aborting the whole relay on a momentary hiccup, departai retries the turn with exponential backoff + jitter:

max_retries: 2   # default; 0 disables

The failure is classified from the exit error + stderr. Transient errors (rate limit, overloaded, 5xx, timeouts, connection reset) are retried; permanent ones (invalid model, auth failure, missing CLI, cancelled by ESC/timeout) abort immediately β€” retrying them wouldn't help. On exhausting the retries, the turn fails as before. Configurable via max_retries, --max-retries, or /config set max-retries.

Context-window awareness

On long tasks the prompt (instructions + spec + task log) grows turn by turn and can approach the model's context window. Before each turn, departai estimates the prompt size and, once per run, warns when it crosses ~80% of the window β€” suggesting log_window to bound growth:

⚠  Agent Alpha's prompt is ~175k tokens β€” 87% of the ~200k context window
   Bound prompt growth by windowing the task log: /config set log-window 6

The estimate is a backend-agnostic heuristic (it doesn't need a tokenizer); the spec preserves long-term state, so older turns can be safely elided.

Large outputs: a single backend stream line is capped at 16 MB by default (raise with DEPARTAI_MAX_STREAM_LINE_MB). On overflow, departai surfaces a clear error rather than silently truncating the turn.

Agent Protocol

Agents follow a built-in protocol (overridable with --instructions):

  • Anchor on the spec β€” the spec.md is the definition of done. Mark [x] on Acceptance Criteria as work is verified. Append to Decisions log for non-obvious choices. Move ambiguities to Open questions. Append-only β€” never weaken or remove existing criteria.
  • Review first β€” each agent critically reviews the previous agent's work before doing anything else. Look for bugs, missing edge cases, regressions.
  • Fix, don't note β€” if something is wrong, fix it. Don't just write "there's a bug".
  • Run tests β€” execute existing tests, write new ones if the project has a test framework.
  • Incremental work β€” focus on one aspect per turn for large tasks. Leave clear handoff notes.
  • Complete: yes requires (1) zero changes AND (2) all spec criteria checked β€” an agent can only mark "Complete: yes" if it reviewed the other agent's work, found no issues, made no code changes itself, AND every Acceptance Criterion is - [x]. This forces a real verification cycle anchored to the spec.
  • Treat orchestrator warnings as priority β€” when the prompt includes a ## Scope warning or ## Possible oscillation detected section, address it FIRST before continuing the work.
  • Escalate to the human only for genuine intent decisions β€” set **Blocked on**: <reason> in the turn summary only when a decision genuinely affects the human's intent and the spec doesn't unambiguously cover it. Time pressure or technical workarounds are NOT valid reasons.

Turn summary format

Each turn, agents append a structured block to the task log:

## Turn 3 - Agent Alpha

**Working Directory**: /path/to/project

**Review of previous turn**: Checked Beta's OG image fix β€” badge text is correct,
image regenerated successfully, grep confirms no stray registration references.

**What I did**: Reviewed all modified files. No changes needed.

**Tests**: Ran `pnpm build` β€” completed successfully.

**Current State**: Registration fully disabled across all surfaces.

**Remaining Issues**: None

**Next Steps**: None β€” task is complete.

**Complete**: yes

**Blocked on**: <OPTIONAL β€” only set when escalating to the human; see Reliability Features above>

---

The **Working Directory** field must be the project root (where source code lives), not the task directory itself. If an agent reports a different path than what the orchestrator started with, the task directory is moved to match β€” this lets agents discover that the actual project lives somewhere else and signal it back.

Completion consensus

The orchestrator stops when ALL of:

  1. The last two consecutive turns both report Complete: yes
  2. The spec Status is ACTIVE (not DRAFT)
  3. Every Acceptance Criterion in the spec is checked - [x]

Since an agent can only say "yes" without making changes, this guarantees a review cycle: implement β†’ review/fix β†’ verify β†’ confirm. The spec criteria requirement adds a second anchor: agents cannot prematurely declare done if the spec still has open work.

Shared Context System

Task directory

<workdir>/
└── .departai/
    β”œβ”€β”€ config.yml                              ← project-level config
    └── tasks/
        └── 20260418-build-rest-api/
            β”œβ”€β”€ task-log.md                     ← structured handoff log
            β”œβ”€β”€ spec.md                         ← definition of done (Goal, Criteria, Files in scope, ...)
            β”œβ”€β”€ spec-preturn-1-agent-alpha-raw.log  ← spec pre-turn raw activity
            β”œβ”€β”€ spec-preturn-2-agent-beta-raw.log
            β”œβ”€β”€ turn-1-agent-alpha-raw.log      ← per-turn activity + output (no internal prompts)
            β”œβ”€β”€ turn-1-agent-alpha-files.txt    ← per-turn files modified (for scope/oscillation detection)
            β”œβ”€β”€ turn-2-agent-beta-raw.log
            └── turn-2-agent-beta-files.txt

Git recommendations

Add the task logs to your project's .gitignore β€” they contain verbose agent output and are only useful locally:

# departai task logs (local agent output)
.departai/tasks/

However, keep .departai/config.yml tracked if you work in a team. This way all developers share the same departai settings (models, max turns, instructions file) when collaborating on the project:

# departai β€” ignore task logs, keep config
.departai/tasks/
!.departai/config.yml

Raw turn logs

Each turn generates a log file with:

  • Activity β€” tool calls the agent made (Read, Edit, Bash, etc.)
  • Output β€” the agent's final result text
  • Stderr β€” error output (if any)

Internal prompting (base instructions, protocol) is NOT included β€” raw logs show only task-relevant information.

Working directory auto-detection

If an agent discovers the project is in a different directory than --dir, it reports the real path in its Working Directory field. The orchestrator detects the mismatch, moves the task directory to the correct project, and continues from there.

Project rules

The orchestrator automatically reads and injects any project convention files it finds:

  • CLAUDE.md
  • AGENTS.md
  • .cursorrules
  • .github/copilot-instructions.md

Architecture

departai/
β”œβ”€β”€ main.go
β”œβ”€β”€ .gitignore
β”œβ”€β”€ go.mod / go.sum
└── internal/
    β”œβ”€β”€ cli/
    β”‚   β”œβ”€β”€ cli.go              # flag parsing, config layering, --version, backend availability check
    β”‚   β”œβ”€β”€ interactive.go      # REPL loop, slash commands, task state, history persistence
    β”‚   β”œβ”€β”€ repl_model.go       # custom bubbletea REPL (textarea + popover autocomplete)
    β”‚   └── onboarding.go       # first-run detection + starter-config seeding
    β”œβ”€β”€ version/
    β”‚   └── version.go          # build/version info (ldflags + runtime/debug fallback)
    β”œβ”€β”€ config/
    β”‚   └── config.go           # YAML config: load, save, layered merge, per-agent models, retries
    β”œβ”€β”€ tui/
    β”‚   β”œβ”€β”€ agentview.go        # bubbletea model: streaming + review + auto-continue
    β”‚   └── style.go            # lipgloss styles
    β”œβ”€β”€ ui/
    β”‚   └── ui.go               # styled terminal output, spinners, colors
    β”œβ”€β”€ agent/
    β”‚   β”œβ”€β”€ agent.go            # Agent, StreamingAgent, StreamEvent interfaces
    β”‚   β”œβ”€β”€ claude/
    β”‚   β”‚   β”œβ”€β”€ claude.go       # Claude Code CLI implementation + model validation
    β”‚   β”‚   β”œβ”€β”€ stream.go       # stream-json parser (stateful Parser for partial-message
    β”‚   β”‚   β”‚                   # deltas + stateless ParseStreamLine fallback for legacy)
    β”‚   β”‚   └── stream_test.go  # parser tests (legacy + partial-message paths)
    β”‚   └── codex/
    β”‚       β”œβ”€β”€ codex.go        # Codex CLI implementation + model validation
    β”‚       β”œβ”€β”€ stream.go       # Codex JSONL parser
    β”‚       └── *_test.go       # parser + ValidateModel tests
    β”œβ”€β”€ orchestrator/
    β”‚   └── orchestrator.go     # turn loop, spec pre-turns, prompt builder, consensus, ESC-to-stop,
    β”‚                           # ErrAgentBlocked / ErrTurnTimeout / ErrOscillationDetected,
    β”‚                           # scope + oscillation detection, transient-error retry,
    β”‚                           # context-window awareness
    └── tasklog/
        β”œβ”€β”€ tasklog.go          # task directory, log read/write/parse, load (+corrupt-log recovery),
        β”‚                       # spec.md primitives, windowed content, touched-files sidecars,
        β”‚                       # synthetic timeout entries
        └── *_test.go           # parsing, spec, windowing, scope, relocate-safety, recovery tests

Key dependencies

Package Purpose
charmbracelet/bubbletea TUI for the streaming agent view and the custom REPL
charmbracelet/bubbles textarea (REPL input) + viewport (scrollable content)
charmbracelet/lipgloss TUI styling
knz/bubbline/history Persistent REPL command history (~/.departai/history.txt)
fatih/color ANSI colors for non-TUI output
briandowns/spinner Spinner for model validation
manifoldco/promptui Arrow-key menus (save scope, task resume, onboarding)
gopkg.in/yaml.v3 Config file parsing

The REPL is built directly on bubbles/textarea (custom multi-line input + inline command popover); only the history package from knz/bubbline is used, for persistent history.

Adding a new agent backend

Implement the agent.Agent interface:

type Agent interface {
    Name() string
    RunTurn(ctx context.Context, workDir string, prompt string) (TurnResult, error)
}

Then add a case to buildAgents() in orchestrator.go and select it with --backend <name> or agent_backend: <name> in config.

Supported backends

Backend CLI Auto-approve flag Output format
claude claude -p <prompt> --dangerously-skip-permissions --output-format stream-json --include-partial-messages
codex codex exec <prompt> --dangerously-bypass-approvals-and-sandbox --json (JSONL)

Both backends implement the agent.StreamingAgent interface, providing live tool-call streaming via the bubbletea TUI. Model validation is backend-specific β€” each backend's ValidateModel function runs a minimal test prompt to verify the model name is accepted.

The Claude backend uses --include-partial-messages to receive token-level deltas (stream_event lines with content_block_start / content_block_delta / content_block_stop sub-events). The parser is stateful: it accumulates deltas per content block and emits agent.StreamEvents carrying a BlockID so the TUI can update the same entry in place as text grows. This eliminates the "silent gap" the TUI used to show when the LLM generated a single large block (e.g. a Write of an 80 KB spec). The Codex backend continues to emit whole-block events; if a future Codex release adds a partial-stream mode, the same pattern can be applied.

Contributing

Contributions are welcome β€” issues, ideas, and pull requests. See ROADMAP.md for where the project is headed and what's up next.

Before submitting a PR, make sure the basics pass:

gofmt -l .        # should print nothing
go vet ./...
go test ./...     # backend-CLI tests auto-skip when claude/codex aren't installed

A full CONTRIBUTING.md (how to add a backend, coding conventions) is on the way.

License

DepartAI is free and open-source software, released under the MIT License.

About

Control two agents working together (in a head-to-head format) to complete advanced user tasks.

Topics

Resources

Code of conduct

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages