Agent: Memory
Section titled “Agent: Memory”These endpoints manage persistent agent memory. Use them to read or modify the memory store, browse a project’s relation graph, run hybrid recall search, and toggle or flush capture. The realm a request acts in is selected per call: X-Hoody-Realm or ?realm= names it ("global" or a 24-hex realm id; the header wins), and omitted, the agent’s active realm. X-Hoody-Config-Dir selects which on-disk install a stateless read or write resolves against. Every call goes through the agent’s URL: Hoody Kit programs are reached through their URLs only, and a request refused by the Source IP Guard gets 403 forbidden.
Data-host classification and recovery
Section titled “Data-host classification and recovery”GET /api/v1/agent/memory/datahost
Section titled “GET /api/v1/agent/memory/datahost”Read the realm’s memory data host. The reply classifies which computer serves this realm’s memory and why it might not be served. state is one of leader (this computer serves it), follower (a healthy peer does), electing (the fleet is choosing, transiently none), unavailable (a host is named but unreachable from here), stuck (recovery cooldown, election errors, or a permission refusal), not_realm_member (this computer is not tagged into the realm), fleet_disabled (no Hoody fleet identity), or realm_blocked (the active realm selection is unavailable). Every one of those is a 200: a realm with no serving host is an answer, not a failure. hosts lists the live claimants and the current host; can_use_self says whether memory.claimDataHost would be offered.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
curl -X GET 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/datahost' \ -H 'Authorization: Bearer <token>' \ -H 'X-Hoody-Config-Dir: /home/user/.hoody'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.getDataHost({ XHoodyConfigDir: '/home/user/.hoody' });{ "status": "ok", "datahost": { "realm": "global", "state": "leader", "host": "67e89abc123def456789abcd-890abcdef12345678901cdef", "server_node": "node-example-1", "reason": "", "self_id": "67e89abc123def456789abcd-890abcdef12345678901cdef", "can_use_self": true, "hosts": [ { "id": "67e89abc123def456789abcd-890abcdef12345678901cdef", "server_node": "node-example-1", "age_ms": 1234 } ] }}| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
PUT /api/v1/agent/memory/datahost
Section titled “PUT /api/v1/agent/memory/datahost”Elects THIS computer as the realm’s memory data host, the recovery action when a realm’s memory has no reachable host. Only self-assignment is implemented; naming a peer is refused 400 unsupported. expect_realm is mandatory in spirit but should be named: the daemon reads an absent field as the global realm rather than as “unspecified”, so omitting it is refused at the edge rather than silently assigning global. A realm switch between the data-host read and this call is refused 409 refused_realm_changed.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
use_self | boolean | Yes | Assign THIS computer. Only true is implemented; false is refused 400 unsupported. |
expect_realm | string | No | The realm this assignment is for: "global" for the global partition, or a 24-hex realm id. Required unless X-Hoody-Realm or ?realm= names the realm; refused 400 when neither does (an empty value means the global realm to the daemon, never “unspecified”), and 400 bad_request when it names another realm than they do. |
curl -X PUT 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/datahost' \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d '{ "use_self": true, "expect_realm": "global" }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.claimDataHost({ use_self: true, expect_realm: 'global',});{ "status": "ok", "outcome": "published", "host": "67e89abc123def456789abcd-890abcdef12345678901cdef"}| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
unsupported | Assignment unsupported | Only assigning THIS computer as the realm’s memory data host is supported; naming a peer container is not implemented (it needs the preferred-key election tiebreak). | Send use_self: true, or run the assignment on the computer you want to host. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "refused_no_coordinator", "message": "no active data-host coordinator for this realm"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
fleet_disabled | No fleet identity | This computer has no Hoody fleet identity, so it cannot be elected as a memory data host. This is a property of the installation, not a transient condition. | Join this computer to the fleet, or assign the data host from a computer that is already a member. |
refused_no_coordinator | No data-host coordinator | No data-host coordinator is active for this realm: the fleet is disabled, the coordinator has stopped, or this computer is not a member of the realm. | Read GET /memory/datahost for the realm’s classified state; the state and reason name which of the three applies. |
refused_realm_changed | Realm changed | The active realm changed between the data-host read and this assignment, so the assignment would have forced a host onto a realm the caller never inspected. It fails closed instead. | Re-read GET /memory/datahost and submit the assignment again with the realm it reports. |
{ "code": "payload_too_large", "message": "request body exceeds the configured size limit"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
payload_too_large | Payload too large | The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it: a well-formed-but-large body is a size violation, not a JSON syntax error. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
{ "code": "stopped", "message": "the data-host coordinator is not running"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
stopped | Coordinator not running | The data-host coordinator is not running, so the assignment could not be published. | Retry shortly; if it persists, read GET /memory/datahost for the realm’s state. |
refused | Assignment refused | The data-host coordinator refused the assignment for a reason it did not classify. The message carries what it reported. | Retry shortly; if it persists, read GET /memory/datahost and inspect the daemon logs. |
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
Status and listings
Section titled “Status and listings”GET /api/v1/agent/memory/status
Section titled “GET /api/v1/agent/memory/status”Reports whether memory is on, whether its store resolved, and what it holds. This is the discriminator the other memory reads cannot be: memory.listProjects and memory.listItems return a successful empty result for a realm whose memory is off, which is byte-identical to a healthy store with nothing in it. enabled is the persisted capture switch, available says whether a store resolved, degraded distinguishes a real fault from an off realm, and reason, remedy, and recoverable describe it. An off or degraded store is a 200 describing that state, not an error. totals covers the whole store; pass ?project= to also get that project’s counts, embedding_coverage, and last_consolidated_at. last_consolidated discriminates recorded, never, or unreadable, because a store that could not be read must not report the same “never” as one that has genuinely never consolidated. degraded_reads names any block whose read failed. Counts are the durable rows and may lag an in-flight capture batch; call memory.flush first for a barrier.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
project | query | string | No | Project key to report per-project counts, embedding coverage, and last-consolidation for. Omitted: only the whole-store totals are returned. |
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
curl -X GET 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/status?project=acme-web' \ -H 'Authorization: Bearer <token>' \ -H 'X-Hoody-Config-Dir: /home/user/.hoody'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.getStatus({ project: 'acme-web' });{ "enabled": true, "available": true, "degraded": false, "reason": "", "remedy": "", "recoverable": false, "remote": false, "project": "acme-web", "memory_model": "claude-opus-4.7", "embeddings_model": "text-embedding-3-large", "totals": { "memories": 142, "observations": 8211, "lessons": 37, "slots": 4 }, "counts": { "memories": 142, "observations": 8211, "lessons": 37, "slots": 4 }, "embedding_coverage": 0.987, "last_consolidated": "recorded", "last_consolidated_at": "2025-01-15T12:00:00Z", "counters": {}, "capture_latency": {}, "breakers": {}, "degraded_reads": []}| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
GET /api/v1/agent/memory/projects
Section titled “GET /api/v1/agent/memory/projects”Lists the memory projects. The response is paged; pass ?page= and ?limit= (0 for no pagination).
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | integer | No | 1-based page number for pagination. |
limit | query | integer | No | Maximum items per page (0 = no pagination). |
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
curl -X GET 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/projects?page=1&limit=50' \ -H 'Authorization: Bearer <token>'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
for await (const item of client.agent.memory.listProjectsIterator({ page: 1, limit: 50 })) { console.log(item);}{ "items": [ { "key": "acme-web", "created_at": "2024-09-12T08:00:00Z", "last_activity_at": "2025-01-15T12:00:00Z", "memory_count": 142, "observation_count": 8211 }, { "key": "acme-mobile", "created_at": "2024-11-02T14:30:00Z", "last_activity_at": "2025-01-15T11:48:00Z", "memory_count": 58, "observation_count": 2104 } ], "meta": { "total": 2, "page": 1, "limit": 50 }}| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
{ "code": "store_unavailable", "message": "memory store unavailable"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
store_unavailable | Memory store unavailable | The memory store could not be opened (degraded remote host, not-warm realm store, divergent/corrupt local DB). The request fails closed rather than silently falling back. | Retry once the store is warm; if persistent, inspect the daemon logs for the degrade reason. |
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
GET /api/v1/agent/memory/items
Section titled “GET /api/v1/agent/memory/items”Lists memory records for a project. Filter via ?project=, ?kind=, ?type=, and ?query=. The type and query filters apply ONLY to kind=memory (the default store); the lesson, slot, and observation stores do not support these filters, so passing type or query with one of those kinds is REJECTED 400 rather than silently returning an unfiltered page. The daemon caps the page size at 200 and never returns an unbounded set, so the response always carries meta.page and meta.limit reflecting the effective page size. An omitted ?limit (or one over 200) pages at 200, not “no pagination”.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
project | query | string | No | Project key to scope the listing to. |
kind | query | string | No | Memory kind/store to filter by. |
type | query | string | No | Memory type to filter by (e.g. workflow, fact). kind=memory ONLY; rejected 400 with a lesson, slot, or observation kind. |
query | query | string | No | Free-text filter over the records. kind=memory ONLY; rejected 400 with a lesson, slot, or observation kind. |
page | query | integer | No | 1-based page number. |
limit | query | integer | No | Items 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. NOT “no pagination”; the daemon never returns an unbounded set. |
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
curl -X GET 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/items?project=acme-web&kind=memory&type=fact&page=1&limit=50' \ -H 'Authorization: Bearer <token>'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
for await (const item of client.agent.memory.listItemsIterator({ project: 'acme-web', kind: 'memory', type: 'fact', page: 1, limit: 50,})) { console.log(item);}{ "items": [ { "id": "67e89abc123def456789abcd", "project": "acme-web", "type": "fact", "title": "Stripe webhook acknowledgement", "content": "Stripe webhooks must be acknowledged within 5 seconds; the retry window is exponential.", "concepts": ["stripe", "webhooks", "reliability"], "files": ["src/webhooks/stripe.ts"], "strength": 8, "version": 1, "is_latest": true, "created_at": "2025-01-15T12:00:00Z", "updated_at": "2025-01-15T12:00:00Z" } ], "meta": { "total": 142, "page": 1, "limit": 50 }}| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
{ "code": "store_unavailable", "message": "memory store unavailable"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
store_unavailable | Memory store unavailable | The memory store could not be opened (degraded remote host, not-warm realm store, divergent/corrupt local DB). The request fails closed rather than silently falling back. | Retry once the store is warm; if persistent, inspect the daemon logs for the degrade reason. |
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
GET /api/v1/agent/memory/items/{id}
Section titled “GET /api/v1/agent/memory/items/{id}”Reads one memory record by id. Pass ?project= and ?kind=; a record the project does not hold is 404 not_found. record carries the stored fields in snake_case (for a memory: id, project, type, title, content, concepts, files, session_ids, source_observation_ids, strength, version, parent_id, supersedes, is_latest, forget_after, tier, retention, last_scored_at, created_at, updated_at, agent_id; a lesson, slot, or observation carries its own).
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | The item id. |
project | query | string | No | Project key the memory belongs to. |
kind | query | string | No | Memory kind/store the record lives in. |
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
curl -X GET 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/items/67e89abc123def456789abcd?project=acme-web&kind=memory' \ -H 'Authorization: Bearer <token>'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.getItem('67e89abc123def456789abcd', { project: 'acme-web', kind: 'memory' });{ "status": "ok", "record": { "id": "67e89abc123def456789abcd", "project": "acme-web", "type": "fact", "title": "Stripe webhook acknowledgement", "content": "Stripe webhooks must be acknowledged within 5 seconds; the retry window is exponential.", "concepts": ["stripe", "webhooks", "reliability"], "files": ["src/webhooks/stripe.ts"], "session_ids": [], "source_observation_ids": [], "strength": 8, "version": 1, "parent_id": "", "supersedes": "", "is_latest": true, "forget_after": "", "tier": "durable", "retention": "permanent", "last_scored_at": "2025-01-15T12:00:00Z", "created_at": "2025-01-15T12:00:00Z", "updated_at": "2025-01-15T12:00:00Z", "agent_id": "67e89abc123def456789000" }}| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "not_found", "message": "resource not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
{ "code": "store_unavailable", "message": "memory store unavailable"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
store_unavailable | Memory store unavailable | The memory store could not be opened (degraded remote host, not-warm realm store, divergent/corrupt local DB). The request fails closed rather than silently falling back. | Retry once the store is warm; if persistent, inspect the daemon logs for the degrade reason. |
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
GET /api/v1/agent/memory/graph
Section titled “GET /api/v1/agent/memory/graph”Returns a paginated page of a project’s memory relation graph: nodes, edges, stats. Filter via ?project= and ?node_type=; page via ?limit= and ?offset=.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
project | query | string | No | Project key whose graph to read. |
node_type | query | string | No | Optional node-type filter. |
limit | query | integer | No | Maximum nodes/edges to return. |
offset | query | integer | No | Pagination offset into the graph. |
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
curl -X GET 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/graph?project=acme-web&node_type=memory&limit=200&offset=0' \ -H 'Authorization: Bearer <token>'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.getGraph({ project: 'acme-web', node_type: 'memory', limit: 200, offset: 0,});{ "nodes": [ { "id": "67e89abc123def456789abcd", "type": "memory", "label": "Stripe webhook acknowledgement", "project": "acme-web" } ], "edges": [ { "source": "67e89abc123def456789abcd", "target": "890abcdef12345678901cdef", "relation": "supersedes" } ], "stats": { "node_count": 142, "edge_count": 287 }, "limit": 200, "offset": 0, "truncated": false}| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
{ "code": "store_unavailable", "message": "memory store unavailable"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
store_unavailable | Memory store unavailable | The memory store could not be opened (degraded remote host, not-warm realm store, divergent/corrupt local DB). The request fails closed rather than silently falling back. | Retry once the store is warm; if persistent, inspect the daemon logs for the degrade reason. |
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
Search
Section titled “Search”POST /api/v1/agent/memory/search
Section titled “POST /api/v1/agent/memory/search”Hybrid recall across a project: BM25 + vector + graph fusion. The query is privacy-stripped before any tokenize or embed; the read is no-touch (it never strengthens future ranking).
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
project | string | No | Project key to search within. |
query | string | No | The natural-language recall query (privacy-stripped server-side). |
limit | integer | No | Maximum hits to return. |
kinds | array | No | Optional memory kinds/stores to restrict the search to. |
skip_graph | boolean | No | Skip the graph-fusion component of recall. |
curl -X POST 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/search' \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d '{ "project": "acme-web", "query": "stripe webhook retry behavior", "limit": 10 }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.search({ project: 'acme-web', query: 'stripe webhook retry behavior', limit: 10,});{ "hits": [ { "id": "67e89abc123def456789abcd", "type": "fact", "title": "Stripe webhook acknowledgement", "score": 0.84, "components": { "bm25": 0.41, "vector": 0.39, "graph": 0.04 } } ]}| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "payload_too_large", "message": "request body exceeds the configured size limit"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
payload_too_large | Payload too large | The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it: a well-formed-but-large body is a size violation, not a JSON syntax error. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
{ "code": "store_unavailable", "message": "memory store unavailable"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
store_unavailable | Memory store unavailable | The memory store could not be opened (degraded remote host, not-warm realm store, divergent/corrupt local DB). The request fails closed rather than silently falling back. | Retry once the store is warm; if persistent, inspect the daemon logs for the degrade reason. |
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
Memory writes
Section titled “Memory writes”POST /api/v1/agent/memory/items
Section titled “POST /api/v1/agent/memory/items”Stores a new memory record. A save here never supersedes an existing memory, however similar: two saves are always two records (an agent’s own saves may still replace a near-duplicate). The reply carries the new record’s id, type, title, and version, and superseded: the id of the record this save replaced, always "" on this route.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project key the memory belongs to. |
content | string | Yes | The memory content. |
type | string | No | Memory type (e.g. workflow, fact). |
concepts | array | No | Concept tags to index the memory under. |
files | array | No | File paths the memory is about. |
ttl_days | integer | No | Days until the memory expires, counted from the save. Omitted, 0, or a negative value means no expiry. Must be a whole number between -2147483648 and 106751 (about 292 years, the longest expiry the store can represent); a value outside that range is REFUSED, never clamped and never treated as no expiry. A fractional value like 30.5 and a numeric string like "30" are both REFUSED too, never truncated or coerced. A silent coercion to 0 would store the memory with no expiry at all while reporting success. |
strength | integer | No | Initial ranking strength, a whole number from 1 (weakest) to 10 (strongest). Omitted or 0 takes the store’s default of 7. Any other value (a negative number, anything above 10, a fractional value, or a numeric string) is REFUSED, never coerced and never silently replaced with the default. |
expect_realm | string | No | Optional realm assertion: "global" or a 24-hex realm id. The write is refused when the daemon’s active realm no longer matches, so it cannot land in a realm the caller switched away from. |
curl -X POST 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/items' \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d '{ "project": "acme-web", "content": "Stripe webhooks must be acknowledged within 5 seconds; the retry window is exponential.", "type": "fact", "concepts": ["stripe", "webhooks", "reliability"], "files": ["src/webhooks/stripe.ts"], "ttl_days": 90, "strength": 8 }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.createItem({ project: 'acme-web', content: 'Stripe webhooks must be acknowledged within 5 seconds; the retry window is exponential.', type: 'fact', concepts: ['stripe', 'webhooks', 'reliability'], files: ['src/webhooks/stripe.ts'], ttl_days: 90, strength: 8,});The operation’s JSON reply is passed through verbatim. The schema permits any JSON object, so a fixed example is not shown; the daemon returns the saved record’s id, type, title, and version, plus superseded (always "" on this route).
| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "realm_mismatch", "message": "expect_realm does not name the agent's active realm, so nothing was read or written; check the active realm, then retry with it"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
realm_mismatch | Realm mismatch | The request’s expect_realm is not the agent’s active realm (it changed, or the caller asserted another one). Nothing was read or written. | Check the agent’s active realm, then retry with expect_realm set to it. |
{ "code": "payload_too_large", "message": "request body exceeds the configured size limit"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
payload_too_large | Payload too large | The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it: a well-formed-but-large body is a size violation, not a JSON syntax error. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
{ "code": "store_unavailable", "message": "memory store unavailable"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
store_unavailable | Memory store unavailable | The memory store could not be opened (degraded remote host, not-warm realm store, divergent/corrupt local DB). The request fails closed rather than silently falling back. | Retry once the store is warm; if persistent, inspect the daemon logs for the degrade reason. |
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
PATCH /api/v1/agent/memory/items/{id}
Section titled “PATCH /api/v1/agent/memory/items/{id}”Patches a memory record by id. An id the project does not hold is 404 not_found. An absent body field preserves the stored value; a present one overwrites it.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | The item id. |
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
project | string | No | Project key the record belongs to. |
kind | string | No | Which store the record lives in. Omitted means memory. It selects which of the fields below apply; observation is not editable. Allowed values: memory, lesson, slot. |
content | string | No | Replacement content. Applies to every kind, and is REQUIRED for kind=slot (a slot edit with no content is refused; use the delete route to remove a slot). |
type | string | No | kind=memory: replacement memory type (e.g. workflow, fact). |
concepts | array | No | kind=memory: replacement concept tags. The whole list is replaced, and a malformed array is rejected rather than silently truncated. |
files | array | No | kind=memory: replacement file paths. The whole list is replaced, and a malformed array is rejected rather than silently truncated. |
strength | integer | No | kind=memory: replacement ranking strength, a whole number from 1 (weakest) to 10 (strongest). Any other value (0, a negative number, anything above 10, a fractional value, or a numeric string) is REFUSED, never coerced, and the stored strength is left unchanged. |
ttl_days | integer | No | kind=memory: days until the memory expires, counted from now. 0 or a negative value CLEARS the expiry and makes the memory permanent, so omit the field entirely on an edit that is not about retention. Must be a whole number between -2147483648 and 106751 (about 292 years, the longest expiry the store can represent); a value outside that range is REFUSED, never clamped, and the stored expiry is left unchanged. A fractional value like 30.5 and a numeric string like "30" are both REFUSED too, never truncated or coerced. |
tier | string | No | kind=memory: replacement storage tier. |
context | string | No | kind=lesson: replacement context. Send it verbatim to preserve it; an absent value preserves the stored one, but the field is how the TUI resends it unchanged. |
confidence | number | No | kind=lesson: replacement confidence. |
expect_realm | string | No | Optional realm assertion: "global" or a 24-hex realm id. The edit is refused when the daemon’s active realm no longer matches. |
curl -X PATCH 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/items/67e89abc123def456789abcd' \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d '{ "project": "acme-web", "kind": "memory", "content": "Updated: Stripe webhooks must be acknowledged within 5 seconds; retries are exponential.", "strength": 9 }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.updateItem('67e89abc123def456789abcd', { project: 'acme-web', kind: 'memory', content: 'Updated: Stripe webhooks must be acknowledged within 5 seconds; retries are exponential.', strength: 9,});The operation’s JSON reply is passed through verbatim. The schema permits any JSON object, so a fixed example is not shown; the daemon returns the updated record’s id, type, title, and version, plus superseded (the id of the record this edit replaced, or "" on a true patch).
| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "not_found", "message": "resource not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
{ "code": "realm_mismatch", "message": "expect_realm does not name the agent's active realm, so nothing was read or written; check the active realm, then retry with it"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
realm_mismatch | Realm mismatch | The request’s expect_realm is not the agent’s active realm (it changed, or the caller asserted another one). Nothing was read or written. | Check the agent’s active realm, then retry with expect_realm set to it. |
{ "code": "payload_too_large", "message": "request body exceeds the configured size limit"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
payload_too_large | Payload too large | The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it: a well-formed-but-large body is a size violation, not a JSON syntax error. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
{ "code": "store_unavailable", "message": "memory store unavailable"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
store_unavailable | Memory store unavailable | The memory store could not be opened (degraded remote host, not-warm realm store, divergent/corrupt local DB). The request fails closed rather than silently falling back. | Retry once the store is warm; if persistent, inspect the daemon logs for the degrade reason. |
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
DELETE /api/v1/agent/memory/items
Section titled “DELETE /api/v1/agent/memory/items”Deletes a memory record. The delete is cross-project. Deletes one or many records in a single call: address them by ids, or by name/id for a slot. To erase a whole project, including its summaries, relation graph, and consolidation residue (none of which are reachable record by record), use memory.deleteProject instead.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
ids | array | No | Record ids to delete. Required for kind=memory, kind=observation, or kind=lesson (the empty/default kind included). A summary:<session_id>-prefixed id deletes a summary. |
id | string | No | A single record id; shorthand for a one-element ids. For kind=slot it is the slot NAME (an alias for name). |
name | string | No | kind=slot: the slot to delete. Takes precedence over id. |
project | string | No | Project key the records belong to. |
kind | string | No | Which store the records live in. Omitted means memory. Allowed values: memory, observation, lesson, slot. |
reason | string | No | Optional reason recorded on the governance audit row. |
expect_realm | string | No | Optional realm assertion: "global" or a 24-hex realm id. The delete is refused when the daemon’s active realm no longer matches. |
curl -X DELETE 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/items' \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d '{ "ids": ["67e89abc123def456789abcd"], "project": "acme-web", "kind": "memory", "reason": "stale and now incorrect" }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.deleteItem({ ids: ['67e89abc123def456789abcd'], project: 'acme-web', kind: 'memory', reason: 'stale and now incorrect',});The operation’s JSON reply is passed through verbatim. The schema permits any JSON object, so a fixed example is not shown; the daemon returns per-id deletion status.
| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "realm_mismatch", "message": "expect_realm does not name the agent's active realm, so nothing was read or written; check the active realm, then retry with it"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
realm_mismatch | Realm mismatch | The request’s expect_realm is not the agent’s active realm (it changed, or the caller asserted another one). Nothing was read or written. | Check the agent’s active realm, then retry with expect_realm set to it. |
{ "code": "payload_too_large", "message": "request body exceeds the configured size limit"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
payload_too_large | Payload too large | The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it: a well-formed-but-large body is a size violation, not a JSON syntax error. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
{ "code": "store_unavailable", "message": "memory store unavailable"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
store_unavailable | Memory store unavailable | The memory store could not be opened (degraded remote host, not-warm realm store, divergent/corrupt local DB). The request fails closed rather than silently falling back. | Retry once the store is warm; if persistent, inspect the daemon logs for the degrade reason. |
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
Memory lifecycle
Section titled “Memory lifecycle”PUT /api/v1/agent/memory/enabled
Section titled “PUT /api/v1/agent/memory/enabled”Flips the memory privacy switch: persists features.memory and applies it immediately. Not restricted to admins (the daemon applies no admin check to this call).
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
enabled | boolean | Yes | Whether memory capture is enabled. |
The SDK reaches this operation through two methods:
client.agent.memory.enable(...): setsenabled: true.client.agent.memory.disable(...): setsenabled: false.
curl -X PUT 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/enabled' \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d '{ "enabled": true }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.enable({});The operation’s JSON reply is passed through verbatim. The schema permits any JSON object, so a fixed example is not shown; the daemon returns the updated enabled state and related fields.
| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "forbidden", "message": "request must arrive through the Hoody proxy"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "not_found", "message": "resource not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
{ "code": "payload_too_large", "message": "request body exceeds the configured size limit"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
payload_too_large | Payload too large | The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it: a well-formed-but-large body is a size violation, not a JSON syntax error. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
store_failed | Agent store failed | One of the agent’s own stores could not be read, parsed, locked, or written, so the operation did not complete. The message names the store (for example “the agent’s settings file is damaged and was left unchanged”). A damaged store is left as it was rather than rewritten. | Retry once; if it persists, repair the named store inside the container. The agent’s log (GET /logs) records a “store failure” entry with the store, the failure kind (io, corrupt, or lock), and a path-free cause such as “open: permission denied” or “invalid JSON at offset 12”; it does not name the file’s path. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
POST /api/v1/agent/memory/flush
Section titled “POST /api/v1/agent/memory/flush”Forces the memory store durability barrier. Not restricted to admins. The body is optional; every _-prefixed key is ignored, and all other keys are passed through verbatim.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
Request body
Section titled “Request body”JSON object. The schema declares no fields; document none and invent none. Every _-prefixed key is ignored (removed before dispatch), the request scope (cwd/config_dir) is added from the scope headers, and all other keys are passed through verbatim. No fields are required.
curl -X POST 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/flush' \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d '{}'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.flush({});The operation’s JSON reply is passed through verbatim. The schema permits any JSON object, so a fixed example is not shown; the daemon returns its flush confirmation.
| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "forbidden", "message": "request must arrive through the Hoody proxy"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "not_found", "message": "resource not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
{ "code": "payload_too_large", "message": "request body exceeds the configured size limit"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
payload_too_large | Payload too large | The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it: a well-formed-but-large body is a size violation, not a JSON syntax error. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
POST /api/v1/agent/memory/consolidate
Section titled “POST /api/v1/agent/memory/consolidate”Requests a consolidation pass for a project. HUMAN-ONLY: consolidation spends multi-LLM passes and evolves memory state irreversibly, so an autonomous caller may NEVER self-approve it. An HTTP request is always treated as coming from a machine, never from an interactive human, so a request that passes the admin check is refused 403 human_only. Run consolidation from an interactive human session (TUI/CLI) instead.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project key to consolidate. |
min_observations | integer | No | Optional minimum-observations threshold for a fact to be consolidated. |
curl -X POST 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/consolidate' \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d '{ "project": "acme-web", "min_observations": 3 }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.consolidate({ project: 'acme-web', min_observations: 3,});{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "human_only", "message": "memory consolidation requires direct human confirmation and is not available to machine callers"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
human_only | Human confirmation required | The operation requires direct human confirmation and is not available to machine callers; an autonomous caller may not self-approve it even with a valid admin token. | Trigger the operation from an interactive human session, not an autonomous/machine-confirmed dispatch. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "not_found", "message": "resource not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
{ "code": "payload_too_large", "message": "request body exceeds the configured size limit"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
payload_too_large | Payload too large | The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it: a well-formed-but-large body is a size violation, not a JSON syntax error. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
Project erasure
Section titled “Project erasure”POST /api/v1/agent/memory/write-intents
Section titled “POST /api/v1/agent/memory/write-intents”Mints the single-use intent a guarded memory write requires. The intent binds {store, op, project}: it is spent the moment it is checked and is rejected for any other operation or project, so a retry after that point needs a fresh one. A request refused before the check (a realm that no longer matches, a missing project) leaves it unspent until it expires. op is currently "wipe_project" only (the intent for memory.deleteProject). It also binds the realm that was active when it was minted, so a realm switch between the mint and the write invalidates it rather than erasing another realm’s project. It expires, so mint it when you submit rather than when a form opens.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
op | string | Yes | The write this intent authorizes. The minted intent is valid for this op alone. Allowed values: wipe_project. |
project | string | Yes | Project key the write will target. The intent is valid for this project alone. |
expect_realm | string | No | Optional realm assertion: "global" or a 24-hex realm id. The request is refused when the daemon’s active realm no longer matches. |
curl -X POST 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/write-intents' \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d '{ "op": "wipe_project", "project": "acme-web" }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.createWriteIntent({ op: 'wipe_project', project: 'acme-web',});{ "status": "ok", "nonce": "intent_67e89abc123def456789abcd", "op": "wipe_project", "project": "acme-web", "expires_in": 300}| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "realm_mismatch", "message": "expect_realm does not name the agent's active realm, so nothing was read or written; check the active realm, then retry with it"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
realm_mismatch | Realm mismatch | The request’s expect_realm is not the agent’s active realm (it changed, or the caller asserted another one). Nothing was read or written. | Check the agent’s active realm, then retry with expect_realm set to it. |
{ "code": "payload_too_large", "message": "request body exceeds the configured size limit"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
payload_too_large | Payload too large | The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it: a well-formed-but-large body is a size violation, not a JSON syntax error. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |
DELETE /api/v1/agent/memory/projects/{project}
Section titled “DELETE /api/v1/agent/memory/projects/{project}”Erases everything a project owns: its observations, memories, summaries, sessions, lessons, slots, documents, embeddings, search postings, relation graph, and provenance, plus the project registry row, the profile cache, and the consolidation cursor and input fingerprints. IRREVERSIBLE, and NOT the same as deleting every item the listing returns: summaries are not an enumerable kind, the relation graph has no delete surface, and none of the residue is addressable by id, so an item-by-item delete leaves a project that still shapes future recall and consolidation. Requires the single-use intent from memory.createWriteIntent (op "wipe_project", same project) in the body as nonce. Capture work queued before the erasure is drained first, and the injection epoch advances on both the success and the failure path, so no session re-injects erased content. The audit row survives by design; it records counts, never content.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
project | path | string | Yes | The project. |
X-Hoody-Cwd | header | string | No | Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd. |
X-Hoody-Config-Dir | header | string | No | Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against. |
X-Hoody-Realm | header | string | No | Per-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
realm | query | string | No | Per-request realm selector, the in:query alias of the X-Hoody-Realm header (read only when the header is absent): “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
nonce | string | Yes | The single-use intent from memory.createWriteIntent, minted for op "wipe_project" and this project. |
reason | string | No | Optional reason recorded on the audit row. |
expect_realm | string | No | Optional realm assertion: "global" or a 24-hex realm id. The request is refused when the daemon’s active realm no longer matches. |
curl -X DELETE 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/memory/projects/acme-web' \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d '{ "nonce": "intent_67e89abc123def456789abcd", "reason": "test cleanup" }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.memory.deleteProject('acme-web', { nonce: 'intent_67e89abc123def456789abcd', reason: 'test cleanup',});{ "status": "ok", "project": "acme-web", "wiped": true, "deleted": 42, "incomplete_erasure": false}| Error Code | Title | Description | Resolution |
|---|
{ "code": "bad_request", "message": "invalid request"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
bad_request | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
realm_scope_unsupported | Realm scope unsupported | A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope. | Omit the realm header on this route, or open a session to scope by realm. |
invalid_realm | Invalid realm selector | The realm selector is malformed (not ""/“global”/a 24-hex id). | Pass a valid realm selector. |
{ "code": "admin_unauthorized", "message": "memory administration requires a valid admin token"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
admin_unauthorized | Rejected by the daemon’s own admin gate | The daemon’s own administrator check refused the request. Access to the HTTP API is decided by the container’s proxy permission policy, but the daemon keeps a separate administrator check: when the daemon was started with its own administrator token, it refuses these operations, because an HTTP request cannot supply that token. In the standard HTTP deployment the daemon has no such token, the check allows the request, and this code is not returned. | Run the daemon in the standard HTTP deployment (--auth-token-path, no separate administrator token) so its check allows HTTP requests, or perform the operation from the agent’s terminal interface inside the container. |
forbidden | Forbidden (Source IP Guard) | Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
{ "code": "write_intent_invalid", "message": "stale write intent — mint a new one and retry"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
write_intent_invalid | Write intent invalid | The single-use write intent was missing, expired, already spent, or minted for a different store, operation, or project. The intent is consumed by the attempt, so a retry always needs a fresh one. | Mint a new intent with POST /memory/write-intents for this exact operation and project, then present its nonce on the write. |
realm_mismatch | Realm mismatch | The request’s expect_realm is not the agent’s active realm (it changed, or the caller asserted another one). Nothing was read or written. | Check the agent’s active realm, then retry with expect_realm set to it. |
{ "code": "payload_too_large", "message": "request body exceeds the configured size limit"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
payload_too_large | Payload too large | The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it: a well-formed-but-large body is a size violation, not a JSON syntax error. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |
{ "code": "rate_limited", "message": "request rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
rate_limited | Too many requests | The per-client request rate limit was exceeded; the gateway throttled the request before dispatch. | Honor the Retry-After header and retry; reduce the request rate. |
{ "code": "internal_error", "message": "internal server error"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
internal_error | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |
{ "code": "store_unavailable", "message": "memory store unavailable"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
store_unavailable | Memory store unavailable | The memory store could not be opened (degraded remote host, not-warm realm store, divergent/corrupt local DB). The request fails closed rather than silently falling back. | Retry once the store is warm; if persistent, inspect the daemon logs for the degrade reason. |
service_unavailable | Realm memory not connected | The request named a realm whose memory is not connected on the agent right now. It connects while the realm is in use (a session in it, or the active realm); a request never connects it. | Honor Retry-After and retry, or use the realm first. |
restriction_unknown | Login restriction unknown | The agent cannot read yet which realms its login may serve (GET /hoody/auth/status reports restriction “unknown”), so it refuses realm-scoped requests until it can. Nothing was read or changed. | Retry after the restriction is readable. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
not_found | Not found | The requested resource does not exist. | Verify the path and identifier. |