# Engram Python SDK

Neural memory format for AI systems — hierarchical, temporal, multi-modal.

[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Installation

```bash
pip install engram
```

With LangChain support:

```bash
pip install engram[langchain]
```

## Quick Start

```python
from engram import MemoryTree

# Create a new memory tree
tree = MemoryTree()

# Add memories
tree.add("The capital of France is Paris.", tags=["geography", "facts"])
tree.add("Python was created by Guido van Rossum.", tags=["programming", "facts"])

# Save to file
tree.save("knowledge.engram")

# Load from file
tree = MemoryTree.from_file("knowledge.engram")
print(f"Loaded {tree.size()} memories")

# Search
results = tree.find_by_tag("facts")
results = tree.search_text("Python")
```

## Core Concepts

### Memory Nodes

Each memory is a `MemoryNode` with:

- **Content** — Text, image, audio, or code
- **Hierarchy** — Parent/child relationships
- **Temporal** — Created, modified, accessed timestamps
- **Quality** — Score, confidence, verification status
- **Embedding** — Optional vector for semantic search
- **Metadata** — Tags and custom properties

### MemoryTree

The `MemoryTree` class manages a collection of nodes:

```python
from engram import MemoryTree, ContentType

tree = MemoryTree()

# Add with options
node = tree.add(
    "Important information",
    content_type=ContentType.TEXT,
    tags=["important"],
    custom={"source": "manual"},
)

# Hierarchy
parent = tree.add("Parent topic")
child = tree.add("Child detail", parent_id=parent.id)

# Access
tree.get(node.id)           # Get by ID
tree.get_all()              # All nodes
tree.get_roots()            # Root nodes only
tree.get_children(parent.id)  # Children of a node

# Search
tree.find_by_tag("important")
tree.find_by_depth(1)
tree.search_text("information")

# With embeddings
import numpy as np
embedding = np.random.rand(384).astype(np.float32)
tree.add("Embedded memory", embedding=embedding)
tree.search_similar(query_embedding, top_k=10)
```

### File I/O

```python
from engram import read_engram, write_engram

# Low-level access
engram_file = read_engram("data.engram")
print(engram_file.header.metadata.source)
print(f"{len(engram_file.nodes)} nodes")

# Modify and save
engram_file.header.metadata.description = "Updated"
write_engram(engram_file, "data.engram")
```

## LangChain Integration

Use Engram as a persistent memory backend for LangChain:

```python
from engram.langchain import EngramMemory
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI

# Create persistent memory
memory = EngramMemory(brain_path="chat.engram")

# Use with LangChain
chain = ConversationChain(
    llm=ChatOpenAI(),
    memory=memory,
)

# Conversations persist across sessions
response = chain.predict(input="Hello!")

# Search conversation history
results = memory.search("Hello")

# Add knowledge for RAG
memory.add_knowledge(
    "Engram is a neural memory format.",
    tags=["product", "definition"]
)

# Access underlying tree
memory.tree.find_by_tag("conversation")
```

### EngramMemory Options

```python
EngramMemory(
    brain_path="chat.engram",   # Path to .engram file
    memory_key="history",        # Key for memory in chain
    input_key="input",           # Key for human input
    output_key="output",         # Key for AI output
    return_messages=False,       # Return Message objects vs string
    max_history=10,              # Max messages to return
)
```

## Binary Format

The `.engram` format is a binary file with:

- **Magic bytes**: `ENGRAM` (6 bytes)
- **Version**: Major.Minor (2 bytes)
- **Header length**: uint32 LE (4 bytes)
- **Header**: MessagePack-encoded metadata
- **Payload**: MessagePack-encoded nodes, entities, links

Integrity is verified via SHA-256 hash stored in the header.

## Compatibility

The Python SDK is fully compatible with:

- `@terronex/engram` — TypeScript/JavaScript SDK
- `engram-rs` — Rust SDK (coming soon)
- `engram-go` — Go SDK (coming soon)

All SDKs read and write the same binary format (Engram v1.0).

## API Reference

### Types

| Type | Description |
|------|-------------|
| `MemoryNode` | A single memory with content, hierarchy, and metadata |
| `Entity` | Named entity extracted from memories |
| `MemoryLink` | Relationship between nodes |
| `EngramFile` | Complete file structure |
| `EngramHeader` | File metadata and configuration |

### Enums

| Enum | Values |
|------|--------|
| `ContentType` | text, image, audio, code, summary |
| `DecayTier` | hot, warm, cold, archive |
| `EntityType` | person, place, organization, concept, event, document |
| `LinkType` | related, references, contradicts, supersedes, elaborates, summarizes, causes, follows |

### Functions

| Function | Description |
|----------|-------------|
| `read_engram(path)` | Read an engram file |
| `write_engram(engram, path)` | Write an engram file |
| `load(path)` | Shorthand for read_engram |
| `save(engram, path)` | Shorthand for write_engram |

## License

MIT — See [LICENSE](LICENSE) for details.

## Links

- [Documentation](https://docs.terronex.dev/engram)
- [TypeScript SDK](https://github.com/Terronex-dev/engram)
- [GitHub](https://github.com/Terronex-dev/engram-py)
