Retrieval
Retrieval returns memory records the caller is allowed to see, ranked for the current task and expanded through graph relationships. The public daemon API exposes RetrieveGraph for task retrieval and RetrieveByID for direct record lookup.
Every retrieval call requires a TrustContext. The trust context controls sensitivity access and scoped visibility.
Trust Rules
Membrane enforces graduated access control on every read:
- A record at or below
trust.max_sensitivityis returned in full. - A record exactly one level above
trust.max_sensitivitymay be returned redacted. - A record two or more levels above
trust.max_sensitivityis omitted. - If
trust.scopesis non-empty, scoped records must match one of those values. Unscoped records are visible to all allowed callers.
| Record sensitivity | Caller max | Result |
|---|---|---|
low | medium | Full record |
medium | medium | Full record |
high | medium | Redacted metadata |
hyper | medium | Not returned |
Redacted records keep IDs, type, sensitivity, salience, tags, scope, and timestamps. Payload, provenance, relations, and audit log are stripped.
RetrieveGraph
rpc RetrieveGraph(RetrieveGraphRequest) returns (RetrieveGraphResponse);
Retrieves ranked root memories for a task descriptor, then expands a bounded graph neighborhood around those roots. This is the preferred retrieval method for prompts because it returns both task-relevant roots and the entity, semantic, or provenance records connected to them.
Request fields
task_descriptorstringNatural-language description of the current task. With embeddings configured, this drives semantic similarity search.
trustTrustContextrequiredTrust context that gates all returned records.
memory_typesstring[]Optional memory type filter. Valid values are episodic, working, semantic, competence, plan_graph, and entity.
min_saliencenumberMinimum salience threshold. Records below this value are excluded before graph expansion.
root_limitnumberMaximum number of ranked root records. SDKs default to 10.
node_limitnumberMaximum total graph nodes to return, including roots. SDKs default to 25.
edge_limitnumberMaximum graph edges to return. SDKs default to 100.
max_hopsnumberNumber of relation hops to expand from each root. 0 returns only roots; SDKs default to 1.
Response fields
nodesGraphNode[]Retrieved records wrapped with root and hop metadata.
edgesGraphEdge[]Graph edges between returned records.
root_idsstring[]IDs of the records selected as ranked roots.
selectionSelectionResultOptional selector metadata when competence or plan graph candidates were scored.
Examples
resp, 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 resp.Nodes {
fmt.Printf("Found: %s (type=%s, root=%t, hop=%d)\n",
node.Record.ID,
node.Record.Type,
node.Root,
node.Hop,
)
}
const graph = await client.retrieveGraph("fix auth build error", {
trust: {
max_sensitivity: Sensitivity.MEDIUM,
authenticated: true,
actor_id: "build-agent",
scopes: ["project-auth"],
},
memoryTypes: ["entity", "semantic", "competence", "episodic"],
rootLimit: 10,
nodeLimit: 25,
edgeLimit: 100,
maxHops: 1,
});
for (const node of graph.nodes) {
console.log(`${node.record.id} ${node.record.type} root=${node.root} hop=${node.hop}`);
}
graph = client.retrieve_graph(
"fix auth build error",
trust=TrustContext(
max_sensitivity=Sensitivity.MEDIUM,
authenticated=True,
actor_id="build-agent",
scopes=["project-auth"],
),
memory_types=["entity", "semantic", "competence", "episodic"],
root_limit=10,
node_limit=25,
edge_limit=100,
max_hops=1,
)
for node in graph.nodes:
print(f"{node.record.id} {node.record.type.value} root={node.root} hop={node.hop}")
Prompt Projection
For LLM prompts, use the root nodes as the shortest high-signal context, or include all graph nodes when entity and provenance context matter:
const roots = graph.nodes.filter((node) => node.root).map((node) => node.record);
const context = roots.map((record) => JSON.stringify(record)).join("\n");
Use rootLimit, nodeLimit, and maxHops to keep prompt context bounded.
RetrieveByID
rpc RetrieveByID(RetrieveByIDRequest) returns (MemoryRecordResponse);
Fetches a single record by UUID. The same trust rules apply. If the record does not exist or trust denies access, the RPC returns an error.
Request fields
idstringrequiredUUID of the record to retrieve.
trustTrustContextrequiredTrust context that gates access to the record.
Response fields
recordMemoryRecordThe requested typed memory record.
Example
record, err := m.RetrieveByID(ctx, recordID, retrieval.NewTrustContext(
schema.SensitivityHigh,
true,
"support-agent",
[]string{"project-auth"},
))
if err != nil {
log.Fatal(err)
}
fmt.Println(record.ID, record.Type)
const record = await client.retrieveById(recordId, {
trust: {
max_sensitivity: Sensitivity.HIGH,
authenticated: true,
actor_id: "support-agent",
scopes: ["project-auth"],
},
});
record = client.retrieve_by_id(
record_id,
trust=TrustContext(
max_sensitivity=Sensitivity.HIGH,
authenticated=True,
actor_id="support-agent",
scopes=["project-auth"],
),
)
Layer Order
When no memory_types filter is supplied, graph retrieval starts from the same layered ranking model used internally:
working -> entity -> semantic -> competence -> plan_graph -> episodic
The graph expansion can add related records of any allowed type, subject to trust, node, edge, and hop limits.