Quick start
From a clean clone to an approved, cited report. The Docker path needs one command.
Prerequisites
| Needed for | |
|---|---|
| Docker with Compose v2 | The one-command path. Everything runs in containers; the only host port used is the frontend's. |
| A model | Either a provider API key, or Ollama running locally. Without one, use --fake below. |
| Python 3.14+ and Node 26+ | Only for the native development path, and Python with pydantic for verifying a bundle (step 5). |
A search API key is not required — the retriever chain falls back to keyless DuckDuckGo. See Configuration for what each optional key buys you.
1. Clone
git clone https://github.com/adityamhaske/Multi-Agent-Research-Assistant.git
cd Multi-Agent-Research-Assistant
2. Start it
./start.sh
start.sh creates .env if it is missing (generating a JWT_SECRET_KEY for you), checks
the configuration, builds and starts all five services, waits until each reports healthy,
and opens the app.
If .env has neither a provider key nor a MODEL_* route to a keyless provider
(ollama: or custom:), it warns and falls back to fake mode rather than starting
something that cannot run. Fake mode applies to the whole server: every run is then the
scripted demo whatever you ask, and a key saved in the app's Settings goes unused until you
restart with a key or route in .env.
Other modes:
./start.sh --fake # keyless demo: scripted models and fixture sources, no API key
./start.sh --rebuild # force a rebuild of the images
./start.sh --logs # start, then follow logs
./start.sh --stop # stop the stack; data is preserved
./start.sh --reset # stop and delete the database volume (asks first)
Or drive Compose yourself
cp .env.example .env
# In .env set JWT_SECRET_KEY to `openssl rand -hex 32`, and one provider key.
docker compose -f docker-compose.full.yml up --build
The api container runs alembic upgrade head before serving, and the worker and
frontend wait on its readiness, so migrations apply exactly once per deploy. The frontend
is the only published service — it proxies /api/* over the internal network, so auth
cookies stay first-party and the database is never exposed.
3. Open the app
Register an account. On a fresh self-host this is your account; email verification is off by default and should be turned on for anything public (Production deployment).
4. Run your first research
Research in the sidebar starts a run and opens its workspace.
- Ask a question. Ten characters minimum; a real question works better than a keyword.
- Pick a depth —
fast,balanced, orcomprehensive. Depth is the main cost dial: it sets how much the planner decomposes the question. - Submit. You land on the run workspace and the live feed starts. Events stream over
SSE and are also written durably; a dropped stream reconnects with
Last-Event-IDand the backend replays what was missed, so a refresh or a late-joining tab loses nothing. - Review the plan. The run pauses at the design gate before anything is searched. Uncheck any research area you did not ask for, then approve. Approving a plan spends money; it does not create an artifact. (Review and approval)
- Watch the pipeline. Executor and critic work through the tasks; the critic sends weak evidence back within a bounded retry limit.
- Read the record, not just the draft. The workspace tabs run in the order the product argues for — Plan → Report → Claims → Evidence → Sources → Contradictions → Review → Artifact. Claims shows what the report asserts and what each assertion resolved to; Sources separates cited from retrieved-only; Contradictions shows attributed quotations that cannot both hold.
- Review the draft. The Review tab shows what you are approving before you approve it: claims with and without supporting evidence, cited versus retrieved-only sources, unresolved conflicts, and a citation rate that reads "unmeasured" when it was not measured. Approve, or send it back with feedback for a rework — a rework adds a revision and never overwrites the one you just read.
- Take the artifact. Approving the report freezes a
ResearchArtifact. The Artifact tab shows the verifier's own checks and offers the.bundle.json. Reports also export as.mdand.pdf. (Exports)
Once you have seen a run through, Settings → Agents changes how each agent behaves on your next one — and every run records the instructions it ran on. (Agent instructions)
5. Verify the artifact yourself
The bundle is the point of the whole chain: it is checkable by someone who does not trust this application, and does not need it running.
cd backend
python -m research_engine.verify_bundle ~/Downloads/research-abc12345.bundle.json
Exit status is 0 when every check passes and 1 when any fails; add --format json for
machine-readable output. The verifier needs no network, no API key, and no model.
A pass means the artifact is internally consistent and unaltered since approval. It does not mean the research is correct — see the research record for exactly what each check proves and what none of them do.
Try it without a key first
./start.sh --fake
Fake mode runs the real graph with scripted models and fixture retrievers. It calls no model or search provider and costs nothing, so it is the honest way to see the shape of the product — the gates, the live feed, the citation chips, the export — before deciding whether to spend anything.
Demo runs are marked as demo in the database, and every export path stamps the artifact. The bundle carries the flag in a hash-covered field and the verifier prints it above the verdict. A demo report cannot be laundered into a real-looking one.
Native development
If you are going to change the code, run the services directly:
make infra-up # Postgres + Redis only, in Docker
make backend-setup && make migrate
make backend-dev # API → :8000
make worker # Celery worker (new terminal)
make frontend-setup && make frontend-dev # UI → :3031 (new terminal)
Full detail, including the test and lint commands CI runs, is in the Development guide.
If something goes wrong
Troubleshooting covers the failures people actually hit: the app
refusing to boot on a short secret, a stuck PENDING session, an empty live feed, and
Ollama not being detected from inside Docker.