A small, honest operating system for swarms of AI agents.

Enjambre is Spanish for swarm. It takes the agents you already have (Claude Code, Codex, a local model behind Ollama, a hosted API, your own scripts) and gives them what a team of processes needs to work together without lying to each other: a kernel, a queue, leases, a permission gate, a router and a shared memory you can see.

pip install . # from a clone; one dependency (PyYAML)

enjambre demo # open http://127.0.0.1:8765Runs on Linux, macOS and Windows with Python 3.10 or newer; every change is tested on all three.

The demo needs no model and no API key. Four scripted agents run a small editorial pipeline: research, draft, review, publish. The critic stumbles once so you can watch a retry. The writer tries to publish without permission and the gate stops it before it runs. The router explains every choice it makes.

Single agents are easy now. Swarms fail in boring, expensive ways:

- A worker dies holding the GPU, and nobody notices for ten hours.

- A task is reported as done, and the file it promised does not exist.

- A nightly job looks offline two thirds of the time because it only runs every 30 minutes.

- A rule written in the prompt is ignored the one time it matters.

- A failed step leaves everything downstream waiting forever.

enjambre was extracted from a real swarm that runs day and night on a solar-powered workstation and a small cloud server. Every mechanism below exists because one of those failures happened.

my-swarm/

├── swarm.yaml agents, router, scheduler, kernel, memory

├── policy.yaml rules and permissions (hot-reloaded)

├── prompts/<id>.md the role of each agent

└── memory/ markdown notes, shown as the memory graph

enjambre init my-swarm # start from the demo template

enjambre up my-swarm # API + dashboard + schedulerPut the folder in git and every change to your swarm has an author, a date and a revert.

agents:

coder:

adapter: cli

energy: solar # this machine runs on panels: prefer it while the sun is up

options:

command: ["claude", "-p"]

env: [ANTHROPIC_API_KEY] # the only variables the child process can see

reviewer:

adapter: cli

options:

command: ["codex", "exec", "{prompt}"]

stdin: false # the prompt goes in as an argument (never through a shell)

env: [OPENAI_API_KEY]

local:

adapter: openai

options:

base_url: http://localhost:11434/v1

model: qwen3:8b

researcher:

adapter: openai

cost: 0.5

options:

base_url: https://openrouter.ai/api/v1

model: deepseek/deepseek-chat

api_key_env: OPENROUTER_API_KEY # the name of the variable, never the key

router:

weights: {success: 35, latency: 15, cost: 20, energy: 30}

solar_window: {start: "09:30", end: "17:30", timezone: Europe/Madrid}On Windows, CLIs installed with npm are .cmd launchers. enjambre finds them, but only

passes them the prompt through stdin (stdin: true, the default): cmd.exe would re-parse a

prompt given as an argument.

Agents answer with a small JSON contract (status, result, artifacts...). The scheduler

appends it to every prompt, together with the agent's role, the policy and the results of

upstream tasks.

# policy.yaml

rules:

- id: verify

rule: Never report work as done without a check that passed.

operations:

publish: [editor] # only the editor may run tasks with operation: publish

agents:

writer:

forbidden: [Publishing anything yourself.]

vetoed_operations: [publish]# Claude Code

claude mcp add enjambre -- enjambre mcp --dir ./my-swarm

# a remote swarm started with `ENJAMBRE_TOKEN=... enjambre up --host 0.0.0.0`

claude mcp add enjambre -e ENJAMBRE_TOKEN=... -- enjambre mcp --url http://swarm-host:8765# Codex (~/.codex/config.toml)

[mcp_servers.enjambre]

command = "enjambre"

args = ["mcp", "--dir", "/path/to/my-swarm"]Tools: swarm_status, heartbeat, acquire_resource, release_resource, enqueue_task,

claim_task, renew_task, complete_task, get_task, list_tasks, cancel_task,

retry_task, policy_for, check_permission, memory_query, memory_node.

from enjambre import AgentResult, Kernel

k = Kernel("swarm.db")

research = k.enqueue("Collect benchmark numbers", agent="scout")["id"]

chart = k.enqueue("Draw the chart", depends_on=[research], proof="/tmp/chart.png")["id"]

task = k.claim("scout") # atomic

k.complete(task["id"], "scout", AgentResult.completed("numbers collected"))

k.claim("plotter")["id"] == chart # unblockedenjambre demo | init DIR | up [DIR] | run [DIR] | mcp

enjambre enqueue "Title" --agent writer --after TASK_ID --proof /abs/path

enjambre tasks | ps | memory "query"

enjambre run processes the queue until it is idle and exits, which makes a swarm usable

from CI.

enjambre is not an agent framework and not a prompt library. Frameworks such as LangGraph or CrewAI compose model calls inside one program. enjambre sits one level below: it coordinates separate agents and processes, on one machine or several, that already know how to do their job. You can run agents built with any framework inside it.

- Honest state. Liveness is derived, fitness is measured, and a missing measurement is

None, never a decorative zero.

- Leases everywhere. Locks, running tasks and resources all expire. Recovery is the default, not a cleanup script.

- Verification is recorded before it is enforced. A verification gate that blocked closing

tasks once cut a swarm's throughput by 90%. Start with proof_mode: record, switch toenforcewhen your agents declare their artifacts.

- Data is not instructions. Upstream results are labelled as data in every prompt.

- Small on purpose. Standard library plus PyYAML. One SQLite file. No build step for the UI.

Details in docs/architecture.md.

The API binds to 127.0.0.1 by default and refuses other addresses without ENJAMBRE_TOKEN.

CLI agents run without a shell and see only the environment variables you list. API keys are

read from environment variables and rejected if written into swarm.yaml. See

SECURITY.md.

- Evolution loop: the swarm proposes changes to its own genome from measured fitness, a human approves, and a regression triggers an automatic revert.

- Versioned memory segments with atomic writes and rollback per agent.

- Rate-limit buckets per provider, OpenTelemetry export, a Postgres backend for larger swarms.

MIT. Made by GreenAI Network. Bundled third-party code is listed in THIRD_PARTY_NOTICES.md.