A dedicated, always-on frontier-discovery engine. Not a chatbot with a science persona — a coalition of
seven specialized reasoning agents that generate competing hypotheses, referee them against each other in
a live Elo tournament, refine the survivors, and hand back a research overview with a recommended next
experiment. Architecturally descended from Google DeepMind's AI co-scientist (generate → reflect → rank →
evolve → meta-review), rebuilt around a single model — gemini-3.5-flash-lite — with reasoning depth
controlled per call rather than by swapping models, and with a persistence model designed around one idea:
a research thread should never die because a browser tab closed.
This is the successor to Xylia I (the image-analysis / study companion). Xylia II keeps everything about Xylia I that was actually infrastructure — persistent TinyDB storage, full workspace export/import as a single zip, PDF/Markdown/audio export, multimodal file grounding, a sidebar vault of past sessions — and replaces the pedagogical image-analysis features with a purpose-built research coalition. It is a new application, not a reskin.
| File | What it owns |
|---|---|
xylia2_config.py |
Every constant, JSON schema, and thinking-budget policy. No side effects. |
xylia2_database.py |
TinyDB persistence for every table, plus the master export_workspace_zip / import_workspace_zip continuity mechanism. |
xylia2_llm_client.py |
The single point of contact with Gemini — structured JSON calls, plain chat calls, and web-grounded calls, all logged. |
xylia2_agents.py |
The seven-agent coalition (Supervisor, Generation, Reflection, Ranking, Evolution, Proximity, Meta-review) plus Literature grounding, Memory extraction, and Elo tournament math. |
xylia2_orchestrator.py |
Runs the actual research cycle: seeds a pool, runs tournament rounds, decides when to stop, handles focus deep-dives and novelty checks. |
xylia2_export.py |
PDF / Markdown / JSON / spoken-summary generation from research state. |
xylia2_theme.py |
The "Event Horizon" visual identity — CSS injection only, no logic. |
xylia2_app.py |
The Streamlit UI. Run this file. |
tests/test_smoke.py |
A mocked end-to-end integration test — exercises the entire orchestration pipeline against a schema-faithful fake of the Gemini API, with no network and no API key required. Run it after any change to verify the wiring before spending real API calls. |
Total: ~3,600 lines across eight modules, deliberately kept multi-file rather than one monolith — each
file has exactly one job, and none of them import Streamlit except xylia2_app.py itself, so the research
logic is fully testable in isolation (which is exactly what tests/test_smoke.py does).
- State a goal. In the Discovery Lab, write the research question. Attach evidence if you have it — an image, a dataset excerpt, a document. The Supervisor disambiguates the goal, classifies what kind of inquiry it is, and decides how many initial hypotheses it warrants.
- Ground it (optional, on by default). The Literature agent runs a real, live Google Search through the Gemini API's grounding tool and produces a citable brief on what's actually established — so Generation is pushing past the real current edge, not an assumed one.
- Seed the pool. Generation produces the initial competing hypotheses (literature / debate / expand modes). Reflection triages them fast, rejecting anything with an obvious fatal flaw.
- Run rounds. Each round: a few fresh hypotheses are injected, Proximity clusters and retires near-duplicates, Ranking runs pairwise simulated debates and updates Elo ratings, Evolution refines the current top-K into strictly improved variants, and Meta-review synthesizes the whole tournament into an executive summary with recommended next experiments — and decides honestly whether another round would surface anything new.
- Stop conditions. Max rounds reached, ratings converge (stop moving round over round), the meta-review itself says the pool is exhausted, or you stop it by hand. Never silent.
- Everything is durable. Every hypothesis, review, match, evolution event, and meta-review is written to TinyDB the instant it's produced. Download the whole workspace as a zip anytime; re-upload it later — on any machine — to resume exactly where you left off. The zip is the account.
Outside the formal tournament, Collaborate gives you free-form reasoning with Xylia, including the GAN-style adversarial modes from the original design brief (you generate / Xylia critiques harshly, or the reverse, or Xylia argues the strongest case against whatever you just said). Knowledge Memory is the long-horizon context that survives across every future thread and chat — durable facts get extracted automatically, or you can pin/add them by hand.
From Google AI Studio. The app talks to exactly one model,
gemini-3.5-flash-lite, via the current google-genai SDK.
pip install -r requirements.txtgTTS (audio) and weasyprint (PDF) are optional — the app detects their absence and simply hides those
export buttons rather than crashing. WeasyPrint needs system libraries; see requirements.txt for the
apt packages.
mkdir -p .streamlit
cp secrets.toml.example .streamlit/secrets.toml
# edit .streamlit/secrets.toml and paste your real keyOr set the environment variable GEMINI_API_KEY directly — the app checks both.
streamlit run xylia2_app.pypython tests/test_smoke.pyThis runs the full seven-agent pipeline — grounding, generation, tournament rounds, evolution, meta-review, novelty checks, export/import — against a mock of the Gemini API. No key needed, no network call made. If this passes, the orchestration logic is sound and any remaining issues would be about the live model's actual answers, not the plumbing.
Streamlit doesn't serve directly out of a Colab notebook cell, so you need a tunnel. The straightforward path:
# Cell 1 — install
!pip install -q streamlit google-genai tinydb Pillow pandas gTTS
!apt-get -qq install -y libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf2.0-0 libcairo2 libffi-dev
!pip install -q weasyprint
# Cell 2 — upload xylia2_*.py into the Colab filesystem (drag-and-drop into the Files pane,
# or unzip the delivered workspace archive), then write your key
import os
os.makedirs(".streamlit", exist_ok=True)
with open(".streamlit/secrets.toml", "w") as f:
f.write('GEMINI_API_KEY = "your-gemini-api-key-here"\n')
# Cell 3 — launch with a tunnel (cloudflared is the most reliable free option in Colab)
!wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -O cloudflared
!chmod +x cloudflared
import subprocess, time, re
subprocess.Popen(["streamlit", "run", "xylia2_app.py", "--server.port", "8501", "--server.headless", "true"])
time.sleep(6)
tunnel = subprocess.Popen(["./cloudflared", "tunnel", "--url", "http://localhost:8501"],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
for line in tunnel.stdout:
print(line, end="")
if "trycloudflare.com" in line:
break # the printed https://*.trycloudflare.com URL is your live appThis app itself does no GPU work — every heavy computation is a Gemini API call — so a CPU-only Colab runtime is enough; the T4 runtime you use for the AI Art Generator project is not needed here.
- Single model, variable depth.
MODEL_IDinxylia2_config.pyis the only place a model name is ever written. Every agent instead sets athinking_level(minimal→high) appropriate to how hard that specific call needs to think. If you want to try a different Gemini model, this is the one line to change. - Structured output vs. grounded search are mutually exclusive per call. The Gemini API cannot combine
response_json_schemawith thegoogle_searchtool in one request. Grounding is therefore always its own free-text call whose output becomes context fed into the next structured call — never combined into one. SeeXyliaLLMClient.generate_groundedandLiteratureAgentinxylia2_agents.py. - Session state is a cache; TinyDB is the record. Nothing about resuming work depends on Streamlit's session state surviving. Every stage of a tournament round commits to the database as soon as it completes, so a crash mid-round loses at most the in-flight stage, never the round before it.
- Termination is explicit.
ResearchOrchestrator.run_next_roundalways returns areason_codewhen a tournament converges (MAX_ROUNDS,ELO_STABLE,POOL_EXHAUSTED,MANUAL_STOP) — seeTERMINATION_REASONSinxylia2_config.py. The system is built to never leave you wondering whether it stopped on purpose. - Elo pairing seeds by rating proximity, not randomly — closely rated hypotheses produce the most informative debates, and a hypothesis is never repeatedly pitted against one that has already been eliminated from contention.