Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ You have three agents configured: Claude Code for deep reasoning, Codex for fast
| **No episodic memory** | Vector search only | CAST scenes — time/place/topic clustering |
| **No consolidation** | Store everything as-is | CLS sleep cycles — episodic to semantic distillation |
| **No real-time coordination** | Polling or nothing | Active memory signal bus — agents see each other instantly |
| **Concurrent access** | Single-process locks | sqlite-vec WAL — multiple agents, one DB |
| **Agents don't learn** | Retrain or nothing | Skill-policy memory — agents accumulate reusable skills |
| **Concurrent access** | Single-process locks | zvec HNSW — multiple agents, directory-based collections |

---

Expand All @@ -155,6 +156,35 @@ Agent capabilities are stored as memories: *"claude-code: Advanced coding agent.

No new database tables. No separate routing service. The same `Memory.add()` / `Memory.search()` that stores user conversations also stores agent profiles and routes tasks.

### Skill Memory — the self-improvement loop

Agents learn from experience. When an agent completes a task, Engram records the trajectory (actions, tools, results). Successful trajectories accumulate. The Skill Miner analyzes clusters of similar trajectories and extracts reusable **skills** — validated procedures stored as SKILL.md files with YAML frontmatter.

Skills have confidence scores that update on success/failure (Bayesian, asymmetric — failures penalize more). High-confidence skills are automatically suggested when matching tasks arrive. The loop:

```
Agent works → Trajectory recorded → Miner extracts patterns → Skills stored
↑ |
└── Agent applies skill → Outcome logged → Confidence updated ──┘
```

```python
from engram import SmartMemory

m = SmartMemory(preset="smart")

# Search for relevant skills
skills = m.search_skills("fix python import error")

# Apply a skill — returns injectable recipe
result = m.apply_skill(skill_id)

# Report outcome — updates confidence
m.log_skill_outcome(skill_id, success=True)
```

Skills are discovered from `~/.engram/skills/` and `{repo}/.engram/skills/`. Six MCP tools: `search_skills`, `apply_skill`, `log_skill_outcome`, `record_trajectory_step`, `mine_skills`, `get_skill_stats`.

### Handoff

When an agent pauses (rate limit, crash, tool switch), it saves a session digest: task summary, decisions made, files touched, TODOs remaining. The next agent loads it and continues. If no digest was saved, Engram falls back to parsing the conversation logs automatically.
Expand All @@ -171,6 +201,8 @@ When an agent pauses (rate limit, crash, tool switch), it saves a session digest
| **CLS Distillation** | Sleep-cycle replay: episodic to semantic fact extraction |
| **Multi-trace** | Benna-Fusi model — fast/mid/slow decay traces per memory |
| **Intent routing** | Episodic vs semantic query classification |
| **Skill Memory** | SKILL.md files — discover, apply, and mine reusable agent skills |
| **Skill Miner** | Trajectory recording → pattern extraction → skill compilation |
| **Orchestrator** | Agent registry + semantic task routing + CAS claim/release |
| **Handoff bus** | Session digests, checkpoints, JSONL log fallback |
| **Active Memory** | Real-time signal bus with TTL tiers |
Expand Down Expand Up @@ -206,7 +238,7 @@ memory.add("User prefers Python over TypeScript", user_id="u1")
results = memory.search("programming preferences", user_id="u1")
```

**18 MCP tools** — memory CRUD, semantic search, episodic scenes, profiles, decay, session handoff. One command configures Claude Code, Cursor, and Codex:
**14 MCP tools** — memory CRUD, semantic search, session handoff, skill search/apply/mine, trajectory recording. One command configures Claude Code, Cursor, and Codex:

```bash
engram install
Expand Down Expand Up @@ -342,13 +374,14 @@ Works with any tool-calling agent via REST: `engram-api` starts a server at `htt
```
├── engram/ # engram-memory — core Python package
│ ├── core/ # decay, echo, category, scenes, distillation, traces
│ ├── memory/ # Memory class (orchestrates all layers)
│ ├── memory/ # CoreMemory → SmartMemory → FullMemory
│ ├── skills/ # skill schema, store, discovery, executor, miner, trajectories
│ ├── llms/ # LLM providers (gemini, openai, nvidia, ollama)
│ ├── embeddings/ # embedding providers
│ ├── vector_stores/ # sqlite-vec, in-memory
│ ├── vector_stores/ # zvec, sqlite-vec, in-memory
│ ├── db/ # SQLite persistence
│ ├── api/ # REST API endpoints
│ ├── mcp_server.py # MCP server (18 tools)
│ ├── mcp_server.py # MCP server (14 tools)
│ └── cli.py # CLI interface
├── engram-bus/ # engram-bus — agent communication
│ └── engram_bus/ # bus, pub/sub, handoff store, TCP server
Expand Down
Empty file removed engram-bus/tests/__init__.py
Empty file.
43 changes: 40 additions & 3 deletions engram-enterprise/engram_enterprise/api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel, Field

from engram import Memory
from engram.configs.base import EmbedderConfig, LLMConfig, MemoryConfig, VectorStoreConfig
from engram.memory.main import Memory
from engram_enterprise.api.auth import (
enforce_session_issuer,
get_token_from_request,
Expand All @@ -41,6 +42,7 @@
SessionCreateResponse,
)
from engram_enterprise.policy import feature_enabled
from engram_enterprise.kernel import PersonalMemoryKernel
from engram.exceptions import FadeMemValidationError
from engram.observability import add_metrics_routes, logger as structured_logger, metrics

Expand Down Expand Up @@ -103,19 +105,54 @@ class DecayResponse(BaseModel):

_memory: Optional[Memory] = None
_memory_lock = threading.Lock()
_kernel: Optional[PersonalMemoryKernel] = None
_kernel_lock = threading.Lock()


def _fallback_memory_config() -> MemoryConfig:
data_dir = os.path.join(os.path.expanduser("~"), ".engram")
os.makedirs(data_dir, exist_ok=True)
dims = 384
return MemoryConfig(
llm=LLMConfig(provider="mock", config={}),
embedder=EmbedderConfig(provider="simple", config={"embedding_dims": dims}),
vector_store=VectorStoreConfig(
provider="memory",
config={
"collection_name": "engram_enterprise",
"embedding_model_dims": dims,
},
),
history_db_path=os.path.join(data_dir, "enterprise_history.db"),
collection_name="engram_enterprise",
embedding_model_dims=dims,
)


def get_memory() -> Memory:
global _memory
if _memory is None:
with _memory_lock:
if _memory is None:
_memory = Memory()
try:
_memory = Memory()
except Exception as exc:
logger.warning(
"Failed to initialize default Memory config (%s). "
"Falling back to mock/simple in-memory configuration.",
exc,
)
_memory = Memory(config=_fallback_memory_config())
return _memory


def get_kernel():
return get_memory().kernel
global _kernel
if _kernel is None:
with _kernel_lock:
if _kernel is None:
_kernel = PersonalMemoryKernel(get_memory())
return _kernel


def _extract_content(messages: Optional[Union[str, List[Dict[str, Any]]]], content: Optional[str]) -> str:
Expand Down
Empty file.
19 changes: 0 additions & 19 deletions engram-skills/engram_skills/__init__.py

This file was deleted.

11 changes: 0 additions & 11 deletions engram-skills/engram_skills/config.py

This file was deleted.

100 changes: 0 additions & 100 deletions engram-skills/engram_skills/loader.py

This file was deleted.

104 changes: 0 additions & 104 deletions engram-skills/engram_skills/mcp_tools.py

This file was deleted.

Loading
Loading