MirrorNeuron API
Documentation for MirrorNeuron API.
MirrorNeuron API
This document describes the read and control APIs that the CLI tools currently consume.
The goal is to keep these shapes stable enough for future tools such as:
- terminal monitors
- lightweight web dashboards
- automation hooks
- external operational scripts
HTTP REST API (New)
MirrorNeuron runs an embedded HTTP server (powered by Bandit and Plug) offering a clean, RESTful API. This is inspired by modern resource-oriented principles (similar to Apache Airflow's REST API) but remains simpler, JSON-first, and tightly coupled to MirrorNeuron's lightweight multi-agent engine.
By default, the API binds to port 4000. You can change this using the MN_API_PORT environment variable.
Base URL
/api/v1
Endpoints Overview
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/health | Simple liveness check |
| GET | /api/v1/system/summary | Returns cluster nodes and active job overview |
| POST | /api/v1/jobs | Submits a new job by providing a manifest in JSON format |
| GET | /api/v1/jobs | Lists all jobs (supports pagination/filtering) |
| GET | /api/v1/jobs/:job_id | Returns detailed state of a running/completed job |
| POST | /api/v1/jobs/:job_id/cancel | Cancels a running job |
| POST | /api/v1/jobs/cleanup | Clears finished/cancelled jobs from the datastore |
| GET | /api/v1/jobs/:job_id/events | Returns raw event history for a job |
| GET | /api/v1/jobs/:job_id/workflow-progress | Returns normalized progress, failure, trace, and observability summary |
| GET | /api/v1/runs/:run_id/artifacts | Lists run artifacts with stable IDs, size, hash, content type, and URL |
| GET | /api/v1/runs/:run_id/timeline | Returns mn.timeline.v1 timeline records |
| GET | /api/v1/runs/:run_id/observability-summary | Returns compact mn.observability_summary.v1 run summary |
| POST | /api/v1/bundles/:bundle_id/reload | Manually reload a registered job bundle |
| GET | /api/v1/resource | Core resource totals and configured CPU/GPU/memory/disk limits |
| POST/PUT | /api/v1/resource | Set CPU/GPU/memory/disk limits |
| POST | /api/v1/schedules | Create a runtime schedule from manifest JSON, payloads, or an uploaded bundle path |
| GET | /api/v1/schedules | List schedules, optionally filtered by kind or status |
| GET | /api/v1/schedules/:schedule_id | Get one schedule |
| PATCH | /api/v1/schedules/:schedule_id | Update schedule attributes |
| POST | /api/v1/schedules/:schedule_id/pause | Pause a schedule |
| POST | /api/v1/schedules/:schedule_id/resume | Resume a schedule |
| DELETE | /api/v1/schedules/:schedule_id | Delete a schedule |
| POST | /api/v1/schedules/:schedule_id/dispatch | Dispatch a schedule immediately |
| POST | /api/v1/events | Emit a runtime trigger event |
| GET | /api/v1/events | List recent runtime trigger events |
Design Decisions & Differences from Airflow
- Simplicity over Ceremony: Airflow's REST API is heavy and enterprise-oriented. MirrorNeuron's API is lean, using standard query parameters, and maps directly to internal monitor boundaries.
- Explicit Status Fields: The
statusfield drives logic directly (e.g.,pending,running,queued,completed,failed,cancelled). - Control Plane Separation: The HTTP layer is merely a translation boundary into internal Elixir primitives and does no business logic itself.
gRPC And SDK Operator Surfaces
The CLI and Python SDK primarily use gRPC. The gRPC server exposes JSON-safe methods for the newer orchestration features:
| Area | Surface |
|---|---|
| Reconciliation | ReconcileNode |
| Drain and maintenance | DrainNode, CancelNodeDrain, SetNodeMaintenance, GetNodeDrainStatus |
| Services | ListServices, ResolveService, CheckServices |
| Resources | resource get/set methods |
| Deployments | deploy, update, list, status, promote, rollback, pause, resume, fail methods |
| Schedules and events | create, update, list, status, pause, resume, delete, dispatch, emit, and list event methods |
Implementation entry points:
MirrorNeuron/lib/mirror_neuron.exMirrorNeuron/lib/mirror_neuron_grpc/server.exmn-python-sdk/mn_sdk/client.pymn-cli/mn_cli/main.py
API Examples
1. System Health
curl -s http://localhost:4000/api/v1/healthResponse (200 OK):
{
"status": "ok"
}2. System Summary
curl -s http://localhost:4000/api/v1/system/summaryResponse (200 OK):
{
"nodes": [
{
"name": "mn1@192.168.4.183",
"connected_nodes": ["mn1@192.168.4.183"],
"self?": true,
"scheduler_hint": "cluster_member",
"executor_pools": {
"default": { "capacity": 2, "available": 1, "in_use": 1, "queued": 0, "active": 1 }
}
}
],
"jobs": [
{
"job_id": "prime_sweep_40_workers-...",
"status": "running"
}
]
}3. Submit a Job
Provide a fully resolved JSON manifest.
curl -X POST http://localhost:4000/api/v1/jobs \
-H "Content-Type: application/json" \
-d '{
"manifest_version": "1.0",
"graph_id": "simple",
"entrypoints": ["router"],
"nodes": [
{
"node_id": "router",
"agent_type": "router",
"role": "root_coordinator"
}
]
}'Response (201 Created):
{
"id": "simple-12345...",
"status": "pending"
}4. List Jobs
Accepts standard query parameters:
limit=20(default unlimited)include_terminal=false(default true)
curl -s "http://localhost:4000/api/v1/jobs?limit=5"Response (200 OK):
{
"data": [
{
"job_id": "prime_sweep_40_workers-...",
"graph_id": "prime_sweep_40_workers",
"status": "completed",
"submitted_at": "2026-03-28T11:00:00.000Z",
"updated_at": "2026-03-28T11:00:12.000Z"
}
]
}5. Get Job Details
curl -s http://localhost:4000/api/v1/jobs/prime_sweep_40_workers-...Response (200 OK):
{
"job": { ... },
"summary": { ... },
"agents": [ ... ],
"recent_events": [ ... ],
"sandboxes": [ ... ]
}6. Cancel Job
curl -X POST http://localhost:4000/api/v1/jobs/prime_sweep_40_workers-.../cancelResponse (200 OK):
{
"status": "cancelled",
"job_id": "prime_sweep_40_workers-..."
}7. Cleanup Jobs
Clears finished, failed, and cancelled jobs from the datastore. Add ?all=true to forcibly clear all jobs including currently running ones.
curl -X POST http://localhost:4000/api/v1/jobs/cleanupResponse (200 OK):
{
"deleted_count": 2,
"deleted_jobs": ["job_1", "job_2"]
}8. Job Events
curl -s http://localhost:4000/api/v1/jobs/prime_sweep_40_workers-.../eventsResponse (200 OK):
{
"data": [
{
"timestamp": "2026-03-28T11:00:04.000Z",
"type": "sandbox_job_completed",
"agent_id": "prime_worker_0001",
"payload": { ... }
}
]
}9. Reload Bundle
Forces a re-scan and reload of a registered bundle, computing its fingerprint and updating it in memory if any changes occurred.
curl -X POST http://localhost:4000/api/v1/bundles/prime_sweep_40_workers/reloadResponse (200 OK):
{
"bundle_id": "prime_sweep_40_workers",
"changed": true,
"reloaded": true,
"previous_fingerprint": "a1b2c3d4...",
"current_fingerprint": "e5f6g7h8...",
"reason": "api_request",
"message": "Bundle reloaded successfully",
"timestamp": "2026-03-28T11:00:00.000Z"
}Public Elixir API
These functions are exposed from MirrorNeuron.
Job execution
MirrorNeuron.validate_manifest(input)
Validates a job bundle folder.
Input:
input :: String.t()path to a job folder
Return:
{:ok, bundle}{:error, reason}
The bundle includes:
root_pathmanifest_pathpayloads_pathmanifest
MirrorNeuron.run_manifest(input, opts \ [])
Submits a job bundle for execution.
Important options:
await: booleantimeout: integer | :infinityjson: booleanjob_bundle: bundleinternal/advanced path
Return:
{:ok, job_id}whenawait: false{:ok, job_id, job}whenawait: true{:error, reason}
MirrorNeuron.wait_for_job(job_id, timeout \ :infinity)
Waits for terminal status:
completedfailedcancelled
Return:
{:ok, job_map}{:error, reason}
Inspection
MirrorNeuron.inspect_job(job_id)
Reads the persisted job record from Redis.
Return:
{:ok, job_map}{:error, reason}
Typical job fields:
{
"job_id": "prime_sweep_40_workers-...",
"graph_id": "prime_sweep_40_workers",
"job_name": null,
"status": "completed",
"submitted_at": "2026-03-28T11:00:00.000Z",
"updated_at": "2026-03-28T11:00:12.000Z",
"placement_policy": "local",
"recovery_policy": "local_restart",
"root_agent_ids": ["dispatcher"],
"result": {},
"manifest_ref": {
"graph_id": "prime_sweep_40_workers",
"manifest_version": "1.0",
"manifest_path": "/abs/path/manifest.json",
"job_path": "/abs/path/job-folder"
}
}MirrorNeuron.inspect_agents(job_id)
Reads persisted agent snapshots.
Return:
{:ok, [agent_snapshot]}{:error, reason}
Typical agent fields:
{
"agent_id": "prime_worker_0001",
"agent_type": "executor",
"type": "map",
"assigned_node": "mn1@192.168.4.183",
"processed_messages": 1,
"mailbox_depth": 0,
"current_state": {
"runs": 1,
"last_result": {
"sandbox_name": "mirror-neuron-job-...",
"lease": {
"lease_id": "...",
"pool": "default",
"slots": 1
}
}
},
"metadata": {
"paused": false,
"outbound_edges": ["aggregator"]
}
}MirrorNeuron.events(job_id)
Reads the Redis-backed append-only event list for the job.
Return:
{:ok, [event]}{:error, reason}
Typical event fields:
{
"timestamp": "2026-03-28T11:00:04.000Z",
"type": "sandbox_job_completed",
"agent_id": "prime_worker_0001",
"payload": {
"sandbox_name": "mirror-neuron-job-...",
"exit_code": 0,
"pool": "default"
}
}MirrorNeuron.inspect_nodes()
Returns cluster node summaries with executor pool stats.
Return:
[%{...}]
Typical fields:
[
{
"name": "mn1@192.168.4.183",
"connected_nodes": ["mn1@192.168.4.183", "mn2@192.168.4.35"],
"self?": true,
"scheduler_hint": "cluster_member",
"executor_pools": {
"default": {
"capacity": 2,
"available": 1,
"in_use": 1,
"queued": 0,
"active": 1
}
}
}
]Control
MirrorNeuron.pause(job_id)
MirrorNeuron.resume(job_id)
MirrorNeuron.cancel(job_id)
MirrorNeuron.send_message(job_id, agent_id, message)
These are the control-plane mutation APIs currently used by the main CLI.
Monitor API
These functions are implemented in monitor.ex and are intended as the stable read model for operational tooling.
MirrorNeuron.list_jobs(opts \ [])
Returns enriched job summaries.
Supported options:
limit: integerinclude_terminal: boolean
Return:
{:ok, [job_summary]}{:error, reason}
job_summary includes:
job_idgraph_idjob_namestatussubmitted_atupdated_atplacement_policyrecovery_policyexecutor_countactive_executorsnodessandbox_nameslast_event
MirrorNeuron.job_details(job_id, opts \ [])
Returns the full monitor detail view for one job.
Supported options:
event_limit: integerdefault25
Return:
{:ok, details}{:error, reason}
details includes:
jobsummaryagentssandboxesrecent_events
Each agent entry includes:
agent_idagent_typetypeassigned_nodestatusrunning?processed_messagesmailbox_depthpaused?last_errorsandbox_namelease
MirrorNeuron.cluster_overview(opts \ [])
Convenience call that combines:
MirrorNeuron.inspect_nodes/0MirrorNeuron.list_jobs/1
Return:
{:ok, %{"nodes" => [...], "jobs" => [...]}}{:error, reason}
Redis persistence keys
The current monitor API is backed by these Redis structures in redis_store.ex.
Namespace prefix:
mirror_neuronby default- configurable through
:redis_namespace
Key shapes:
mirror_neuron:jobs- Redis set of known job ids
mirror_neuron:job:<job_id>- JSON job record
mirror_neuron:job:<job_id>:events- Redis list of JSON events
mirror_neuron:job:<job_id>:agents- Redis set of agent ids
mirror_neuron:job:<job_id>:agent:<agent_id>- JSON agent snapshot
Pub/Sub channel:
mirror_neuron:channel:events:<job_id>
This event channel is written today but not yet consumed by the terminal monitor. It is the best candidate for future live dashboards.
Failure Model
Job details, workflow progress, failure events, and compact summaries expose a shared failure object using mn.error.v1. Runtime events use error: mn.error.v1; SDK/API progress responses normalize that into top-level failure plus step and agent failure fields. Legacy reason and status_reason remain for compatibility and should be treated as display strings derived from failure.desc when available.
Compact job details and workflow progress also expose trace_id and observability_summary when a run store exists. The summary uses mn.observability_summary.v1 and includes status, duration, trace id, event/log/error/warning/timeline/artifact counts, retry count, failed step or agent when known, resource peaks, token totals, and artifact links. The normalized execution timeline is available from /api/v1/runs/:run_id/timeline and from the run stream when the timeline channel is requested.
Run artifact listings include observability artifacts with stable IDs and download metadata:
events_jsonl,logs_jsonl,errors_jsonl,timeline_jsonl,timeline_json,observability_summary_json- Rotated segments such as
events_jsonl_001,logs_jsonl_001,errors_jsonl_001
Each artifact entry includes size, SHA-256 hash, content type, and URL. Clients should link to errors.jsonl, events.jsonl, logs.jsonl, and timeline.jsonl instead of embedding large log blobs in job detail views.
Terminal CLI
The user-facing CLI is mn.
Common commands:
mn node list
mn job status <job_id>
mn job monitor <job_id>
mn job cancel <job_id>The CLI uses the Python SDK over gRPC for most control paths. See CLI Reference.
Stability guidance
For future tools, prefer consuming:
MirrorNeuron.list_jobs/1MirrorNeuron.job_details/2MirrorNeuron.cluster_overview/1
Avoid coupling directly to raw Redis keys unless you are building low-level operational tooling.