BioAgents Architecture
BioAgents is the AI layer of the platform. It is a separate ElizaOS deployment that the API reaches over HTTP and that no browser talks to directly. It holds a knowledge base of the papers researchers register, a knowledge graph of published papers, and a protein structure plugin over public structural databases. The API proxies to all three and keeps a paper registry of its own on top.
It is not a pipeline that turns an uploaded PDF into triples. Papers you register are indexed so the agent can answer questions about them. The graph is loaded separately from curated records. This page describes what each part does and which routes reach it.
The framework underneath
BioAgents runs on the ElizaOS agent framework, which supplies the runtime, the plugin mechanism, the character that gives the agent its persona, messaging channels over HTTP and Socket.IO, and Postgres storage with pgvector through its SQL plugin. The agent's text model comes from whichever provider key the deployment sets, OpenAI, Anthropic or OpenRouter. The API addresses one agent, either the one named by BIOAGENTS_AGENT_ID or the first active one, and authenticates to the server with an API key when the server requires it.
Three plugins
Knowledge base
plugin-knowledge is what a registered paper lands in. A PDF is read with pdf.js, the text is split into chunks, each chunk is embedded, and chunks are stored in Postgres with pgvector. Documents are keyed by content, so uploading the same file twice returns the existing document. A search returns the chunks nearest to the query with a similarity score. The agent uses the same index to ground its answers.
| Route | What it does |
|---|---|
POST /api/bioagents/knowledge/upload?agent_id= | Uploads a file into the agent's knowledge base (multipart file) |
GET /api/bioagents/knowledge/search?agent_id=&q=&limit= | Nearest chunks for a query, 1 to 100 results |
POST /api/bioagents/knowledge | Adds a text document with title, content and keywords |
POST /api/bioagents/search | The same search against the active agent, with query in the body |
Results are normalised to { name, entity_type, identifier, similarity }, where name is the source file and identifier the chunk id.
Knowledge graph
plugin-kg answers research questions from Oxigraph, a SPARQL triple store of scientific papers stored as JSON-LD with one named graph per DOI. It offers typed searches by concept, author and DOI, stores generated hypotheses in a graph of their own, and runs a question pipeline. In that pipeline the agent's text model plans the searches and writes the synthesis, and the plugin builds every SPARQL query from typed inputs. The routes and the vocabulary are on Knowledge Graph Integration.
Protein structure
plugin-structure looks up proteins in AlphaFold DB, AlphaMissense, UniProt and 3D-Beacons. The API proxies four read routes.
| Route | What it does |
|---|---|
GET /api/bioagents/structure/resolve?q=&taxon= | Resolve a gene or protein name to a UniProt accession |
GET /api/bioagents/structure/report?accession= | A structure report for the accession |
GET /api/bioagents/structure/variant?accession=&variant= | The AlphaMissense verdict for a variant |
GET /api/bioagents/structure/models?accession= | Available models from 3D-Beacons |
GET /api/bioagents/structure/health is public. Answers from the plugin are validated by the API before they are returned, and the plugin's 400 and 404 verdicts pass through.
Asking the agent
POST /api/bioagents/query sends a question of 1 to 4000 characters to the agent's persona through its messaging channel and returns the answer with the DOIs it cited.
curl -X POST https://api.ekayana.io/api/bioagents/query \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "query": "What is known about BRCA1 and homologous recombination?" }'{ "answer": "...", "sources": ["https://doi.org/10.1038/...", "https://doi.org/10.1016/..."] }POST /api/bioagents/query-ws asks the same question over the Socket.IO channel. GET /api/bioagents/health and GET /api/bioagents/agents are public and report whether the server answers and which agents are online.
Registering a paper
A paper is a file you uploaded plus a DID. POST /api/research-paper creates a DID of kind paper whose public metadata document carries the title, authors and keywords, records the paper, and answers 202 while ingestion runs in the background.
curl -X POST https://api.ekayana.io/api/research-paper \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"file_cid": "bafybeig...",
"title": "CRISPR-Cas9 Gene Editing for Neurodegenerative Diseases",
"authors": ["Jane Smith", "John Doe"],
"doi": "10.1038/s41586-021-03819-2",
"keywords": ["CRISPR", "neurodegeneration"]
}'{ "message": "paper registered", "did": "did:bio:devnet:9Ls2...", "status": "pending" }Ingestion does two things. It opens the sealed file and uploads it to the knowledge base, which extracts, chunks and embeds the text. This can take minutes for a long paper. If a DOI was given, it also asks the knowledge graph for that DOI's record and fills in whatever you left empty. That covers the abstract, venue, date, authors, keywords, and the paper's subject terms as biological_entities. Anything you supplied wins. The paper's status moves from pending to completed, or to failed with an error, or is skipped when you passed "ingest": false.
| Route | What it does |
|---|---|
GET /api/research-paper/did/{did} | The paper record with its status |
GET /api/research-paper/cid/{cid} | The most recent paper registered for a file |
GET /api/research-paper/search?query= | Registered papers whose title, abstract, authors or keywords contain the query |
PUT /api/research-paper/{did} | Edit title, authors, DOI, abstract, keywords, date, journal or entities |
POST /api/research-paper/{did}/ingest | Run ingestion again after a failure or a skip |
GET /api/research-paper/{did}/knowledge-graph | The knowledge graph record for the paper's DOI |
Rerunning ingestion is safe, because the knowledge base keys documents by content and returns the existing one. A run still within its upload timeout is left alone and the call answers 409.
AI analysis, separately
POST /api/ai/process-paper is separate from BioAgents. It extracts the text of one of your files with a PDF parser and asks an OpenAI model for a structured reading.
curl -X POST https://api.ekayana.io/api/ai/process-paper \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "cid": "bafybeig...", "title": "CRISPR-Cas9 Gene Editing for Neurodegenerative Diseases" }'{
"success": true,
"analysis": {
"title": "...", "authors": ["..."], "doi": "10.1038/...",
"summary": "...",
"key_findings": ["..."],
"biological_entities": [{ "name": "BRCA1", "entity_type": "gene", "description": "..." }],
"methods": ["..."], "keywords": ["..."], "applications": ["..."]
}
}It works on any file you own or hold a read pass for and accepts an optional model from GET /api/ai/models. It is available only when the operator has configured an OpenAI key, and answers 503 otherwise. What it returns is a model's reading of the text rather than a lookup in the graph. POST /api/ai/chat offers the same model as a plain chat.
Security and privacy
Two boundaries matter here.
The API decrypts a paper only for its owner's ingestion. The knowledge base receives the plaintext of a paper because the account that owns it registered it. Nothing crosses that line for a file that was merely shared with you, because registration requires the file to be your own upload.
The knowledge base is shared by every user of the agent. Chunks indexed for one account are searchable by every account that can query the agent, and the agent grounds its answers in them for everyone. Register a paper only if its text may be read by every user of the platform. A prepublication manuscript belongs in sealed storage and nowhere else. The API forwards questions to the agent under its own server key rather than under the user's identity. The BioAgents routes involve no UCAN, and a session token is the only credential they check.