MOSAIC: Building a Multi-Agent Clinical Trial AI Engine

Clinical research produces more evidence than any human team can read. Roughly half a million studies are registered on ClinicalTrials.gov, PubMed indexes over 37 million citations, and thousands of new records appear every week. The bottleneck in modern medicine is no longer data collection — it is comprehension at scale.
MOSAIC (Multi-Agent Clinical Trial Intelligence Engine) is a reference architecture for solving that bottleneck. It combines a retrieval-augmented generation (RAG) pipeline over registry and literature data, a durable memory layer, and a supervised team of specialised AI agents orchestrated with LangGraph. This article walks through the full system: data sources, ingestion, embeddings, retrieval, memory, agent design, human oversight, deployment on Google Cloud, monitoring, security, and the trade-offs we would make differently at enterprise scale.
It is written for two audiences at once. If you are a clinical or commercial stakeholder, the conceptual sections explain what each layer buys you. If you are an engineer, the tables, schemas and code fragments are enough to start building.
Why Clinical Research Needs AI
A single therapeutic question — say, whether a class of GLP-1 agonists shows consistent cardiovascular benefit across sponsors — touches hundreds of registered trials and thousands of publications. Answering it properly means reading protocols, matching registry entries to published results, checking whether primary endpoints changed mid-study, and noticing which sponsors never published at all.
Done manually, that is weeks of specialist time per question. Done with a naive chatbot, it is fast and wrong. The interesting engineering problem sits between the two: how do you get machine speed with evidence-grade traceability?
- Volume: over 500,000 registered studies, growing by roughly 30,000 per year.
- Fragmentation: registry records, results postings, journal articles and regulatory documents live in different systems with different identifiers.
- Silent failure: a substantial share of completed trials never post results, so absence of evidence is itself a signal worth detecting.
- Protocol drift: outcome measures are frequently changed after enrolment begins, which is invisible unless you diff registry versions.
- Language and structure: eligibility criteria and adverse-event narratives are free text, not fields you can query with SQL.
Every one of those problems is a retrieval, comparison or reasoning task. That is exactly the shape of work that agentic AI systems handle well — provided the architecture keeps the model grounded in real documents.
Problems with Traditional Clinical Research Tooling
Before describing MOSAIC, it helps to be precise about what existing tools do not do.
| Approach | What it does well | Where it breaks |
|---|---|---|
| Keyword search on registries | Fast lookup of a known trial ID or sponsor | Misses semantic equivalents; cannot compare across studies |
| Systematic literature review | Rigorous, peer-reviewable, high trust | Takes 6–18 months; outdated on publication day |
| BI dashboards on registry exports | Good counts and trends | No reasoning over free text; no linkage to publications |
| Single-prompt LLM chat | Instant natural-language answers | Hallucinates trial IDs; no provenance; no memory; context limits |
| Fine-tuned domain model | Fluent in medical register | Facts frozen at training time; expensive to refresh |
The recurring failure is provenance. In clinical contexts an answer without a citation chain is not an answer — it is a liability. MOSAIC is designed so that every claim can be traced back to a chunk, a document, a source URL and a retrieval timestamp.
What Is MOSAIC?
MOSAIC is a multi-agent clinical trial intelligence engine. Instead of one large prompt attempting everything, it decomposes a research question into specialised sub-tasks, runs them in parallel where possible, and reconciles the findings through a supervisor agent that owns the final synthesis.
In one sentence: MOSAIC turns registry and literature corpora into an auditable analytical workforce.
Its four defining properties:
- Grounded — every agent answers from retrieved passages, never from parametric memory alone.
- Specialised — each agent has a narrow mandate, its own tools, and its own evaluation set.
- Stateful — episodic, procedural and semantic memory persist between sessions.
- Supervised — a human reviewer can interrupt, correct, or approve before conclusions are published.
Architecture Overview
The system is a five-layer stack. Data flows upward; control flows downward from the supervisor.
┌──────────────────────────────────────────────────────────┐
│ 5. INTERFACE Web app · API clients · Reports · Alerts │
├──────────────────────────────────────────────────────────┤
│ 4. ORCHESTRATION LangGraph supervisor + 6 sub-agents │
│ parallel fan-out · human-in-the-loop · checkpoints │
├──────────────────────────────────────────────────────────┤
│ 3. REASONING GPT-4o · RAG retriever · memory manager │
├──────────────────────────────────────────────────────────┤
│ 2. STORAGE PostgreSQL + pgvector · GCS · metadata DB │
├──────────────────────────────────────────────────────────┤
│ 1. INGESTION ClinicalTrials.gov API · PubMed E-utils │
│ parsers · normalisers · chunkers · embedders │
└──────────────────────────────────────────────────────────┘Each layer is independently deployable. The ingestion layer runs as scheduled jobs, storage is managed infrastructure, reasoning and orchestration run in a stateless FastAPI service on Cloud Run, and the interface is a thin client over the API.
Data Sources
ClinicalTrials.gov
The primary registry source. The modern v2 REST API returns structured JSON per study: identification, status, sponsors, conditions, interventions, eligibility, outcome measures, results postings and a full version history. That version history is the raw material for detecting protocol drift.
Practical notes from production: paginate with the page token rather than offsets, store the raw payload verbatim before any transformation, and keep the record version hash so re-ingestion is idempotent.
PubMed
The literature counterpart, accessed through the NCBI E-utilities. Fetch titles, abstracts, MeSH terms, publication dates, and — crucially — any registry identifiers mentioned in the record, which is how you link a publication back to its trial.
| Source | Unit | Volume | Refresh | Primary use |
|---|---|---|---|---|
| ClinicalTrials.gov | Study record | ~500k | Daily delta | Design, status, sponsor, results posting |
| ClinicalTrials.gov history | Record version | Millions | Daily delta | Endpoint changes, timeline shifts |
| PubMed | Citation + abstract | 37M+ | Daily delta | Published outcomes, safety signals |
| Internal documents | PDF / DOCX | Client-specific | On upload | Protocols, CSRs, internal memos |
Data Ingestion Layer
Ingestion is deliberately boring: fetch, validate, normalise, persist raw, then transform. Every stage is retryable and every artefact keeps a source URL plus a fetch timestamp.
async def ingest_study(nct_id: str) -> None:
raw = await ctgov.fetch_study(nct_id) # 1. fetch
validate(raw) # 2. schema check
await gcs.put_json(f"raw/ctgov/{nct_id}.json", raw) # 3. immutable raw
study = normalise_study(raw) # 4. typed model
await db.upsert_study(study) # 5. relational facts
docs = build_documents(study) # 6. text units
for doc in docs:
chunks = chunk(doc, size=800, overlap=120)
vectors = await embed_batch([c.text for c in chunks])
await db.upsert_chunks(doc, chunks, vectors) # 7. pgvectorDocument Parsing
Registry JSON is already structured, so parsing effort concentrates on PDFs: protocols, statistical analysis plans, and clinical study reports. Layout-aware extraction matters — a naive text dump destroys tables, and tables are where the endpoints live. Preserve section headings as chunk metadata; that single decision improves retrieval precision more than most re-ranker tuning.
Cloud Storage
Google Cloud Storage holds every raw payload and uploaded document, with object versioning enabled and lifecycle rules moving cold objects to nearline storage. The rule is simple: the database can always be rebuilt from the bucket.
PostgreSQL
PostgreSQL stores the relational truth — studies, sponsors, conditions, interventions, outcomes, publications and their links — alongside the vector index. Keeping both in one engine avoids the consistency problems of a separate vector store and lets you filter semantically and structurally in a single query.
create table study (
nct_id text primary key,
title text not null,
phase text,
status text,
sponsor_id bigint references sponsor(id),
start_date date,
completion_date date,
results_posted boolean default false,
raw_uri text not null,
fetched_at timestamptz not null default now()
);
create table chunk (
id bigserial primary key,
nct_id text references study(nct_id) on delete cascade,
section text,
content text not null,
embedding vector(1536) not null,
source_url text not null
);
create index on chunk using hnsw (embedding vector_cosine_ops);
create index on chunk (nct_id, section);Vector Database, Embeddings and Chunking
pgvector turns PostgreSQL into a competent vector database. With an HNSW index, approximate nearest-neighbour search over tens of millions of chunks stays in the low tens of milliseconds — fast enough that retrieval is never the bottleneck in an agent loop.
Chunking Strategy
Chunking decides retrieval quality more than embedding choice does. Our defaults, arrived at empirically:
- Chunk on semantic boundaries first (section, then paragraph), and only fall back to fixed windows inside oversized sections.
- Target 600–900 tokens with 10–15% overlap.
- Never split a table across chunks; serialise it as Markdown and keep it whole.
- Prepend a short context header (study ID, phase, section name) to every chunk before embedding.
- Store section, sponsor and phase as filterable columns so retrieval can be narrowed pre-search.
Embeddings
A 1536-dimension general-purpose embedding model handles biomedical text well when chunks carry context headers. Batch embedding calls, cache by content hash, and version the model name on every row — the day you upgrade models, you need to know which vectors are stale.
| Dimension | SQL / relational | Vector search |
|---|---|---|
| Query type | Exact filters, joins, aggregates | Semantic similarity |
| Example | All Phase III trials completed in 2024 | Trials describing fatigue as a secondary endpoint |
| Precision | Deterministic | Probabilistic, needs re-ranking |
| Latency | Sub-millisecond with indexes | Tens of milliseconds with HNSW |
| Best used for | Cohort construction, counting, eligibility | Concept discovery, narrative comparison |
MOSAIC uses both in one query: structural filters narrow the candidate set, vector similarity ranks within it. This hybrid pattern beats either approach alone on almost every clinical benchmark we run.
Retrieval-Augmented Generation (RAG)
RAG is the grounding mechanism. Instead of asking the model what it remembers, MOSAIC retrieves the evidence and asks the model to reason over it, with citations required in the output schema.
question
│
├─▶ query rewrite (expand acronyms, add MeSH synonyms)
├─▶ structural filter ──▶ candidate set (SQL)
├─▶ vector search ──▶ top-k chunks (pgvector, k≈40)
├─▶ cross-encoder rerank ──▶ top-n chunks (n≈8)
├─▶ prompt assembly (chunks + memory + task schema)
├─▶ GPT-4o reasoning
└─▶ answer + citations + confidenceRAG vs Fine-Tuning
| Criterion | RAG | Fine-tuning |
|---|---|---|
| Knowledge freshness | Live — reindex and it is current | Frozen at training time |
| Provenance | Native citations | None |
| Cost to update | Cost of embedding new documents | Full retraining cycle |
| Controls hallucination | Strongly, when grounding is enforced | Weakly |
| Teaches style / format | Weakly | Strongly |
| Right choice for MOSAIC | Yes — facts change weekly | Only for output formatting |
The practical answer is not either-or. Use RAG for facts and, if needed, a light fine-tune or a well-engineered system prompt for tone and structure.
AI Memory
Retrieval gives an agent knowledge of documents. Memory gives it knowledge of the work. MOSAIC keeps three distinct memory types, each with its own store and lifecycle.
Episodic Memory
What happened. Every session records the question asked, the plan produced, agents invoked, evidence retrieved, and the reviewer verdict. Episodic memory makes runs reproducible and lets a follow-up question inherit context without re-running the pipeline.
Procedural Memory
How to do things. Reusable playbooks: how to detect an endpoint change, which filters produce a clean sponsor cohort, which query rewrites work for oncology terminology. Procedural memory is what turns a corrected mistake into a permanent improvement.
Semantic Memory
What is true. A curated knowledge layer — validated entity mappings between sponsors, drug synonyms, condition ontologies, and confirmed trial-to-publication links. Facts enter semantic memory only after human confirmation, which keeps it trustworthy enough to short-circuit retrieval.
| Memory | Stores | Written by | Read when |
|---|---|---|---|
| Episodic | Run traces, decisions, verdicts | Every run automatically | Follow-up questions, audit |
| Procedural | Playbooks, heuristics, prompts | Learning loop after review | Planning phase |
| Semantic | Verified entities and links | Human-approved extraction | Retrieval and disambiguation |
The LangGraph Multi-Agent System
LangGraph models the workflow as a state graph rather than a chain: nodes are agents, edges are conditional transitions, and the shared state object carries the accumulating evidence. That structure is what makes parallelism, retries, interrupts and checkpointing tractable.
┌────────────────┐
question ───▶│ SUPERVISOR │◀──── memory
└───────┬────────┘
┌───────────┬───────┼───────┬───────────┬──────────┐
▼ ▼ ▼ ▼ ▼ ▼
┌──────────┐ ┌────────┐ ┌──────┐ ┌────────┐ ┌────────┐ ┌────────┐
│ Broken │ │Missing │ │Sponsor│ │Pattern │ │Timeline│ │ Side │
│ Promises │ │Results │ │Analysis│ │ Finder │ │ │ │ Effect │
└────┬─────┘ └───┬────┘ └──┬───┘ └───┬────┘ └───┬────┘ └───┬────┘
└───────────┴─────────┴─────────┴──────────┴──────────┘
▼
┌────────────────┐
│ SYNTHESIS + │
│ HUMAN REVIEW │
└───────┬────────┘
▼
report · citations · memory writeSupervisor Agent
The supervisor decomposes the question, decides which specialists are relevant, dispatches them, and reconciles conflicting findings. It never analyses evidence itself — that separation keeps its prompt small and its behaviour predictable. It also owns budget: maximum agent invocations, token ceilings and wall-clock limits per run.
Broken Promises Agent
Compares registry versions to detect changed primary or secondary endpoints after enrolment started, silently widened eligibility, or shifted statistical plans. Output is a diff with dates, the pre- and post-change wording, and a severity judgement.
Missing Results Agent
Identifies completed studies with no results posted and no matching publication after the reporting window. Cross-checks PubMed by registry ID, sponsor, and title similarity before declaring a gap — false positives here are expensive to a reader's trust.
Sponsor Analysis Agent
Profiles a sponsor's portfolio: phase distribution, therapeutic focus, completion rates, average time from completion to reporting, and comparative reporting discipline against peers.
Pattern Finder Agent
Looks across cohorts for recurring design choices — surrogate endpoint preferences, comparator selection, unusual enrolment ratios — using clustering over embeddings plus structured aggregation.
Timeline Agent
Reconstructs each study's chronology from version history: registration, first posting, enrolment milestones, completion, results posting, publication. Surfaces anomalous gaps.
Side Effect Detection Agent
Extracts adverse events from results postings and abstracts, normalises terminology, and flags disproportionate reporting relative to comparator arms. This agent is deliberately conservative: it reports signals for human epidemiological review, never conclusions.
Parallel Execution
Independent agents fan out concurrently. Because each writes to a distinct slice of the shared state, LangGraph merges results without contention. In practice a six-agent run finishes in roughly the time of the slowest agent plus synthesis — typically three to five times faster than sequential execution.
graph = StateGraph(ResearchState)
graph.add_node("supervisor", supervisor)
for name, agent in SPECIALISTS.items():
graph.add_node(name, agent)
graph.add_edge(name, "synthesis")
graph.add_conditional_edges("supervisor", route_to_specialists, list(SPECIALISTS))
graph.add_node("synthesis", synthesise)
graph.add_node("review", human_review)
graph.add_edge("synthesis", "review")
app = graph.compile(
checkpointer=PostgresSaver(pool),
interrupt_before=["review"],
)Human-in-the-Loop
The graph interrupts before publication. A reviewer sees the draft synthesis with every citation inline, and can approve, edit, reject with a reason, or send a specific agent back for another pass. Because state is checkpointed in PostgreSQL, review can happen hours later without re-running anything.
Continuous Learning
Reviewer decisions are training data. Rejections with reasons become procedural memory entries and regression test cases; approved entity resolutions become semantic memory. Over months the system needs fewer corrections in the same domains — measurable as a falling edit rate per report.
| Dimension | Single-agent LLM | Multi-agent MOSAIC |
|---|---|---|
| Prompt complexity | One large, brittle prompt | Small, testable prompts per role |
| Parallelism | None | Native fan-out |
| Failure mode | Whole answer degrades | One agent degrades, others hold |
| Evaluation | End-to-end only | Per-agent test sets |
| Traceability | Opaque | Per-agent evidence trail |
| Cost control | Hard to attribute | Per-agent budgets and metrics |
| Best for | Simple Q&A | Multi-step analytical research |
FastAPI Backend
FastAPI exposes the graph over HTTP: async by default, typed request and response models through Pydantic, and generated OpenAPI docs that make the service easy to consume from a web client or another agent.
@router.post("/research", response_model=RunAccepted, status_code=202)
async def start_research(req: ResearchRequest, user: User = Depends(auth)):
run_id = str(uuid4())
await runs.create(run_id, user.tenant_id, req.question)
background.add_task(execute_graph, run_id, req)
return RunAccepted(run_id=run_id, stream_url=f"/research/{run_id}/stream")
@router.get("/research/{run_id}/stream")
async def stream(run_id: str, user: User = Depends(auth)):
await runs.assert_owner(run_id, user.tenant_id)
return EventSourceResponse(agent_events(run_id))Long analyses run as background tasks with server-sent events streaming agent-level progress, so the interface can show which specialist is working rather than an undifferentiated spinner.
Deployment on Google Cloud Run
Cloud Run suits this workload: containerised, scales to zero between research runs, scales out under load, and handles long-lived streaming connections. Cloud SQL for PostgreSQL hosts the database with pgvector enabled; GCS holds documents; Cloud Scheduler triggers ingestion jobs.
| Component | Service | Why |
|---|---|---|
| API + agents | Cloud Run | Stateless, scale-to-zero, streaming support |
| Database | Cloud SQL (PostgreSQL + pgvector) | Relational truth and vectors in one engine |
| Documents | Cloud Storage | Immutable raw layer, versioned, lifecycle rules |
| Scheduled ingestion | Cloud Scheduler + Cloud Run Jobs | Daily deltas without idle cost |
| Secrets | Secret Manager | Rotation, IAM-scoped access, audit trail |
| Logs and traces | Cloud Logging + LangSmith | Infrastructure and reasoning observability |
Monitoring and Observability
LangSmith
Agent systems fail in ways infrastructure metrics never reveal: a retrieval returns plausible but irrelevant chunks, an agent loops, a prompt regression halves citation accuracy. LangSmith traces every node — inputs, outputs, tokens, latency — so a bad answer can be replayed step by step. Curated failure cases become an evaluation set that runs on every prompt change.
Cloud Logging and Metrics
Structured logs carry run ID, tenant, agent name and token cost, which makes per-tenant cost attribution a query rather than a project. Alerts we run in production:
- Retrieval hit rate below threshold (grounding is failing).
- Citation coverage below 95% of factual claims.
- P95 run latency above the agreed SLA.
- Token spend per run exceeding budget by 2x.
- Reviewer rejection rate trending upward week over week.
Security and Compliance
Registry and literature data are public, but the moment a client uploads internal protocols the system enters regulated territory. The controls that matter:
- Secret Manager for all credentials and model keys, with rotation and IAM-scoped access — never environment files in images.
- Tenant isolation enforced at the database layer, not only in application code.
- Encryption in transit and at rest, with customer-managed keys where the client requires it.
- EU data residency by region pinning for European clients, plus data-processing agreements with every subprocessor.
- Audit logging of every retrieval, every model call and every reviewer decision.
- Prompt-injection defences: uploaded documents are treated as untrusted data, never as instructions, and tool access is allow-listed per agent.
- No patient-identifiable data in prompts unless the deployment is explicitly designed and contracted for it.
Real-World Applications
- Competitive intelligence: continuous monitoring of a competitor's trial portfolio, with alerts on new registrations and endpoint changes.
- Portfolio due diligence: rapid evidence assessment of an asset before licensing or acquisition.
- Regulatory preparation: assembling and cross-checking the evidence base ahead of a submission.
- Literature surveillance: weekly digests of new publications relevant to a defined therapeutic question, with provenance.
- Site and feasibility analysis: identifying comparable trials, enrolment patterns and realistic timelines.
- Transparency reporting: quantifying reporting compliance across sponsors or institutions.
Benefits
| Outcome | Typical impact |
|---|---|
| Time to first evidence-backed answer | Days to weeks → minutes |
| Coverage of the relevant corpus | Sampled → exhaustive within scope |
| Traceability | Manual notes → citation per claim |
| Reviewer effort | Research and writing → verification only |
| Repeatability | Analyst-dependent → deterministic pipeline with stored traces |
Challenges and Honest Limitations
A credible architecture article names its weak points.
- Entity resolution is genuinely hard. Sponsor names, drug synonyms and site identifiers are inconsistent across sources; semantic memory reduces but does not eliminate the problem.
- Absence of data is ambiguous. A missing results posting may reflect an exemption, not misconduct — the system must present signals, not verdicts.
- Cost scales with reasoning depth. Multi-agent fan-out multiplies token spend; per-agent budgets are mandatory, not optional.
- Evaluation needs domain experts. Automated metrics catch regressions, not clinical nuance.
- Model dependency. Provider changes shift behaviour, so pin versions and keep the evaluation suite running.
- Latency. A thorough run takes minutes, not seconds. Design the interface around progress, not instant answers.
The Future of Multi-Agent AI in Healthcare
Three shifts are already visible in production systems.
- Standardised agent interoperability, so specialist agents from different vendors can be composed like microservices.
- Knowledge graphs merging with vector retrieval — structure for relationships, embeddings for nuance, queried together.
- Longer-horizon autonomy with tighter oversight: agents that monitor a therapeutic area continuously and escalate only when something material changes.
The direction of travel is not replacing clinical experts. It is compressing the mechanical part of research so expert judgement is applied to conclusions rather than to reading.
Healthcare AI Trends to Watch
- Regulatory frameworks maturing, with the EU AI Act pushing documentation and risk classification into standard practice.
- Small specialised models handling extraction cheaply, reserving frontier models for synthesis.
- Evidence-grade evaluation becoming a procurement requirement, not a nice-to-have.
- On-premise and EU-resident deployments becoming the default for pharmaceutical clients.
Conclusion
MOSAIC is not a single model doing clever things. It is an architecture in which grounded retrieval, durable memory, specialised agents and human oversight each do one job well. That separation is what makes the output trustworthy enough to act on — and the system maintainable enough to keep running.
If you are building in this space, start with the ingestion and retrieval layers. Get provenance right before adding agents. Everything above the storage layer is replaceable; the evidence trail is not.
Key Takeaways
- Clinical research is a comprehension problem, and multi-agent AI is a comprehension architecture.
- Hybrid retrieval — structural filters plus vector similarity in PostgreSQL with pgvector — outperforms either alone.
- RAG handles facts; fine-tuning handles style. Do not confuse the two.
- Three memory types (episodic, procedural, semantic) convert one-off runs into a system that improves.
- LangGraph gives parallelism, checkpointing and human interrupts that a linear chain cannot.
- Human-in-the-loop is a feature, not a limitation, in any regulated domain.
- Observability at the reasoning layer (LangSmith) matters as much as infrastructure monitoring.
- Provenance is the product: an answer without citations has no clinical value.
Frequently asked questions
Related articles
A pragmatic guide for Helsinki-based companies deciding between off-the-shelf LLM tools and a custom RAG system trained on internal knowledge.
How Finnish SMEs and enterprises are cutting manual work with custom AI automation. Real patterns from logistics, manufacturing and e-commerce.
What Finnish and European B2B buyers expect from modern SaaS: GDPR compliance, EU-only hosting, transparent pricing in euros, and human support.
Related Services
Tags
- Multi-Agent AI
- Clinical Trial AI
- Healthcare AI
- Agentic AI
- LangGraph
- RAG
- pgvector
- GPT-4o
- FastAPI
- Google Cloud
- LLM Development
- Enterprise AI
- AI Architecture
- Clinical Research
- Human-in-the-Loop
- Vector Search
- AI Automation
- GDPR
Need a custom AI solution?
Kooshk Tech builds:
- Multi-Agent AI
- Healthcare AI
- RAG Systems
- Enterprise AI
- AI Automation
Monthly AI & automation insights
Practical playbooks for Finnish businesses. No spam. Unsubscribe anytime.