Skip to main content
Membrane exposes a 15-method gRPC service backed by protoc-generated stubs. All request and response payloads are JSON-encoded and carried in protobuf bytes fields, so any gRPC client that can set metadata headers and read raw bytes can call the API.

Connection details

PropertyValue
Default addresslocalhost:9090
ProtocolgRPC (HTTP/2)
Payload encodingJSON inside protobuf bytes fields
TLSOptional — set tls_cert_file and tls_key_file in config
AuthenticationBearer token via authorization metadata header
Rate limitingToken bucket; configurable via rate_limit_per_second

Authentication

When api_key is configured, every RPC must include an authorization metadata header with the value Bearer <your-key>.
grpcurl example
grpcurl \
  -H 'authorization: Bearer your-key' \
  -d '{"task_descriptor": "fix build error", "trust": {"max_sensitivity": "medium", "authenticated": true}, "memory_types": ["semantic", "competence"], "limit": 10}' \
  -plaintext \
  localhost:9090 \
  membrane.v1.MembraneService/Retrieve
If no api_key is set in configuration, authentication is disabled and the authorization header is ignored.

TLS

Enable TLS by providing certificate and key paths in your configuration file:
config.yaml
tls_cert_file: "/path/to/server.crt"
tls_key_file: "/path/to/server.key"
When TLS is enabled, use -insecure instead of -plaintext with grpcurl, or supply the CA certificate with --cacert.

All methods

MethodCategoryDescription
IngestEventIngestionCreate an episodic record from an event
IngestToolOutputIngestionCreate an episodic record from a tool invocation
IngestObservationIngestionCreate a semantic record from a subject-predicate-object observation
IngestOutcomeIngestionUpdate an existing episodic record with an outcome status
IngestWorkingStateIngestionCreate a working memory record from a task state snapshot
RetrieveRetrievalLayered retrieval with trust context and salience filtering
RetrieveByIDRetrievalFetch a single record by ID
SupersedeRevisionAtomically replace a record with a new version
ForkRevisionCreate a conditional variant of an existing record
RetractRevisionMark a record as retracted (salience → 0, audit trail preserved)
MergeRevisionCombine multiple records into one consolidated record
ContestRevisionMark a record as contested by conflicting evidence
ReinforceSalienceBoost a record’s salience
PenalizeSalienceReduce a record’s salience by a specified amount
GetMetricsObservabilityRetrieve a point-in-time metrics snapshot

Connecting with TypeScript

Install the official TypeScript client:
npm install @gustycube/membrane
typescript client
import { MembraneClient, Sensitivity } from "@gustycube/membrane";

const client = new MembraneClient("localhost:9090", { apiKey: "your-key" });

// Ingest an event
const record = await client.ingestEvent("tool_call", "task#1", {
  summary: "Ran database migration successfully",
  tags: ["db", "migration"],
});

// Retrieve with trust context
const results = await client.retrieve("database operations", {
  trust: {
    max_sensitivity: Sensitivity.MEDIUM,
    authenticated: true,
    actor_id: "ts-agent",
    scopes: [],
  },
  memoryTypes: ["semantic", "competence"],
});

client.close();

Connecting with Python

Install the Python client:
pip install -e clients/python
python client
from membrane import MembraneClient, Sensitivity, TrustContext

client = MembraneClient("localhost:9090", api_key="your-key")

# Ingest an event
record = client.ingest_event(
    source="my-agent",
    event_kind="tool_call",
    ref="task#1",
    summary="Ran database migration successfully",
    tags=["db", "migration"],
)

# Retrieve with trust context
results = client.retrieve(
    task_descriptor="database operations",
    trust=TrustContext(max_sensitivity=Sensitivity.MEDIUM, authenticated=True),
    memory_types=["semantic", "competence"],
)

Connecting with grpcurl

List available methods:
grpcurl -plaintext localhost:9090 list membrane.v1.MembraneService
Call IngestEvent:
grpcurl \
  -H 'authorization: Bearer your-key' \
  -d '{
    "source": "build-agent",
    "event_kind": "tool_call",
    "ref": "build#42",
    "summary": "Executed go build, failed with linker error",
    "tags": ["build", "error"]
  }' \
  -plaintext \
  localhost:9090 \
  membrane.v1.MembraneService/IngestEvent
Call GetMetrics:
grpcurl \
  -H 'authorization: Bearer your-key' \
  -d '{}' \
  -plaintext \
  localhost:9090 \
  membrane.v1.MembraneService/GetMetrics

Proto definition

The full service definition is at api/proto/membrane/v1/membrane.proto. The Go package is github.com/GustyCube/membrane/api/grpc/gen/membranev1.
membrane.proto
syntax = "proto3";

package membrane.v1;

service MembraneService {
    rpc IngestEvent(IngestEventRequest) returns (IngestResponse);
    rpc IngestToolOutput(IngestToolOutputRequest) returns (IngestResponse);
    rpc IngestObservation(IngestObservationRequest) returns (IngestResponse);
    rpc IngestOutcome(IngestOutcomeRequest) returns (IngestResponse);
    rpc IngestWorkingState(IngestWorkingStateRequest) returns (IngestResponse);
    rpc Retrieve(RetrieveRequest) returns (RetrieveResponse);
    rpc RetrieveByID(RetrieveByIDRequest) returns (MemoryRecordResponse);
    rpc Supersede(SupersedeRequest) returns (MemoryRecordResponse);
    rpc Fork(ForkRequest) returns (MemoryRecordResponse);
    rpc Retract(RetractRequest) returns (RetractResponse);
    rpc Merge(MergeRequest) returns (MemoryRecordResponse);
    rpc Contest(ContestRequest) returns (ContestResponse);
    rpc Reinforce(ReinforceRequest) returns (ReinforceResponse);
    rpc Penalize(PenalizeRequest) returns (PenalizeResponse);
    rpc GetMetrics(GetMetricsRequest) returns (MetricsResponse);
}

Build docs developers (and LLMs) love