brain / src /services /api /routes /agent.py
Leon4gr45's picture
Upload folder using huggingface_hub (part 3)
a55ea57 verified
Raw History Blame Contribute Delete
4.66 kB
"""Compact, stable HTTP contract for external memory agents."""
from copy import deepcopy
from functools import lru_cache
import os
from fastapi import APIRouter, Depends, Request
from fastapi.openapi.utils import get_openapi
from src.constants.data import BRAIN_VERSION
from src.services.agent_memory import (
memory_context,
memory_search,
memory_store,
memory_task_status,
)
from src.services.api.constants.agent import (
AgentContextRequest,
AgentMemoryRequest,
AgentSearchRequest,
)
from src.services.api.dependencies import get_brain_id
from src.services.data.main import data_adapter
from src.services.workspaces import public_base_url
AGENT_PREFIX = "/brains/{workspace_slug}/agent"
agent_router = APIRouter(prefix=AGENT_PREFIX, tags=["agent-memory"])
def _workspace(request: Request):
return data_adapter.get_workspace(request.state.workspace_slug)
def _base(request: Request) -> str:
root = public_base_url(os.getenv("PUBLIC_BASE_URL"), str(request.base_url))
return f"{root}/brains/{request.state.workspace_slug}/agent"
@agent_router.post("/search")
async def agent_search(
body: AgentSearchRequest,
request: Request,
brain_id: str = Depends(get_brain_id),
):
return {
"workspace": request.state.workspace_slug,
"results": await memory_search(body.query, body.limit, brain_id),
}
@agent_router.post("/context")
async def agent_context(
body: AgentContextRequest,
request: Request,
brain_id: str = Depends(get_brain_id),
):
result = await memory_context(body.query, body.max_tokens, brain_id)
return {**result, "workspace": request.state.workspace_slug}
@agent_router.post("/memory", status_code=202)
async def agent_memory(
body: AgentMemoryRequest,
request: Request,
brain_id: str = Depends(get_brain_id),
):
result = await memory_store(
text=body.text,
metadata=body.metadata,
brain_id=brain_id,
request=request,
)
return {
"workspace": request.state.workspace_slug,
"status": "queued",
"task_id": result["task_id"],
}
@agent_router.get("/tasks/{task_id}")
async def agent_task(
task_id: str,
request: Request,
brain_id: str = Depends(get_brain_id),
):
result = await memory_task_status(task_id, brain_id)
return {**result, "workspace": request.state.workspace_slug}
@agent_router.get("/capabilities")
async def agent_capabilities(request: Request):
workspace = _workspace(request)
root = _base(request)
public_root = root.removesuffix(f"/brains/{workspace.slug}/agent")
workspace_root = f"{public_root}/brains/{workspace.slug}"
return {
"workspace": {
"slug": workspace.slug,
"brain_id": workspace.brain_id,
"display_name": workspace.display_name,
},
"capabilities": {
"search": True,
"context": True,
"memory_write": True,
"tasks": True,
"mcp": True,
"neighbors": True,
},
"endpoints": {
"native_api": f"{workspace_root}/api",
"native_openapi": f"{workspace_root}/api/openapi.json",
"agent_api": root,
"agent_openapi": f"{root}/openapi.json",
"mcp": f"{workspace_root}/mcp",
},
}
@lru_cache(maxsize=1)
def _agent_schema_template() -> dict:
routes = [route for route in agent_router.routes if route.path != f"{AGENT_PREFIX}/openapi.json"]
schema = get_openapi(
title="BrainAPI Agent Memory API",
version=BRAIN_VERSION,
description="Stable workspace-scoped memory API for external agents.",
routes=routes,
)
schema.setdefault("components", {}).setdefault("securitySchemes", {}).update(
{
"BrainPAT": {"type": "apiKey", "in": "header", "name": "BrainPAT"},
"BearerAuth": {"type": "http", "scheme": "bearer"},
}
)
for item in schema.get("paths", {}).values():
for operation in item.values():
if isinstance(operation, dict) and "responses" in operation:
operation["security"] = [{"BrainPAT": []}, {"BearerAuth": []}]
# Advertise paths relative to the workspace-specific server URL.
schema["paths"] = {
path.removeprefix(AGENT_PREFIX): item
for path, item in schema.get("paths", {}).items()
}
return schema
@agent_router.get("/openapi.json", include_in_schema=False)
async def agent_openapi(request: Request):
schema = deepcopy(_agent_schema_template())
schema["servers"] = [{"url": _base(request)}]
return schema