| title | Go Library |
|---|---|
| description | Use Membrane as an embedded Go library without running the daemon. |
Membrane can run inside your Go process. The embedded facade exposes the same core model as the daemon: graph-aware capture, trust-gated graph retrieval, revision, reinforcement, and metrics.
go get github.com/BennettSchwartz/membranecfg := membrane.DefaultConfig()
cfg.PostgresDSN = os.Getenv("MEMBRANE_POSTGRES_DSN")
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()Use CaptureMemory for events, tool output, observations, working state, and agent turns. The response contains the primary record plus any linked records or graph edges.
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)| Source kind | Use for |
|---|---|
event |
User messages, agent replies, errors, status changes |
tool_output |
Tool calls and structured results |
observation |
Subject-predicate-object facts |
working_state |
In-flight task state |
agent_turn |
Generic agent turn capture |
_, err := m.CaptureMemory(ctx, ingestion.CaptureMemoryRequest{
Source: "auth-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,
})_, err := m.CaptureMemory(ctx, ingestion.CaptureMemoryRequest{
Source: "auth-agent",
SourceKind: "working_state",
Content: map[string]any{
"thread_id": "session-001",
"state": "executing",
"next_actions": []string{"run tests", "review output"},
"context_summary": "Refactoring auth middleware",
},
Summary: "Auth refactor in progress",
Tags: []string{"auth", "working"},
Sensitivity: schema.SensitivityLow,
})RecordOutcome updates an existing episodic record with success, failure, or partial outcome state.
updated, err := m.RecordOutcome(ctx, ingestion.IngestOutcomeRequest{
Source: "auth-agent",
TargetRecordID: capture.PrimaryRecord.ID,
OutcomeStatus: schema.OutcomeStatusSuccess,
})RetrieveGraph returns ranked root records and a bounded graph neighborhood. Every retrieval request needs a TrustContext.
graph, err := m.RetrieveGraph(ctx, &retrieval.RetrieveGraphRequest{
TaskDescriptor: "debug auth retry failures",
Trust: retrieval.NewTrustContext(
schema.SensitivityMedium,
true,
"auth-agent",
[]string{"project-auth"},
),
MemoryTypes: []schema.MemoryType{
schema.MemoryTypeEntity,
schema.MemoryTypeSemantic,
schema.MemoryTypeCompetence,
schema.MemoryTypeEpisodic,
},
RootLimit: 8,
NodeLimit: 20,
EdgeLimit: 80,
MaxHops: 1,
MinSalience: 0.2,
})
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,
)
}Fetch a single record by ID:
record, err := m.RetrieveByID(ctx, capture.PrimaryRecord.ID, retrieval.NewTrustContext(
schema.SensitivityHigh,
true,
"auth-agent",
[]string{"project-auth"},
))Revision operations update durable knowledge with audit entries.
newRec := &schema.MemoryRecord{ /* ... */ }
superseded, err := m.Supersede(ctx, oldRecordID, newRec, "agent", "updated fact")
forkedRec := &schema.MemoryRecord{ /* ... */ }
forked, err := m.Fork(ctx, sourceID, forkedRec, "agent", "different in staging")
err = m.Retract(ctx, recordID, "agent", "no longer accurate")
mergedRec := &schema.MemoryRecord{ /* ... */ }
merged, err := m.Merge(ctx, []string{id1, id2}, mergedRec, "agent", "deduplicated")
err = m.Contest(ctx, recordID, conflictingRecordID, "agent", "conflicting evidence")err := m.Reinforce(ctx, recordID, "agent", "used successfully")
err = m.Penalize(ctx, recordID, 0.2, "agent", "not useful for this task")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)
fmt.Printf("Embedding coverage: %.2f\n", snap.EmbeddingCoverage)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.PostgresDSN = os.Getenv("MEMBRANE_POSTGRES_DSN")
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),
)
}