Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

**One terminal. Every agent you have. Working at once.**

Claude Code, Codex, and OpenCode are remarkable at running one task deeply. Medulla is what runs a hundred of them. It decides what work to hand out, places each piece on a harness that can do it, streams back what every one of them is doing, and keeps a live picture of the whole operation in front of you.
Claude Code, Codex, and OpenCode are remarkable at running one task deeply. Medulla is what runs a hundred of them. It decides what work to hand out, places each piece on an agent that can do it, streams back what every one of them is doing, and keeps a live picture of the whole operation in front of you.

Fleets with everyone.

Expand Down Expand Up @@ -43,14 +43,14 @@ Prebuilt binaries ship for Linux (x86\_64, aarch64), macOS (Apple Silicon), and

**Repositories it understands.** Point Medulla at your projects once. It writes a short profile for each and uses it to route work to the right place, rather than guessing from a directory name.

**Plans that actually run.** A workflow is a saved, multi-step plan whose steps each run as a real harness session — with parallel branches, and approval gates where a human has to say yes. Ask for one in plain words and an agent will build it for you.
**Plans that actually run.** A workflow is a saved, multi-step plan whose steps each run as a real agent session — with parallel branches, and approval gates where a human has to say yes. Ask for one in plain words and an agent will build it for you.

**Small surface, low spend.** The bulk of your fleet's output never reaches the orchestrator's context. It reasons over a distilled, current picture, so what you pay orchestrator rates on stays small however much is running underneath.

## Documentation

**Routing › Harnesses** also manages named OpenRouter-backed presets that reuse
Claude Code or Codex as the coding harness. Presets select an OpenRouter model
**Routing › Harness Types** also manages named OpenRouter-backed presets that
reuse Claude Code or Codex as the coding CLI. Presets select an OpenRouter model
and fleet host while referring to `OPENROUTER_API_KEY` by environment-variable
name only; restart the local host after saving one. See
[`config.example.toml`](config.example.toml) for the complete shape.
Expand All @@ -60,7 +60,7 @@ Full documentation: **[tinyhumans.gitbook.io/medulla](https://tinyhumans.gitbook
* [Workers and Sessions](https://tinyhumans.gitbook.io/medulla/features/workers-and-sessions) — capacity, threads, and what survives.
* [Workflows](https://tinyhumans.gitbook.io/medulla/features/workflows) — authored multi-step plans and their runs.
* [MEDULLA.md Workspace Profiles](https://tinyhumans.gitbook.io/medulla/features/workspace-profiles) — telling the orchestrator what a repo is.
* [Orchestrator Routing](https://tinyhumans.gitbook.io/medulla/features/routing) — cognitive tiers, harness selection, strategies.
* [Orchestrator Routing](https://tinyhumans.gitbook.io/medulla/features/routing) — cognitive tiers, harness-type selection, strategies.
* [Token Efficiency and Budgets](https://tinyhumans.gitbook.io/medulla/features/token-efficiency) — small surfaces and enforced budgets.

Building on Medulla, or running it yourself? Everything technical — the TUI in depth, the CLI, worker daemons, configuration, architecture, and the SDK — is in **[Developers](https://tinyhumans.gitbook.io/medulla/developers)**.
Expand All @@ -73,7 +73,7 @@ Request access and tell us what you are orchestrating.

## Why an orchestrator

Ask a harness to coordinate other harnesses and you hit the same quiet failure mode everywhere: the orchestrator is just another model with a transcript, and every harness it manages writes into that transcript. Accuracy degrades well before the context window fills. An orchestrator that reads raw fleet traffic stops scaling at a handful of agents — long before it runs out of room, it stops being able to think.
Ask a coding agent to coordinate other coding agents and you hit the same quiet failure mode everywhere: the orchestrator is just another model with a transcript, and every agent it manages writes into that transcript. Accuracy degrades well before the context window fills. An orchestrator that reads raw fleet traffic stops scaling at a handful of agents — long before it runs out of room, it stops being able to think.

Orchestration is becoming the dominant pattern in agentic systems, yet it has been running on architectures designed for chat. A chat model manages one thread. An orchestrator has to hold an operation in its head: agents in flight, work being decomposed and delegated, results streaming back, decisions made continuously. Medulla is built for that.

Expand Down
103 changes: 69 additions & 34 deletions docs/TERMINOLOGY.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,48 +14,68 @@ system works on its behalf.

## Agent

A connected worker that executes **tasks**. Agents live inside a **workspace** on
a **host**, are surfaced through a **harness**, and are listed in `agent_list`.
Each agent has a set of **tools**, an MCP server inventory, and a health snapshot
A **declared** working identity on a **host**: a `harness` type × **workspace**
directory, written down in `[fleet].agentDeclarations` and carrying an `agentId`,
an optional name, `roles`, and a workspace `strategy`. Agents are declared, never
discovered — an agent exists because somebody wrote it down, not because a
process happens to be running. One host runs as many agents as you declare.

The orchestrator delegates **tasks** to agents and lists them in `agent_list`;
each agent has a set of **tools**, an MCP server inventory, and a health snapshot
(consecutive-ok / consecutive-failed). An agent is **idle** when it has no running
tasks and **busy** otherwise. The orchestrator delegates to agents; a manager
_manages_ them.
**sessions** and **busy** otherwise. A manager _manages_ agents.

## Harness

A runtime environment adapter — the layer that boots, supervises, and
communicates with a coding assistant CLI. Medulla supports several harness kinds:
**A type, not a thing.** `harness` is the attribute on an agent that says which
coding-assistant CLI its sessions run — `claude`, `codex`, `opencode`, or a
custom preset. It is a value in a dropdown; it is never an entity in the model,
never a level in the containment chain, and never a noun in the UI (the thing an
operator interacts with is an **agent** or one of its **sessions**).

| Harness | Transport |
| ----------- | ------------------------------------------------------- |
| Claude Code | ACP (Agent Client Protocol) over stdio, or legacy JSONL |
| Codex | ACP over stdio |
| OpenCode | ACP over stdio |
In code it also names the runtime adapter that boots, supervises, and talks to
that CLI:

A harness surfaces a **status** (idle / running / stopped), a **task board**
| Harness type | Transport |
| ------------ | ------------------------------------------------------- |
| Claude Code | ACP (Agent Client Protocol) over stdio, or legacy JSONL |
| Codex | ACP over stdio |
| OpenCode | ACP over stdio |

The adapter surfaces a **status** (idle / running / stopped), a **task board**
(tracked tasks with status open → active → blocked → done / cancelled), and an
**event stream** (instruction queued, cycle start/end, task-board changes). The
public wire shapes live in the `harness_contract` module and are versioned
independently of any implementation.

## Host

A machine in the fleeta physical or virtual environment that runs one or more
**harnesses**. A host is declared (not probed) and carries resource metadata
(CPU, memory). It is the top of the containment chain:
A machine, local or remotethe environment the agents declared on it run in. A
host is declared (not probed) and carries resource metadata (CPU, memory). It is
the top of the containment chain:

```text
Host → Agent → Session
```
Host → Harness → Workspace → Agent
```

The local host is always present; a remote host is added by tiny.place address
and contributes the agents declared over there. This tree is what both the Agents
tab and the Hosts tab render, and its union is what the hub advertises to the
backend — one projection, rendered twice.

*(The legacy `[fleet]` capacity snapshot still carries an older
`Host → Harness → Workspace → Agent` chain in its own types. That describes
declared capacity, not the entity model above.)*

## Workspace

A filesystem directory exposed by a **harness** on a **host**. A workspace is
where agents read, write, and run code. Each workspace can carry a `MEDULLA.md`
A filesystem directory an **agent** works in, declared as part of that agent
together with its `strategy`: `checkout` (every session of the agent shares the
directory, so they run serially — the v1 default) or `worktree` (a carved
per-session copy, so they run in parallel — a follow-up). A workspace is where
agents read, write, and run code. Each workspace can carry a `MEDULLA.md`
**profile** — a short frontmatter + prose summary that tells the orchestrator
what the directory _is_ and how to route work over it. Workspaces are registered
in the fleet configuration; without a registration entry the orchestrator cannot
place work there.
what the directory _is_ and how to route work over it.

## Hub

Expand All @@ -75,8 +95,23 @@ tool calls and agent delegation are internal to the cycle.

## Session

A conversation thread between the user and the orchestrator. Sessions come in
two orthogonal axes:
**An agent session** is one running instance of an **agent** — what a **task**
actually executes in, and the row under an agent on the Agents rail. It carries a
`sessionId`, its launch anchor and workspace context, and two facts that are
independent of each other:

- **`origin`** — `orchestrator` (auto-created by a dispatch, labelled from its
task) or `user` (opened from the UI and named by the operator). Origin never
changes.
- **`owner`** — who may drive it right now. Ownership moves: `ctrl-g` takes a
session from the orchestrator, handing it back returns it, and dispatch skips
any session the operator holds.

A task **is** an agent session; the two differ only by origin. Sessions are never
roster entries — only their control state rides the advert.

The word also names the transport-level conversation the SDK keys by
`(conversation × provider)`. Those come in two orthogonal axes:

- **Class:** `Bounded` (one turn — a single cycle) or `Unbound` (long-lived,
spanning multiple cycles).
Expand Down Expand Up @@ -131,7 +166,7 @@ orchestrator match tasks to agents by what they can reach, rather than guessing.
Placing a **manager** at a specific **host** + **workspace**. A deployment is
the concrete instantiation of the fleet's declared containment chain. The
orchestrator selects a host and workspace from the fleet registry, spawns the
manager there, and the manager then picks a harness and begins delegating. Once
manager there, and the manager then picks an agent and begins delegating. Once
placed, a deployment is fixed for the cycle — a manager cannot move to a
different host or workspace.

Expand All @@ -140,8 +175,8 @@ different host or workspace.
A saved, multi-step **directed graph** definition, usually acyclic but allowed to
contain bounded loops (see the `loop` node). Each step is a
node — triggers, agent dispatches, transforms, code execution, HTTP requests, and
more. An `agent` node runs as a real **harness** session (Claude Code, Codex, or
OpenCode). Workflows are authored as JSON files, stored in layered directories
more. An `agent` node runs as a real **agent session** on the harness type it
names (Claude Code, Codex, or OpenCode). Workflows are authored as JSON files, stored in layered directories
(personal + per-repository), run through the vendored `tinyflows` engine, and
surfaced in the TUI's Workflows tab with a canvas, run overlay, and copilot.

Expand Down Expand Up @@ -170,16 +205,16 @@ with `medulla init` and registered with `medulla workspace add`.

## Provider

A coding-assistant CLI that a **harness** wraps. The three supported providers
are `claude` (Claude Code), `codex` (OpenAI Codex), and `opencode`. A provider is
selected per-task; the daemon spawns the CLI as a subprocess and communicates
over ACP or legacy JSONL.
A coding-assistant CLI — the same axis as an agent's **harness** type, seen from
the process end. The three supported providers are `claude` (Claude Code),
`codex` (OpenAI Codex), and `opencode`. The daemon spawns the CLI as a subprocess
and communicates over ACP or legacy JSONL.

## Daemon

A long-running background process (`medulla daemon --headless`) that listens for
inbound **task frames** from the **hub**, spawns **providers** through
**harnesses**, and streams results back. One daemon = one **workspace**; a fleet
inbound **task frames** from the **hub**, spawns **providers** through their
harness adapters, and streams results back. One daemon = one **workspace**; a fleet
is N daemon processes, not one daemon with N directories.

## TUI
Expand Down
20 changes: 10 additions & 10 deletions docs/workflows.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Workflows

A Medulla task is one instruction handed to one harness. A **workflow** is a
A Medulla task is one instruction handed to one agent. A **workflow** is a
saved, multi-step plan: a directed graph whose `agent` steps each run as a real
coding-harness session — Claude Code, Codex, or OpenCode — in the order and with
the parallelism the graph declares. The graph is usually acyclic, but it may
contain a **bounded loop**: a `loop` node repeats a section until its
`max_iterations` cap or its `condition` says stop.
agent session — on Claude Code, Codex, or OpenCode — in the order and with the
parallelism the graph declares. The graph is usually acyclic, but it may contain
a **bounded loop**: a `loop` node repeats a section until its `max_iterations`
cap or its `condition` says stop.

The engine is [`tinyflows`](https://github.com/tinyhumansai/tinyflows), vendored
under `vendor/tinyflows` (see [vendoring.md](vendoring.md)). Medulla supplies the
Expand Down Expand Up @@ -160,7 +160,7 @@ is meaningless, or wrong, on another. Name both when you mean both.

A harness that is not one of the three built-in CLIs is taken as a custom
harness preset id — the ones this machine has configured are listed by
`workflow_host` and in the TUI's Routing → Harnesses screen. Whether the *worker*
`workflow_host` and in the TUI's Routing → Harness Types screen. Whether the *worker*
that runs the step exposes that preset is only answered when it runs.

`harness` must be written plainly, never as a `=`-expression. Which binary and
Expand Down Expand Up @@ -384,7 +384,7 @@ Workflows is a top-level tab: a sidebar, a canvas, and a copilot.
it never reached are dimmed, and the inspector shows the node's duration and
any diagnostics.
- **The copilot** (`c`) is a conversation that edits the graph. Ask for a change
in plain words; a real harness session makes it with the MCP tools below, and
in plain words; a real agent session makes it with the MCP tools below, and
the graph is then re-read from the store so the transcript reports what
actually changed rather than whatever the agent said it did.

Expand Down Expand Up @@ -423,7 +423,7 @@ compatible:
- A worker's capability probe now advertises `workflows` — the ids it has
installed, with names, descriptions, and step counts.
- A task frame may carry a `workflow` field. Naming one makes the worker run that
saved graph instead of handing the frame's `text` to a harness; the text
saved graph instead of handing the frame's `text` to an agent; the text
becomes the trigger payload. The ack, the reply, the correlation, and the
work-snapshot attachment are all the ordinary ones, so an orchestrator that
knows nothing about workflows still sees a task it dispatched and a task that
Expand Down Expand Up @@ -457,7 +457,7 @@ request that changes what this host holds.
Everything is served from the same layered store the Workflows tab, the
`medulla workflow` subcommand and the MCP tools read — a socket `get` and
`medulla workflow get` are one implementation, so they cannot drift. `copilot` is
not a read: it is a whole authoring turn on this machine's own harness, with the
not a read: it is a whole authoring turn on this machine's own agent, with the
`medulla-workflows` tools attached, and its result is derived from re-reading the
store afterwards rather than from what the model said it did.

Expand Down Expand Up @@ -486,7 +486,7 @@ Three properties are load-bearing rather than incidental:
A run reports itself in the *existing* `harness_work` vocabulary — a
`plan_update` naming every node, `todo_update` as steps settle, `subagent_start`
per agent node, and a `run_result`. So a workflow renders through the same pane
that shows a harness's own todo list, with no rendering code of its own.
that shows an agent's own todo list, with no rendering code of its own.

## Configuration

Expand Down
2 changes: 1 addition & 1 deletion src/sdk/src/hub/handoff/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};

/// Who holds a harness, as the orchestrator is told.
///
/// The SDK-side spelling of the TUI's `HarnessControl`. Deliberately a second
/// The SDK-side spelling of the TUI's `SessionControl`. Deliberately a second
/// type rather than `serde` on the first: that enum's contract is that it is
/// process-local and never serialized, and it is the single gate on dispatch.
/// Deriving `Serialize` onto it would quietly make it a wire type and put the
Expand Down
2 changes: 1 addition & 1 deletion src/sdk/src/sessions/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl fmt::Display for SessionClass {
/// # Origin is not ownership
///
/// This is deliberately **not** "who may drive it now". That is *control*
/// (`HarnessControl` in the app crate, `owner` in the spec), it moves at runtime,
/// (`SessionControl` in the app crate, `owner` in the spec), it moves at runtime,
/// and the two answer different questions:
///
/// | | Origin | Control / owner |
Expand Down
2 changes: 1 addition & 1 deletion src/sdk/src/ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ UI-facing data surface shared with the terminal app: `events` (the folded event
- [`agents/`](./agents/) — Pure view-model fold: turn the flat event stream into one lane per cognitive tier plus one lane per connected roster agent / anonymous task / peer session, with a row model for the Agents list and pre-wrapped transcript lines. A port of the TS `deriveAgentLanes` / `agentRowModel` / `laneLines` essentials.
- [`chat_store/`](./chat_store/) — On-disk chat persistence for the Chat tab's thread trees.
- [`command/`](./command/) — Slash-command parsing, the command catalog, and the `/copy` transcript helper.
- [`decisions/`](./decisions/) — Prepared operator decisions derived from harness escalations and pending worker questions. The fold is UI-agnostic so terminal and future hosts share stable ids, ordering, deduplication, and answer routing.
- [`decisions/`](./decisions/) — Prepared operator decisions derived from agent escalations and pending worker questions. The fold is UI-agnostic so terminal and future hosts share stable ids, ordering, deduplication, and answer routing.
- [`events/`](./events/) — The TUI event vocabulary: every library `CycleEvent` plus the host-sourced rows (cycle framing, conversation turns, agent/session status, effects). `TuiEvent` deserializes any JSON `{kind, ...}` shape, keeping unknown kinds as a passthrough so a newer backend never drops rows on an older TUI.
- [`fleet/`](./fleet/) — Pure view-model for the Fleet view: turn the declared capacity (`Host → Harness → Workspace → Agent`) and the agent-template catalog into a flattened row model plus pre-wrapped detail lines.
- [`harness/`](./harness/) — Read-only view-model helpers for the agent-harness contract: a compact task board rendering for a `HarnessStatus` payload, and a one-line budget note for an agent's `AgentBudgetMetadata` seat stamp. Pure formatting only — the `medulla-tui` crate turns the returned `Line`s / strings into ratatui spans.
Expand Down
Loading
Loading