Prometheus

Open-source, model-agnostic agent framework for local hardware. Tool calls that actually work on local models. Your hardware, your model, your memory. MIT licensed.

Get Prometheus GitHub Architecture

MIT License · Python 3.11+ · Active Development · 6,700+ Tests

Status: Active development. Expect rough edges. Fixes land weekly. Feedback welcome.

The Stack

One stack, all local-first. Every layer composes downward, and everything stands on Prometheus.

Blackboard
In Development
Cognition
In Development
Beacon The desktop cockpit. Sits on Prometheus.
Live — Hardening
Beacon iOS The cockpit in your pocket. Same daemon, same control plane.
Live — Beta
Prometheus The agent harness. Stands alone on your hardware. You are here.
Live — Open Source
Runs on your hardware — llama.cpp · Ollama · your GPU
Origins

Everything that makes Prometheus interesting was built from scratch:

Prometheus is an original codebase, not a fork: 308 of its 348 Python modules were written from scratch or ported from OAra's own skillforge-engine — the other 40 carry a header naming the upstream file they were adapted from (31 OpenHarness, 6 Hermes Agent, 3 OpenClaw), all listed in NOTICE — including everything that makes it interesting: the Model Adapter Layer, SENTINEL, SYMBIOTE, the Wiki Knowledge System, the coding engine, the backend registry, and the fine-tuning gym. It began in April 2026 as a scaffold renamed from the MIT-licensed OpenHarness (the tool base class, the bash tool, the cron scheduler, the first agent loop), with specific pieces adapted from the Hermes Agent (the xAI OAuth sign-in, the memory tool, Slack-adapter and skill-curator patterns) and OpenClaw (the memory extractor's cadence, MCP naming and transport), and has been built out far beyond that start — the engine has since diverged to under 4% code similarity with its starting point. Every adapted file names its source in a header comment. The gateways, LSP integration and teacher escalation were designed by studying prior art and implemented clean-room; design influences with no code copied are credited in NOTICE.

The Guards

A passing test proves the code runs. It does not prove anything calls it. Every guard below exists because a feature was built, tested, green — and never wired. Each one is a test that fails the build rather than a convention someone has to remember.

Enforced byThe invariant
test_no_site_resolves_the_wiki_root_independently No source file may resolve the wiki root on its own — one resolver, or the build fails.
test_every_live_config_key_exists_in_the_default_template Every key in the live config must exist in the shipped template — live ⊆ template, with no allowlist. Compares against a real install, so it skips on a fresh clone where there is nothing to compare.
test_no_new_config_key_without_a_reader A register of config keys nothing reads, which can only shrink. An unregistered key with no reader fails — and a registered key that gains one fails as stale, so the list cannot rot.
test_example_call_uses_real_param_names A tool's advertised example must validate against its own schema. The example ships inside the tool advertisement, so a wrong one teaches the model a parameter that does not exist.
test_every_guard_declares_its_enforcement Every media and rate check declares fail-closed or fail-open at construction. The registry is built at module level, so an undeclared guard is an import error, not a test failure.
test_tripwire_end_to_end An acceptance test that terminates in a registered test double fails — registration is what makes a double detectable. Wildcard exemptions are refused; only individually-named doubles pass. Runs a real inner pytest against the actual enforcement hook.
test_every_advertised_document_extension_is_admitted Every allowlisted file type must be provably admitted, not merely “not refused”. Breach tests prove the door closes; only admission tests prove it opens.

The last one is there because its absence shipped. A control suite whose every case asked “does disabling this let something bad through?” — and none asked “does this let the permitted things through?” — stayed green while the document surface silently degraded to PDF-only: 19 of 20 advertised types refused, including two the allowlist explicitly permitted. Over-refusal looks exactly like the control working.

Core Systems
Agent Loop

Pydantic-validated tool calls, PreToolUse/PostToolUse hook pipeline, permission governance. Works with any model.

Lossless Context Management

DAG-based conversation compression. Every message persisted to SQLite. Old messages summarized into expandable nodes. FTS5 full-text search. Works within 32K context windows.

SENTINEL

Proactive background intelligence. Watches telemetry, sends nudges via Telegram during idle. AutoDream engine: wiki lint, memory consolidation, telemetry digest, knowledge synthesis. Budget-capped. Never exceeds autonomous trust level.

Wiki Knowledge System

Compounding knowledge base (Karpathy's LLM Wiki concept). Memory Extractor runs every 30 min. WikiCompiler builds entity pages with cross-references. Query results file back as new pages. Obsidian-compatible.

Security Gate

4-level trust: BLOCKED, APPROVE, AUTO, AUTONOMOUS. 8 always-blocked patterns + configurable deny lists. Workspace boundary enforcement. Bash intent analysis. Memory security scanning. Token-authenticated REST + WebSocket control plane.

Public Surface Hardening

The chat gateways are the one surface exposed to the internet by design, so they are checked cheapest-and-earliest-first. Per-chat rate budgets under a global ceiling, with messages and media counted separately and a refusal costing nothing. Declared MIME before any transfer, the size cap before download — then the download itself under a hard byte ceiling, because the peer supplies that size and the pre-check believed it. Magic bytes are sniffed after; a declared type that disagrees with the sniffed one is refused. The honest limit: signature-less text formats have no bytes to verify, so they are trusted on their declared type, bounded by the allowlist.

Model Adapter Layer

Validator catches malformed tool calls. Formatter translates between model formats. Enforcer constrains output to valid schemas (configurable strictness per model). Retry engine with structured error feedback.

Coding Mode

Point the agent at a coding task and it iterates in a sandbox until the build and tests pass — "iterate-to-green." With LSP enabled, diagnostics feed type errors back into the same loop, so it self-corrects against compiler ground truth. The result is a reviewable diff — nothing touches your branches until you merge.

Fine-Tuning Flywheel

Successful tool-call traces and adapter repair-pairs are captured, stored, and mined into an exportable dataset (capture → store → miner → export). Browse collected pairs with /pairs. The data-collection half of a LoRA loop for the local model — training is on the roadmap. All of it fed by telemetry that never leaves your disk — your own training data, not someone else's — and one config line turns it off entirely.

Record a Skill

Demonstrate a task once — screen and DOM captured — and the daemon distills it into a reusable skill. Two-tier trust: auto-learned skills stay quarantined until you promote them. A screen recording of you doing your job is among the most revealing data you own, and every frame of it stays on your disk — which is the structural reason a hosted product cannot offer the same feature: shipping your screen to someone else's server is the feature, and the problem.

Evals with Judge Provenance

A local LLM judge scores task completion, tool accuracy, and hallucination using constrained decoding on your own hardware — zero API cost — with failure classification and trend tracking. Every score records which judge produced it: base URL, model, and whether that model was pinned or auto-detected from whatever the endpoint had loaded. Pinned is the field that matters and cannot be inferred from the model name, because an auto-detected judge records the same name as a pinned one while only the pinned run is reproducible. Records written before this carry no judge at all — that means unknown, permanently, and they are not compared across paths.

Durable Runtime

Sessions survive daemon restarts. A running turn can be stopped mid-flight. Artifacts produced in chat are downloadable from the session.

Backend Registry

One table of every local inference box you own, probed for the served model, its reported context window, detected vision and latency. Each box is a slash command and a row in the model picker; a switch is probed first and refused if the box is down; the chat is budgeted at that box's window and the choice survives restarts. The picker, the fallback chain, Anatomy and /api/status all read the same table.

Beacon Desktop

Beacon is the native desktop cockpit for the daemon — chat with live tool timelines, coding runs and a Loop Manager, documents with AI redlines, Kanban, and per-provider key management across eighteen views. The model picker lists your own boxes — each with its live health — above the cloud presets, and an iOS client rides the same control plane. It pairs with a one-time 6-digit code and works over localhost or your tailnet. The daemon stays the source of truth; Beacon is the window into it.

Beacon Mission Control connected to a freshly installed Prometheus daemon

Mission Control, freshly paired.

Beacon has its own page →
Architecture
Your Machine (or split across two)
│
├── Prometheus daemon (systemd)
│   ├── Agent Loop
│   ├── Telegram / Slack / Discord Gateway
│   ├── Heartbeat + Cron
│   ├── Memory Extractor
│   ├── Wiki Compiler
│   ├── SENTINEL
│   ├── LCM Engine
│   ├── SYMBIOTE (GitHub research → safe grafting → blue-green swap)
│   └── AnatomyScanner (infra self-awareness)
│
├── Model Provider (local or remote)
│   ├── llama.cpp         any GGUF model
│   ├── Ollama            one-line model pulls
│   ├── Anthropic API     Claude via API key
│   ├── OpenAI-compat     any provider with /v1/chat
│   ├── Gemini / xAI      xAI via API key or SuperGrok subscription OAuth
│   └── DeepSeek / Kimi (Moonshot) / GLM (Z.ai) / MiMo
│
├── SQLite databases
│   ├── memory.db
│   ├── telemetry.db
│   └── lcm.db
│
└── ~/.prometheus/
    ├── wiki/             knowledge base
    ├── sentinel/         dream logs
    ├── skills/auto/      learned skills
    └── workspace/        sandboxed execution

Runs single-machine or split brain/GPU across two boxes. All data in SQLite on your filesystem. Nothing phones home.

Install

Three ways to get it. Two work today; the third is honest about not being ready.

From source — works today

Clone the repo and install it editable with the full extra. The three steps below are this path. Best if you want to read or change the code, or run the test suite.

One command, from Git — works today

An isolated install of the oara command straight from the main branch, with uv or pipx. Then oara setup.

uv tool install 'oara-prometheus[full] @ git+https://github.com/OAraLabs/Prometheus'
# or: pipx install 'oara-prometheus[full] @ git+https://github.com/OAraLabs/Prometheus'
Homebrew & PyPI — coming

The tap oaralabs/tap exists and the oara name is reserved on PyPI, but neither serves a package yet: brew install and pip install oara will not give you Prometheus today. Both open with the first published release.

Prerequisites: Python 3.11+, a running llama.cpp / Ollama / LM Studio / vLLM instance (or a cloud API key), optional bot tokens for the messaging gateways.

1. Clone & Install
git clone https://github.com/OAraLabs/Prometheus.git && cd Prometheus
pip install -e '.[full]'
2. Setup
oara setup      # detects llama.cpp / Ollama / LM Studio / vLLM, writes config, smoke-tests
# no local GPU yet? start on a cloud model and switch later:
oara setup --provider anthropic --api-key-env ANTHROPIC_API_KEY --model claude-sonnet-5
3. Run
oara daemon     # always-on: web API + gateways + cron

If anything misbehaves, oara doctor checks every subsystem and prints a fix hint per failure.

On first daemon start a web API token is minted and printed once — re-print it with oara token show.

On Linux, oara install-service writes a systemd user unit so the daemon survives reboots.

Prefer setup from a couch? Skip oara setup and run oara daemon bare — it boots in setup mode and prints a one-time 6-digit pairing code. Beacon's wizard does the rest.

bash read_file write_file edit_file grep glob web_search web_fetch youtube_transcript download_file image_generate video_generate cron_create cron_delete cron_list task_create task_get task_list task_update task_stop task_output todo_write skill agent ask_user message tts notebook_edit dashboard browser anatomy audit_query lcm_grep lcm_expand lcm_describe lcm_expand_query wiki_compile wiki_query wiki_lint sentinel_status mcp_status * lsp * sessions_list sessions_send sessions_spawn tool_search memory github_search symbiote_scout symbiote_harvest symbiote_graft symbiote_status

Read-only tools run in parallel via asyncio.gather. Mutating tools run sequentially. Security hooks fire on every call. Dynamic MCP tools extend the set at runtime.

* mcp_status and lsp register only when their subsystems are enabled; audit_query registers with the security gate. Forty-nine tools register by default.

Interface
CommandDescription
/startWelcome message
/statusModel, uptime, tools, memory stats, SENTINEL state
/helpList commands and capabilities
/resetClear conversation (identity persists)
/clearClear conversation context
/modelCurrent model and provider
/wikiWiki stats — page count, recent updates
/sentinelSENTINEL status and last dream results
/benchmarkRun evaluation suite
/contextToken budget breakdown with visual progress bar
/skillsLoaded skills
/profileSwitch agent profiles
/anatomyInfrastructure snapshot
/beaconWeb bridge status + links
/steerInject a mid-turn course-correction while the agent is working
/queueQueue a message for the agent to pick up after the current task
/pairsBrowse captured repair-pairs / golden traces
/approve /deny /pendingManage approval queue
/claude /gpt /gemini /xaiPer-session cloud provider override (xAI via API key or SuperGrok subscription)
/deepseek /kimi /glm /mimoPer-chat cloud override — expansion providers
/localClear override, return to the primary local model
/backendsWhat every local inference box is serving — model, window, vision, latency (refresh re-probes)
/4090 /mini …Point this chat at a named local box (one command per backends: entry; probed first, refused if down; /mini qwen2.5:7b-instruct picks a vetted model)
/workspace <path>Point this chat at a repo — the security gate, project instruction files and per-turn checkpoints follow
/routeShow this chat's current provider + model

Telegram, Slack, and Discord gateways run at parity — 40+ slash commands on Telegram. CLI REPL included, plus the Beacon desktop app.

Provenance

An original codebase, not a fork — the full account is in Origins above. Every adapted file names its source in a header comment; complete notices live in NOTICE.

Project Structure
prometheus/
├── src/prometheus/
│   ├── engine/          # Agent loop, sessions, streaming
│   ├── adapter/         # Model Adapter Layer (validator, formatter, enforcer, retry, router)
│   ├── providers/       # llama_cpp, ollama, openai_compat, anthropic, xai_oauth, registry, backends (the local-box registry)
│   ├── tools/builtin/   # 50+ builtin tools
│   ├── hooks/           # PreToolUse / PostToolUse + hot reload + LSP diagnostics
│   ├── permissions/     # Security gate + audit + exfiltration + approval queue
│   ├── security/        # Log + capture redaction, path guard, dangerous-code scanner
│   ├── checkpoints/     # Per-turn workspace snapshots + restore
│   ├── memory/          # LCM engine, wiki compiler, extractor, store
│   ├── context/         # Token budget, 2-tier compression, prompt assembly
│   ├── gateway/         # Telegram, Slack, Discord, cron, heartbeat, media cache, archive
│   ├── sentinel/        # Observer, AutoDream, wiki lint, memory consolidation
│   ├── mcp/             # MCP runtime, transport, adapter
│   ├── lsp/             # Language server client, orchestrator, diagnostics hook
│   ├── evals/           # LLM judge, metrics, failure classifier, trend tracking
│   ├── coordinator/     # Subagent spawning, divergence detection, checkpoint/rollback
│   ├── learning/        # Skill creator, skill refiner, periodic nudge
│   ├── infra/           # AnatomyScanner, project configs
│   ├── cli/             # Identity generation, migration tool
│   ├── skills/          # Skill loader + registry
│   ├── tasks/           # Background task manager (bash + agent tasks)
│   ├── telemetry/       # Tool call tracking + cost tracking
│   ├── tracing/         # Phoenix/OpenTelemetry spans
│   └── config/          # Settings, paths, env var overrides, profiles
├── templates/           # Identity templates (no personal data)
├── skills/              # 103-file skill library (opt-in)
├── tests/               # 6,700+ tests across 403 files
├── docs/                # Architecture, model registry, sprint reports
├── audits/              # Timestamped audit reports (diffable across runs)
├── gym/                 # Eval & fine-tuning gym (repair-pair capture, benchmark tasks)
├── .githooks/           # Pre-commit hook (blocks secrets, Tailscale IPs, host refs)
├── config/prometheus.yaml.default   # Reference config (no secrets)
├── scripts/daemon.py    # Dev shim — the installed `oara daemon` is the entry point
└── PROMETHEUS.md        # Agent instructions (like CLAUDE.md)