These endpoints read and mutate the agent’s process-wide settings, manage model-fusion composites, and configure BYOA (bring-your-own-agent) ACP backend delegates (currently claude) and their per-backend secrets. Use them when you need to inspect the effective merged settings, edit the home ~/.hoody/settings.json via a shallow patch, manage custom fusion models, or arm/disarm a delegated ACP backend and pin its default model or per-agent env secrets.
Returns the effective merged settings (home → project → settings.local.json, top-level merge) plus the home-layer object that settings.patch mutates. Process-wide config (global/no-realm): settings have no realm dimension at any layer, so a per-request realm header returns 400 realm_scope_unsupported.
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
Applies a SHALLOW top-level merge into the home ~/.hoody/settings.json (a null value deletes a key). Top-level only: sending {"features":{...}} REPLACES the whole features object. Process-wide config (global/no-realm): settings have no realm dimension, so a per-request realm header returns 400 realm_scope_unsupported.
SECURITY: security-load-bearing keys (deny_list, deny_urls, features, allowed_directories, hooks, disableAllHooks, mcp_servers, tools) cannot be modified over HTTP and return 403 settings_key_protected — edit settings.json at the host to change a guardrail (except mcp_servers, which is managed via the /api/v1/agent/mcp/* routes). A non-null top-level model is rejected 400: nothing consumes it (pin a model on the chat agent via PATCH /agents/{name}/model, or switch a live session via PATCH /sessions/{id}/model); {"model": null} still deletes a previously-persisted value. Returns the resulting home object.
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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.
{
"code":"settings_key_protected",
"message":"settings key 'deny_list' is security-load-bearing and cannot be modified over HTTP"
}
Error Code
Title
Description
Resolution
settings_key_protected
Settings key protected
The patch targets a security-load-bearing top-level settings key (deny_list, features, allowed_directories, hooks, mcp_servers, …). These guardrail keys cannot be modified over HTTP.
Edit settings.json at the host to change a guardrail key; omit it from the HTTP patch.
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
{
"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.
Lists the persisted model-fusion composites (fusion.list). Pass ?include_invalid=true to also receive the entries that failed validation as a TOP-LEVEL invalid array beside items (each with the failure reason and its stable raw-file index; never mixed into or paginated with the selectable items) so a broken composite is editable/deletable. Global/no-realm: composites are process-wide config with no realm dimension, so a per-request realm header returns 400 realm_scope_unsupported.
When true, also return composites that failed validation as a top-level invalid array beside items (each with a reason + raw-file index) so a broken composite is editable/deletable.
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 (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
Creates or updates a model-fusion composite keyed by slug (fusion.upsert). The body is the daemon FusionSpec under spec. The persisted key is derived from spec.name (lowercased, separators collapsed to -); the path {slug} must normalize to the same slug or the request is rejected 400 slug_mismatch — the path cannot rename what the body describes. Structural invariants (name/method/members, cycle guard, non-zero context window) are validated server-side.
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
"message":"path slug \"foo\" does not match spec.name \"bar\" (slug \"bar\")"
}
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.
slug_mismatch
Path slug does not match spec.name
The path {slug} and the slug derived from body spec.name normalize to different values; the daemon persists by the spec.name-derived slug, so honoring the request would write a composite the URL does not name.
Use the spec.name-derived slug in the path (lowercase, separators collapsed to -), or change spec.name.
{
"code":"forbidden",
"message":"request must arrive through the Hoody proxy"
}
Error Code
Title
Description
Resolution
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
{
"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.
{
"code":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
Reports the BYOA delegated-session backend availability (claude) — enabled flag, on-PATH status, trust posture (acp.status). A fixed status object, NOT a paginated collection.
The report is resolved through the layered settings the delegated session would use, so X-Hoody-Config-Dir (override) and X-Hoody-Cwd (project layer) are folded. For remote BYOA, a bound X-Hoody-Container switches the report to on-container detection/login probing, and X-Hoody-Realm scopes that probe (threaded as realm_selector). A realm header WITHOUT a container returns 400 realm_scope_unsupported (the local report has no realm dimension).
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
Arms (or disarms) a BYOA ACP backend for delegated sessions (acp.set_enabled). A delegated session — POST /sessions with backend: "acp" — is refused by the daemon while its backend is disabled, so this is the prerequisite for the whole delegated-session capability on a host configured over HTTP. Writes tools.acp_agents.<agent>.enabled in settings.json. Returns 404 unknown_agent for anything that is not a known BYOA backend (claude).
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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.
{
"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
Forbidden — the request was refused by the server’s admin gate.
Run the daemon with socket auth (--auth-token-path) and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway; or, for the interactive TUI Memory tab over the socket, present the daemon’s configured Memory-admin token.
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
The named ACP agent is not a known BYOA backend, so a per-agent secret reference would be dead (no launch spec reads it).
Use "claude" — the only BYOA backend.
{
"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":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).
Sets the default model (and reasoning effort) a BYOA ACP backend runs on (acp.set_agent_model). These are the values the daemon passes to the backend at connect; a delegated session started without an explicit model inherits them. An empty value clears the pin and returns the backend to its own default. Returns 404 unknown_agent for anything that is not a known BYOA backend (claude).
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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.
{
"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
Forbidden — the request was refused by the server’s admin gate.
Run the daemon with socket auth (--auth-token-path) and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway; or, for the interactive TUI Memory tab over the socket, present the daemon’s configured Memory-admin token.
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
The named ACP agent is not a known BYOA backend, so a per-agent secret reference would be dead (no launch spec reads it).
Use "claude" — the only BYOA backend.
{
"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":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).
Stores (or clears) one per-backend env VALUE for a BYOA ACP agent (acp.set_secret) in the dedicated 0600 ~/.hoody/acp-secrets.env store under acp/<agent>/<ENVKEY> (atomic temp+rename, flock). settings.json holds only the env KEY NAMES; the VALUE lives ONLY in the 0600 store. An empty value DELETES (unsets) the reference.
SECURITY: the value is NEVER returned — the reply confirms only (agent, key, stored|cleared). Returns 404 unknown_agent for an agent that is not a known BYOA backend (claude).
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
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.
{
"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
Forbidden — the request was refused by the server’s admin gate.
Run the daemon with socket auth (--auth-token-path) and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway; or, for the interactive TUI Memory tab over the socket, present the daemon’s configured Memory-admin token.
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
The named ACP agent is not a known BYOA backend, so a per-agent secret reference would be dead (no launch spec reads it).
Use "claude" — the only BYOA backend.
{
"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":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).