Luxas is an open-source, multi-agent system for autonomous scientific research. Give it a topic in RESEARCH.md and it crawls the literature (OpenAlex, arXiv, CrossRef, paywalled venues via an anti-detect browser) and reads the papers it found. Then it designs and runs experiments — with impl and tests written by sibling agents blind to each other — and produces publication-grade figures from the raw results. Finally it writes a LaTeX report, submits it to adversarial content + figure + layout review, and emits a compiled PDF with real citations. Multi-hour, crash-recoverable, no human in the loop.
Luxas is a harness, not a model. The intelligence comes from Claude (Anthropic; Opus / Sonnet / Haiku across roles) and OpenAI o3 for math, with one-line family-wide redirect to DeepSeek-v4 (~10× cheaper, 1M context) or Kimi via an env variable.
Luxas' job is to give that intelligence a durable workspace: file-backed memory (no embeddings, no vector store), externalized brain state, detached Node sub-agent processes, an independent-author pattern that blocks self-review pathologies, and deterministic finish-gates that no prompt can talk past.
Built on top of pi-mono — Mario Zechner's agent-loop / tool-lifecycle / hook primitives, vendored as .tgz under vendor/. See Comparison for how Luxas differs from LangGraph, CrewAI, AutoGPT, Sakana AI Scientist, and Claude Code.
[![][node-shield]][node-link] [![][typescript-shield]][ts-link] [![][pi-mono-shield]][pi-mono-link] [![][license-shield]][license-link]
luxas.im — an autonomous research colleague: from a question to a compiled manuscript, while you sleep. Try it in the browser, no install.
Example Reports · Quick Start · How It Works · Comparison · Agents · Skills · Safety · Security · FAQ · Citation
Skip to Quick Start if you came to install.
Nine end-to-end runs are browsable at luxas.im/gallery — each is the full PDF the agent produced from a single one-line topic, including citations, self-generated figures, and adversarial-review notes:
Each started from a single luxas init --prompt "..." and ran end-to-end with no human writing in the manuscript itself. A few required restarts or pi_pushback.md iterations when the reviewer and brain genuinely disagreed; the harness is built around those crashes rather than against them.
npm install alone is not enough; agents shell out to LaTeX, Python, and tmux. Install once:
# macOS
brew install --cask mactex # or basictex for ~150MB
brew install poppler tmux python@3.11
pip3 install matplotlib numpy
# Linux (Debian/Ubuntu)
sudo apt install texlive-latex-extra texlive-fonts-recommended poppler-utils tmux python3-matplotlib python3-numpy
git clone https://github.com/Muuuun/luxas.git && cd luxas
npm install && npm link # `luxas` now on PATH; skip & use `npx tsx src/index.ts` instead
export ANTHROPIC_API_KEY="..." # default; also DEEPSEEK_API_KEY / KIMI_API_KEY for non-Claude
luxas init ~/research/x --prompt "Survey LLM chain-of-thought reasoning"
luxas run ~/research/x --model opus
luxas status ~/research/x # check progress
luxas figures ~/research/x # rerun only figure / typesetter loop
luxas list # all projects Luxas has ever touched
luxas run ~/research/x # default — every agent uses its declared frontmatter model (full Claude)
luxas run ~/research/x --profile dual # canonical preset: deepseek-v4-pro for text + k2p5 (Moonshot Kimi) for vision
luxas run ~/research/x --model deepseek-v4-pro # same family-wide redirect as --profile dual but no vision override (figures break)
luxas run ~/research/x --model opus # brain-only override (sub-agents follow their own .md)
--profile dual and any --model deepseek-* redirect every agent that declared haiku/sonnet/opus to the deepseek model via applyProfile() in src/agents/spawn.ts. Provider-specific picks (gpt-5.2 for the math agent, o3 for reasoning) bypass — those are deliberate. Vision-required agents (illustrator / illustrator_write / typesetter) need a separate vision profile because DeepSeek is text-only; --profile dual sets it for you (k2p5 → Moonshot Kimi).
Anecdotal cost per full run (check <project>/.agent/usage.log for real numbers):
| Profile | $/run | Notes |
|---|---|---|
| Default (full Claude) | $20–80 | Best content quality; only profile with Anthropic prompt caching |
--profile dual (DeepSeek text + Kimi vision) |
$2–10 | Loses ephemeral cache_control; figures via Kimi |
Luxas vendors four pi-mono packages as .tgz in vendor/ and assembles them into a research agent:
| Layer | File | Role |
|---|---|---|
| System prompt | src/agents/definitions/brain.md |
3 cache-controlled blocks — methodology body (1h cache), RESEARCH.md + skills (cache), <active_agents> + <plan_status> (mutable, in-place rebuild) |
| Tools | src/tools/ |
read/write/edit/bash, compile_latex, init_report, spawn_agent, idle, request_pi_review, figure-gen, wolfram, finish |
| Context transform | src/context.ts |
Per-agent dynamic context, two-stage compaction (60K warning → 80K compress with summary carry-over) |
| Hooks | src/hooks.ts |
RESEARCH.md write-protect, cost limit (process.exit on exceed), search rate limit, per-turn logging, state snapshots |
| PI fallback monitor | src/pi-agent.ts |
Schedules reviewer sub-agent every 50 turns and on milestone tool calls — Opus persona that reads project state and submits continue / steer / stop to reviews/pi_feedback.md |
Brain accounting (cost, tokens, PI counters, compaction markers) is reverse-scanned from log.jsonl on restart. Sub-agents are detached Node processes with their own conversation files; brain talks to them via active-agents.json and harvests via heartbeat + orphan recovery on resume. The idle tool blocks the brain at zero LLM cost while background work runs. Per-project memory lives in notes/*.md (smart-truncated when over budget); cross-project memory in ~/.sisyphus/{projects.json,memory.md} is auto-injected into new project context.
The experiment agent doesn't write code itself. Three phases:
tool_impl (writes scripts/<tool>.py from the description alone) and tool_review (writes tests/test_<tool>.py from the description alone) in parallel, blind to each other. Pytest is the only ground truth; SendMessage ferries failures back to tool_impl for fixes (3-revision cap).data/experiments/<EXP_ID>/runs/run_N/results.json, append a ## L2.X section to notes/experiments.md.After return, the harness auto-spawns experiment_reviewer for adversarial post-hoc audit (satisfied / revise).
The blind impl+test split blocks the self-circular failure where impl-and-test are written together (the impl redefines a field's semantics so its self-reported value passes its own assertion — observed live: max_pair_distance_um got redefined as post-move distance = 0; tests passed; the tool was wrong).
notes/plan.md is the commitment source of truth — each ### E_N heading is a hard commitment. notes/experiments.md is the audit log — each ## L2.N section is the experiment agent's record with Status: Complete / Pending. Two aligned gates enforce closure: the finish tool blocks unless every ### E_N has a matching ## L2.N with Status: Complete, and the reviewer cannot issue stop while any active plan ### E_N is missing or non-Complete. Aligned at both layers, so a "STOP after Pending → brain deadlocked" race is structurally impossible.
Two more invariants: scope reduction is plan.md-only — prose like "(Descoped)" next to an ### E_N heading does not remove it; and Deferred is not a status (removed Apr-26 after observed abuse as a soft escape hatch). The brain-write-lock on notes/experiments.md (only experiment agents may append) is the Safety table's notes/experiments.md write lock row.
Before any stop verdict, the reviewer runs <figure_finalize_loop>: enumerate \includegraphics from report.tex, spawn one illustrator per source script to regenerate against report/figures/style_guide.md, one global-audit illustrator for figure-internals (palette / spines / typography / clipping) → reviews/illustrator_notes.md, one typesetter to rasterize the PDF page-by-page for document-level issues (float distance, caption integrity, column overflow, missing-file red boxes) → reviews/typesetter_notes.md. Loop breaks only when both notes report status: all-clear; the <figure_convergence> tag in reviewer context short-circuits re-audits of unchanged artifacts.
Closest neighbours fall into two groups. Research-domain-specific agents (deep-research / AI-scientist class): Sakana's AI Scientist runs ML-benchmark experiments end-to-end but doesn't do literature surveys with citations. General agent frameworks: LangGraph (declarative graphs), CrewAI (role-based crews), AutoGPT (LLM-driven control). Claude Code is the single-session coding agent.
Luxas is research-domain-specific with a compiled-PDF-with-real-citations as the deliverable (not arbitrary text or code), file-backed and crash-recoverable (replays from log.jsonl, no in-process state), and multi-model out of the box (one env var redirects the whole Anthropic family to DeepSeek-v4 or Kimi).
| Luxas | AI Scientist (Sakana) | LangGraph | CrewAI | AutoGPT | Claude Code | |
|---|---|---|---|---|---|---|
| Control flow | file-based + hook-enforced gates | scripted pipeline | declarative graph you build | role-based crew | LLM-driven (fragile) | one chat session |
| Crash-recoverable | ✓ stateless harness, replays from log.jsonl |
✗ | ✓ via checkpointer (SQLite/Postgres) | ✗ | ✗ | ✗ |
| Detached sub-agents | ✓ Node processes + heartbeat + orphan recovery | ✗ | ✗ in-process | ✗ in-process | ✗ | ✗ |
| Multi-model native | Claude + DeepSeek + Kimi + OpenAI o3 via one env var | OpenAI / Anthropic | DIY plumbing | DIY plumbing | OpenAI-focused | Anthropic-only |
| Output artifact | compiled LaTeX PDF with \resultref number-provenance |
LaTeX paper from ML experiments | whatever you wire | whatever you wire | text + files | text + code |
| Literature survey | ✓ OpenAlex/arXiv/CrossRef/paywall browser | ✗ (uses cached refs) | ✗ | ✗ | ✗ | ✗ |
| Adversarial self-review | content + figure-internal + PDF-layout, three layers | reviewer agent (single layer) | none built-in | none built-in | none | none |
When to use Luxas: you have a research topic, want a literature survey or small-scale computational study, and the deliverable is a compiled report with real citations and figures. Reproducible, auditable (every number traces to a JSON key via provref), runs unattended for multiple hours.
When NOT to use Luxas: you want a general-purpose agent framework you can graft onto arbitrary tasks (use LangGraph or pi-agent-core directly), or you want an interactive coding session (use Claude Code).
14 agent types — brain plus 13 sub-agent kinds. Each lives in src/agents/definitions/<name>.md (YAML frontmatter + markdown body); adding an agent or changing its permissions is one .md edit. Three execution modes from spawn_agent: foreground (blocks, returns result), parallel (tasks: [...] — N concurrent), background (background: true — detached, harvested on next turn). Spawn depth capped at 2 (MAX_SPAWN_DEPTH in src/agents/spawn.ts).
| Agent | Model | Role |
|---|---|---|
| brain | Opus (high) | Main driver. Decomposes RESEARCH.md, surveys literature, sequences experiments, writes the report, iterates on PI feedback |
| search | Sonnet | Literature discovery — OpenAlex / arXiv / CrossRef / citation chains / web / anti-detect |
$ claude mcp add luxas \
-- python -m otcore.mcp_server <graph>