Documentation: - docs/API.md: Complete API reference with examples - All endpoints with curl examples - Python SDK example - Error responses and rate limits - docs/RBAC.md: RBAC system documentation - Two-level access control explained - Built-in roles (admin, portfolio-agent, authenticated-user) - Authentik configuration guide - Scope mapping examples for roles/permissions - Troubleshooting guide JWT Integration: - Add 'roles' field to JwtClaims struct - Wire roles from Authentik JWT to RBAC Claims - API key users get 'admin' role by default Tests: - Add test_to_rbac_claims_with_roles - Verify roles extraction from JWT - 670 tests passing
8.0 KiB
Memory API Reference
Authentication
All endpoints require authentication via JWT token (from Authentik) or API key fallback.
JWT Authentication (Recommended)
# Get token from Authentik
TOKEN=$(curl -s -X POST https://authentik.riotpiao.com/application/o/token/ \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" | jq -r '.access_token')
# Use token in requests
curl -H "Authorization: Bearer $TOKEN" \
http://memory.riotpiao.com/memory/query?project=homelab&query=kubernetes
API Key Authentication (Fallback)
curl -H "apikey: YOUR_API_KEY" \
http://memory.riotpiao.com/memory/query?project=homelab&query=kubernetes
Endpoints
Health Check
GET /health
Response:
{
"status": "ok",
"uptime_secs": 3600
}
Query Memory
Search learned knowledge using semantic + hybrid search.
GET /memory/query?project={project}&query={query}&limit={limit}&method={method}
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| project | string | Yes | Project to search in |
| query | string | Yes | Search query |
| limit | int | No | Max results (default: 10) |
| method | string | No | semantic or hybrid (default: hybrid) |
Example:
curl -H "Authorization: Bearer $TOKEN" \
"http://memory.riotpiao.com/memory/query?project=homelab&query=fix%20kubernetes%20port%20conflict&limit=5"
Response:
{
"query": "fix kubernetes port conflict",
"project": "homelab",
"method": "hybrid",
"results": [
{
"level": "L1",
"score": 0.92,
"text": "To fix port conflicts in Kubernetes...",
"source": "troubleshooting/ports.md",
"provenance": ["session-123"]
}
]
}
RBAC: Requires memory:read permission. Results filtered by user's project/visibility access.
Context Lookup (Three-Tier RAG)
Get contextual knowledge for tool/task with failure diagnosis.
POST /memory/context
Content-Type: application/json
Body:
{
"project": "homelab",
"tool": "kubectl",
"task": "debug-pod",
"scope": "tool_context",
"budget": 8192,
"failure_log": "CrashLoopBackOff: container exited with code 1"
}
Example:
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"homelab","tool":"kubectl","task":"debug-pod","budget":4096}' \
http://memory.riotpiao.com/memory/context
Response:
{
"tier": 1,
"lessons": [
{
"tier": 1,
"level": "L1",
"score": 1.0,
"text": "CrashLoopBackOff usually means...",
"matched_kind": "symptom",
"seen_count": 15
}
],
"skills": [
{
"name": "diagnose-pod-failure",
"score": 0.95,
"description": "Debug Kubernetes pod crashes"
}
],
"budget": {
"limit": 4096,
"used": 2048,
"dropped": []
}
}
RBAC: Requires memory:read permission + project access.
Ingest Records
Add new knowledge to memory.
POST /memory/ingest
Content-Type: application/json
Body:
{
"project": "homelab",
"ingest_id": "session-2024-01-15-001",
"source": "conversation://claude/session-123",
"records": [
{"text": "Kubernetes uses port 6443 for API server..."},
{"text": "To change the port, edit /etc/kubernetes/manifests/kube-apiserver.yaml"}
]
}
Example:
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"homelab","ingest_id":"test-001","source":"manual","records":[{"text":"Test fact"}]}' \
http://memory.riotpiao.com/memory/ingest
Response:
{
"status": "accepted",
"ingest_id": "test-001",
"records_queued": 1
}
RBAC: Requires memory:write permission + project write access.
Learn from Text
Process and learn from a block of text (chunking + embedding + synthesis).
POST /memory/learn
Content-Type: application/json
Body:
{
"project": "homelab",
"text": "# Kubernetes Networking\n\nKubernetes uses CNI plugins...",
"query": "What are the key networking concepts?",
"chunk_size": 2000,
"memory_budget": 4096
}
Example:
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"homelab","text":"# Guide\nSome content...","query":"Summarize this"}' \
http://memory.riotpiao.com/memory/learn
RBAC: Requires memory:write permission + project write access.
List Projects
Get all accessible projects.
GET /memory/projects
Example:
curl -H "Authorization: Bearer $TOKEN" \
http://memory.riotpiao.com/memory/projects
Response:
{
"projects": ["homelab", "portfolio"],
"count": 2
}
RBAC: Returns only projects user has read access to.
List Skills
Get extracted skills.
GET /memory/skills
Response:
{
"skills": [
{
"name": "diagnose-pod-failure",
"description": "Debug Kubernetes pod issues",
"when_to_use": "Pod in CrashLoopBackOff or Error state"
}
],
"count": 1
}
RBAC: Requires memory:read permission.
Ingest Status
Check status of an ingest job.
GET /memory/ingest/{ingest_id}
Example:
curl -H "Authorization: Bearer $TOKEN" \
http://memory.riotpiao.com/memory/ingest/session-2024-01-15-001
Response:
{
"ingest_id": "session-2024-01-15-001",
"status": "completed",
"records_processed": 5,
"created_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:30:05Z"
}
Error Responses
401 Unauthorized
{
"error": "unauthorized",
"reason": "missing Authorization header"
}
403 Forbidden
{
"error": "forbidden",
"reason": "missing capability: memory:write"
}
Or with RBAC:
{
"error": "forbidden",
"reason": "access denied to project 'secret-project'"
}
429 Too Many Requests
{
"error": "rate_limited",
"reason": "exceeded 1000 requests/hour for /memory/query"
}
Rate Limits
| Endpoint | Limit |
|---|---|
/memory/ingest |
100/hour |
/memory/query |
1000/hour |
/memory/context |
100/hour |
/memory/learn |
100/hour |
Rate limits are per-user (based on JWT sub claim).
SDK Examples
Python
import requests
class MemoryClient:
def __init__(self, base_url, token):
self.base_url = base_url
self.headers = {"Authorization": f"Bearer {token}"}
def query(self, project, query, limit=10):
resp = requests.get(
f"{self.base_url}/memory/query",
params={"project": project, "query": query, "limit": limit},
headers=self.headers
)
resp.raise_for_status()
return resp.json()
def ingest(self, project, records, source="api"):
import uuid
resp = requests.post(
f"{self.base_url}/memory/ingest",
json={
"project": project,
"ingest_id": str(uuid.uuid4()),
"source": source,
"records": [{"text": r} for r in records]
},
headers=self.headers
)
resp.raise_for_status()
return resp.json()
# Usage
client = MemoryClient("http://memory.riotpiao.com", TOKEN)
results = client.query("homelab", "kubernetes networking")
curl One-Liners
# Query
curl -H "Authorization: Bearer $TOKEN" \
"http://memory.riotpiao.com/memory/query?project=homelab&query=kubernetes"
# Ingest
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"project":"homelab","ingest_id":"'$(uuidgen)'","source":"cli","records":[{"text":"New fact"}]}' \
http://memory.riotpiao.com/memory/ingest
# Context
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"project":"homelab","tool":"kubectl","task":"debug"}' \
http://memory.riotpiao.com/memory/context