415 lines
8.0 KiB
Markdown
415 lines
8.0 KiB
Markdown
# Memory API Reference
|
|||
|
|
|
||
|
|
## Authentication
|
||
|
|
|
||
|
|
All endpoints require authentication via JWT token (from Authentik) or API key fallback.
|
||
|
|
|
||
|
|
### JWT Authentication (Recommended)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
curl -H "apikey: YOUR_API_KEY" \
|
||
|
|
http://memory.riotpiao.com/memory/query?project=homelab&query=kubernetes
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Endpoints
|
||
|
|
|
||
|
|
### Health Check
|
||
|
|
|
||
|
|
```http
|
||
|
|
GET /health
|
||
|
|
```
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"status": "ok",
|
||
|
|
"uptime_secs": 3600
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Query Memory
|
||
|
|
|
||
|
|
Search learned knowledge using semantic + hybrid search.
|
||
|
|
|
||
|
|
```http
|
||
|
|
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:**
|
||
|
|
```bash
|
||
|
|
curl -H "Authorization: Bearer $TOKEN" \
|
||
|
|
"http://memory.riotpiao.com/memory/query?project=homelab&query=fix%20kubernetes%20port%20conflict&limit=5"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"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.
|
||
|
|
|
||
|
|
```http
|
||
|
|
POST /memory/context
|
||
|
|
Content-Type: application/json
|
||
|
|
```
|
||
|
|
|
||
|
|
**Body:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"project": "homelab",
|
||
|
|
"tool": "kubectl",
|
||
|
|
"task": "debug-pod",
|
||
|
|
"scope": "tool_context",
|
||
|
|
"budget": 8192,
|
||
|
|
"failure_log": "CrashLoopBackOff: container exited with code 1"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
```bash
|
||
|
|
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:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"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.
|
||
|
|
|
||
|
|
```http
|
||
|
|
POST /memory/ingest
|
||
|
|
Content-Type: application/json
|
||
|
|
```
|
||
|
|
|
||
|
|
**Body:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"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:**
|
||
|
|
```bash
|
||
|
|
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:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"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).
|
||
|
|
|
||
|
|
```http
|
||
|
|
POST /memory/learn
|
||
|
|
Content-Type: application/json
|
||
|
|
```
|
||
|
|
|
||
|
|
**Body:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"project": "homelab",
|
||
|
|
"text": "# Kubernetes Networking\n\nKubernetes uses CNI plugins...",
|
||
|
|
"query": "What are the key networking concepts?",
|
||
|
|
"chunk_size": 2000,
|
||
|
|
"memory_budget": 4096
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
```bash
|
||
|
|
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.
|
||
|
|
|
||
|
|
```http
|
||
|
|
GET /memory/projects
|
||
|
|
```
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
```bash
|
||
|
|
curl -H "Authorization: Bearer $TOKEN" \
|
||
|
|
http://memory.riotpiao.com/memory/projects
|
||
|
|
```
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"projects": ["homelab", "portfolio"],
|
||
|
|
"count": 2
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**RBAC:** Returns only projects user has read access to.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### List Skills
|
||
|
|
|
||
|
|
Get extracted skills.
|
||
|
|
|
||
|
|
```http
|
||
|
|
GET /memory/skills
|
||
|
|
```
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"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.
|
||
|
|
|
||
|
|
```http
|
||
|
|
GET /memory/ingest/{ingest_id}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
```bash
|
||
|
|
curl -H "Authorization: Bearer $TOKEN" \
|
||
|
|
http://memory.riotpiao.com/memory/ingest/session-2024-01-15-001
|
||
|
|
```
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"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
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"error": "unauthorized",
|
||
|
|
"reason": "missing Authorization header"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 403 Forbidden
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"error": "forbidden",
|
||
|
|
"reason": "missing capability: memory:write"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Or with RBAC:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"error": "forbidden",
|
||
|
|
"reason": "access denied to project 'secret-project'"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 429 Too Many Requests
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"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
|
||
|
|
|
||
|
|
```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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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
|
||
|
|
```
|