This document describes how to use the APIs provided by this repository.
There are two different API surfaces:
- Local API: starts from a SQLite graph you build with
intern-atlas build. - Hosted Intern Atlas client: calls a hosted Intern Atlas service for broader graph evidence, idea generation, and idea evaluation.
The local API is included in this repository. The hosted API is optional and is accessed through the intern-atlas remote ... CLI or InternAtlasClient.
Build a graph from the example paper metadata:
intern-atlas build \
--input examples/papers.txt \
--out outputs/local_graph.db \
--json outputs/local_graph.json \
--no-llmStart the local API and UI:
intern-atlas serve \
--db outputs/local_graph.db \
--host 127.0.0.1 \
--port 8000Open:
http://127.0.0.1:8000/
OpenAPI docs:
http://127.0.0.1:8000/api/docs
The local server allows browser calls from localhost and 127.0.0.1 by
default. Add more allowed origins for a deployed frontend with:
export INTERN_ATLAS_CORS_ORIGINS="https://your-app.example.com"Use a base URL variable for curl examples:
BASE=http://127.0.0.1:8000/apiThe local API reads a SQLite database produced by intern-atlas build.
Core objects:
- Paper: one paper node.
- Method: extracted method entity, such as
Transformer,LoRA, orFlashAttention. - Paper-method link: whether a paper introduces, uses, extends, or compares a method.
- Evolution edge: method-level relation between two papers, stored in the
citationstable. - Subgraph: a bounded set of papers plus edges between them.
Raw edge direction:
source_id -> target_id
newer paper -> older paper
Example: if FlashAttention extends Transformer, the edge is:
FlashAttention -> Attention Is All You Need
This is a citation-style direction. When presenting evolution to humans, read it as older to newer:
Attention Is All You Need -> FlashAttention
GET /
Browser workspace for the local graph.
Features:
- shows graph statistics;
- builds
/api/v1/evidence/contextevidence packs from a research query; - can switch between the local SQLite graph and a hosted Intern Atlas API;
- provides real
light,balanced, anddeepretrieval modes; - filters by year range, edge type, method text, node count, edge count, and graph depth;
- opens a local paper neighborhood for a selected paper;
- renders a timeline-style SVG graph;
- lists papers, method edges, bottlenecks, mechanisms, and timeline entries;
- downloads the current evidence view as JSON, paper CSV, edge CSV, or Markdown prompt context;
- copies prompt context when clipboard permission is available.
When Hosted API is selected, the browser does not call the hosted service
directly. It calls local proxy endpoints under /api/v1/remote/..., which avoids
browser CORS issues and keeps the hosted API key out of the repository.
Example:
open http://127.0.0.1:8000/On headless servers, open the URL through SSH port forwarding:
ssh -L 8000:127.0.0.1:8000 user@serverNew integrations should prefer /api/v1/... endpoints. The older /api/...
endpoints remain available for compatibility.
Core v1 endpoints:
POST /api/v1/evidence/context
GET /api/v1/methods/search
GET /api/v1/evolution/edges
GET /api/v1/papers/{paper_id}/neighborhood
GET /api/v1/papers/search
POST /api/v1/query
GET /api/v1/llm/tools
POST /api/v1/remote/health
POST /api/v1/remote/evidence/context
POST /api/v1/remote/papers/neighborhood
POST /api/v1/remote/assist/context
POST /api/v1/remote/ideas
POST /api/v1/remote/eval
The most important endpoint for LLM and agent systems is:
POST /api/v1/evidence/context
It returns an evidence pack containing papers, method-evolution edges, bottlenecks, mechanisms, a timeline, and prompt-ready context.
Request:
{
"query": "efficient long-context attention",
"mode": "balanced",
"max_papers": 20,
"max_edges": 40,
"depth": 1,
"year_from": 2020,
"year_to": 2026,
"edge_type": "extends",
"method": "attention",
"include_prompt_context": true
}Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
query |
string | required | Research topic, idea seed, or evaluation target. |
mode |
string | balanced |
light, balanced, or deep; controls maximum depth and default scale. |
max_papers |
integer | 20 |
Requested paper cap. Effective cap is also bounded by mode. |
max_edges |
integer | 40 |
Requested edge cap. Effective cap is also bounded by mode. |
depth |
integer/null | mode default | Graph expansion depth. light caps at 0, balanced at 2, deep at 4. |
year_from |
integer/null | none | Keep papers at or after this year. |
year_to |
integer/null | none | Keep papers at or before this year. |
edge_type |
string/null | none | Keep only a specific evolution edge type. |
method |
string/null | none | Keep edges associated with a source, target, or paper method. |
include_prompt_context |
boolean | true |
Include prompt-ready Markdown-like context. |
Response shape:
{
"query": "efficient long-context attention",
"papers": [],
"method_edges": [],
"bottlenecks": [],
"mechanisms": [],
"timeline": [],
"suggested_prompt_context": "Use this Intern Atlas evidence pack...",
"counts": {
"papers": 0,
"method_edges": 0,
"bottlenecks": 0,
"mechanisms": 0
},
"parameters": {
"mode": "balanced",
"depth": 1,
"max_papers": 20,
"max_edges": 40,
"year_from": 2020,
"year_to": 2026,
"edge_type": "extends",
"method": "attention"
}
}Example:
curl -X POST "$BASE/v1/evidence/context" \
-H "Content-Type: application/json" \
-d '{"query":"efficient attention","max_papers":20,"max_edges":40}'Fetch tool metadata for an LLM application:
curl "$BASE/v1/llm/tools"Use these endpoints when you are running the local server but want to query a hosted Intern Atlas deployment. This is the recommended path for browser apps running on localhost because the local server handles the outbound hosted call.
Configuration can be provided in each request body:
{
"base_url": "https://intern-atlas.opendatalab.org.cn/",
"api_key": "YOUR_ATLAS_API_KEY"
}The client accepts either the website root or the API root. These are equivalent:
https://intern-atlas.opendatalab.org.cn/
https://intern-atlas.opendatalab.org.cn/api
If omitted, the server reads:
export INTERN_ATLAS_REMOTE_BASE_URL="https://your-host.example.com/api"
export INTERN_ATLAS_API_KEY="YOUR_ATLAS_API_KEY"Health:
curl -X POST "$BASE/v1/remote/health" \
-H "Content-Type: application/json" \
-d '{"base_url":"https://intern-atlas.opendatalab.org.cn/"}'Hosted website search through the local proxy:
curl -X POST "$BASE/v1/remote/search" \
-H "Content-Type: application/json" \
-d '{
"query": "FlashAttention",
"search_type": "auto",
"limit": 20,
"include_subgraph": true,
"base_url": "https://intern-atlas.opendatalab.org.cn/"
}'Hosted website subgraph query through the local proxy:
curl -X POST "$BASE/v1/remote/query" \
-H "Content-Type: application/json" \
-d '{
"query": "efficient attention",
"max_nodes": 80,
"base_url": "https://intern-atlas.opendatalab.org.cn/"
}'Hosted evidence through the local proxy. If the hosted deployment does not expose
/api/v1/evidence/context, the client falls back to /api/assist/context.
curl -X POST "$BASE/v1/remote/evidence/context" \
-H "Content-Type: application/json" \
-d '{
"query": "efficient long-context attention",
"mode": "deep",
"depth": 4,
"max_papers": 60,
"max_edges": 120,
"year_from": 2020,
"base_url": "https://intern-atlas.opendatalab.org.cn/",
"api_key": "YOUR_ATLAS_API_KEY"
}'Hosted paper neighborhood through the local proxy:
curl -X POST "$BASE/v1/remote/papers/neighborhood" \
-H "Content-Type: application/json" \
-d '{"paper_id":"PAPER_ID","depth":1,"limit":80,"base_url":"https://intern-atlas.opendatalab.org.cn/"}'Hosted branch, ancestry, shortest path, and evolution-chain data:
curl -X POST "$BASE/v1/remote/papers/branch" \
-H "Content-Type: application/json" \
-d '{"paper_id":"PAPER_ID","depth":2,"limit":80,"base_url":"https://intern-atlas.opendatalab.org.cn/"}'
curl -X POST "$BASE/v1/remote/papers/ancestry" \
-H "Content-Type: application/json" \
-d '{"paper_id":"PAPER_ID","depth":2,"limit":80,"base_url":"https://intern-atlas.opendatalab.org.cn/"}'
curl -X POST "$BASE/v1/remote/path" \
-H "Content-Type: application/json" \
-d '{"from_id":"NEWER_PAPER_ID","to_id":"OLDER_PAPER_ID","direction":"both","max_depth":10,"base_url":"https://intern-atlas.opendatalab.org.cn/"}'
curl -X POST "$BASE/v1/remote/visualization/evolution-chain" \
-H "Content-Type: application/json" \
-d '{"domain":"attention","max_chains":5,"base_url":"https://intern-atlas.opendatalab.org.cn/"}'Idea-generation and evaluation proxy endpoints are also available:
curl -X POST "$BASE/v1/remote/ideas" \
-H "Content-Type: application/json" \
-d '{"query":"efficient long-context attention","use_llm":false}'
curl -X POST "$BASE/v1/remote/eval" \
-H "Content-Type: application/json" \
-d '{"idea":"Use FlashAttention and LoRA for efficient ViT tuning.","use_llm":false}'See LLM_TOOL_INTEGRATION.md for provider-facing integration patterns.
GET /api/health
Checks that the API process can read the SQLite database.
Example:
curl "$BASE/health"Response:
{
"status": "ok",
"database": {
"file": "local_graph.db",
"connected": true
}
}GET /api/manifest
Returns service metadata and the main endpoint list.
Example:
curl "$BASE/manifest"Response:
{
"name": "Intern Atlas Local API",
"version": "0.1.0",
"database": "local_graph.db",
"docs": "/api/docs",
"endpoints": [
"GET /api/health",
"GET /api/stats",
"GET /api/papers/search?q=...",
"GET /api/papers/{paper_id}",
"GET /api/edges",
"POST /api/query",
"POST /api/assist/context"
]
}GET /api/stats
Returns counts for the local graph.
Example:
curl "$BASE/stats"Response:
{
"papers": 3,
"methods": 5,
"edges": 1
}Fields:
papers: number of paper nodes.methods: number of method entities.edges: number of non-background evolution edges.
GET /api/papers
Lists paper nodes.
Query parameters:
| Name | Type | Default | Max | Description |
|---|---|---|---|---|
offset |
integer | 0 |
none | Pagination offset. |
limit |
integer | 50 |
200 |
Number of papers returned. |
Example:
curl "$BASE/papers?offset=0&limit=20"Response item:
{
"paper_id": "local_attention_is_all_you_need_6843568f00",
"title": "Attention Is All You Need",
"abstract": "We introduce the Transformer...",
"year": 2017,
"authors": [],
"venue": "NeurIPS",
"status": "full",
"paper_type": "research"
}GET /api/papers/search
Searches paper title and abstract using SQLite LIKE.
Query parameters:
| Name | Type | Default | Max | Description |
|---|---|---|---|---|
q |
string | "" |
200 chars | Search text. |
limit |
integer | 20 |
50 |
Number of papers returned. |
Example:
curl "$BASE/papers/search?q=attention&limit=10"Python:
import requests
papers = requests.get(
"http://127.0.0.1:8000/api/papers/search",
params={"q": "attention", "limit": 10},
timeout=30,
).json()GET /api/papers/{paper_id}
Returns one paper plus its method links.
Example:
curl "$BASE/papers/local_attention_is_all_you_need_6843568f00"Response:
{
"paper_id": "local_attention_is_all_you_need_6843568f00",
"title": "Attention Is All You Need",
"abstract": "We introduce the Transformer...",
"year": 2017,
"authors": [],
"venue": "NeurIPS",
"status": "full",
"paper_type": "research",
"methods": [
{
"method_id": "m_transformer_9236e026",
"canonical_name": "Transformer",
"relationship": "introduces",
"confidence": 0.8
}
]
}Errors:
404: paper id does not exist in the local graph.
GET /api/methods
Searches method names and descriptions.
Query parameters:
| Name | Type | Default | Max | Description |
|---|---|---|---|---|
q |
string | "" |
200 chars | Search text. |
offset |
integer | 0 |
none | Pagination offset. |
limit |
integer | 50 |
200 |
Number of methods returned. |
Example:
curl "$BASE/methods?q=Transformer&limit=20"Response item:
{
"method_id": "m_transformer_9236e026",
"canonical_name": "Transformer",
"description": "",
"origin_paper_id": "local_attention_is_all_you_need_6843568f00"
}GET /api/edges
Returns non-background methodology edges.
Query parameters:
| Name | Type | Default | Max | Description |
|---|---|---|---|---|
paper_id |
string | none | none | If set, returns edges touching that paper. |
edge_type |
string | none | none | Filter by edge type. |
method |
string | none | 200 chars | Filter by source or target method text. |
offset |
integer | 0 |
none | Pagination offset. |
limit |
integer | 100 |
1000 |
Number of edges returned. |
Supported edge_type values:
extends: newer work generalizes or builds on older work.improves: newer work improves a metric or capability.replaces: newer work substitutes a prior mechanism.adapts: newer work transfers a method to a new domain.combines: newer work combines multiple method lines.uses_component: newer work uses a component from older work.compares: newer work uses older work as a comparison baseline.
Example:
curl "$BASE/edges?edge_type=extends&limit=20"
curl "$BASE/edges?paper_id=local_attention_is_all_you_need_6843568f00"
curl "$BASE/v1/evolution/edges?method=transformer&limit=20"Response item:
{
"source_paper_id": "local_flashattention_fast_and_memory_efficient_exact_attention_wit_70736e063f",
"target_paper_id": "local_attention_is_all_you_need_6843568f00",
"edge_type": "extends",
"bottleneck": "Potential methodological continuity inferred from shared terminology.",
"mechanism": "Heuristic relation. Rebuild with an LLM for evidence-grounded bottlenecks and mechanisms.",
"dimension": "method_continuity",
"confidence": 0.61,
"source_method": "transformer",
"target_method": "transformer"
}GET /api/papers/{paper_id}/neighborhood
Returns a bounded subgraph around one paper.
Query parameters:
| Name | Type | Default | Max | Description |
|---|---|---|---|---|
depth |
integer | 1 |
4 |
BFS depth over non-background edges. |
limit |
integer | 100 |
300 |
Maximum paper nodes returned. |
Example:
curl "$BASE/papers/local_attention_is_all_you_need_6843568f00/neighborhood?depth=1&limit=80"Response:
{
"papers": {
"PAPER_ID": {
"paper_id": "PAPER_ID",
"title": "Paper title",
"abstract": "...",
"year": 2022,
"authors": [],
"venue": "",
"status": "full",
"paper_type": "research"
}
},
"edges": [
{
"source_paper_id": "NEWER_ID",
"target_paper_id": "OLDER_ID",
"edge_type": "extends",
"bottleneck": "...",
"mechanism": "...",
"dimension": "...",
"confidence": 0.9
}
],
"center_id": "PAPER_ID"
}POST /api/query
Searches matching paper titles/abstracts, expands one hop over edges, and returns a subgraph.
Request body:
{
"query": "efficient attention",
"max_nodes": 80
}Fields:
| Name | Type | Required | Description |
|---|---|---|---|
query |
string | yes | Search phrase. |
max_nodes |
integer | no | Maximum papers in the returned subgraph. Range: 1-300. Default: 60. |
Example:
curl -X POST "$BASE/query" \
-H "Content-Type: application/json" \
-d '{"query":"efficient attention","max_nodes":80}'Response shape is the same as /api/papers/{paper_id}/neighborhood.
POST /api/assist/context
Returns papers, edges, and a compact text context block that can be pasted into your own LLM workflow.
Request body:
{
"query": "efficient attention",
"max_nodes": 80
}Example:
curl -X POST "$BASE/assist/context" \
-H "Content-Type: application/json" \
-d '{"query":"efficient attention","max_nodes":80}'Response:
{
"query": "efficient attention",
"papers": [
{
"paper_id": "local_attention_is_all_you_need_6843568f00",
"title": "Attention Is All You Need",
"year": 2017
}
],
"evolution_edges": [
{
"source_paper_id": "local_flashattention_fast_and_memory_efficient_exact_attention_wit_70736e063f",
"target_paper_id": "local_attention_is_all_you_need_6843568f00",
"edge_type": "extends"
}
],
"suggested_prompt_context": "Research query: efficient attention\n\nRelevant papers:\n..."
}Typical downstream use:
import requests
from openai import OpenAI
ctx = requests.post(
"http://127.0.0.1:8000/api/assist/context",
json={"query": "efficient attention", "max_nodes": 80},
timeout=60,
).json()
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "system",
"content": "Use only the supplied graph evidence. Do not invent paper titles.",
},
{
"role": "user",
"content": ctx["suggested_prompt_context"] + "\n\nPropose two research directions.",
},
],
)
print(response.choices[0].message.content)import requests
BASE = "http://127.0.0.1:8000/api"
papers = requests.get(
f"{BASE}/papers/search",
params={"q": "attention", "limit": 10},
timeout=30,
).json()
first = papers[0]
subgraph = requests.get(
f"{BASE}/papers/{first['paper_id']}/neighborhood",
params={"depth": 1, "limit": 80},
timeout=30,
).json()
print(first["title"])
print(len(subgraph["papers"]), len(subgraph["edges"]))import requests
ctx = requests.post(
"http://127.0.0.1:8000/api/assist/context",
json={"query": "long-context attention", "max_nodes": 100},
timeout=60,
).json()
print(ctx["suggested_prompt_context"])The hosted API is useful when your local graph is too small and you need broader literature evidence.
The CLI exposes these hosted calls:
intern-atlas remote health
intern-atlas remote search "FlashAttention" --include-subgraph
intern-atlas remote query "efficient attention" --max-nodes 80
intern-atlas remote chain "attention" --max-chains 5
intern-atlas remote evidence "efficient long-context attention"
intern-atlas remote context "efficient long-context attention"
intern-atlas remote methods "Transformer"
intern-atlas remote edges --method attention --limit 20
intern-atlas remote path NEWER_PAPER_ID OLDER_PAPER_ID --direction both
intern-atlas remote ideas "efficient long-context attention" --use-llm
intern-atlas remote eval "Use FlashAttention and LoRA for efficient ViT tuning."The default hosted base URL is:
https://intern-atlas.opendatalab.org.cn/api
The CLI also accepts the site root:
intern-atlas remote health --base-url "https://intern-atlas.opendatalab.org.cn/"If that public endpoint returns 502 or another upstream error, point the client
at your own deployed Intern Atlas API with --base-url or
INTERN_ATLAS_REMOTE_BASE_URL.
Override it:
intern-atlas remote context \
"efficient long-context attention" \
--base-url "https://intern-atlas.opendatalab.org.cn/"If your hosted deployment requires an API key:
intern-atlas remote ideas \
"efficient long-context attention" \
--api-key "$INTERN_ATLAS_API_KEY" \
--use-llmFetch a v1 evidence pack from a hosted service:
intern-atlas remote evidence \
"efficient long-context attention" \
--max-papers 30 \
--max-edges 80 \
--api-key "$INTERN_ATLAS_API_KEY"from intern_atlas.remote import InternAtlasClient
client = InternAtlasClient()
try:
health = client.health()
print(health)
evidence = client.evidence_context(
"efficient long-context attention",
max_papers=20,
max_edges=40,
)
print(evidence["suggested_prompt_context"])
methods = client.search_methods("Transformer", limit=20)
print(methods)
edges = client.evolution_edges(method="attention", limit=20)
print(edges)
ctx = client.assist_context(
"efficient long-context attention",
budget="balanced",
use_mcts=True,
token_budget=6000,
)
print(ctx["suggested_prompt_context"])
ideas = client.generate_ideas(
"efficient long-context attention",
use_llm=False,
evidence_budget="balanced",
)
print(ideas)
review = client.evaluate_idea(
"Use FlashAttention and LoRA for parameter-efficient vision transformer tuning.",
use_llm=False,
)
print(review)
finally:
client.close()With API key:
client = InternAtlasClient(api_key="YOUR_ATLAS_API_KEY")With a custom base URL:
client = InternAtlasClient(
base_url="https://intern-atlas.opendatalab.org.cn/",
api_key="YOUR_ATLAS_API_KEY",
)Calls:
GET /api/health
Use it for monitoring and connectivity checks.
evidence_context(query, max_papers=20, max_edges=40, mode="balanced", depth=None, year_from=None, year_to=None, edge_type=None, method=None, include_prompt_context=True)
Calls:
POST /api/v1/evidence/context
Arguments:
query: research topic, idea seed, or evaluation target.max_papers: maximum relevant papers returned.max_edges: maximum methodology edges returned.mode:light,balanced, ordeep.depth: optional graph expansion depth, bounded by the selected mode.year_from: optional lower year bound.year_to: optional upper year bound.edge_type: optional edge type filter.method: optional method text filter.include_prompt_context: whether to include prompt-ready context text.
Calls:
GET /api/v1/methods/search
Arguments:
q: method name or partial method text.limit: maximum methods returned.offset: pagination offset.
evolution_edges(paper_id=None, edge_type=None, method=None, year_from=None, year_to=None, limit=100, offset=0)
Calls:
GET /api/v1/evolution/edges
Arguments:
paper_id: optional paper filter.edge_type: optional edge-type filter.method: optional source or target method filter.year_from: optional lower year bound for both edge endpoints.year_to: optional upper year bound for both edge endpoints.limit: maximum edges returned.offset: pagination offset.
Calls:
GET /api/v1/papers/{paper_id}/neighborhood
Arguments:
paper_id: local paper id.depth: graph search depth.limit: maximum paper nodes returned.
Calls:
POST /api/assist/context
Arguments:
query: research direction.budget:light,balanced, ordeep.use_mcts: whether to request chain search with MCTS when supported by the server.token_budget: approximate prompt context budget.
Calls:
POST /api/ideas
Arguments:
query: research direction.use_llm: ask the hosted service to use its configured LLM.evidence_budget:light,balanced, ordeep.
Calls:
POST /api/eval
Arguments:
idea: research idea text.use_llm: ask the hosted service to add LLM qualitative review when supported.
Local API:
404: requested paper was not found.422: request validation failed, usually a missingqueryor invalidlimit.500: database or server error.
Hosted API:
401or403: missing, invalid, or under-scoped API key.429: rate limit.5xx: hosted service unavailable or upstream LLM failed.
Python pattern:
import httpx
try:
res = httpx.post(
"http://127.0.0.1:8000/api/query",
json={"query": "attention", "max_nodes": 80},
timeout=60,
)
res.raise_for_status()
except httpx.HTTPStatusError as exc:
print("API error:", exc.response.status_code, exc.response.text)
except httpx.RequestError as exc:
print("Network error:", exc)The local API does not require authentication by default because it is meant to run on your own machine.
The hosted client supports bearer-token auth:
client = InternAtlasClient(api_key="YOUR_ATLAS_API_KEY")Do not commit secrets.
Recommended shell pattern:
export INTERN_ATLAS_API_KEY="..."
intern-atlas remote context "efficient attention" --api-key "$INTERN_ATLAS_API_KEY"Repository .gitignore excludes .env, generated SQLite databases, and paper corpora.
intern-atlas build \
--pdf-dir ./papers \
--out outputs/my_graph.db \
--json outputs/my_graph.json
intern-atlas serve --db outputs/my_graph.dbOpen:
http://127.0.0.1:8000/
intern-atlas build \
--input examples/papers.txt \
--out outputs/smoke.db \
--no-llm
intern-atlas stats --db outputs/smoke.dbcurl -X POST "$BASE/assist/context" \
-H "Content-Type: application/json" \
-d '{"query":"efficient attention","max_nodes":80}' \
> context.jsonThen pass suggested_prompt_context to your own model.
intern-atlas remote context "efficient long-context attention"This is useful before you have enough local papers for a meaningful graph.
Local API limitations:
- Search is simple SQLite
LIKE, not full semantic retrieval. - Heuristic graphs are intentionally conservative and may miss true relationships.
- LLM-built graphs depend on the quality of the configured model and paper text extraction.
- A local graph only covers the papers you provide.
Use the hosted API when you need large-scale graph context.