-
Notifications
You must be signed in to change notification settings - Fork 2
API Reference
This document provides complete REST API documentation for the Agent Brain server.
The Agent Brain API is a RESTful JSON API built with FastAPI. It provides endpoints for:
- Health Monitoring: Server status and indexing progress
- Document Querying: Semantic, keyword, hybrid, graph, and multi-mode search
- Document Indexing: Index documents and code from folders
Interactive documentation is available at:
-
Swagger UI:
http://localhost:8000/docs -
ReDoc:
http://localhost:8000/redoc -
OpenAPI JSON:
http://localhost:8000/openapi.json
The Agent Brain API does not require authentication by default. It binds to 127.0.0.1 and is accessible only from localhost.
For network deployment, implement authentication via a reverse proxy (nginx, Traefik) or enable CORS restrictions.
http://127.0.0.1:8000
For per-project instances, read the port from .claude/agent-brain/runtime.json:
{
"base_url": "http://127.0.0.1:49321",
"port": 49321
}Check server health status.
Response 200 OK:
{
"status": "healthy",
"message": "Server is running and ready for queries",
"timestamp": "2024-01-15T10:30:00Z",
"version": "1.2.0",
"mode": "project",
"instance_id": "abc123",
"project_id": "my-project"
}Status Values:
| Status | Description |
|---|---|
healthy |
Ready for queries |
indexing |
Indexing in progress |
degraded |
Running with issues |
unhealthy |
Not operational |
Get detailed indexing status.
Response 200 OK:
{
"total_documents": 150,
"total_chunks": 1200,
"total_doc_chunks": 800,
"total_code_chunks": 400,
"indexing_in_progress": false,
"current_job_id": null,
"progress_percent": 0.0,
"last_indexed_at": "2024-01-15T10:30:00Z",
"indexed_folders": ["/path/to/docs"],
"supported_languages": ["python", "typescript"],
"graph_index": {
"enabled": true,
"initialized": true,
"entity_count": 120,
"relationship_count": 250,
"store_type": "simple"
}
}Execute a search query.
Request Body:
{
"query": "how does authentication work",
"top_k": 5,
"similarity_threshold": 0.7,
"mode": "hybrid",
"alpha": 0.5,
"source_types": ["doc", "code"],
"languages": ["python", "typescript"],
"file_paths": ["src/**/*.py"]
}Parameters:
| Field | Type | Default | Description |
|---|---|---|---|
query |
string | (required) | Search query (1-1000 chars) |
top_k |
integer | 5 |
Results to return (1-50) |
similarity_threshold |
float | 0.7 |
Minimum similarity (0.0-1.0) |
mode |
string | "hybrid" |
Search mode |
alpha |
float | 0.5 |
Hybrid balance (0=BM25, 1=Vector) |
source_types |
array | null |
Filter by ["doc", "code"]
|
languages |
array | null |
Filter by languages |
file_paths |
array | null |
Filter by file patterns |
Mode Values:
| Mode | Description |
|---|---|
bm25 |
Keyword-only search |
vector |
Semantic-only search |
hybrid |
BM25 + Vector fusion |
graph |
Knowledge graph traversal |
multi |
All three with RRF |
Response 200 OK:
{
"results": [
{
"text": "Authentication is configured via...",
"source": "/path/to/docs/auth.md",
"score": 0.92,
"vector_score": 0.92,
"bm25_score": 0.85,
"chunk_id": "chunk_abc123",
"source_type": "doc",
"language": "markdown",
"graph_score": null,
"related_entities": null,
"relationship_path": null,
"metadata": {
"chunk_index": 0,
"total_chunks": 5
}
}
],
"query_time_ms": 125.5,
"total_results": 1
}Response Fields:
| Field | Type | Description |
|---|---|---|
text |
string | Chunk content |
source |
string | Source file path |
score |
float | Combined/primary score |
vector_score |
float | Semantic similarity score |
bm25_score |
float | Keyword match score |
graph_score |
float | Graph traversal score |
chunk_id |
string | Unique chunk identifier |
source_type |
string |
"doc" or "code"
|
language |
string | Programming language |
related_entities |
array | GraphRAG related entities |
relationship_path |
array | GraphRAG relationship paths |
metadata |
object | Additional metadata |
Errors:
| Code | Description |
|---|---|
400 |
Invalid query (empty or too long) |
503 |
Index not ready |
Get the number of indexed chunks.
Response 200 OK:
{
"total_chunks": 1200,
"ready": true
}Start indexing documents from a folder.
Request Body:
{
"folder_path": "/path/to/documents",
"chunk_size": 512,
"chunk_overlap": 50,
"recursive": true,
"include_code": true,
"supported_languages": ["python", "typescript"],
"code_chunk_strategy": "ast_aware",
"generate_summaries": false,
"include_patterns": ["docs/**/*.md", "src/**/*.py"],
"exclude_patterns": ["node_modules/**", "__pycache__/**"]
}Parameters:
| Field | Type | Default | Description |
|---|---|---|---|
folder_path |
string | (required) | Path to folder |
chunk_size |
integer | 512 |
Chunk size in tokens (128-2048) |
chunk_overlap |
integer | 50 |
Overlap in tokens (0-200) |
recursive |
boolean | true |
Scan subdirectories |
include_code |
boolean | false |
Include source code files |
supported_languages |
array | null |
Languages to index |
code_chunk_strategy |
string | "ast_aware" |
"ast_aware" or "text_based"
|
generate_summaries |
boolean | false |
Generate LLM summaries |
include_patterns |
array | null |
Glob patterns to include |
exclude_patterns |
array | null |
Glob patterns to exclude |
Response 202 Accepted:
{
"job_id": "job_abc123def456",
"status": "started",
"message": "Indexing started for /path/to/documents"
}Errors:
| Code | Description |
|---|---|
400 |
Invalid folder path |
409 |
Indexing already in progress |
Add documents from another folder to the existing index.
Same request/response format as POST /index.
Reset the index (delete all documents).
Response 200 OK:
{
"job_id": "reset",
"status": "completed",
"message": "Index has been reset successfully"
}Errors:
| Code | Description |
|---|---|
409 |
Cannot reset during indexing |
interface QueryRequest {
query: string; // 1-1000 characters
top_k?: number; // 1-50, default 5
similarity_threshold?: number; // 0.0-1.0, default 0.7
mode?: "bm25" | "vector" | "hybrid" | "graph" | "multi"; // default "hybrid"
alpha?: number; // 0.0-1.0, default 0.5
source_types?: string[]; // ["doc", "code"]
languages?: string[]; // ["python", "typescript", ...]
file_paths?: string[]; // Glob patterns
}interface QueryResponse {
results: QueryResult[];
query_time_ms: number;
total_results: number;
}
interface QueryResult {
text: string;
source: string;
score: number;
vector_score?: number;
bm25_score?: number;
graph_score?: number;
chunk_id: string;
source_type: string;
language?: string;
related_entities?: string[];
relationship_path?: string[];
metadata: Record<string, any>;
}interface IndexRequest {
folder_path: string;
chunk_size?: number; // 128-2048, default 512
chunk_overlap?: number; // 0-200, default 50
recursive?: boolean; // default true
include_code?: boolean; // default false
supported_languages?: string[];
code_chunk_strategy?: "ast_aware" | "text_based"; // default "ast_aware"
generate_summaries?: boolean; // default false
include_patterns?: string[];
exclude_patterns?: string[];
}interface IndexResponse {
job_id: string;
status: string;
message?: string;
}interface HealthStatus {
status: "healthy" | "indexing" | "degraded" | "unhealthy";
message?: string;
timestamp: string; // ISO 8601
version: string;
mode?: string;
instance_id?: string;
project_id?: string;
active_projects?: number;
}interface IndexingStatus {
total_documents: number;
total_chunks: number;
total_doc_chunks: number;
total_code_chunks: number;
indexing_in_progress: boolean;
current_job_id?: string;
progress_percent: number;
last_indexed_at?: string; // ISO 8601
indexed_folders: string[];
supported_languages: string[];
graph_index?: GraphIndexStatus;
}
interface GraphIndexStatus {
enabled: boolean;
initialized: boolean;
entity_count: number;
relationship_count: number;
store_type: string;
}{
"detail": "Error message describing what went wrong"
}| Code | Description |
|---|---|
200 |
Success |
202 |
Accepted (async operation started) |
400 |
Bad Request (invalid parameters) |
404 |
Not Found |
409 |
Conflict (e.g., indexing in progress) |
500 |
Internal Server Error |
503 |
Service Unavailable (index not ready) |
Query Errors:
// Empty query
{
"detail": "Query cannot be empty"
}
// Index not ready
{
"detail": "Index not ready. Indexing is in progress."
}
// GraphRAG not enabled
{
"detail": "GraphRAG not enabled. Set ENABLE_GRAPH_INDEX=true in environment."
}Index Errors:
// Folder not found
{
"detail": "Folder not found: /path/to/nonexistent"
}
// Already indexing
{
"detail": "Indexing already in progress. Please wait for completion."
}Health Check:
curl http://localhost:8000/healthSearch Query:
curl -X POST http://localhost:8000/query \
-H "Content-Type: application/json" \
-d '{
"query": "authentication implementation",
"mode": "hybrid",
"top_k": 10
}'Start Indexing:
curl -X POST http://localhost:8000/index \
-H "Content-Type: application/json" \
-d '{
"folder_path": "/path/to/project",
"include_code": true,
"recursive": true
}'Reset Index:
curl -X DELETE http://localhost:8000/indexUsing httpx:
import httpx
BASE_URL = "http://localhost:8000"
async def search_documents(query: str, mode: str = "hybrid"):
async with httpx.AsyncClient() as client:
response = await client.post(
f"{BASE_URL}/query",
json={
"query": query,
"mode": mode,
"top_k": 10,
}
)
response.raise_for_status()
return response.json()
async def index_folder(folder_path: str, include_code: bool = False):
async with httpx.AsyncClient() as client:
response = await client.post(
f"{BASE_URL}/index",
json={
"folder_path": folder_path,
"include_code": include_code,
}
)
response.raise_for_status()
return response.json()
# Usage
results = await search_documents("authentication")
for result in results["results"]:
print(f"{result['source']}: {result['score']:.2f}")Polling for Indexing Completion:
import asyncio
import httpx
async def wait_for_indexing():
async with httpx.AsyncClient() as client:
while True:
response = await client.get(f"{BASE_URL}/health/status")
status = response.json()
if not status["indexing_in_progress"]:
print(f"Indexing complete: {status['total_chunks']} chunks")
break
print(f"Progress: {status['progress_percent']:.1f}%")
await asyncio.sleep(2)Using fetch:
const BASE_URL = 'http://localhost:8000';
async function searchDocuments(query, mode = 'hybrid') {
const response = await fetch(`${BASE_URL}/query`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query,
mode,
top_k: 10,
}),
});
if (!response.ok) {
throw new Error(`Query failed: ${response.statusText}`);
}
return response.json();
}
// Usage
const results = await searchDocuments('authentication');
results.results.forEach(result => {
console.log(`${result.source}: ${result.score.toFixed(2)}`);
});The Agent Brain API does not implement rate limiting by default. For production deployments, implement rate limiting at the reverse proxy level.
The API version is included in the health response:
{
"version": "1.2.0"
}Breaking changes will increment the major version number.
- Configuration Reference - Server and query settings
- Deployment Guide - Production deployment
- Plugin Guide - CLI and skill integration
- Design-Architecture-Overview
- Design-Query-Architecture
- Design-Storage-Architecture
- Design-Class-Diagrams
- GraphRAG-Guide
- Agent-Skill-Hybrid-Search-Guide
- Agent-Skill-Graph-Search-Guide
- Agent-Skill-Vector-Search-Guide
- Agent-Skill-BM25-Search-Guide
Search
Server
Setup
- Pluggable-Providers-Spec
- GraphRAG-Integration-Spec
- Agent-Brain-Plugin-Spec
- Multi-Instance-Architecture-Spec