- Node-guardian running on MacBook and updating metrics - NODE2 agents (Atlas, Greeter, Oracle, Builder Bot) assigned to node-2-macbook-m4max - Swapper models displaying correctly (8 models) - DAGI Router agents showing with correct status (3 active, 1 stale) - Router health check using node_cache for remote nodes
321 lines
6.5 KiB
Markdown
321 lines
6.5 KiB
Markdown
# Memory Orchestrator Service
|
|
|
|
**Port:** 7008
|
|
**Purpose:** Unified memory API for DAARION agents
|
|
|
|
## Features
|
|
|
|
✅ **Multi-layer memory:**
|
|
- Short-term: Recent conversations & events (PostgreSQL)
|
|
- Mid-term: Semantic memory with RAG (Vector store)
|
|
- Long-term: Knowledge base (Docs, roadmaps)
|
|
|
|
✅ **Semantic search:**
|
|
- Vector embeddings (BGE-M3 or similar)
|
|
- Cosine similarity search
|
|
- Fallback to text search if pgvector unavailable
|
|
|
|
✅ **Flexible storage:**
|
|
- PostgreSQL for structured data
|
|
- pgvector for embeddings (optional)
|
|
- Filesystem for knowledge base (Phase 3 stub)
|
|
|
|
## API
|
|
|
|
### POST /internal/agent-memory/query
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"agent_id": "agent:sofia",
|
|
"microdao_id": "microdao:7",
|
|
"channel_id": "optional-channel-uuid",
|
|
"query": "What were recent changes in this microDAO?",
|
|
"limit": 5,
|
|
"kind_filter": ["conversation", "dao-event"]
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"items": [
|
|
{
|
|
"id": "mem-uuid",
|
|
"kind": "conversation",
|
|
"score": 0.87,
|
|
"content": "User discussed Phase 3 implementation...",
|
|
"meta": {
|
|
"source": "channel:...",
|
|
"timestamp": "..."
|
|
},
|
|
"created_at": "2025-11-24T12:34:56Z"
|
|
}
|
|
],
|
|
"total": 3,
|
|
"query": "What were recent changes..."
|
|
}
|
|
```
|
|
|
|
### POST /internal/agent-memory/store
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"agent_id": "agent:sofia",
|
|
"microdao_id": "microdao:7",
|
|
"channel_id": "optional",
|
|
"kind": "conversation",
|
|
"content": {
|
|
"user_message": "How do I start Phase 3?",
|
|
"agent_reply": "First, copy PHASE3_MASTER_TASK.md..."
|
|
},
|
|
"metadata": {
|
|
"channel_name": "dev-updates",
|
|
"message_id": "msg-123"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"ok": true,
|
|
"id": "mem-uuid-123"
|
|
}
|
|
```
|
|
|
|
### POST /internal/agent-memory/summarize
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"agent_id": "agent:sofia",
|
|
"microdao_id": "microdao:7",
|
|
"limit": 10
|
|
}
|
|
```
|
|
|
|
**Response (Phase 3 stub):**
|
|
```json
|
|
{
|
|
"summary": "Recent activity summary: 10 memories retrieved. [Full summary in Phase 4]",
|
|
"items_processed": 10
|
|
}
|
|
```
|
|
|
|
## Setup
|
|
|
|
### Prerequisites
|
|
|
|
**PostgreSQL with pgvector (optional):**
|
|
```sql
|
|
CREATE EXTENSION IF NOT EXISTS vector;
|
|
```
|
|
|
|
**Or without pgvector:**
|
|
- Service will work with fallback text search
|
|
|
|
### Environment Variables
|
|
|
|
```bash
|
|
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/daarion
|
|
EMBEDDING_ENDPOINT=http://localhost:8001/embed # Optional
|
|
MEMORY_ORCHESTRATOR_SECRET=dev-secret-token
|
|
```
|
|
|
|
### Local Development
|
|
|
|
```bash
|
|
cd services/memory-orchestrator
|
|
|
|
# Install
|
|
pip install -r requirements.txt
|
|
|
|
# Run
|
|
python main.py
|
|
```
|
|
|
|
### Docker
|
|
|
|
```bash
|
|
docker build -t memory-orchestrator .
|
|
docker run -p 7008:7008 \
|
|
-e DATABASE_URL="postgresql://..." \
|
|
memory-orchestrator
|
|
```
|
|
|
|
## Memory Types
|
|
|
|
### Short-term (7 days retention)
|
|
- Recent channel messages
|
|
- Event log
|
|
- Quick lookup by time
|
|
|
|
**Storage:** `agent_memories_short` table
|
|
|
|
### Mid-term (90 days retention)
|
|
- Semantic search
|
|
- Conversation context
|
|
- Task history
|
|
|
|
**Storage:** `agent_memories_vector` table (with embeddings)
|
|
|
|
### Long-term (permanent)
|
|
- Knowledge base
|
|
- Docs & roadmaps
|
|
- Structured knowledge
|
|
|
|
**Storage:** Filesystem (Phase 3 stub)
|
|
|
|
## Integration with agent-runtime
|
|
|
|
```python
|
|
import httpx
|
|
|
|
async def get_agent_context(agent_id, query):
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.post(
|
|
"http://memory-orchestrator:7008/internal/agent-memory/query",
|
|
headers={"X-Internal-Secret": "dev-secret-token"},
|
|
json={
|
|
"agent_id": agent_id,
|
|
"microdao_id": "microdao:7",
|
|
"query": query,
|
|
"limit": 5
|
|
}
|
|
)
|
|
return response.json()
|
|
|
|
async def save_conversation(agent_id, user_msg, agent_reply):
|
|
async with httpx.AsyncClient() as client:
|
|
await client.post(
|
|
"http://memory-orchestrator:7008/internal/agent-memory/store",
|
|
headers={"X-Internal-Secret": "dev-secret-token"},
|
|
json={
|
|
"agent_id": agent_id,
|
|
"microdao_id": "microdao:7",
|
|
"kind": "conversation",
|
|
"content": {
|
|
"user_message": user_msg,
|
|
"agent_reply": agent_reply
|
|
}
|
|
}
|
|
)
|
|
```
|
|
|
|
## Embedding Service
|
|
|
|
### Option 1: Local Embedding (Recommended for Phase 3)
|
|
|
|
Use sentence-transformers or similar:
|
|
|
|
```python
|
|
# Simple embedding server (Flask/FastAPI)
|
|
from sentence_transformers import SentenceTransformer
|
|
|
|
model = SentenceTransformer('BAAI/bge-m3')
|
|
|
|
@app.post("/embed")
|
|
def embed(text: str):
|
|
embedding = model.encode(text).tolist()
|
|
return {"embedding": embedding}
|
|
```
|
|
|
|
### Option 2: OpenAI Embeddings
|
|
|
|
```python
|
|
# Update embedding_client.py to use OpenAI
|
|
import openai
|
|
|
|
embedding = openai.embeddings.create(
|
|
input=text,
|
|
model="text-embedding-ada-002"
|
|
)
|
|
```
|
|
|
|
### Option 3: No Embedding (Fallback)
|
|
|
|
Service will use simple text search (ILIKE) if embedding service unavailable.
|
|
|
|
## Database Schema
|
|
|
|
### agent_memories_short
|
|
```sql
|
|
CREATE TABLE agent_memories_short (
|
|
id UUID PRIMARY KEY,
|
|
agent_id TEXT NOT NULL,
|
|
microdao_id TEXT NOT NULL,
|
|
channel_id TEXT,
|
|
kind TEXT NOT NULL,
|
|
content JSONB NOT NULL,
|
|
metadata JSONB,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
```
|
|
|
|
### agent_memories_vector
|
|
```sql
|
|
CREATE TABLE agent_memories_vector (
|
|
id UUID PRIMARY KEY,
|
|
agent_id TEXT NOT NULL,
|
|
microdao_id TEXT NOT NULL,
|
|
channel_id TEXT,
|
|
kind TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
content_json JSONB,
|
|
embedding vector(1024), -- pgvector
|
|
metadata JSONB,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
```
|
|
|
|
## Roadmap
|
|
|
|
### Phase 3 (Current):
|
|
- ✅ Short-term memory (PostgreSQL)
|
|
- ✅ Mid-term memory (Vector search)
|
|
- ✅ Long-term stub (KB filesystem)
|
|
- ✅ Semantic search with embeddings
|
|
- ✅ Fallback to text search
|
|
|
|
### Phase 3.5:
|
|
- 🔜 LLM-based summarization
|
|
- 🔜 Memory consolidation
|
|
- 🔜 Context pruning
|
|
- 🔜 Advanced RAG strategies
|
|
|
|
### Phase 4:
|
|
- 🔜 Knowledge base indexing
|
|
- 🔜 Multi-modal memory (images, files)
|
|
- 🔜 Memory sharing across agents
|
|
- 🔜 Forgetting mechanisms
|
|
|
|
## Troubleshooting
|
|
|
|
**pgvector not available?**
|
|
- Service will work with text search fallback
|
|
- To enable: `CREATE EXTENSION vector;` in PostgreSQL
|
|
|
|
**Embeddings not working?**
|
|
- Check embedding service: `curl http://localhost:8001/embed`
|
|
- Service will use fallback if unavailable
|
|
|
|
**Slow queries?**
|
|
- Check indexes: `EXPLAIN ANALYZE SELECT ...`
|
|
- Tune ivfflat index parameters
|
|
- Consider increasing `lists` parameter
|
|
|
|
---
|
|
|
|
**Status:** ✅ Phase 3 Ready
|
|
**Version:** 1.0.0
|
|
**Last Updated:** 2025-11-24
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|