Deep-research agent with evidence-gated output. Each claim is backed by a stored source; each run is replayable from the evidence store.
- Pluggable LLM backend: Ollama (default), OpenAI, or llama.cpp.
Switch via
RC_LLM_PROVIDERor the--providerCLI flag — no code changes. See SystemDesign/providers.md. - Optional adversarial critic: off by default; enable per-run via
--critic,/critic on, orcritic_enabled: true. See SystemDesign/critic.md. - Evidence-gated finalization: four strategies (direct / sectional / two_phase / chunked), every claim traced to an evidence id.
Full design: SystemDesign/ARCHITECTURE.md · Layer map: SystemDesign/ARCHITECTURE_LAYERS.md · Third-party audit: SystemDesign/third-parties.md · Secret inventory: SystemDesign/secret-inventory.md.
- Python 3.11+ (tested on 3.14).
- One of: Ollama (local native install), an OpenAI API key, or a
llama.cpp
serverin OpenAI-compat mode. - Docker Desktop — required for the
python_execsandbox tool and the Kroki diagram service. - RAM: 16 GB minimum, 32 GB recommended with a local model.
# 1. Install
python -m pip install -e ".[dev]"
# 2. Create .env from template and fill in secrets
copy .env.example .env
# (required: RC_SERPER_API_KEY, RC_ZYTE_API_KEY,
# plus whichever provider you pick, e.g. RC_OPENAI_API_KEY)
# 3. Build the Python-exec sandbox image (needed for python_exec tool)
docker build -t researchcore-sandbox:latest -f Dockerfile.sandbox .
# 4. Initialise the evidence-store DB (creates data/researchcore.db)
python -m alembic upgrade headThe CLI picks the provider and model from flags; you don't need to edit
.env to switch backends.
# Default: pick up RC_LLM_PROVIDER from .env (interactive mode)
python cli.py
# OpenAI (uses RC_OPENAI_MODEL from .env, default gpt-5), one-shot, critic on
python cli.py --provider openai --critic "What's new in TLS 1.3?"
# Explicit model override (use gpt-5 / gpt-4o / o-series for deeper runs)
python cli.py --provider openai --model gpt-5 --critic "What's new in TLS 1.3?"
# Local Ollama, specific tag, 10-minute deadline
python cli.py --provider ollama --model llama3.1:8b --deadline 10 "Explain DP-SGD"
# llama.cpp server running locally on port 9090
python cli.py --provider llama_cpp --base-url http://127.0.0.1:9090/v1 --model Qwen2.5-7B-Instruct
# Custom OpenAI-compatible endpoint (Azure / Groq / vLLM / LM Studio)
python cli.py --provider openai --base-url https://my-proxy/v1 --model gpt-4.1-miniFlag reference:
| Flag | Purpose |
|---|---|
--provider {ollama,openai,llama_cpp} |
Override RC_LLM_PROVIDER for this run. |
--model <name> |
Main model (maps to the right field per provider). |
--base-url <url> |
Override the provider's base URL. |
--critic |
Enable the adversarial critic pass. |
-v, --verbose |
Log every outbound HTTP call (LLM, Serper, Zyte, Kroki) + DEBUG events. |
--deadline <min> |
Time budget (1–120 min). |
<query> |
One-shot mode; omit for interactive. |
API keys are never passed as CLI flags — always via .env
(RC_OPENAI_API_KEY, RC_LLAMA_CPP_API_KEY, RC_LLM_API_TOKEN).
research> your research question here
research> /provider show current provider / model / critic status
research> /critic [on|off] toggle critic pass for this session
research> /deadline 15 change deadline (1–120 min)
research> /history list runs in this session
research> /last show the last result again
research> /help full help
research> /quit exit
Launch the API server (separate from the CLI):
# Remote GPU Ollama over SSH tunnel (uses start.ps1 + .env)
.\start.ps1
# OR local Ollama (no tunnel)
.\start-local.ps1
# OR plain uvicorn (works with any RC_LLM_PROVIDER)
python -m uvicorn src.api.app:app --host 0.0.0.0 --port 8080 --reloadEndpoints (all protected by Authorization: Bearer $RC_API_TOKEN if set):
# Start a deep-research task
curl -X POST http://localhost:8080/research `
-H "Content-Type: application/json" `
-H "Authorization: Bearer $env:RC_API_TOKEN" `
-d '{\"query\": \"Compare Qwen2.5 vs Llama 3.1\", \"critic_enabled\": true}'
# Stream progress
curl -N http://localhost:8080/research/{run_id}/stream `
-H "Authorization: Bearer $env:RC_API_TOKEN"
# Final result — JSON (structured) or Markdown (same report as CLI)
curl http://localhost:8080/research/{run_id} # JSON
curl http://localhost:8080/research/{run_id}/markdown # text/markdown
curl http://localhost:8080/research/{run_id}/evidence
curl http://localhost:8080/research/{run_id}/steps
# Health (no auth)
curl http://localhost:8080/health
curl http://localhost:8080/health/servicespytest # full suite (no network — all HTTP is mocked)
pytest tests/test_llm_providers.py # provider contract tests
pytest --cov=src --cov-report=term-missingAgentX/
├── cli.py interactive CLI + one-shot mode
├── start.ps1 / start-local.ps1 operator scripts (Windows)
├── .env.example config template (secrets are blank)
├── pyproject.toml
├── config/
│ ├── settings.py Pydantic Settings, RC_ prefix
│ └── tool_schemas.py JSON schemas for tool arguments
├── src/
│ ├── api/ FastAPI routes + lifespan
│ ├── llm/
│ │ ├── provider.py LLMProvider Protocol + errors
│ │ ├── providers/ OllamaProvider, OpenAICompatibleProvider
│ │ ├── factory.py build_llm_provider(settings)
│ │ ├── client.py LLMClient facade
│ │ └── {prompts,schemas,response_parser}.py
│ ├── orchestrator/ runner + state machine + recovery + budget
│ ├── tools/ web_search, web_fetch, pdf_read, python_exec, …
│ ├── critic/ optional adversarial review (gated)
│ ├── finalizer/ direct / sectional / two_phase / chunked
│ ├── evidence_store/ async SQLite via SQLAlchemy
│ ├── scratchpad/ per-run in-memory Ledger + filesystem artifacts
│ └── logging_/
├── tests/
├── migrations/ Alembic
├── artifacts/ per-run notes (gitignored)
├── data/ SQLite DB (gitignored)
└── SystemDesign/
├── ARCHITECTURE.md
├── ARCHITECTURE_LAYERS.md
├── providers.md
├── critic.md
├── third-parties.md
└── secret-inventory.md
| Problem | Fix |
|---|---|
LLMConfigError: openai provider requires … |
Missing RC_OPENAI_API_KEY in .env. |
Ollama connection refused via --provider ollama |
Ollama daemon not running (ollama serve), or wrong RC_LLM_BASE_URL. |
llama.cpp 404 on /v1/models |
llama.cpp server not started with OpenAI-compat mode. |
CRITIC skipped in logs |
Expected — critic is off by default. Add --critic. |
RC_SERPER_API_KEY not set — web_search will fail. |
Set it in .env. |
python_exec fails |
Docker Desktop not running, or researchcore-sandbox image missing. |