// Literature triage as a pipeline: screen abstracts against the criteria,
// read the included papers, extract an evidence table. A scientist settles
// the borderline calls the screener marks as UNSURE.
const SWARMS_API = "https://api.swarms.world/v1/swarm/completions"
type Abstract = { id: string; title: string; text: string }
type SwarmResponse = {
output: unknown
usage: { input_tokens: number; output_tokens: number; total_tokens: number }
}
const CRITERIA =
"Include: primary data, in vivo or human, on the target in a fibrotic model. " +
"Exclude: reviews, in silico only, non-mammalian models."
export async function triageLiterature(abstracts: Abstract[]): Promise<SwarmResponse> {
const corpus = abstracts.map((a) => "[" + a.id + "] " + a.title + "\n" + a.text).join("\n\n")
const res = await fetch(SWARMS_API, {
method: "POST",
headers: {
"x-api-key": process.env.SWARMS_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Literature Triage",
description: "Abstract screen, full-text review and evidence extraction with sources.",
swarm_type: "SequentialWorkflow",
task: "Criteria: " + CRITERIA + "\n\nAbstracts:\n\n" + corpus,
agents: [
{
agent_name: "Abstract Screener",
system_prompt:
"Screen each abstract against the criteria. Return one line per id: INCLUDE, EXCLUDE or UNSURE, " +
"then the criterion that decided it. UNSURE goes to a scientist; never guess.",
model_name: "gemini-2.5-flash", // many short abstracts, a fast model is enough
max_loops: 1,
},
{
agent_name: "Full-text Reviewer",
system_prompt:
"For each INCLUDE, summarise model system, intervention, endpoint, effect size and n, " +
"quoting the passage each value comes from. Mark values you cannot find as NOT REPORTED.",
model_name: "gemini-2.5-pro", // long context for the full texts
max_loops: 1,
},
{
agent_name: "Evidence Extractor",
system_prompt:
"Build a markdown evidence table: paper id, model, intervention, endpoint, effect, n, quote. " +
"One row per finding. Do not fill cells that the reviewer marked NOT REPORTED.",
model_name: "claude-haiku-5-5",
max_loops: 1,
},
],
max_loops: 1,
}),
})
if (!res.ok) throw new Error("Swarms API " + res.status + ": " + (await res.text()))
return (await res.json()) as SwarmResponse
}
triageLiterature([
{ id: "P-001", title: "Kinase inhibition reduces collagen deposition in a bleomycin model", text: "..." },
{ id: "P-002", title: "A review of kinase signalling in fibrosis", text: "..." },
{ id: "P-003", title: "Docking study of kinase ligands", text: "..." },
]).then((r) => console.log(r.output, r.usage.total_tokens + " tokens"))