Skip to main content

Multi-agent project orchestration system

Project description

Loom

Multi-agent project orchestration. Break a goal into a dependency graph of tasks, then let multiple AI agents work through them in parallel.

Postgres is the source of truth, Redis is the cache and event bus, a FastMCP server gives Claude Code (or any MCP client) full access to the task graph.

# Install from the repo (requires access)
pipx install git+ssh://git@github.com/MennoAf/agent_loom.git

loom init
loom up
# Open Claude Code — Loom tools auto-register via .mcp.json

How It Works

decompose → claim → work → done → unblock dependents

Loom decomposes large goals into a DAG of tasks, then lets agents (or humans) claim, execute, and complete them concurrently. An orchestrator monitors the system: sweeping expired claims, retrying failures, escalating blockers, and dispatching merges.

┌─────────────┐     ┌──────────┐     ┌───────────┐
│  Claude Code │────▶│ MCP Server│────▶│ Postgres  │
│  (agent)     │◀────│ (FastMCP) │◀────│ (tasks)   │
└─────────────┘     └──────────┘     └───────────┘
                         │
                    ┌────▼────┐
                    │  Redis   │
                    │ (cache + │
                    │  events) │
                    └─────────┘

Write path: MCP tool → Postgres (ACID) → Redis cache sync → event publish → dependency resolution.

Read path: MCP tool → Redis (fast) → Postgres fallback on cache miss.

Quick Start

# 1. Install (from the repo — requires access)
pipx install git+ssh://git@github.com/MennoAf/agent_loom.git

# Or install from a local clone:
#   git clone git@github.com:MennoAf/agent_loom.git && pipx install ./agent_loom

# 2. Initialize a project
cd my-project
loom init --name my-project

# 3. Start services
loom up

# 4. Verify everything works
loom doctor

# 5. Open Claude Code in the same directory
#    Loom MCP tools auto-register via .mcp.json

# 6. Decompose a goal into tasks (auto-scans your codebase)
loom decompose "Build a REST API with user authentication"

# 7. Check project status
loom status

API Key Setup

Loom needs an LLM API key for AI-powered skills (decompose, enrichment, escalation). Set it once — it applies to all projects.

Anthropic (default):

export ANTHROPIC_API_KEY="sk-ant-..."

OpenAI / OpenAI-compatible (Gemini, Ollama, vLLM, LiteLLM):

export LOOM_SKILLS_PROVIDER=openai
export OPENAI_API_KEY="sk-..."

# For local models or custom endpoints:
export LOOM_SKILLS_BASE_URL=http://localhost:11434/v1   # Ollama example

Or set it in ~/.loom/config.yaml for global config:

skills:
  provider: anthropic         # or "openai"
  api_key: "sk-ant-..."
  base_url: ""                # custom endpoint for OpenAI-compatible APIs

Priority order: LOOM_SKILLS_API_KEY > provider-specific env var (ANTHROPIC_API_KEY or OPENAI_API_KEY) > ~/.loom/config.yaml > project .loom/config.yaml.

Multi-LLM Provider Support

Loom supports any LLM accessible via the Anthropic or OpenAI API format:

Provider Config
Anthropic (default) ANTHROPIC_API_KEY — Claude models
OpenAI LOOM_SKILLS_PROVIDER=openai + OPENAI_API_KEY
Gemini LOOM_SKILLS_PROVIDER=openai + OPENAI_API_KEY + LOOM_SKILLS_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai/
Ollama LOOM_SKILLS_PROVIDER=openai + LOOM_SKILLS_BASE_URL=http://localhost:11434/v1
vLLM / LiteLLM LOOM_SKILLS_PROVIDER=openai + LOOM_SKILLS_BASE_URL=http://localhost:8000/v1

Install the OpenAI SDK when using non-Anthropic providers:

pipx inject loom-agents openai

Individual skills can override the global provider via YAML frontmatter:

# .loom/skills/my-skill.md
---
name: my-skill
provider: openai
model: gpt-4o
---

CLI Reference

Command Description
loom init [--name NAME] Scaffold a new project (config, docker-compose, .mcp.json, AGENTS.md)
loom up Start Postgres + Redis, run migrations, create project in DB
loom down Stop containers
loom doctor Check system health (Docker, Postgres, Redis, config, project)
loom status [TASK_ID] Project overview or single task detail
loom create TITLE [--suggest-deps] [--depends-on ID] Create a task (with optional dependency suggestions)
loom claim TASK_ID [--agent NAME] Claim a pending task
loom done TASK_ID [--output JSON] [--branch-name BR] Mark a claimed task as done
loom fail TASK_ID --reason TEXT Mark a task as failed
loom heartbeat TASK_ID [--progress TEXT] [--percent N] Extend claim TTL with optional progress
loom reset TASK_ID [--clear-output] Reset a stuck or failed task back to pending
loom idea TITLE [--context JSON] Capture an idea for the backlog
loom ideas [--drop ID] List all ideas, or drop one
loom decompose GOAL [options] Decompose a goal into a task graph using AI
loom graph [--format json|mermaid|summary] Show the dependency graph
loom scan [--execute] Process completion markers from .loom/completions/
loom recover [--execute] Classify and recover orphaned tasks (dry-run by default)
loom orchestrate [--once|--daemon] Run the orchestrator (single sweep or continuous)
loom dead-letter [--retry TASK_ID] List or retry permanently failed tasks
loom workflow list|run|resume|status Manage workflows
loom project list|create|switch|archive Manage projects
loom agent create|list|deactivate Manage agent auth (RBAC)
loom skill list|run List or run skills
loom config show|set View or update configuration
loom dashboard [--port PORT] Open the web dashboard
loom digest [--vault PATH] Write daily digest to Obsidian vault
loom deploy [--project GCP_ID] Deploy to GCP Cloud Run

Decompose

loom decompose turns a goal into a full task graph. It auto-scans your codebase by default to avoid generating tasks for code that already exists.

Flag Description
--from FILE Read goal from a file instead of the command line
-y, --yes Skip confirmation, write directly to DB
--depth N Max hierarchy depth (default: 3)
--no-enrich Skip context/criteria/complexity enrichment
--enrich-concurrency N Max parallel enrichment calls (default: 5)
--no-scan Disable automatic codebase scanning
--scan-root PATH Scan a specific directory (default: current directory)
--no-validate Skip codebase validation of generated tasks
--no-merge Skip merging of trivially small tasks
--min-complexity N Threshold for trivial-task merging (default: 2)
--optimize-parallel Run parallelism optimization pass
--epic-id ID Decompose an existing epic into subtasks
--force-leaf Convert childless epics to pending tasks

The decompose pipeline:

  1. LLM generates a hierarchical task graph from your goal
  2. Auto-fix paths — stale file references corrected against real file tree
  3. Codebase validation — marks tasks as pre-completed when code already exists
  4. Trivial merge — folds tiny tasks into parents
  5. File-affinity merge — groups tasks sharing files to prevent merge conflicts
  6. Enrichment — adds context, acceptance criteria, and complexity scores (parallel, ~2-3 min for 30 tasks)

Doctor

loom doctor runs 9 checks to verify your setup:

$ loom doctor
Loom Doctor

  ✓ Docker Desktop running
  ✓ Loom initialized (.loom/config.yaml)
  ✓ docker-compose.loom.yml exists
  ✓ Postgres connectable
  ✓ Redis connectable
  ✓ Migrations up to date
  ! API key not configured (optional — needed for decompose/skills)
  ✓ .mcp.json has loom entry
  ✓ Project exists in database

Some checks failed. See suggestions above.

Dependency Suggestions

When creating tasks, Loom can suggest related existing tasks as potential dependencies:

loom create "Add user authentication" --suggest-deps
# Created task loom-a1b2c3d4: Add user authentication
#
# Suggested dependencies:
#   loom-e5f6g7h8: Set up database models (score: 0.45 — title overlap: 0.40, file overlap: 0.50)
#   loom-i9j0k1l2: Create user API endpoints (score: 0.35 — title overlap: 0.30, file overlap: 0.40)
#
# Use --depends-on to add dependencies, e.g.:
#   loom create "Add user authentication" --depends-on loom-e5f6g7h8

Also available via MCP: loom_create(title="...", suggest_deps=True).

MCP Tools

Available to any MCP client when the Loom server is running:

Tool Description
loom_ready List tasks with no open blockers, sorted by priority
loom_claim Atomically claim a task (SELECT FOR UPDATE SKIP LOCKED)
loom_done Mark complete with output, trigger dependency resolution
loom_fail Mark failed, trigger retry or dead letter
loom_escalate Flag a task as blocked with escalation message
loom_create Create a task (with optional suggest_deps for dependency suggestions)
loom_status Task detail, filtered list, or project overview
loom_update Update task fields (title, context, priority, deps, status)
loom_message Send a message to another agent
loom_decompose Decompose a goal or epic into a task graph
loom_graph Full dependency graph (JSON, Mermaid, or summary)
loom_heartbeat Extend claim TTL with progress tracking
loom_reset Reset a stuck/failed task back to pending
loom_batch_done Mark multiple tasks done/dead-lettered at once
loom_batch_claim Atomically claim multiple tasks at once
loom_verify_paths Pre-flight check that file paths in tasks exist
loom_round_summary Post-round summary: run tests, snapshot status
loom_orchestrate Plan execution waves based on dependency graph and file overlap
loom_orchestrate_tick Run a single orchestrator sweep (expire claims, retry, escalate)
loom_workflow Run, resume, or check workflow status
loom_dead_letter List permanently failed tasks
loom_projects List all projects
loom_create_project Create a new project
loom_switch_project Switch active project
loom_archive_project Archive a project
loom_idea Capture an idea for the backlog
loom_issue File an issue (optionally targeting another project)
loom_issues List open issues for the current project
loom_recover Classify and recover orphaned tasks

Architecture

Data Model

Tasks form a directed acyclic graph (DAG) with dependencies:

  • ID: loom-{8 hex chars} (e.g., loom-a1b2c3d4)
  • Status: ideapendingclaimeddone | failed | blocked | epic
  • Priority: p0 (critical), p1 (high), p2 (normal)
  • Dependencies: task IDs that must complete first

Orchestrator

When running as a daemon (loom orchestrate --daemon), the orchestrator periodically:

  1. Sweeps expired claims — releases tasks held past their TTL
  2. Detects stale agents — flags claimed tasks with no recent heartbeat
  3. Retries failed tasks — exponential backoff with jitter, up to max_retries
  4. Handles escalations — runs debug_failure with per-task dedup guards and rate limiting
  5. Dispatches merges — detects merge tasks and runs them with a Redis distributed lock
  6. Checks completion — detects when all tasks are done

Merge Agent

When an agent calls loom_done with a branch_name, Loom creates a p0 merge task. The orchestrator acquires a Redis lock to serialize merges and dispatches the merge executor: merge branch → run tests → push → cleanup (or rollback on failure).

Resilience

If the orchestrator dies, work is not lost:

  1. Completion markersloom done / loom fail write JSON to .loom/completions/ as a filesystem fallback
  2. CLI self-report — subagents without MCP access report via CLI (loom done, loom fail, loom heartbeat)
  3. Recoveryloom recover classifies claimed tasks (marker → complete, stale → re-queue, expired → re-queue, active → leave)
loom recover              # dry-run
loom recover --execute    # apply recovery plan
loom scan --execute       # process filesystem markers only

Module Contracts

Module Responsibility
graph/store.py Only writer to Postgres for task data
graph/cache.py Only reader from Redis; falls back to store.py
bus/channels.py All Redis key patterns (no string literals elsewhere)
mcp/tools.py Thin coordinators (each tool ≤15 lines)
skills/providers.py LLM client abstraction (Anthropic + OpenAI protocol)
db/migrations/ Append-only — never modify existing files

Features

Idea Backlog

Ideas capture "what should we work on next?" without cluttering the active task graph:

loom idea "Add webhook support"
loom ideas                             # list backlog
loom ideas --drop loom-a1b2c3d4        # remove one
loom decompose --epic-id loom-a1b2c3d4 # promote → decompose

Skills

10 built-in AI skills (works with any configured provider):

Skill Purpose
decompose_project Break a goal into a hierarchical task graph
write_task_context Generate rich context for a task
define_done Create testable acceptance criteria
estimate_complexity Estimate task complexity and effort
debug_failure Diagnose failures and propose fixes
review_output Review output against acceptance criteria
generate_test_plan Generate a test plan for a task
write_spec Write a technical specification
identify_parallelism Find tasks that can run in parallel
summarize_graph Generate a project status narrative

Custom skills: add .md files to .loom/skills/ with YAML frontmatter. Skills can specify their own provider and model to use a different LLM than the global default.

Workflows

Multi-step pipelines chaining skills and actions:

Workflow Steps
ship_feature spec → decompose → confirm → write tasks
debug_and_fix diagnose → confirm → create fix tasks
audit_codebase decompose → find parallelism → confirm → write tasks → summarize
deploy_to_prod generate test plan → confirm → write deploy tasks

Custom workflows: add .yaml files to .loom/workflows/.

Multi-Project Support

Tasks are isolated per project — each has its own task graph, ready queue, and cache namespace.

loom project create "my-api" -d "REST API backend"
loom project list
loom project switch <PROJECT_ID>
loom project archive <PROJECT_ID>

Web Dashboard

Built-in HTMX + Jinja2 dashboard — no npm, no build step:

loom dashboard    # Opens http://localhost:8765/dashboard
  • Kanban task board with priority badges
  • Mermaid.js dependency graph with status-colored nodes
  • Project overview with progress bars
  • Real-time SSE updates
  • Dark mode (follows system preference)

Agent Auth & RBAC

Optional role-based access control (disabled by default):

export LOOM_AUTH_ENABLED=true
loom agent create my-worker --role worker   # prints API key
Role Access
readonly loom_ready, loom_status, loom_graph, loom_projects
worker + loom_claim, loom_done, loom_fail, loom_heartbeat, loom_message
lead + loom_create, loom_update, loom_escalate, loom_decompose, loom_workflow
admin all tools

Observability

Metrics: Prometheus-compatible at /metrics — tasks created/completed/failed, cache hits/misses, circuit breaker state, tool duration.

Tracing: Optional OpenTelemetry support:

pip install loom-agents[otel]
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317

Circuit breaker: Redis cache auto-falls back to Postgres after 5 consecutive failures, recovers after 30s.

Configuration

Three layers (later overrides earlier): ~/.loom/config.yaml.loom/config.yaml → environment variables.

Environment Variables

Variable Description Default
LOOM_SKILLS_PROVIDER LLM provider (anthropic or openai) anthropic
LOOM_SKILLS_BASE_URL Custom API endpoint (for Ollama, vLLM, etc.)
LOOM_SKILLS_API_KEY API key for LLM skills (falls back to provider-specific key)
LOOM_SKILLS_MODEL Model for AI skills claude-sonnet-4-6
LOOM_DATABASE_URL Postgres connection string postgresql://loom:loom_local@localhost:5432/loom
LOOM_REDIS_URL Redis connection string redis://localhost:6379
LOOM_MCP_PORT MCP server port 8765
LOOM_LOG_LEVEL Logging level INFO
LOOM_PROJECT_ID Project UUID (from config)
LOOM_ENRICHMENT_CONCURRENCY Max parallel enrichment tasks 5
LOOM_CLAIM_TTL Claim timeout in seconds 1800
LOOM_MAX_RETRIES Max retry attempts before dead letter 3
LOOM_ENABLE_ESCALATION Enable AI-generated fix tasks on failure true
LOOM_SLACK_WEBHOOK_URL Slack webhook for notifications
LOOM_OBSIDIAN_VAULT_PATH Obsidian vault for daily digests
LOOM_AUTH_ENABLED Enable agent RBAC false
LOOM_GCP_PROJECT GCP project (enables Secret Manager)

Example config.yaml

loom:
  project_name: my-project
  project_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

database:
  url: postgresql://loom:loom_local@localhost:5432/loom

redis:
  url: redis://localhost:6379

skills:
  provider: anthropic         # or "openai"
  api_key: ""                 # or use env var
  base_url: ""                # for OpenAI-compatible endpoints
  model: claude-sonnet-4-6
  max_tokens: 8192
  enrichment_concurrency: 5

orchestration:
  claim_ttl_seconds: 1800
  max_retries: 3
  enable_escalation: true

integrations:
  slack_webhook_url: ""
  obsidian_vault_path: ""

Deployment

Local (default)

loom init && loom up
# MCP server runs via Claude Code's .mcp.json auto-registration

Docker Compose (full stack)

docker compose -f docker-compose.loom.yml --profile mcp up

GCP Cloud Run

loom deploy --project my-gcp-project --region us-central1

Supports Cloud SQL Auth Proxy, Memorystore TLS, Secret Manager, structured logging, and graceful shutdown. See the deploy command help for details.

Testing

1100+ tests using testcontainers (real Postgres 16 + Redis 7). Docker Desktop required.

uv run pytest tests/ -v                    # all tests
uv run pytest tests/ -v -m "not live"      # skip tests needing real API keys

Development

git clone git@github.com:MennoAf/agent_loom.git
cd agent_loom
uv sync
uv run pytest tests/ -v

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

loom_agents-1.1.2.tar.gz (415.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

loom_agents-1.1.2-py3-none-any.whl (201.0 kB view details)

Uploaded Python 3

File details

Details for the file loom_agents-1.1.2.tar.gz.

File metadata

  • Download URL: loom_agents-1.1.2.tar.gz
  • Upload date:
  • Size: 415.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for loom_agents-1.1.2.tar.gz
Algorithm Hash digest
SHA256 2ce0fb64e008379f61f8ebb8f73f4193b3d26652dfff2e378c0998632424d149
MD5 bf18725374fd57d889374b5228fa4266
BLAKE2b-256 3b2c27034316e4220e989d6509d6c5077f5d47e3cc7665e1fe3706ae0b1c636c

See more details on using hashes here.

Provenance

The following attestation bundles were made for loom_agents-1.1.2.tar.gz:

Publisher: publish.yml on MennoAf/agent_loom

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file loom_agents-1.1.2-py3-none-any.whl.

File metadata

  • Download URL: loom_agents-1.1.2-py3-none-any.whl
  • Upload date:
  • Size: 201.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for loom_agents-1.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 78497ea5fed4eef914b11e766ffced611ecf1071b14f4f50ff9295777b617ce2
MD5 83aeac129a7fd11ee05ef4a06e8c4edb
BLAKE2b-256 22ee76c05f5cc52b1d3c14d7bece65b5cac6184b85ad4f23b09c8193cb36c51c

See more details on using hashes here.

Provenance

The following attestation bundles were made for loom_agents-1.1.2-py3-none-any.whl:

Publisher: publish.yml on MennoAf/agent_loom

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page