Server endpoints
The FastAPI server runs on http://localhost:8000 by default. Interactive docs are available at /docs.
Health
GET /health
Returns the server status and the health of each connected component.
Response
{
"status": "ok",
"turingdb": "ok",
"valkey": "ok"
}
status is "ok" only when all components are healthy. Individual components report "ok" or "down".
Dev — one-time setup
POST /dev/build_vector_index
Builds the vector index from all graph nodes that have a text property.
This endpoint is intended to be called once after TuringDB is loaded with graph data. The index persists inside TuringDB — you do not need to rebuild it on subsequent server restarts.
The build is idempotent: already-computed embedding batches (stored as CSVs in data_dir) are skipped. You can safely re-run it after an interrupted build.
Request body
{
"graph_name": "reactome",
"model": "minishlab/potion-base-32M"
}
| Field | Description |
|---|---|
graph_name | Name of the TuringDB graph to index |
model | Embedding model to use (must be in the model registry) |
Supported models
| Model | Dimensions | Provider |
|---|---|---|
snowflake-arctic-embed:33m | 384 | Ollama |
all-minilm:22m | 384 | Ollama |
all-minilm:33m | 384 | Ollama |
minishlab/potion-base-8M | 256 | sentence-transformers |
minishlab/potion-base-32M | 512 | sentence-transformers |
minishlab/static-similarity-mrl-multilingual-v1 | 256 | sentence-transformers |
Response
{
"index_name": "reactome_minishlab_potion_base_32M",
"total_chunks": 48320,
"batches_total": 48,
"batches_computed": 12,
"batches_skipped": 36
}
| Field | Description |
|---|---|
index_name | Name of the created TuringDB vector index |
total_chunks | Total text chunks across all nodes |
batches_total | Number of embedding batches |
batches_computed | Batches that required embedding (new work) |
batches_skipped | Batches loaded from cache (already computed) |
Example
curl -X POST http://localhost:8000/dev/build_vector_index \
-H "Content-Type: application/json" \
-d '{"graph_name": "reactome", "model": "minishlab/potion-base-32M"}'
The TUI's RAG tab has a "Build index" button that does the same thing.
Vector search
POST /vector/search
Embeds a query string and returns the top-k most similar nodes from the vector index.
Request body
{
"query": "ATP synthesis in mitochondria",
"graph_name": "reactome",
"model": "minishlab/potion-base-32M",
"top_k": 5
}
| Field | Default | Description |
|---|---|---|
query | — | Natural language search query |
graph_name | — | Graph to search |
model | — | Embedding model (must match the model used at build time) |
top_k | 5 | Number of results to return |
Response
A JSON array of matching nodes:
[
{
"dbId": 12345,
"displayName": "ATP synthesis coupled to electron transport",
"text": "..."
}
]
Chat
GET /chat/bootstrap-anon
Creates an anonymous session cookie (anon_id, 3-day expiry, httponly) and redirects back to the Streamlit app. Called automatically by the app when no cookie is present.
If the cookie is already present but older than 2 hours, the anon ID is rotated and a fresh cookie is set.
POST /chat/message
Enqueues a chat job and returns immediately with HTTP 202 Accepted. The request is processed asynchronously by a background worker pool — use GET /chat/job/{job_id} to poll for the result or GET /chat/job/{job_id}/stream to receive SSE events.
Rate limiting applies when the request carries an x-anon-id header: 20 requests / 10 min and 500 000 tokens / 10 min per user.
Request body
{
"message": "What pathways involve ATP?",
"session_id": "optional-uuid"
}
| Field | Description |
|---|---|
message | User's message |
session_id | Existing session ID (omit to start a new session) |
Request headers
| Header | Description |
|---|---|
x-anon-id | Anonymous user token (set by the app from the anon_id cookie) |
x-llm-provider | Override LLM provider for this request: ollama or mistral |
x-llm-agent-model | Override the agent model name |
x-llm-router-provider | Override the router LLM provider |
x-llm-router-model | Override the router model name |
All x-llm-* headers are optional. When omitted, the server uses the values from its .env configuration.
Response — HTTP 202
{
"job_id": "uuid",
"session_id": "uuid",
"status": "pending"
}
| Field | Description |
|---|---|
job_id | ID to pass to the job endpoints below |
session_id | UUID for this session (pass back on subsequent requests) |
status | Always "pending" at submission time |
GET /chat/job/{job_id}
Poll for the status and result of a queued job.
Response
{
"job_id": "uuid",
"status": "done",
"result": {
"session_id": "uuid",
"answer": "...",
"route_taken": "agent",
"sources": [...],
"token_usage": {"input_tokens": 123, "output_tokens": 456}
}
}
status is one of "pending", "running", "done", or "error". The result field is present only when status is "done"; error (a string) is present only when status is "error". Returns 404 if the job has expired (TTL: 10 minutes).
GET /config
Returns the server's active LLM configuration. Used by the UI to initialise provider and model dropdowns with server-side defaults.
Response
{
"llm_provider": "ollama",
"router_provider": "ollama",
"ollama_agent_model": "qwen2.5:7b",
"ollama_router_model": "qwen2.5:3b",
"mistral_agent_model": "mistral-large-latest",
"mistral_router_model": "mistral-small-latest"
}
GET /chat/job/{job_id}/stream
SSE stream for a job. Emits routing and agent step events in real time, then a final job_done or job_error event.
| Event | Data | When |
|---|---|---|
routing_started | {} | Router begins classifying the message |
routing_done | {route, confidence, reasoning} | Router finishes |
agent_step | {iteration, model} | Each agent LLM call |
tool_call | {tool, args} | Each tool invocation |
tool_result | {tool, summary} | Tool result (truncated at 200 chars) |
job_done | Full ChatResponse JSON | Job completed successfully |
job_error | {error} | Job failed |
GET /chat/sessions
Returns all live session IDs for a user. Expired sessions are pruned lazily.
Query parameters
| Parameter | Description |
|---|---|
anon_id | The anon_id cookie value |
Response
{"sessions": ["uuid-1", "uuid-2"]}
GET /chat/session/{session_id}
Returns the full message history for a session. Returns 404 if the session has expired or does not exist.
Response
{
"session_id": "uuid",
"name": "My session",
"created_at": 1712345678.0,
"messages": [
{"role": "user", "content": "What is EGFR?", "route": null, "confidence": null},
{"role": "assistant", "content": "EGFR is...", "route": "agent", "confidence": 0.91}
]
}
PATCH /chat/session/{session_id}
Renames a session. Returns 404 if the session does not exist.
Request body
{"name": "My renamed session"}
Response
{"session_id": "uuid", "name": "My renamed session"}
DELETE /chat/session/{session_id}
Deletes a session and removes it from the user's session list. Returns HTTP 204 with no body.
Pass x-anon-id header to ensure the session is also removed from the user's session index in Valkey.
MCP (Model Context Protocol)
POST /mcp/*
The server exposes a FastMCP server mounted at /mcp. External AI agents (Claude Desktop, OpenAI Agents SDK, etc.) can connect to this endpoint to use the knowledge graph as a tool.
Two tools are available:
| Tool | Parameters | Description |
|---|---|---|
vector_search | sentence, graph_name, top_k | Semantic similarity search over the indexed graph |
graph_query | cypher_query, graph_name | Execute a Cypher query and return results |
Both tools create their own TuringDB client per call using the chat-agent configuration (TURINGDB_URL, TURINGDB_PORT).
Query (stub)
POST /query
Warning
This endpoint is not implemented and raises NotImplementedError. It is a placeholder for a future single-call vector search + RAG endpoint.