# Clew Engine: Database Adapter Specification

## Overview

The Clew Engine uses a **pluggable adapter architecture** to support multiple database backends. This enables the BYO DB (Bring Your Own Database) strategy — customers can use their existing infrastructure instead of provisioning new databases.

---

## Architecture

```
┌────────────────────────────────────────────────────────────┐
│                      Clew Engine                           │
│  ┌──────────────────────────────────────────────────────┐  │
│  │               Adapter Layer (Protocol)               │  │
│  │   VectorStore        GraphStore        Embeddings    │  │
│  └───────┬─────────────────┬─────────────────┬──────────┘  │
│          │                 │                 │             │
│  ┌───────▼──────┐   ┌──────▼──────┐   ┌──────▼──────┐      │
│  │ Vector       │   │ Graph       │   │ Embedding   │      │
│  │ Adapters     │   │ Adapters    │   │ Adapters    │      │
│  └──────────────┘   └─────────────┘   └─────────────┘      │
└────────────────────────────────────────────────────────────┘
```

---

## Protocol Definitions

### VectorStore Protocol

```python
class VectorStore(Protocol):
    async def search(
        self,
        query_vector: List[float],
        limit: int = 10,
        filters: Optional[Dict] = None
    ) -> List[SearchResult]
    
    async def upsert(
        self,
        id: str,
        vector: List[float],
        payload: Dict
    ) -> None
```

### GraphStore Protocol

```python
class GraphStore(Protocol):
    async def traverse(
        self,
        start_node_id: str,
        relationship_types: List[str],
        depth: int = 1
    ) -> TraversalResult
    
    async def create_node(
        self,
        node_type: str,
        properties: Dict
    ) -> str
    
    async def create_relationship(
        self,
        source_id: str,
        target_id: str,
        rel_type: str,
        properties: Optional[Dict] = None
    ) -> None
```

---

## Supported Adapters

### Vector Store Adapters

| Adapter | Status | Use Case |
|---------|--------|----------|
| `QdrantAdapter` | ✅ Implemented | Default, best performance |
| `PgVectorAdapter` | ✅ Implemented | Postgres users, single-DB setup |
| `OpenSearchAdapter` | 📋 Planned | Enterprise, existing ES/OS infra |
| `MilvusAdapter` | 📋 Planned | Large-scale vector workloads |

### Graph Store Adapters

| Adapter | Status | Use Case |
|---------|--------|----------|
| `Neo4jAdapter` | ✅ Implemented | Default, full Cypher support |
| `PgAgeAdapter` | 📋 Planned | Postgres-only environments |
| `NeptuneAdapter` | 📋 Planned | AWS-native customers |
| `NoOpGraphAdapter` | ✅ Implemented | Vector-only mode |

### Embedding Adapters

| Adapter | Status | Use Case |
|---------|--------|----------|
| `OpenAIAdapter` | ✅ Implemented | Production, best quality |
| `OllamaAdapter` | ✅ Implemented | Local/offline, privacy |
| `HashEmbeddings` | ✅ Implemented | Deterministic fallback for testing |
| `VoyageAdapter` | 📋 Planned | Code-specific embeddings |

---

## Customer Personas & Recommended Stacks

| Persona | Vector | Graph | Embeddings | Notes |
|---------|--------|-------|------------|-------|
| **Indie/Startup** | Qdrant | Neo4j | Ollama | Default stack, all local |
| **Postgres Shop** | pgvector | AGE or NoOp | OpenAI | Single database |
| **Enterprise (ES)** | OpenSearch | Neo4j | OpenAI | Leverage existing infra |
| **AWS Native** | OpenSearch | Neptune | Bedrock | Fully managed |
| **Privacy-First** | Qdrant | Neo4j | Ollama | Air-gapped deployment |

---

## Configuration

Adapters are selected via environment variables:

```bash
# Vector Store
CLEW_VECTOR_ADAPTER=qdrant          # qdrant | pgvector | opensearch
QDRANT_HOST=localhost
QDRANT_PORT=6333

# Or for pgvector:
CLEW_VECTOR_ADAPTER=pgvector
POSTGRES_URI=postgresql://user:pass@localhost/clew

# Graph Store
CLEW_GRAPH_ADAPTER=neo4j            # neo4j | pgage | noop
NEO4J_URI=bolt://localhost:7687

# Embeddings
CLEW_EMBEDDING_ADAPTER=openai       # openai | ollama | voyage
OPENAI_API_KEY=sk-...
```

---

## NoOp Graph Mode

For customers who only need vector search (no relationship traversal):

```python
class NoOpGraphAdapter(GraphStore):
    """Stub adapter for vector-only deployments."""
    
    async def traverse(self, start_node_id, relationship_types, depth=1):
        return TraversalResult(
            nodes=[],
            edges=[],
            metadata={"mode": "vector_only", "graph_disabled": True}
        )
    
    async def create_node(self, node_type, properties):
        return properties.get("id", str(uuid.uuid4()))
    
    async def create_relationship(self, source_id, target_id, rel_type, properties=None):
        pass  # No-op
```

This enables Clew to work with **just** Postgres + pgvector — no Neo4j required.

---

## Implementation Priority

1. **V1 (Current)**
   - QdrantAdapter ✅
   - Neo4jAdapter ✅
   - OpenAI/Ollama Embeddings ✅

2. **V1.1 (Next)**
   - PgVectorAdapter ← broadest adoption potential
   - NoOpGraphAdapter ← enables Postgres-only deployments

3. **V2 (Future)**
   - OpenSearchAdapter ← enterprise demand
   - PgAgeAdapter ← true single-DB solution
   - VoyageAdapter ← code-specific embeddings
