Open source · Self-hosteable · MIT License

The memory layer your AI agents have been missing

Persistent memory, shared context, and full action history for any agent framework. Drop-in backend in minutes.

terminal
git clone https://github.com/GerardSole/CrewLayer
cd CrewLayer && cp .env.example .env
docker compose up -d
# ✓  API ready at http://localhost:8000
# ✓  Dashboard at  http://localhost:8000/dashboard
441 tests passing · MIT License · Self-hosteable

Works with your stack

LangChain
AutoGen
LlamaIndex
CrewAI
Vercel AI
Claude
OpenAI

Features

Everything your agent needs to remember

One backend. Every capability you need to ship production-grade agents.

🧠

Persistent Memory

Short-term in Redis, long-term in pgvector. Semantic recall by similarity. Auto-extracted from conversations with Claude.

📋

Action Logger

Immutable append-only log of every tool call. Debug, audit, and replay any agent action with full input/output context.

🗒️

Shared Blackboard

Key-value store for multi-agent coordination with real-time pub/sub over Redis. Agents communicate without polling.

🔑

Multi-tenant

Every resource isolated per tenant. API key auth with granular scopes. Built for teams and SaaS products from day one.

📊

Evaluations

Rate agent responses, detect anomalies automatically, and run A/B tests on prompts with built-in LLM-as-a-judge scoring.

🔌

MCP Server

Use CrewLayer directly from Claude Code and Claude Desktop as MCP tools. No HTTP code. Just call the tools.

How it works

Your agent. Your framework. Our memory.

CrewLayer sits behind your agent as a stateful backend. You bring the logic; we handle everything else.

1

Create an agent

Register your agent in CrewLayer to get a unique agent_id. One API call — that's it.

2

Connect your framework

Use our Python SDK, TypeScript SDK, REST API, or MCP server. Works with any agent framework.

3

Everything persists

Memories, actions, and context are stored automatically. Your agent remembers across every session.

agent.py
from crewlayer import CrewLayerClient

client = CrewLayerClient(api_key="crwl_...")

# Your agent learns something important
client.memory.save(
    agent_id="...",
    content="User prefers concise answers",
    importance=0.9
)

# Next session — it remembers
memories = client.memory.recall(
    agent_id="...",
    query="user preferences"
)
# → [{"content": "User prefers concise answers",
#      "similarity": 0.97}]

# Log every tool call automatically
client.actions.log(
    agent_id="...",
    tool_name="web_search",
    input_params={"query": "latest AI news"},
    output_result={"count": 12},
    status="success"
)

Production ready

Built for production from day one

No toy features. Every capability is production-grade and covered by 441 tests.

Semantic search with pgvector
Automatic memory extraction with Claude
Memory decay and deduplication
Episode grouping across sessions
Prompt version control with diff and rollback
Real-time anomaly detection
A/B testing for agent configurations
LLM-as-a-judge auto-evaluation
Full audit log for every operation
Prometheus metrics + Grafana dashboard

Integrations

Works with every major framework

Copy-paste examples. No boilerplate. Wire in your agent_id and go.

Add persistent memory to any LangChain agent in under 10 lines.

langchain_agent.py
from langchain.agents import AgentExecutor
from crewlayer import CrewLayerClient

cl = CrewLayerClient(api_key="crwl_...")
AGENT_ID = "550e8400-e29b-41d4-a716-446655440000"

def enrich_with_memory(query: str) -> str:
    memories = cl.memory.recall(AGENT_ID, query=query, top_k=5)
    context = "\n".join(f"- {m['content']}" for m in memories)
    return f"Relevant context:\n{context}\n\nQuery: {query}"

# Wrap your existing AgentExecutor
executor = AgentExecutor.from_agent_and_tools(agent, tools)
response = executor.invoke({"input": enrich_with_memory(user_query)})

# Persist new memories after the call
cl.memory.save(AGENT_ID, content=response["output"], importance=0.7)

Plug CrewLayer into AutoGen agents as a stateful memory backend.

autogen_agent.py
import autogen
from crewlayer import CrewLayerClient

cl = CrewLayerClient(api_key="crwl_...")
AGENT_ID = "550e8400-e29b-41d4-a716-446655440000"

class MemoryAssistant(autogen.AssistantAgent):
    def generate_reply(self, messages, sender, **kwargs):
        last_msg = messages[-1]["content"]

        # Pull relevant memories before responding
        memories = cl.memory.recall(AGENT_ID, query=last_msg, top_k=5)
        if memories:
            mem_ctx = "\n".join(f"- {m['content']}" for m in memories)
            messages = [
                {"role": "system", "content": f"Memory:\n{mem_ctx}"}
            ] + messages

        reply = super().generate_reply(messages, sender, **kwargs)

        # Log the action
        cl.actions.log(AGENT_ID, tool_name="generate_reply",
                       input_params={"query": last_msg},
                       output_result={"reply": reply}, status="success")
        return reply

Use CrewLayer alongside LlamaIndex's query engine for persistent cross-session context.

llamaindex_agent.py
from llama_index.core import VectorStoreIndex
from crewlayer import CrewLayerClient

cl = CrewLayerClient(api_key="crwl_...")
AGENT_ID = "550e8400-e29b-41d4-a716-446655440000"

index = VectorStoreIndex.from_documents(docs)
query_engine = index.as_query_engine()

def query_with_memory(question: str) -> str:
    # Enrich query with agent's long-term memory
    past = cl.memory.recall(AGENT_ID, query=question, top_k=3)
    enriched = question
    if past:
        enriched += "\n\n[Agent memory]\n"
        enriched += "\n".join(m["content"] for m in past)

    response = query_engine.query(enriched)

    # Persist response as a new memory
    cl.memory.save(AGENT_ID, content=str(response), importance=0.7)
    return str(response)

Add stateful memory to Vercel AI SDK routes in a few lines of TypeScript.

app/api/chat/route.ts
import { streamText } from 'ai'
import { openai } from '@ai-sdk/openai'
import { CrewLayerClient } from '@crewlayer/sdk'

const cl = new CrewLayerClient({ apiKey: process.env.CREWLAYER_API_KEY! })
const AGENT_ID = '550e8400-e29b-41d4-a716-446655440000'

export async function POST(req: Request) {
  const { messages } = await req.json()
  const lastMsg = messages.at(-1)?.content ?? ''

  // Pull relevant memories for context
  const memories = await cl.memory.recall(AGENT_ID, {
    query: lastMsg, topK: 5
  })
  const memCtx = memories.map(m => `- ${m.content}`).join('\n')

  const result = streamText({
    model: openai('gpt-4o'),
    system: `You are a helpful assistant.\n\nMemory:\n${memCtx}`,
    messages,
    onFinish: async ({ text }) => {
      // Persist assistant reply as a new memory
      await cl.memory.save(AGENT_ID, { content: text, importance: 0.6 })
    }
  })

  return result.toDataStreamResponse()
}

Dashboard

Full visibility into every agent

Web dashboard included. See memories, actions, evaluations, and agent status in real time. No extra setup required.

Memory explorer with semantic search
Action replay and full audit history
A/B test results and prompt version history
Anomaly alerts and LLM evaluation scores
Agent status history with 3-second polling
CrewLayer — Agents
Agent Status Updated
🤖
sales-agent-v2
550e8400-e29b-41d4-a7…
working 2s ago
🤖
support-agent
f47ac10b-58cc-4372-a5…
idle 4m ago
🤖
data-pipeline
6ba7b810-9dad-11d1-80…
error 11m ago
🤖
research-agent
6ba7b812-9dad-11d1-80…
working just now
4 agents · 2 working View all →

Self-host

Yours to run, yours to own

No SaaS pricing. No data leaving your infrastructure. Deploy on any machine that runs Docker — your VPS, AWS, bare metal, or local dev machine. CrewLayer is MIT-licensed and always will be.

No vendor lock-in Your data stays yours MIT License
terminal
# 1. Clone and configure
git clone https://github.com/GerardSole/CrewLayer
cd CrewLayer
cp .env.example .env
# Edit .env — add your ANTHROPIC_API_KEY

# 2. Start everything with one command
docker compose up -d

# Starts: PostgreSQL · Redis · API · Dashboard
# API        → http://localhost:8000
# Dashboard  → http://localhost:8000/dashboard

# 3. Optional: observability stack
docker compose -f docker-compose.observability.yml up -d
# Prometheus → :9090   Grafana → :3000

Comparison

How CrewLayer compares

The only solution that gives you everything in one self-hosted package.

Feature CrewLayer Mem0 Zep Build it yourself
Persistent memory ✓ ✓ ✓ weeks
Semantic recall ✓ ✓ ✓ weeks
Action logging ✓ ✗ ✗ weeks
Multi-agent context ✓ ✗ partial weeks
Evaluations & A/B testing ✓ ✗ ✗ ✗
Self-hosteable ✓ paid plan ✓ ✓
Open source ✓ ✓ ✓ ✓
MCP server ✓ ✗ ✗ ✗

Give your agents a memory

Open source. Self-hosteable. Production ready.

Read the documentation →