### Install Membrane Go Library Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/go-library.mdx Install the Membrane Go library using the go get command. ```bash go get github.com/BennettSchwartz/membrane ``` -------------------------------- ### Install and Run Documentation Development Server Source: https://github.com/bennettschwartz/membrane/blob/master/README.md Installs project dependencies and starts a local development server for the documentation site. Ensure Wrangler is configured for deployment. ```bash npm install npm run docs:dev npm run docs:build # Deploy to Cloudflare Workers when Wrangler is configured npm run docs:deploy ``` -------------------------------- ### Python Client Setup and Testing Source: https://github.com/bennettschwartz/membrane/blob/master/CONTRIBUTING.md Install the Python client with development dependencies and run its tests. Ensure the Python client is functional after changes. ```bash python -m pip install -e "clients/python[dev]" python -m pytest clients/python/tests/ ``` -------------------------------- ### Install Python Client Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/overview.mdx Install the Python client library for Membrane. This is a prerequisite for using the Python code examples. ```bash pip install -e clients/python ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/bennettschwartz/membrane/blob/master/docs/sdks/python.mdx Install the Python SDK with development dependencies and set it up for local development using pip. ```bash cd clients/python pip install -e .[dev] pytest ``` -------------------------------- ### Install Python SDK Source: https://github.com/bennettschwartz/membrane/blob/master/README.md Install the Python SDK using pip. The 'dev' extra installs development dependencies for testing. ```bash python -m pip install -e "clients/python[dev]" python -m pytest clients/python/tests ``` -------------------------------- ### CaptureMemory Request Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/ingestion.mdx Example of how to construct and use the CaptureMemoryRequest. Ensure all required fields like Content are provided. ```go capture, err := m.CaptureMemory(ctx, ingestion.CaptureMemoryRequest{ Source: "auth-agent", SourceKind: "tool_output", Content: map[string]any{ "tool_name": "go test", "args": map[string]any{"packages": []string{"./pkg/auth"}}, "result": map[string]any{"exit_code": 0}, }, ReasonToRemember: "Successful auth package verification", Summary: "Auth package tests passed", Tags: []string{"auth", "tests"}, Scope: "project-auth", Sensitivity: schema.SensitivityLow, }) ``` -------------------------------- ### Complete Go Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/go-library.mdx A full example demonstrating the initialization of the Membrane client, capturing memory, retrieving graph data, and printing results. Ensure proper error handling and deferred cleanup. ```go package main import ( "context" "fmt" "log" "github.com/BennettSchwartz/membrane/pkg/ingestion" "github.com/BennettSchwartz/membrane/pkg/membrane" "github.com/BennettSchwartz/membrane/pkg/retrieval" "github.com/BennettSchwartz/membrane/pkg/schema" ) func main() { cfg := membrane.DefaultConfig() cfg.DBPath = "my-agent.db" m, err := membrane.New(cfg) if err != nil { log.Fatal(err) } defer m.Stop() ctx := context.Background() if err := m.Start(ctx); err != nil { log.Fatal(err) } capture, err := m.CaptureMemory(ctx, ingestion.CaptureMemoryRequest{ Source: "auth-agent", SourceKind: "event", Content: map[string]any{ "ref": "thread-1:turn-7", "text": "Refactored auth middleware and verified package tests", }, ReasonToRemember: "Keep auth refactor context", Summary: "Refactored auth middleware", Tags: []string{"auth"}, Sensitivity: schema.SensitivityLow, }) if err != nil { log.Fatal(err) } graph, err := m.RetrieveGraph(ctx, &retrieval.RetrieveGraphRequest{ TaskDescriptor: "debug auth", Trust: retrieval.NewTrustContext( schema.SensitivityMedium, true, "auth-agent", nil, ), MemoryTypes: []schema.MemoryType{ schema.MemoryTypeEntity, schema.MemoryTypeSemantic, schema.MemoryTypeEpisodic, }, RootLimit: 5, NodeLimit: 20, MaxHops: 1, }) if err != nil { log.Fatal(err) } fmt.Printf("Captured %s and retrieved %d graph nodes\n", capture.PrimaryRecord.ID, len(graph.Nodes), ) } ``` -------------------------------- ### Multi-step Workflow Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/concepts/plan-graphs.mdx Demonstrates the ingestion of an episodic record, extraction into a plan graph, retrieval of plan graphs, and reinforcement after a successful run. This example illustrates a complex tool graph for setting up a project. ```go // 1. An episodic record with a complex tool graph is ingested automatically // during agent execution. It might look like this in memory: episodicPayload := &schema.EpisodicPayload{ Kind: "episodic", Timeline: []schema.TimelineEvent{ {T: t1, EventKind: "setup_project", Ref: "step#1", Summary: "Init repo"}, {T: t2, EventKind: "install_deps", Ref: "step#2", Summary: "npm install"}, {T: t3, EventKind: "build", Ref: "step#3", Summary: "npm run build"}, }, ToolGraph: []schema.ToolNode{ {ID: "n1", Tool: "git_init", Args: map[string]any{"path": "./"}}, {ID: "n2", Tool: "npm_install", Args: map[string]any{}, DependsOn: []string{"n1"}}, {ID: "n3", Tool: "npm_build", Args: map[string]any{}, DependsOn: []string{"n2"}}, }, Outcome: schema.OutcomeStatusSuccess, } // 2. The consolidation pipeline extracts a plan graph from this episode. // The resulting plan graph will have: // - Node n1: Op="git_init" // - Node n2: Op="npm_install" // - Node n3: Op="npm_build" // - Edge n1→n2: kind=control // - Edge n2→n3: kind=control // - Intent: "setup_project" (from first timeline event kind) // 3. Retrieve plan graphs for a task resp, _ := m.RetrieveGraph(ctx, &retrieval.RetrieveGraphRequest{ TaskDescriptor: "set up a new project", Trust: &retrieval.TrustContext{ MaxSensitivity: schema.SensitivityLow, Authenticated: true, }, MemoryTypes: []schema.MemoryType{ schema.MemoryTypePlanGraph, }, RootLimit: 5, NodeLimit: 10, MaxHops: 0, }) for _, node := range resp.Nodes { r := node.Record if p, ok := r.Payload.(*schema.PlanGraphPayload); ok { fmt.Printf("Plan: %s (intent=%s, executions=%d, failure_rate=%.2f)\n", p.PlanID, p.Intent, p.Metrics.ExecutionCount, p.Metrics.FailureRate, ) for _, node := range p.Nodes { fmt.Printf(" Node %s: op=%s\n", node.ID, node.Op) } for _, edge := range p.Edges { fmt.Printf(" Edge %s → %s (%s)\n", edge.From, edge.To, edge.Kind) } } } // 4. Reinforce the plan after a successful run if len(resp.RootIDs) > 0 { m.Reinforce(ctx, resp.RootIDs[0], "project-agent", "plan completed successfully") } ``` -------------------------------- ### Full YAML Configuration Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/configuration.mdx This example shows all available fields in the Membrane YAML configuration file. Fields not specified will retain their default values. ```yaml backend: "sqlite" db_path: "membrane.db" # postgres_dsn: "postgres://membrane:membrane@localhost:5432/membrane?sslmode=disable" listen_addr: ":9090" decay_interval: "1h" consolidation_interval: "6h" default_sensitivity: "low" selection_confidence_threshold: 0.7 graph_default_root_limit: 10 graph_default_node_limit: 25 graph_default_edge_limit: 100 graph_default_max_hops: 1 # Optional embedding-backed retrieval (Postgres only) # embedding_endpoint: "https://api.openai.com/v1/embeddings" # embedding_model: "text-embedding-3-small" # embedding_dimensions: 1536 # embedding_api_key: "" # or set MEMBRANE_EMBEDDING_API_KEY # Optional LLM-backed semantic extraction (Postgres only) # llm_endpoint: "https://api.openai.com/v1/chat/completions" # llm_model: "gpt-5-mini" # llm_api_key: "" # or set MEMBRANE_LLM_API_KEY # Optional ingest-side interpretation for CaptureMemory # ingest_llm_enabled: true # ingest_llm_endpoint: "https://api.openai.com/v1/chat/completions" # ingest_llm_model: "gpt-5-mini" # ingest_llm_api_key: "" # or set MEMBRANE_INGEST_LLM_API_KEY # Security (prefer environment variables for keys) # encryption_key: "" # or set MEMBRANE_ENCRYPTION_KEY # api_key: "" # or set MEMBRANE_API_KEY # tls_cert_file: "" # tls_key_file: "" rate_limit_per_second: 100 ``` -------------------------------- ### Install Membrane TypeScript Client Source: https://github.com/bennettschwartz/membrane/blob/master/clients/typescript/README.md Install the Membrane TypeScript SDK using npm. ```bash npm install @bennettschwartz/membrane ``` -------------------------------- ### Create and Start Membrane Instance Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/go-library.mdx Initialize a new Membrane instance with a default configuration, specifying the database path, and start it. Ensure to defer the Stop() call to properly shut down the instance. ```go cfg := membrane.DefaultConfig() cfg.DBPath = "my-agent.db" m, err := membrane.New(cfg) if err != nil { log.Fatal(err) } ctx := context.Background() if err := m.Start(ctx); err != nil { log.Fatal(err) } defer m.Stop() ``` -------------------------------- ### Build Local SDK and Install Dependencies Source: https://github.com/bennettschwartz/membrane/blob/master/examples/agent-harness/README.md Builds the local TypeScript SDK and installs npm packages. Run this before setting up LLM configurations. ```bash npm --prefix ../../clients/typescript run build npm install ``` -------------------------------- ### OpenClaw Membrane Plugin Development Setup Source: https://github.com/bennettschwartz/membrane/blob/master/clients/openclaw/README.md Commands to set up the development environment for the OpenClaw Membrane plugin. This includes installing dependencies, building the project, and running tests. ```bash cd clients/openclaw npm install npm run build npm test ``` -------------------------------- ### Install and Build TypeScript SDK Source: https://github.com/bennettschwartz/membrane/blob/master/README.md Installs npm dependencies and builds the TypeScript SDK for the Membrane client. ```bash npm --prefix clients/typescript install npm --prefix clients/typescript run build ``` -------------------------------- ### Create Environment File Source: https://github.com/bennettschwartz/membrane/blob/master/examples/agent-harness/README.md Copies the example environment file to .env. This file is used to store sensitive API keys for LLM access. ```bash cp .env.example .env ``` -------------------------------- ### Go RetrieveByID Example Usage Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/retrieval.mdx Example of how to use RetrieveByID and handle potential errors like record not found or access denied. ```go rec, err := m.RetrieveByID(ctx, "550e8400-e29b-41d4-a716-446655440000", trust) if errors.Is(err, storage.ErrNotFound) { // record does not exist } else if errors.Is(err, retrieval.ErrAccessDenied) { // insufficient trust } ``` -------------------------------- ### Development: Install Dependencies Source: https://github.com/bennettschwartz/membrane/blob/master/clients/typescript/README.md Install project dependencies for TypeScript client development. ```bash cd clients/typescript npm install ``` -------------------------------- ### Install Membrane Python Client Source: https://github.com/bennettschwartz/membrane/blob/master/clients/python/README.md Install the client library using pip. Use the `[dev]` extra for development dependencies like pytest. ```bash pip install -e clients/python ``` ```bash pip install -e clients/python[dev] # includes pytest ``` -------------------------------- ### Start Membrane Daemon with Default SQLite Storage Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/deployment.mdx Start the membraned daemon with default settings, which uses SQLite for storage and creates 'membrane.db' in the current directory. ```bash ./bin/membraned ``` -------------------------------- ### IngestToolOutput Go Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/ingestion.mdx Creates an episodic record with a populated tool graph node. Use this when a tool has been executed. ```go rec, err := svc.IngestToolOutput(ctx, ingestion.IngestToolOutputRequest{ Source: "agent-core", ToolName: "run_bash", Args: map[string]any{"command": "ls -la"}, Result: "total 8", }) ``` -------------------------------- ### Start Membrane Daemon with Postgres Source: https://github.com/bennettschwartz/membrane/blob/master/docs/quickstart.mdx Starts the Membrane daemon using a PostgreSQL database with the pgvector extension. Ensure Docker is running and the PostgreSQL service is configured. ```bash docker compose up -d ./bin/membraned --postgres-dsn postgres://membrane:membrane@localhost:5432/membrane_test?sslmode=disable ``` -------------------------------- ### Start Membrane Daemon with Custom Config File Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/deployment.mdx Start the membraned daemon by loading settings from a specified YAML configuration file. Command-line flags will override values from the config file. ```bash ./bin/membraned --config /etc/membrane/config.yaml ``` -------------------------------- ### Start Membrane Daemon with PostgreSQL Storage Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/deployment.mdx Start the membraned daemon and configure it to use PostgreSQL for storage by providing a PostgreSQL DSN. This enables concurrent writers. ```bash ./bin/membraned --postgres-dsn postgres://membrane:membrane@localhost:5432/membrane_test?sslmode=disable ``` -------------------------------- ### Install OpenClaw Membrane Plugin Source: https://github.com/bennettschwartz/membrane/blob/master/clients/openclaw/README.md Install the plugin using npm. This command should be run within your OpenClaw extensions directory. ```bash npm install @vainplex/openclaw-membrane ``` -------------------------------- ### IngestWorkingState Go Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/ingestion.mdx Creates a working record from a snapshot of current task state. Use this to track the progress and next steps of ongoing tasks. ```go rec, err := svc.IngestWorkingState(ctx, ingestion.IngestWorkingStateRequest{ Source: "agent-core", ThreadID: "session-xyz", State: schema.TaskStateExecuting, NextActions: []string{"run tests", "review output"}, ContextSummary: "Refactoring the auth module", }) ``` -------------------------------- ### Membrane YAML Configuration Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/membrane.mdx An example configuration file for Membrane using YAML format. It specifies backend, connection strings, intervals, sensitivity, limits, and endpoints for embeddings and LLMs. ```yaml backend: postgres postgres_dsn: "postgres://user:pass@localhost:5432/membrane" listen_addr: ":9090" decay_interval: 1h consolidation_interval: 6h default_sensitivity: low selection_confidence_threshold: 0.7 graph_default_root_limit: 10 graph_default_node_limit: 25 graph_default_edge_limit: 100 graph_default_max_hops: 1 embedding_endpoint: "https://api.openai.com/v1/embeddings" embedding_model: "text-embedding-3-small" embedding_dimensions: 1536 llm_endpoint: "https://api.openai.com/v1/chat/completions" llm_model: "gpt-5-mini" ingest_llm_enabled: true ingest_llm_endpoint: "https://api.openai.com/v1/chat/completions" ingest_llm_model: "gpt-5-mini" rate_limit_per_second: 100 ``` -------------------------------- ### Start Membrane Daemon with Overridden Settings Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/deployment.mdx Start the membraned daemon and override specific settings like the database path and listen address directly via command-line flags, without using a config file. ```bash ./bin/membraned --db /data/membrane.db --addr :8080 ``` -------------------------------- ### Quick Start Python SDK Source: https://github.com/bennettschwartz/membrane/blob/master/docs/sdks/python.mdx Connect to the Membrane gRPC daemon, capture memory, and retrieve graph data. Ensure the client is closed after use. ```python from membrane import MembraneClient, Sensitivity, SourceKind, TrustContext client = MembraneClient("localhost:9090") capture = client.capture_memory( { "ref": "src/auth.py", "text": "Refactored auth middleware and verified package tests", "file": "src/auth.py", }, source_kind=SourceKind.EVENT, reason_to_remember="Keep the auth refactor available for future debugging", summary="Refactored auth middleware", sensitivity=Sensitivity.LOW, tags=["auth", "python"], ) print(capture.primary_record.id) trust = TrustContext( max_sensitivity=Sensitivity.MEDIUM, authenticated=True, actor_id="agent-1", ) graph = client.retrieve_graph( "debug auth", trust=trust, memory_types=["entity", "semantic", "competence", "episodic"], root_limit=5, node_limit=20, max_hops=1, ) for node in graph.nodes: print(f"[{node.record.type.value}] {node.record.id} root={node.root} hop={node.hop}") client.close() ``` -------------------------------- ### RetrieveGraph Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/retrieval.mdx Demonstrates how to retrieve a graph of memories based on a task descriptor and trust context. It shows how to set various limits for roots, nodes, and edges, and how to iterate through the returned nodes. ```go trust := retrieval.NewTrustContext( schema.SensitivityMedium, true, "user:alice", []string{"project:auth"}, ) resp, err := m.RetrieveGraph(ctx, &retrieval.RetrieveGraphRequest{ TaskDescriptor: "debug auth retries", Trust: trust, MemoryTypes: []schema.MemoryType{ schema.MemoryTypeEntity, schema.MemoryTypeSemantic, schema.MemoryTypeCompetence, schema.MemoryTypeEpisodic, }, RootLimit: 8, NodeLimit: 20, EdgeLimit: 80, MaxHops: 1, }) if err != nil { log.Fatal(err) } for _, node := range resp.Nodes { fmt.Println(node.Record.ID, node.Record.Type, node.Root, node.Hop) } ``` -------------------------------- ### IngestEvent Go Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/ingestion.mdx Creates an episodic record from a discrete event. Use this to log specific user actions or system events. ```go rec, err := svc.IngestEvent(ctx, ingestion.IngestEventRequest{ Source: "agent-core", EventKind: "user_input", Ref: "msg-abc123", Summary: "User asked about deployment strategy", Tags: []string{"deployment", "strategy"}, }) ``` -------------------------------- ### Start Lifecycle Method Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/membrane.mdx Begins background decay and consolidation schedulers. If embeddings are configured, it also backfills missing embeddings. Requires a context for cancellation. ```APIDOC ## Start ### Description Begins background decay and consolidation schedulers. If embeddings are configured, it also backfills missing embeddings. ### Function Signature ```go func (m *Membrane) Start(ctx context.Context) error ``` ``` -------------------------------- ### Full TypeScript + OpenAI LLM Integration Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/llm-integration.mdx This example demonstrates a full integration of Membrane with OpenAI for LLM agent workflows. It covers graph retrieval, prompt formatting, LLM completion, memory capture, and reinforcement. Ensure Membrane and OpenAI API keys are set as environment variables. ```typescript import OpenAI from "openai"; import { MembraneClient, Sensitivity, SourceKind, type GraphNode, } from "@bennettschwartz/membrane"; const memory = new MembraneClient("localhost:9090", { apiKey: process.env.MEMBRANE_API_KEY, }); const llm = new OpenAI({ apiKey: process.env.LLM_API_KEY, // OpenAI-compatible providers are supported here, for example: // baseURL: "https://openrouter.ai/api/v1", }); const graph = await memory.retrieveGraph("plan auth service rollout", { trust: { max_sensitivity: Sensitivity.MEDIUM, authenticated: true, actor_id: "planner-agent", scopes: ["project-auth"], }, memoryTypes: ["entity", "semantic", "competence", "working", "plan_graph"], rootLimit: 10, nodeLimit: 25, edgeLimit: 100, maxHops: 1, }); function formatNode(node: GraphNode): string { return JSON.stringify({ id: node.record.id, type: node.record.type, root: node.root, hop: node.hop, confidence: node.record.confidence, salience: node.record.salience, payload: node.record.payload, }); } const context = graph.nodes.map(formatNode).join("\n"); const completion = await llm.chat.completions.create({ model: "gpt-5.5", messages: [ { role: "system", content: "Use memory context as evidence. Cite record ids." }, { role: "user", content: `Task: plan auth service rollout\n\nMemory:\n${context}` }, ], }); const answer = completion.choices[0]?.message?.content ?? ""; const planCapture = await memory.captureMemory( { task: "plan auth service rollout", answer, }, { source: "planner-agent", sourceKind: SourceKind.AGENT_TURN, reasonToRemember: "Persist the generated rollout plan and its supporting context", summary: answer.slice(0, 500), tags: ["llm", "plan", "auth"], scope: "project-auth", sensitivity: Sensitivity.MEDIUM, } ); await memory.reinforce( planCapture.primary_record.id, "planner-agent", "plan was accepted after review" ); memory.close(); ``` -------------------------------- ### IngestObservation Go Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/ingestion.mdx Creates a semantic record from a subject-predicate-object observation. Use this for factual statements about entities. ```go rec, err := svc.IngestObservation(ctx, ingestion.IngestObservationRequest{ Source: "agent-core", Subject: "user:alice", Predicate: "prefers_language", Object: "Go", Tags: []string{"preference"}, }) ``` -------------------------------- ### Quick Start: Capture and Retrieve Memory Source: https://github.com/bennettschwartz/membrane/blob/master/clients/typescript/README.md Demonstrates basic usage of capturing memory and retrieving a graph. Requires a running Membrane daemon and an API key. ```typescript import { MembraneClient, Sensitivity, SourceKind } from "@bennettschwartz/membrane"; const client = new MembraneClient("localhost:9090", { apiKey: "your-api-key" }); const capture = await client.captureMemory( { ref: "src/main.ts", text: "Refactored auth middleware", file: "src/main.ts" }, { sourceKind: SourceKind.EVENT, reasonToRemember: "Keep the auth refactor in long-term memory", summary: "Refactored auth middleware", sensitivity: Sensitivity.LOW, tags: ["auth", "typescript"] } ); const graph = await client.retrieveGraph("debug auth", { trust: { max_sensitivity: Sensitivity.MEDIUM, authenticated: true, actor_id: "agent-1", scopes: [] }, rootLimit: 10, nodeLimit: 25, edgeLimit: 100, maxHops: 1 }); console.log(capture.primary_record.id, graph.nodes.length); client.close(); ``` -------------------------------- ### Configure Client with TLS and Authentication Source: https://github.com/bennettschwartz/membrane/blob/master/clients/typescript/README.md Example of configuring the Membrane client with TLS, custom CA certificate, API key, and timeout. ```typescript const client = new MembraneClient("membrane.example.com:443", { tls: true, tlsCaCertPath: "/path/to/ca.pem", apiKey: "your-api-key", timeoutMs: 10_000 }); ``` -------------------------------- ### Get System Metrics Snapshot Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/membrane.mdx Retrieves a point-in-time snapshot of the system's metrics. Requires a context. ```go func (m *Membrane) GetMetrics(ctx context.Context) (*metrics.Snapshot, error) ``` -------------------------------- ### Quick Start: Context Manager Source: https://github.com/bennettschwartz/membrane/blob/master/clients/python/README.md Use the MembraneClient as a context manager for automatic connection management. Captures a memory using a structured content format. ```python with MembraneClient("localhost:9090") as client: capture = client.capture_memory( {"subject": "user", "predicate": "prefers", "object": {"language": "Python"}}, source_kind=SourceKind.OBSERVATION, sensitivity=Sensitivity.LOW, ) ``` -------------------------------- ### Run Go Membrane Application Source: https://github.com/bennettschwartz/membrane/blob/master/docs/quickstart.mdx Execute the Go program to start the Membrane instance and process memory operations. This command will create a local database file named `my-agent.db`. ```bash go run main.go ``` -------------------------------- ### Membrane Configuration Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/quickstart.mdx This YAML file demonstrates the default configuration for Membrane. Override these settings using a YAML config file or CLI flags. Secrets should be sourced from environment variables. ```yaml backend: "sqlite" db_path: "membrane.db" listen_addr: ":9090" decay_interval: "1h" consolidation_interval: "6h" default_sensitivity: "low" selection_confidence_threshold: 0.7 # Graph retrieval defaults graph_default_root_limit: 10 graph_default_node_limit: 25 graph_default_edge_limit: 100 graph_default_max_hops: 1 # Optional embedding-backed retrieval (Postgres only) # embedding_endpoint: "https://api.openai.com/v1/embeddings" # embedding_model: "text-embedding-3-small" # embedding_dimensions: 1536 # embedding_api_key: "" # or set MEMBRANE_EMBEDDING_API_KEY # Optional LLM-backed consolidation (Postgres only) # llm_endpoint: "https://api.openai.com/v1/chat/completions" # llm_model: "gpt-5-mini" # llm_api_key: "" # or set MEMBRANE_LLM_API_KEY # Optional ingest-side interpretation for CaptureMemory # ingest_llm_enabled: true # ingest_llm_endpoint: "https://api.openai.com/v1/chat/completions" # ingest_llm_model: "gpt-5-mini" # ingest_llm_api_key: "" # or set MEMBRANE_INGEST_LLM_API_KEY # Security # encryption_key: "" # or set MEMBRANE_ENCRYPTION_KEY # api_key: "" # or set MEMBRANE_API_KEY # tls_cert_file: "" # tls_key_file: "" ``` -------------------------------- ### Get System Metrics Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/go-library.mdx Retrieve system metrics such as total records and retrieval usefulness. Handle potential errors during metric retrieval. ```go snap, err := m.GetMetrics(ctx) if err != nil { log.Fatal(err) } fmt.Printf("Total records: %d\n", snap.TotalRecords) fmt.Printf("Retrieval usefulness: %.2f\n", snap.RetrievalUsefulness) ``` -------------------------------- ### TypeScript Client Development Commands Source: https://github.com/bennettschwartz/membrane/blob/master/CONTRIBUTING.md Commands for installing TypeScript dependencies, syncing protobuf definitions, type checking, testing, and building the TypeScript client. Essential for frontend development. ```bash make ts-install cd clients/typescript && npm run check:proto-sync make ts-typecheck make ts-test make ts-build ``` -------------------------------- ### IngestOutcome Go Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/ingestion.mdx Updates an existing episodic record with outcome data. Use this to mark the success or failure of a task associated with a record. ```go updated, err := svc.IngestOutcome(ctx, ingestion.IngestOutcomeRequest{ Source: "agent-core", TargetRecordID: rec.ID, OutcomeStatus: schema.OutcomeStatusSuccess, }) ``` -------------------------------- ### Quick Start: Capture, Retrieve, Reinforce Source: https://github.com/bennettschwartz/membrane/blob/master/clients/python/README.md Connect to the Membrane daemon, capture a memory, retrieve relevant memories as a graph, reinforce a memory, and close the connection. ```python from membrane import MembraneClient, Sensitivity, SourceKind, TrustContext # Connect to the running Membrane daemon client = MembraneClient("localhost:9090") # Capture a rich memory candidate capture = client.capture_memory( {"ref": "src/main.py", "text": "Refactored authentication module"}, source_kind=SourceKind.EVENT, reason_to_remember="Keep the auth refactor available for future debugging", summary="Refactored authentication module", sensitivity=Sensitivity.LOW, ) print(f"Created record: {capture.primary_record.id}") # Retrieve memories relevant to a task trust = TrustContext( max_sensitivity=Sensitivity.MEDIUM, authenticated=True, actor_id="agent-1", ) graph = client.retrieve_graph("fix the login bug", trust=trust, root_limit=5) for node in graph.nodes: print(f" [{node.record.type.value}] {node.record.id} hop={node.hop}") # Reinforce a useful memory client.reinforce(capture.primary_record.id, actor="agent-1", rationale="Used successfully") # Clean up client.close() ``` -------------------------------- ### Initialize Membrane Instance Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/membrane.mdx Initializes all subsystems from Config and returns a ready-to-start Membrane. Ensure to defer stopping the Membrane and handle potential errors during startup. ```go cfg := membrane.DefaultConfig() cfg.DBPath = "my-agent.db" m, err := membrane.New(cfg) if err != nil { log.Fatal(err) } deferr m.Stop() if err := m.Start(context.Background()); err != nil { log.Fatal(err) } ``` -------------------------------- ### Go Library: Embedded Membrane Client Source: https://github.com/bennettschwartz/membrane/blob/master/README.md Integrate Membrane directly into a Go application. This example shows how to initialize, start, capture memory, and retrieve a graph using the Go SDK. ```go package main import ( "context" "log" "github.com/BennettSchwartz/membrane/pkg/ingestion" "github.com/BennettSchwartz/membrane/pkg/membrane" "github.com/BennettSchwartz/membrane/pkg/retrieval" "github.com/BennettSchwartz/membrane/pkg/schema" ) func main() { m, err := membrane.New(membrane.DefaultConfig()) if err != nil { log.Fatal(err) } defer m.Stop() ctx := context.Background() if err := m.Start(ctx); err != nil { log.Fatal(err) } capture, err := m.CaptureMemory(ctx, ingestion.CaptureMemoryRequest{ Source: "agent", SourceKind: "observation", Content: map[string]any{ "subject": "auth-service", "predicate": "uses_database", "object": "PostgreSQL", }, Summary: "auth-service uses PostgreSQL", Tags: []string{"auth-service", "postgres"}, }) if err != nil { log.Fatal(err) } graph, err := m.RetrieveGraph(ctx, &retrieval.RetrieveGraphRequest{ TaskDescriptor: "debug auth-service latency", Trust: &retrieval.TrustContext{ MaxSensitivity: schema.SensitivityMedium, Authenticated: true, }, MemoryTypes: []schema.MemoryType{ schema.MemoryTypeEntity, schema.MemoryTypeSemantic, schema.MemoryTypeCompetence, }, RootLimit: 10, MaxHops: 2, }) if err != nil { log.Fatal(err) } log.Printf("captured=%s graph_nodes=%d", capture.PrimaryRecord.ID, len(graph.Nodes)) } ``` -------------------------------- ### Conditional Forked Record Example Source: https://github.com/bennettschwartz/membrane/blob/master/docs/concepts/revision-operations.mdx Example of creating a forked record with conditional validity, specifying conditions for its applicability. ```go forkedRec := &schema.MemoryRecord{ Type: schema.MemoryTypeSemantic, Sensitivity: schema.SensitivityLow, Payload: &schema.SemanticPayload{ Kind: "semantic", Subject: "build", Predicate: "uses_flags", Object: "-race -cover", Validity: schema.Validity{ Mode: schema.ValidityModeConditional, Conditions: map[string]any{"environment": "dev"}, }, }, } ``` -------------------------------- ### Get Metrics Source: https://github.com/bennettschwartz/membrane/blob/master/clients/python/README.md Get a snapshot of daemon metrics. This provides insights into the operational status and performance of the Membrane daemon. ```APIDOC ## get_metrics ### Description Get a snapshot of daemon metrics. ### Method Signature `get_metrics()` ### Parameters None. ``` -------------------------------- ### Start Docker Compose Database Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/deployment.mdx Command to start the PostgreSQL database defined in your docker-compose.yml file in detached mode. ```bash docker compose up -d ``` -------------------------------- ### Build and Run Membrane Server Source: https://github.com/bennettschwartz/membrane/blob/master/README.md Clones the repository, builds the project, and runs the Membrane server. Uses local SQLite storage by default. ```bash git clone https://github.com/BennettSchwartz/membrane.git cd membrane make build ./bin/membraned ``` -------------------------------- ### Membrane Client Initialization with Options Source: https://github.com/bennettschwartz/membrane/blob/master/docs/sdks/typescript.mdx Illustrates how to instantiate the MembraneClient with various configuration options, including TLS, API key, and call timeouts. This example shows how to connect to a secure endpoint and set custom timeouts. ```typescript const client = new MembraneClient("membrane.example.com:443", { tls: true, tlsCaCertPath: "/path/to/ca.pem", apiKey: process.env.MEMBRANE_API_KEY, timeoutMs: 10_000, }); ``` -------------------------------- ### Build and Test Commands Source: https://github.com/bennettschwartz/membrane/blob/master/CONTRIBUTING.md Common commands for building, testing, linting, and formatting the Go project. Run these locally to ensure code quality. ```bash make build # Build the daemon binary make test # Run all tests make lint # Run linters (go vet + staticcheck) make fmt # Format code ``` -------------------------------- ### Install Python Dependencies for Vector E2E Eval Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/observability.mdx Install the necessary Python dependencies for running the vector end-to-end evaluation suite. ```bash python3 -m pip install -r tools/eval/requirements.txt ``` -------------------------------- ### Write a Go Memory Loop with Membrane Source: https://github.com/bennettschwartz/membrane/blob/master/docs/quickstart.mdx This Go program demonstrates how to initialize Membrane, capture memory records, and retrieve information from the memory graph. It sets up a default configuration, starts the Membrane instance, captures two memory entries, and then retrieves a graph based on a task descriptor. ```go package main import ( "context" "fmt" "log" "github.com/BennettSchwartz/membrane/pkg/ingestion" "github.com/BennettSchwartz/membrane/pkg/membrane" "github.com/BennettSchwartz/membrane/pkg/retrieval" "github.com/BennettSchwartz/membrane/pkg/schema" ) func main() { cfg := membrane.DefaultConfig() cfg.DBPath = "my-agent.db" m, err := membrane.New(cfg) if err != nil { log.Fatal(err) } defer m.Stop() ctx := context.Background() if err := m.Start(ctx); err != nil { log.Fatal(err) } capture, err := m.CaptureMemory(ctx, ingestion.CaptureMemoryRequest{ Source: "build-agent", SourceKind: "tool_output", Content: map[string]any{ "tool": "go test", "args": []string{"./..."}, "result": "auth package passed", }, Context: map[string]any{"thread_id": "session-001"}, ReasonToRemember: "Keep successful test context for future auth work", Summary: "Auth package tests passed", Tags: []string{"auth", "tests"}, Scope: "project-auth", Sensitivity: schema.SensitivityLow, }) if err != nil { log.Fatal(err) } fmt.Printf("Captured primary record: %s\n", capture.PrimaryRecord.ID) _, _ = m.CaptureMemory(ctx, ingestion.CaptureMemoryRequest{ Source: "build-agent", SourceKind: "observation", Content: map[string]any{ "subject": "user", "predicate": "prefers_language", "object": "Go", }, ReasonToRemember: "Remember user language preference", Summary: "User prefers Go", Tags: []string{"preference"}, Sensitivity: schema.SensitivityLow, }) graph, err := m.RetrieveGraph(ctx, &retrieval.RetrieveGraphRequest{ TaskDescriptor: "fix auth build error", Trust: retrieval.NewTrustContext( schema.SensitivityMedium, true, "build-agent", []string{"project-auth"}, ), MemoryTypes: []schema.MemoryType{ schema.MemoryTypeEntity, schema.MemoryTypeSemantic, schema.MemoryTypeCompetence, schema.MemoryTypeEpisodic, }, RootLimit: 10, NodeLimit: 25, EdgeLimit: 100, MaxHops: 1, }) if err != nil { log.Fatal(err) } for _, node := range graph.Nodes { fmt.Printf("Found: %s (type=%s, root=%t, hop=%d)\n", node.Record.ID, node.Record.Type, node.Root, node.Hop, ) } } ``` -------------------------------- ### New Constructor Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/membrane.mdx Initializes all subsystems from a Config and returns a ready-to-start Membrane instance. It requires a valid configuration and handles potential errors during initialization. ```APIDOC ## New ### Description Initializes all subsystems from `Config` and returns a ready-to-start `Membrane`. ### Function Signature ```go func New(cfg *Config) (*Membrane, error) ``` ### Usage Example ```go cfg := membrane.DefaultConfig() cfg.DBPath = "my-agent.db" m, err := membrane.New(cfg) if err != nil { log.Fatal(err) } defer m.Stop() if err := m.Start(context.Background()); err != nil { log.Fatal(err) } ``` ``` -------------------------------- ### Conventional Commit Message Examples Source: https://github.com/bennettschwartz/membrane/blob/master/CONTRIBUTING.md Examples of conventional commit messages, including optional scopes for different parts of the project like Python or gRPC. ```bash feat: add new retrieval filter option feat(python): add working state ingestion method fix: correct decay calculation for linear curves fix(grpc): validate merge ID count docs: update retrieval API documentation test: add atomicity tests for revision operations ci: add staticcheck to CI pipeline ``` -------------------------------- ### Quick Start: Capture Memory and Retrieve Graph Source: https://github.com/bennettschwartz/membrane/blob/master/docs/sdks/typescript.mdx Demonstrates basic usage of the Membrane TypeScript SDK. It shows how to instantiate the client, capture memory with specific details, retrieve a graph based on search criteria, and log results. Ensure the Membrane gRPC daemon is running and accessible. ```typescript import { MembraneClient, Sensitivity, SourceKind, } from "@bennettschwartz/membrane"; const client = new MembraneClient("localhost:9090", { apiKey: "your-api-key", }); const capture = await client.captureMemory( { ref: "src/auth.ts", text: "Refactored auth middleware and verified package tests", file: "src/auth.ts", }, { sourceKind: SourceKind.EVENT, reasonToRemember: "Keep the auth refactor available for future debugging", summary: "Refactored auth middleware", sensitivity: Sensitivity.LOW, tags: ["auth", "typescript"], } ); const graph = await client.retrieveGraph("debug auth", { trust: { max_sensitivity: Sensitivity.MEDIUM, authenticated: true, actor_id: "agent-1", scopes: [], }, memoryTypes: ["entity", "semantic", "competence", "episodic"], rootLimit: 10, nodeLimit: 25, edgeLimit: 100, maxHops: 1, }); console.log(capture.primary_record.id, graph.nodes.length); client.close(); ``` -------------------------------- ### Development Build and Test Commands Source: https://github.com/bennettschwartz/membrane/blob/master/README.md Commonly used commands for building the project, running tests, and building client SDKs and documentation. ```bash make build make test npm --prefix clients/typescript run build npm run docs:build ``` -------------------------------- ### Enable TLS with Server Certificate and Key Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/overview.mdx Configure TLS by specifying the paths to your server certificate and private key files in the configuration. ```yaml tls_cert_file: "/path/to/server.crt" tls_key_file: "/path/to/server.key" ``` -------------------------------- ### Get Metrics Source: https://github.com/bennettschwartz/membrane/blob/master/docs/sdks/typescript.mdx Retrieves system-wide metrics, such as the total number of records. ```APIDOC ## getMetrics ### Description Retrieves system-wide metrics, such as the total number of records. ### Method `async getMetrics(): Promise` ### Response #### Success Response - **Metrics** - An object containing various system metrics, including `total_records`. ``` -------------------------------- ### Memory Type Constants Source: https://github.com/bennettschwartz/membrane/blob/master/docs/sdks/typescript.mdx Examples of using predefined MemoryType constants to specify the type of memory being operated on. ```typescript MemoryType.EPISODIC; MemoryType.WORKING; MemoryType.SEMANTIC; MemoryType.COMPETENCE; MemoryType.PLAN_GRAPH; MemoryType.ENTITY; ``` -------------------------------- ### Get Metrics Snapshot Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/go/membrane.mdx Retrieves a point-in-time snapshot of the system's metrics. This can be used for monitoring and performance analysis. ```APIDOC ## Get Metrics Snapshot ### Description Retrieves a point-in-time snapshot of the system's metrics. This can be used for monitoring and performance analysis. ### Method Not applicable (Go function call) ### Function Signature `func (m *Membrane) GetMetrics(ctx context.Context) (*metrics.Snapshot, error)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response Returns a `metrics.Snapshot` object containing system metrics. #### Response Example None ``` -------------------------------- ### Get System Metrics Source: https://github.com/bennettschwartz/membrane/blob/master/docs/sdks/typescript.mdx Asynchronously retrieves system-wide metrics. The returned metrics object contains properties like total_records. ```typescript const metrics = await client.getMetrics(); console.log(metrics.total_records); ``` -------------------------------- ### Capture Memory with Tool Output Source: https://github.com/bennettschwartz/membrane/blob/master/docs/guides/go-library.mdx Capture memory for events, tool output, observations, working state, and agent turns. This example demonstrates capturing tool output, including arguments, result, and context. ```go capture, err := m.CaptureMemory(ctx, ingestion.CaptureMemoryRequest{ Source: "auth-agent", SourceKind: "tool_output", Content: map[string]any{ "tool_name": "go test", "args": map[string]any{"packages": []string{"./pkg/auth"}}, "result": map[string]any{"exit_code": 0, "stdout": "ok ./pkg/auth"}, }, Context: map[string]any{"thread_id": "session-001"}, ReasonToRemember: "Successful auth package verification", Summary: "Auth package tests passed", Tags: []string{"auth", "tests"}, Scope: "project-auth", Sensitivity: schema.SensitivityLow, }) if err != nil { log.Fatal(err) } fmt.Println(capture.PrimaryRecord.ID) ``` -------------------------------- ### Metrics Snapshot Structure Source: https://github.com/bennettschwartz/membrane/blob/master/docs/api/metrics.mdx This is an example of the JSON structure returned by the GetMetrics API, showing various performance and operational statistics of the agent. ```json { "collected_at": "2026-02-05T14:23:10Z", "total_records": 160, "records_by_type": { "episodic": 80, "entity": 18, "semantic": 35, "competence": 15, "plan_graph": 7, "working": 5 }, "avg_salience": 0.62, "avg_confidence": 0.78, "salience_distribution": { "0.0-0.2": 14, "0.2-0.4": 22, "0.4-0.6": 34, "0.6-0.8": 50, "0.8-1.0": 40 }, "active_records": 148, "pinned_records": 3, "total_audit_entries": 890, "memory_growth_rate": 0.15, "retrieval_usefulness": 0.42, "competence_success_rate": 0.85, "plan_reuse_frequency": 2.3, "revision_rate": 0.08 } ``` -------------------------------- ### Clone Membrane Repository Source: https://github.com/bennettschwartz/membrane/blob/master/docs/quickstart.mdx Clone the official Membrane repository and navigate into the project directory. This is the first step for both embedded and daemon setups. ```bash git clone https://github.com/BennettSchwartz/membrane.git cd membrane ``` -------------------------------- ### Initialize Membrane Client with Context Manager Source: https://github.com/bennettschwartz/membrane/blob/master/docs/sdks/python.mdx Use the Membrane client as a context manager for automatic resource management. Ensure the client is properly closed after use. ```python with MembraneClient("localhost:9090") as client: capture = client.capture_memory({"text": "Remember this"}) ```