hence · multi-agent plan coordination

A plan your agents can reason about.

A task is ready IF its dependencies are done AND no blocker has appeared. Traditional task systems can't express that. Hence plans are defeasible logic programs — readiness is derived, blockers defeat it, and agents claim tasks as the plan re-reasons. Twenty-one LLM providers. Isolated worktrees. Merged results.

SPL plans · defeasible readiness rules · kanban view Claude · Codex · Gemini · Cursor · 21+ providers Local or hence.run · NDJSON events · lifecycle hooks

Multi-agent orchestration is task management that lies to itself about dependencies.

The moment you have more than one LLM agent, you need readiness logic: "task X is ready if A is done, B is reviewed, and no blocker C exists." Task managers model the first condition. Workflow engines bolt the rest on top as code. Neither gives you a plan you can query.

What you have today

A Kanban board where readiness is a human's judgement and "blocked" is a sticker, not a derivation.

A DAG workflow engine (Airflow, Temporal) that encodes dependencies but can't defeat a task because a blocker rule just fired.

A shell script that launches agents in parallel and hopes they don't step on each other's uncommitted work.

What hence gives you

A plan in SPL (Spindle Lisp) — tasks, dependencies, readiness rules, and defeaters that block tasks when conditions warrant it.

Spawn with isolation — each agent gets its own git worktree. Hence merges results back and re-reasons about what's next.

Query the planhence query explain task-X tells you exactly why a task is ready, or why-not if it isn't.

From a plan file to agents running in isolated worktrees.

A small plan: build a CRUD API. Two agents (coder, reviewer). Click through.

01
Write the plan
Tasks, deps, readiness rules, defeaters — in SPL.
02
Ask what's next
Hence derives the ready set defeasibly.
03
Spawn an agent
Isolated worktree, picked LLM, streaming events.
04
Kanban view
Backlog / ready / in-flight / done / blocked.
05
Explain the plan
Why is this task ready? Why is that one not?
hence · crud-api.spl
; crud-api.spl

(task schema    :desc "define models")
(task crud      :desc "build handlers"   :deps (schema))
(task review    :desc "code review"      :deps (crud))
(task deploy    :desc "ship it"          :deps (review))

; readiness rules (defeasible)
(defeasible r-ready (done ?x) => (releases ?x))

; defeater: don't deploy if incidents are open
(defeater r-freeze
   (open-incident ?i) => (not (ready deploy)))
$ hence task next plan.spl

ready:
   · schema     no deps, no defeaters

waiting:
   · crud      (needs: schema)
   · review    (needs: crud)
   · deploy    (needs: review)

# Ready set is *derived*, not hand-maintained.
# Adding a blocker changes it without editing the tasks.
$ hence task assign plan.spl schema --agent claude
assigned schema → claude

$ hence agent spawn plan.spl --agent claude
spawning claude in worktree .hence/wt-schema
[14:22:01] claude  tool=read       spec/models.md
[14:22:04] claude  tool=edit       src/models.rs
[14:22:11] claude  tool=bash       cargo check         
[14:22:18] claude  claim-complete  schema

merging wt-schema → main  ✓ 4 files, 0 conflicts

# Each agent isolated; hence merges and re-reasons.
$ hence plan board plan.spl

  backlog     │  ready      │  in-flight │  done        │  blocked
  ────────────┼─────────────┼────────────┼──────────────┼──────────
              │  crud        │            │  schemadeploy      │             │            │              │
  review      │             │            │              │

$ # trigger a blocker
$ hence task block plan.spl deploy --reason "open incident"

$ hence plan board plan.spl
  backlog     │  ready      │  in-flight │  done        │  blocked
  ────────────┼─────────────┼────────────┼──────────────┼──────────
              │  crud        │            │  schemadeploy
  review      │             │            │              │
$ hence query explain ready-crud plan.spl

goal: (ready crud)             [+d]

└─ rule r-ready            crud-api.spl:9
   ├─ (done schema)         [+d]  claim · wt-schema
   └─ no defeater fires     [+d]

$ hence query why-not ready-deploy plan.spl

goal: (ready deploy)           [-d]

blocked by:
   r-freeze fires on (open-incident i-92)
   would succeed if: (open-incident i-92) retracted

Three capabilities no multi-agent runner combines.

01 · Reasoned plans

Readiness you can derive.

Plans are Spindle Lisp (SPL) programs, not YAML. Defeasible logic means "normally ready, unless blocker" is a first-class construct. Query the plan and get a derivation.

  • SPL: tasks, deps, rules, defeaters
  • Ready set derived, not maintained
  • Query: explain, why-not, require
  • Blockers defeat readiness cleanly
  • Plan is a text file you can diff
02 · Isolated agents

Worktrees, merged results.

Each agent claims a task and spawns in its own git worktree. When it's done, hence merges the result back and re-reasons. No more shell scripts that lose work when two agents edit the same file.

  • git worktree per task
  • Automatic merge with conflict detection
  • Lifecycle hooks (pre-spawn, post-merge)
  • Claim / complete / release semantics
  • NDJSON event stream for every step
03 · BYO model

Twenty-one providers, one interface.

Claude, Codex, Qwen, Gemini, Cursor, local Ollama, and fifteen more. Pick per task: use Claude for tricky code review, a fast local model for boilerplate. No vendor lock-in.

  • 21+ LLM provider adapters
  • Per-task model selection
  • Local files or hence.run for multi-machine
  • Kanban, stream, and TUI views
  • AGPL-3.0

A plan. A reasoner. A pool of agents with their own worktrees.

The plan is an SPL file. The reasoner is Spindle — the same defeasible engine that proves goals in theories. Tasks are goals; readiness is a conclusion; blockers are defeaters. Agents are the executors.

┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ plan.spl │ │ hence runtime │ │ agent pool │ │ │ │ │ │ │ │ tasks │─────►│ spindle reason │─────►│ claude │ │ deps │ │ derive ready │ │ codex │ │ rules │ │ emit next │ │ gemini │ │ defeaters │ │ spawn worktree │ │ ollama / local │ └──────────────────┘ │ stream events │ │ 21+ providers │ │ merge results │ └──────────────────┘ └──────────────────┘ │ ▲ │ │ claim / complete │ └───────────────────────────┘ ┌───────────────────────────────────┐ │ local · hence.run multi-machine │ │ NDJSON · kanban · TUI │ └───────────────────────────────────┘

Re-reasons after every step

Task completes → hence re-derives readiness. New blocker → defeats ready tasks. The plan stays coherent.

Plans are diffable

SPL is text. Review a plan in a PR. Write them by hand, or have an LLM generate one and check it in.

Worktrees keep work honest

No agent can corrupt another's context. Merge is explicit. Conflicts surface at the merge, not the spawn.

Kanban is a view, not a source of truth

The plan is the source. The board is derived. Drag nothing; the reasoner moves cards for you.

Events are NDJSON

Pipe to jq, to a log shipper, to your own UI. No proprietary bus; everything's a line of JSON.

Multi-machine when you want it

hence.run hosts plans across machines so teams of agents on separate boxes coordinate via one plan.

Frequently asked questions.

How is this different from Airflow / Temporal / Prefect?
Those engines model dependencies (DAG edges) and imperative control flow. They don't model defeat — "this task would be ready, but a policy says don't." Hence uses defeasible logic so blockers are declarative, auditable, and derivable. They're also not built for LLM agents in git worktrees.
How is this different from running agents in parallel with a shell script?
Shell scripts don't reason about readiness, don't merge results, and don't know when a blocker should defeat a task. Hence does all three, and gives you an NDJSON event stream, an explain query, and a kanban view for free.
Do I need Spindle to use hence?
Spindle is embedded — you don't install it separately. If you've never written defeasible logic, the task/deps syntax is familiar; rules and defeaters show up only when you want them.
Which LLM providers work?
21+ at last count: Claude Code, Codex, Gemini CLI, Cursor, Qwen, Ollama, and more. Adapters are small shims; adding a new one is under 100 lines.
Is hence.run required?
No. Everything works from a local plan file. hence.run is a hosted control plane for multi-machine coordination, event persistence, and shared plans across a team.
Where's the source?
Open source, AGPL-3.0. Binary releases for macOS (Apple Silicon) and Linux. Built in Rust.

Give your agents a plan that reasons as it runs.

Write the plan. Spawn the agents. Query the derivation. Isolated worktrees and merged results, from one text file.

install: cargo install hence-cli