ferrum-agent — Multi-Agent Orchestration Runtime
Multi-agent orchestration runtime that coordinates forge-agent (coding operator), ferrum-mcp (tool layer), taste-memory (user context), ferrum-memory (working memory), and ferrum-evals (CI gate) into coherent multi-step workflows.
Python 3.12 — primary language
FastAPI — REST API server
LangGraph — workflow orchestration engine
PostgreSQL (SQLAlchemy async + Alembic) — state persistence
Redis — job queues and CloudEvents pub/sub
Pydantic v2 — data contracts
Streamlit — operator UI
uv — dependency management
cp .env.example .env
# Edit .env with your service URLs and API keys
docker compose up -d postgres redis nats
uvicorn src.main:app --reload --port 8003
curl http://localhost:8003/health
# → {"status":"ok","langgraph":"ok","postgres":"ok","redis":"ok"}
ferrum-agent (planner + coordinator)
├── forge-agent node (coding tasks)
├── search subagent (read-only retrieval)
└── reviewer node (output validation)
forge-agent is an operator inside ferrum-agent, not replaced by it.
┌── ferrum-agent ──────────────────────────────────────────────┐
│ │
│ ┌─ LangGraph Workflow Graph ────────────────────────────┐ │
│ │ START → [planner] → [executor] → [reviewer] → END │ │
│ │ ↑ ↓ ↓ │ │
│ │ └── retry ──┘ [approval_gate] │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ REST API · A2A Endpoint · Operator UI · Control Plane │
└────────────────────────────────────────────────────────────────┘
Method
Endpoint
Description
POST
/job
Create a new job
GET
/job/{job_id}
Query job state
GET
/job/{job_id}/stream
SSE stream of job events
POST
/job/{job_id}/approve
Resolve pending approval
DELETE
/job/{job_id}
Cancel a job
Method
Endpoint
Description
GET
/template
List templates
POST
/template
Register template
POST
/template/{id}/run
Run from template
Method
Endpoint
Description
GET
/.well-known/agent.json
Agent discovery
POST
/a2a/tasks/send
Receive external task
GET
/a2a/tasks/{id}
Task status
POST
/a2a/tasks/{id}/resubscribe
Subscribe to events
Method
Endpoint
Description
GET
/health
Health check
GET
/metrics
Prometheus metrics
The core LangGraph workflow has 4 nodes and 2 conditional edges :
Planner — retrieves user context from taste-memory, generates ExecutionPlan via LLM
Executor — iterates steps, delegates to forge-agent (coding) or ferrum-mcp (tool calls)
Reviewer — validates step results against acceptance criteria, calls ferrum-evals
Approval Gate — persists approval to Postgres, waits for human decision, enforces timeout
START → planner → executor → reviewer
↓
approve → END
retry_step → executor (loop)
escalate_to_human → approval_gate → executor
All events emitted via NATS (Redis pub/sub fallback in v1):
Event Type
Description
ferrum.workflow.job_started
Job created
ferrum.workflow.step_started
Step execution begins
ferrum.workflow.step_completed
Step execution completes
ferrum.workflow.approval_required
Human approval needed
ferrum.workflow.job_completed
Job finished successfully
ferrum.workflow.job_failed
Job failed
Variable
Default
Description
FERRUM_AGENT_PORT
8003
Server port
POSTGRES_URL
...
PostgreSQL connection string
REDIS_URL
redis://localhost:6379
Redis connection string
NATS_URL
nats://localhost:4222
NATS connection (optional)
FERRUM_MCP_URL
http://localhost:3000
ferrum-mcp service URL
FERRUM_MEMORY_URL
http://localhost:8000
ferrum-memory service URL
TASTE_MEMORY_URL
http://localhost:8001
taste-memory service URL
FERRUM_EVALS_URL
http://localhost:8002
ferrum-evals service URL
FORGE_AGENT_URL
http://localhost:8004
forge-agent service URL
ANTHROPIC_API_KEY
""
LLM provider key
PLANNER_MODEL
claude-sonnet-4-6
Planner LLM
REVIEWER_MODEL
claude-haiku-4-5-20251001
Reviewer LLM
AUTO_APPROVE_RISK_LEVEL
low
Auto-approve below this risk
DEFAULT_BUDGET_USD
5.00
Default job budget
DEFAULT_MAX_DURATION_SECS
3600
Default job duration limit
OTEL_EXPORTER_OTLP_ENDPOINT
http://localhost:4317
OTel collector endpoint
API_KEY_SECRET
...
Bearer token for auth
ferrum-agent/
├── pyproject.toml # uv-managed dependencies
├── Dockerfile
├── docker-compose.yml # agent + postgres + redis + nats
├── alembic/ # Database migrations
├── contracts/ # Platform-wide data contracts
│ ├── execution_plan.py # ExecutionPlan, ExecutionStep, BudgetSpec
│ ├── agent_card.py # A2A AgentCard
│ ├── trace_envelope.py # OTel TraceEnvelope
│ └── workflow_events.py # CloudEvents, ReviewDecision, ApprovalDecision
├── src/
│ ├── main.py # FastAPI app factory
│ ├── api/ # REST endpoints
│ │ ├── jobs.py # /job/*
│ │ ├── templates.py # /template/*
│ │ └── a2a.py # A2A protocol
│ ├── graph/ # LangGraph workflow
│ │ ├── workflow.py # StateGraph definition
│ │ ├── state.py # WorkflowState TypedDict
│ │ └── nodes/ # Workflow nodes
│ │ ├── planner.py
│ │ ├── executor.py
│ │ ├── reviewer.py
│ │ └── approval_gate.py
│ ├── operators/ # External service clients
│ │ ├── forge_client.py
│ │ ├── mcp_client.py
│ │ └── memory_client.py
│ ├── storage/ # Persistence layer
│ │ ├── postgres.py
│ │ └── redis.py
│ ├── events/ # CloudEvents
│ │ └── cloud_events.py
│ ├── auth/ # Authentication
│ │ └── api_key.py
│ └── risk/ # Risk management
│ └── classifier.py
├── ui/
│ └── app.py # Streamlit operator dashboard
├── examples/ # Usage examples
└── tests/
├── unit/
└── integration/
Risk Level
Examples
Default Policy
low
read_file, grep, git_status, memory_search
Auto-approve
medium
write_file, run_tests, git_commit
Auto-approve if budget allows
high
bash_exec, git_push, external API calls
Always require human approval
Destructive operations (rm, reset --hard, drop table) are blocklisted entirely.
# Run all tests
uv run pytest
# Run unit tests only
uv run pytest tests/unit/
# Run integration tests only
uv run pytest tests/integration/
# Run with coverage
uv run pytest --cov=src --cov-report=html
ferrum-agent and forge-agent are co-adapting agents . The coordination protocol prevents feedback loops:
Structured plan format — Planner emits typed ExecutionPlan, forge-agent receives one Task at a time
Fixed acceptance criteria — Each step's criteria are set at plan time and are immutable
Budget caps — Hard token + time limits per step prevent runaway reinforcement loops
Human approval gates — Human judgment breaks machine-induced feedback loops on consequential actions
Cooling-off on repeated failures — Same (step_type, task_type) pair failing 3x triggers a failure_pattern in ferrum-memory
# Start all services (agent + postgres + redis + nats)
docker compose up -d
# Check health
docker compose ps
# Stop all services
docker compose down
Proprietary — Ferrum Platform