Skip to content

Persistent agent memory — read, write, search, and control the project memory store. These endpoints forward to the daemon’s memory.* RPCs, with active-realm-scoped reads and writes, daemon-paginated listings, and a daemon-side human-only gate on consolidation.

The HTTP edge has no service-level auth; hoody-proxy is the boundary (kit network-position trust). The daemon’s memAdminGate over the Unix socket may still return admin_unauthorized when a socket admin capability is configured.

Read a project’s memory relation graph. Returns a paginated page of memory.graph — nodes, edges, and stats. Filter via ?project=&node_type= and page via ?limit=&offset=. The daemon’s memAdminGate may still return admin_unauthorized when a socket admin capability is configured. Active-realm-scoped (a realm header is rejected). Returns 503 store_unavailable when the memory store is not warm.

NameInTypeRequiredDescription
projectquerystringNoProject key whose graph to read.
node_typequerystringNoOptional node-type filter.
limitqueryintegerNoMaximum nodes/edges to return.
offsetqueryintegerNoPagination offset into the graph.
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1): the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1) selecting which on-disk .hoody install a stateless read/write resolves.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1): global or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — the in:query alias of X-Hoody-Realm (read only when the header is absent).
{
"nodes": [
{
"id": "fact_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
"type": "fact",
"label": "Payment provider is Stripe"
},
{
"id": "workflow_01HMZ3KB7T3F2N4P6X8YZWQJVR",
"type": "workflow",
"label": "Deploy to staging"
}
],
"edges": [
{
"from": "fact_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
"to": "workflow_01HMZ3KB7T3F2N4P6X8YZWQJVR",
"relation": "supports"
}
],
"stats": {
"node_count": 142,
"edge_count": 318
},
"limit": 200,
"offset": 0,
"truncated": false
}
const graph = await client.agent.memory.getMemoryGraph({
project: "hoody-platform",
node_type: "fact",
limit: 200,
offset: 0
});

Lists memory records for a project (memory.list). Filter via ?project=&kind=&type=&query=. The listing is daemon-paginated: the daemon caps the page size at 200 and never returns an unbounded set. An omitted ?limit (or one over 200) pages at 200, not “no pagination” — the response always carries meta.page and meta.limit reflecting the effective page size. Active-realm-scoped: a realm header is rejected.

NameInTypeRequiredDescription
projectquerystringNoProject key to scope the listing to.
kindquerystringNoMemory kind/store to filter by.
typequerystringNoMemory type to filter by (e.g. workflow, fact).
queryquerystringNoFree-text filter over the records.
pagequeryintegerNo1-based page number.
limitqueryintegerNoItems per page (1..200). 0 or omitted pages at the 200 ceiling; a value over 200 is clamped to 200. The effective page size is echoed in meta.limit.
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — in:query alias of X-Hoody-Realm.
{
"items": [
{
"id": "mem_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
"project": "hoody-platform",
"kind": "fact",
"type": "fact",
"content": "Payment provider is Stripe.",
"created_at": "2026-01-15T12:34:56Z"
},
{
"id": "mem_01HMZ3KB7T3F2N4P6X8YZWQJVR",
"project": "hoody-platform",
"kind": "workflow",
"type": "workflow",
"content": "Deploy to staging: 1) run migration 2) restart app 3) verify health",
"created_at": "2026-01-15T13:01:22Z"
}
],
"meta": {
"total": 47,
"page": 1,
"limit": 200
}
}
for await (const page of client.agent.memory.listMemoryItemsIterator({
project: "hoody-platform",
kind: "fact",
type: "fact",
query: "stripe",
limit: 200
})) {
for (const item of page.items) {
console.log(item.id, item.content);
}
}

Reads one memory record by id (memory.detail). Pass ?project=&kind= to disambiguate. The daemon’s memAdminGate may still return admin_unauthorized when a socket admin capability is configured.

NameInTypeRequiredDescription
idpathstringYesPath identifier.
projectquerystringNoProject key the memory belongs to.
kindquerystringNoMemory kind/store the record lives in.
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — in:query alias of X-Hoody-Realm.
{
"id": "mem_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
"project": "hoody-platform",
"kind": "fact",
"type": "fact",
"content": "Payment provider is Stripe.",
"created_at": "2026-01-15T12:34:56Z",
"updated_at": "2026-01-15T12:34:56Z"
}
const item = await client.agent.memory.getMemoryItem({
id: "mem_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
project: "hoody-platform",
kind: "fact"
});

Lists the memory projects (memory.projects). The daemon’s memAdminGate may still return admin_unauthorized when a socket admin capability is configured. Active-realm-scoped: a realm header is rejected.

NameInTypeRequiredDescription
pagequeryintegerNo1-based page number for pagination.
limitqueryintegerNoMaximum items per page (0 = no pagination).
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — in:query alias of X-Hoody-Realm.
{
"items": [
{
"project": "hoody-platform",
"item_count": 47,
"last_capture": "2026-01-15T13:01:22Z"
},
{
"project": "docs-site",
"item_count": 12,
"last_capture": "2026-01-14T09:15:00Z"
}
],
"meta": {
"total": 2,
"page": 1,
"limit": 0
}
}
for await (const page of client.agent.memory.listMemoryProjectsIterator({
limit: 50
})) {
for (const project of page.items) {
console.log(project.project, project.item_count);
}
}

Hybrid recall across a project (memory.search): BM25 + vector + graph fusion. The query is privacy-stripped server-side before any tokenize/embed; the read is no-touch (it never strengthens future ranking). The daemon’s memAdminGate may still return admin_unauthorized when a socket admin capability is configured. Active-realm-scoped: a realm header is rejected. Returns 503 store_unavailable when the memory store is not warm.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — in:query alias of X-Hoody-Realm.
NameTypeRequiredDescription
projectstringNoProject key to search within.
querystringNoThe natural-language recall query (privacy-stripped server-side).
limitintegerNoMaximum hits to return.
kindsarrayNoOptional memory kinds/stores to restrict the search to.
skip_graphbooleanNoSkip the graph-fusion component of recall.
{
"project": "hoody-platform",
"query": "how do we deploy to staging",
"limit": 10,
"kinds": ["fact", "workflow"],
"skip_graph": false
}
{
"hits": [
{
"id": "mem_01HMZ3KB7T3F2N4P6X8YZWQJVR",
"project": "hoody-platform",
"kind": "workflow",
"type": "workflow",
"head": "Deploy to staging: 1) run migration 2) restart app 3) verify health",
"scores": {
"bm25": 0.82,
"vector": 0.91,
"graph": 0.45,
"fused": 0.87
}
},
{
"id": "mem_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
"project": "hoody-platform",
"kind": "fact",
"type": "fact",
"head": "Staging URL is https://staging.hoody.dev",
"scores": {
"bm25": 0.55,
"vector": 0.78,
"graph": 0.30,
"fused": 0.61
}
}
]
}
const results = await client.agent.memory.searchMemory({
project: "hoody-platform",
query: "how do we deploy to staging",
limit: 10,
kinds: ["fact", "workflow"]
});

Stores a new memory record (memory.save). The daemon’s memAdminGate may still return admin_unauthorized when a socket admin capability is configured.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — in:query alias of X-Hoody-Realm.
NameTypeRequiredDescription
projectstringNoProject key the memory belongs to.
contentstringNoThe memory content.
typestringNoMemory type (e.g. workflow, fact).
{
"project": "hoody-platform",
"content": "Payment provider is Stripe.",
"type": "fact"
}
{
"id": "mem_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
"project": "hoody-platform",
"kind": "fact",
"type": "fact",
"content": "Payment provider is Stripe.",
"created_at": "2026-01-15T12:34:56Z"
}
const saved = await client.agent.memory.saveMemoryItem({
project: "hoody-platform",
content: "Payment provider is Stripe.",
type: "fact"
});

Patches a memory record by id (memory.edit). The daemon’s memAdminGate may still return admin_unauthorized when a socket admin capability is configured.

NameInTypeRequiredDescription
idpathstringYesPath identifier.
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — in:query alias of X-Hoody-Realm.
NameTypeRequiredDescription
projectstringNoProject key the memory belongs to.
kindstringNoMemory kind/store the record lives in.
contentstringNoReplacement memory content.
{
"project": "hoody-platform",
"kind": "fact",
"content": "Payment provider is Stripe (primary) and Adyen (EU fallback)."
}
{
"id": "mem_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
"project": "hoody-platform",
"kind": "fact",
"type": "fact",
"content": "Payment provider is Stripe (primary) and Adyen (EU fallback).",
"updated_at": "2026-01-15T14:22:10Z"
}
const edited = await client.agent.memory.editMemoryItem({
id: "mem_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
content: "Payment provider is Stripe (primary) and Adyen (EU fallback)."
});

Deletes a memory record (memory.delete). This is the cross-project delete — pass the identity in the body. The daemon’s memAdminGate may still return admin_unauthorized when a socket admin capability is configured.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — in:query alias of X-Hoody-Realm.
NameTypeRequiredDescription
idstringYesMemory record id.
projectstringNoProject key the memory belongs to.
kindstringNoMemory kind/store the record lives in.
{
"id": "mem_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
"project": "hoody-platform",
"kind": "fact"
}
{
"id": "mem_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
"deleted": true
}
await client.agent.memory.deleteMemoryItem({
id: "mem_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
project: "hoody-platform",
kind: "fact"
});

Flips the memory privacy switch (memory.set_enabled) — persists features.memory and flips the live store. Not admin-gated. The body is {enabled: bool}.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — in:query alias of X-Hoody-Realm.
NameTypeRequiredDescription
enabledbooleanNoWhether memory capture is enabled.
{
"enabled": true
}
{
"enabled": true,
"persisted": true
}
await client.agent.memory.setMemoryEnabled({
enabled: true
});

Forces the memory store durability barrier (memory.flush). Not admin-gated. The request body is empty; the gateway scrubs every _-prefixed key and folds in the request scope (cwd/config_dir) before dispatch.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — in:query alias of X-Hoody-Realm.

This endpoint accepts no body.

{
"flushed": true,
"barrier_id": "durability_01HMZ3K9X8R7P2V4N6YTBJWQ5C",
"duration_ms": 42
}
await client.agent.memory.flushMemory();

Requests a consolidation pass for a project (memory.consolidate). HUMAN-ONLY: consolidation spends multi-LLM passes and evolves memory state irreversibly, so an autonomous caller may never self-approve it. The gateway server-stamps the machine marker and the daemon’s human-only gate always refuses an HTTP call with 403 human_only (the HTTP edge has no service-level auth, but the human-only gate is a second, non-bypassable daemon factor).

Active-realm-scoped (a realm header is rejected).

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — in:query alias of X-Hoody-Realm.
NameTypeRequiredDescription
projectstringYesProject key to consolidate.
min_observationsintegerNoOptional minimum-observations threshold for a fact to be consolidated.
{
"project": "hoody-platform",
"min_observations": 3
}
{
"code": "bad_request",
"message": "invalid request"
}
Error CodeTitleDescriptionResolution
bad_requestBad requestThe request was malformed or carried invalid parameters.Correct the request body or query parameters.
realm_scope_unsupportedRealm scope unsupportedA per-request realm header was supplied to an active-only / global-no-realm RPC.Omit the realm header on this route, or open a session to scope by realm.
// The daemon will refuse this with 403 human_only when called over HTTP.
// Run consolidation from an interactive TUI/CLI session instead.
try {
await client.agent.memory.consolidateMemory({
project: "hoody-platform",
min_observations: 3
});
} catch (err) {
// err.code === "human_only" — expected for machine callers
}