# Agent: Hooks

**Page:** api/agent/hooks

[Download Raw Markdown](./api/agent/hooks.md)

---

{/* AUTO-GENERATED — Do not edit manually. Regenerate with: npm run docs:api:generate */}



## Agent: Hooks

Lifecycle hooks let you run arbitrary commands on agent events. The endpoints below let you list, upsert, delete, toggle, test-fire, reload, disable-all, and acknowledge the trust prompt for the hooks of a live session. Hooks are session-scoped: every call requires a live `session_id`, and every guarded mutation (upsert, delete, toggle, disable-all) requires a single-use nonce minted by `begin-write`.


All write operations are guarded by a two-step nonce. Call `POST /api/v1/agent/hooks/begin-write` first with the target `op` (one of `upsert`, `delete`, `toggle`, `set_disabled`) and the `scope`, then present the returned nonce on the matching write. The nonce binds to that session + op + scope tuple and is single-use — a nonce minted for `op:toggle` is rejected by `upsert` and vice versa.


---

### `GET /api/v1/agent/hooks`

Lists the lifecycle hooks for a live session. Returns the live + on-disk hook summaries (`live`, `session`), drift detection (`stale`), the per-scope settings files, and the execution-trust probe. This is not a paginated list envelope — the daemon payload is surfaced verbatim. A per-request realm header is rejected because this is an active-only RPC.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `session_id` | query | string | No | Live session id (hooks are session-scoped; required by the daemon RPC). Query alias of the body `session_id` (the body value wins). |
| `realm` | query | string | No | Per-request realm selector — alias of `X-Hoody-Realm` (read only when the header is absent): `"global"` or a 24-hex id. Rejected on active-only routes. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope: `.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. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). Rejected on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector: `"global"` or a 24-hex id. Rejected on active-only routes. |

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `session_id` | string | No | Live session id (hooks are session-scoped). May be supplied here OR as the `?session_id` query alias; the body value wins. |

### Responses



```json
{
  "live": [
    {
      "name": "lint-on-save",
      "description": "Run project linter before persisting any record",
      "event": "PreRecordSave",
      "matcher": "*.go",
      "command": "gofmt -l .",
      "enabled": true,
      "timeout": 30
    }
  ],
  "session": [
    {
      "name": "lint-on-save",
      "description": "Run project linter before persisting any record",
      "event": "PreRecordSave",
      "matcher": "*.go",
      "command": "gofmt -l .",
      "enabled": true,
      "timeout": 30
    }
  ],
  "stale": [],
  "files": [
    {
      "scope": "project",
      "path": "/workspace/.hoody/settings.json",
      "exists": true
    }
  ],
  "trust": {
    "acknowledged": true,
    "required": false
  }
}
```


```json
{
  "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. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | 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. |


```json
{
  "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. |


```json
{
  "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. |



### SDK Usage



```bash
curl -X GET "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks?session_id=sess_8f2c1a" \
  -H "Authorization: Bearer <token>"
```


```ts
await client.agent.hooks.listHooks(
  { session_id: "sess_8f2c1a" }
);
```



---

### `POST /api/v1/agent/hooks/begin-write`

Issues the two-step write nonce required before **every** guarded hook mutation — not just `upsert`/`delete` but also `toggle` and `disable-all`. The returned nonce binds to the `session + op + scope` tuple and is single-use; the nonce for `op:toggle` is not accepted by `upsert`, and so on.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `realm` | query | string | No | Per-request realm selector — alias of `X-Hoody-Realm` (read only when the header is absent): `"global"` or a 24-hex id. Rejected on active-only routes. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. Required by routes that resolve a cwd. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). Rejected on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector: `"global"` or a 24-hex id. Rejected on active-only routes. |

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `session_id` | string | Yes | Live session id (hooks are session-scoped). |
| `op` | string | Yes | The write the nonce authorizes; one of: `upsert`, `delete`, `toggle`, `set_disabled`. The nonce is rejected by any other `op`. |
| `scope` | string | Yes | Scope of the settings file the write targets (e.g. `project`/`user`); the nonce binds to its resolved path. |

```json
{
  "session_id": "sess_8f2c1a",
  "op": "upsert",
  "scope": "project"
}
```

### Responses



```json
{
  "nonce": "nonce_a9b8c7d6e5f40392",
  "scope": "project",
  "op": "upsert",
  "session_id": "sess_8f2c1a",
  "expires_at": "2026-03-04T12:34:56Z"
}
```


```json
{
  "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. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | 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. |


```json
{
  "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. |


```json
{
  "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. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |


```json
{
  "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. |


```json
{
  "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. |


```json
{
  "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). | Honor `Retry-After` and retry. |



### SDK Usage



```bash
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/begin-write" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sess_8f2c1a",
    "op": "upsert",
    "scope": "project"
  }'
```


```ts
await client.agent.hooks.beginHookWrite({
  session_id: "sess_8f2c1a",
  op: "upsert",
  scope: "project"
});
```



---

### `PUT /api/v1/agent/hooks`

Creates or updates a hook (`hooks.upsert`). Requires the begin-write nonce minted for `op:upsert` and a live `session_id`. Defining a hook persists an arbitrary command that fires on lifecycle events. Creating a **new** hook requires non-empty `name` and `description` (the daemon rejects an undocumented create); updating an existing hook may omit them to preserve the current values.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `realm` | query | string | No | Per-request realm selector — alias of `X-Hoody-Realm` (read only when the header is absent): `"global"` or a 24-hex id. Rejected on active-only routes. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. Required by routes that resolve a cwd. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). Rejected on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector: `"global"` or a 24-hex id. Rejected on active-only routes. |

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `session_id` | string | Yes | Live session id (hooks are session-scoped). |
| `nonce` | string | Yes | The single-use write nonce from `beginHookWrite` minted for `op:upsert` + this scope; the RPC fails closed without it. |
| `scope` | string | No | Scope of the settings file to write (must match the nonce's scope). |
| `event` | string | No | Lifecycle event the hook fires on. |
| `matcher` | string | No | Matcher selecting when the hook fires. |
| `command` | string | No | Command to run when the hook fires. |
| `timeout` | integer | No | Per-fire timeout (optional). |
| `name` | string | No | Short human label shown in the Hooks tab (required when creating a new hook; omit to preserve on update). |
| `description` | string | No | Short description of what the hook does (required when creating a new hook; omit to preserve on update). |

```json
{
  "session_id": "sess_8f2c1a",
  "nonce": "nonce_a9b8c7d6e5f40392",
  "scope": "project",
  "event": "PreRecordSave",
  "matcher": "*.go",
  "command": "gofmt -l .",
  "timeout": 30,
  "name": "lint-on-save",
  "description": "Run project linter before persisting any record"
}
```

### Responses



```json
{
  "ok": true,
  "hook": {
    "name": "lint-on-save",
    "description": "Run project linter before persisting any record",
    "event": "PreRecordSave",
    "matcher": "*.go",
    "command": "gofmt -l .",
    "enabled": true,
    "timeout": 30
  }
}
```


```json
{
  "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. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | 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. |


```json
{
  "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. |


```json
{
  "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. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |


```json
{
  "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. |


```json
{
  "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. |


```json
{
  "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). | Honor `Retry-After` and retry. |



### SDK Usage



```bash
curl -X PUT "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sess_8f2c1a",
    "nonce": "nonce_a9b8c7d6e5f40392",
    "scope": "project",
    "event": "PreRecordSave",
    "matcher": "*.go",
    "command": "gofmt -l .",
    "timeout": 30,
    "name": "lint-on-save",
    "description": "Run project linter before persisting any record"
  }'
```


```ts
await client.agent.hooks.upsertHook({
  session_id: "sess_8f2c1a",
  nonce: "nonce_a9b8c7d6e5f40392",
  scope: "project",
  event: "PreRecordSave",
  matcher: "*.go",
  command: "gofmt -l .",
  timeout: 30,
  name: "lint-on-save",
  description: "Run project linter before persisting any record"
});
```



---

### `DELETE /api/v1/agent/hooks`

Deletes a hook (`hooks.delete`). Requires the begin-write nonce minted for `op:delete` and a live `session_id`.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `realm` | query | string | No | Per-request realm selector — alias of `X-Hoody-Realm` (read only when the header is absent): `"global"` or a 24-hex id. Rejected on active-only routes. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. Required by routes that resolve a cwd. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). Rejected on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector: `"global"` or a 24-hex id. Rejected on active-only routes. |

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `session_id` | string | Yes | Live session id (hooks are session-scoped). |
| `nonce` | string | Yes | The single-use write nonce from `beginHookWrite` minted for `op:delete` + this scope; the RPC fails closed without it. |
| `scope` | string | No | Scope of the settings file to write (must match the nonce's scope). |

```json
{
  "session_id": "sess_8f2c1a",
  "nonce": "nonce_a9b8c7d6e5f40392",
  "scope": "project"
}
```

### Responses



```json
{
  "ok": true,
  "deleted": "lint-on-save"
}
```


```json
{
  "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. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | 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. |


```json
{
  "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. |


```json
{
  "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. |


```json
{
  "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. |


```json
{
  "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). | Honor `Retry-After` and retry. |



### SDK Usage



```bash
curl -X DELETE "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sess_8f2c1a",
    "nonce": "nonce_a9b8c7d6e5f40392",
    "scope": "project"
  }'
```


```ts
await client.agent.hooks.deleteHook({
  session_id: "sess_8f2c1a",
  nonce: "nonce_a9b8c7d6e5f40392",
  scope: "project"
});
```



---

### `POST /api/v1/agent/hooks/toggle`

Toggles a single hook's enabled state (`hooks.toggle`). Requires the begin-write nonce minted for `op:toggle` and a live `session_id`.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `realm` | query | string | No | Per-request realm selector — alias of `X-Hoody-Realm` (read only when the header is absent): `"global"` or a 24-hex id. Rejected on active-only routes. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. Required by routes that resolve a cwd. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). Rejected on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector: `"global"` or a 24-hex id. Rejected on active-only routes. |

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `session_id` | string | Yes | Live session id (hooks are session-scoped). |
| `nonce` | string | Yes | The single-use write nonce from `beginHookWrite` minted for `op:toggle` + this scope; the RPC fails closed without it. |
| `scope` | string | No | Scope of the settings file to write (must match the nonce's scope). |

```json
{
  "session_id": "sess_8f2c1a",
  "nonce": "nonce_a9b8c7d6e5f40392",
  "scope": "project"
}
```

### Responses



```json
{
  "ok": true,
  "name": "lint-on-save",
  "enabled": false
}
```


```json
{
  "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. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | 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. |


```json
{
  "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. |


```json
{
  "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. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |


```json
{
  "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. |


```json
{
  "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. |


```json
{
  "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). | Honor `Retry-After` and retry. |



### SDK Usage



```bash
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/toggle" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sess_8f2c1a",
    "nonce": "nonce_a9b8c7d6e5f40392",
    "scope": "project"
  }'
```


```ts
await client.agent.hooks.toggleHook({
  session_id: "sess_8f2c1a",
  nonce: "nonce_a9b8c7d6e5f40392",
  scope: "project"
});
```



---

### `POST /api/v1/agent/hooks/disable-all`

Disables (or re-enables) all hooks at once (`hooks.set_disabled`). Requires the begin-write nonce minted for `op:set_disabled` and a live `session_id`.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `realm` | query | string | No | Per-request realm selector — alias of `X-Hoody-Realm` (read only when the header is absent): `"global"` or a 24-hex id. Rejected on active-only routes. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. Required by routes that resolve a cwd. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). Rejected on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector: `"global"` or a 24-hex id. Rejected on active-only routes. |

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `session_id` | string | Yes | Live session id (hooks are session-scoped). |
| `nonce` | string | Yes | The single-use write nonce from `beginHookWrite` minted for `op:set_disabled` + this scope; the RPC fails closed without it. |
| `scope` | string | No | Scope of the settings file to write (must match the nonce's scope). |

```json
{
  "session_id": "sess_8f2c1a",
  "nonce": "nonce_a9b8c7d6e5f40392",
  "scope": "project"
}
```

### Responses



```json
{
  "ok": true,
  "disabled": true,
  "scope": "project"
}
```


```json
{
  "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. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | 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. |


```json
{
  "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. |


```json
{
  "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. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |


```json
{
  "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. |


```json
{
  "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. |


```json
{
  "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). | Honor `Retry-After` and retry. |



### SDK Usage



```bash
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/disable-all" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sess_8f2c1a",
    "nonce": "nonce_a9b8c7d6e5f40392",
    "scope": "project"
  }'
```


```ts
await client.agent.hooks.disableAllHooks({
  session_id: "sess_8f2c1a",
  nonce: "nonce_a9b8c7d6e5f40392",
  scope: "project"
});
```



---

### `POST /api/v1/agent/hooks/reload`

Reloads the hook configuration from disk (`hooks.reload`). Pass a live `session_id` to also receive the reloaded summary.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `realm` | query | string | No | Per-request realm selector — alias of `X-Hoody-Realm` (read only when the header is absent): `"global"` or a 24-hex id. Rejected on active-only routes. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. Required by routes that resolve a cwd. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). Rejected on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector: `"global"` or a 24-hex id. Rejected on active-only routes. |

### Request Body

This endpoint does not declare body fields. The request is forwarded to the daemon `hooks.reload` RPC; reserved `_`-prefixed keys are ignored and the request scope (cwd/config_dir) is applied automatically. All other keys are passed through. Pass `session_id` to receive the reloaded summary.

```json
{}
```

### Responses



```json
{
  "ok": true,
  "reloaded": 4,
  "files": [
    {
      "scope": "project",
      "path": "/workspace/.hoody/settings.json",
      "exists": true
    }
  ]
}
```


```json
{
  "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. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | 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. |


```json
{
  "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. |


```json
{
  "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. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |


```json
{
  "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. |


```json
{
  "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. |


```json
{
  "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). | Honor `Retry-After` and retry. |



### SDK Usage



```bash
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/reload" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{}'
```


```ts
await client.agent.hooks.reloadHooks({});
```



---

### `POST /api/v1/agent/hooks/test`

Test-fires a hook command (`hooks.test`). This **executes an arbitrary command now**. Requires a live `session_id` (hooks are session-scoped).


`hooks.test` runs the hook command on the agent host. Treat it like remote code execution — only fire hooks whose command you trust.


### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `realm` | query | string | No | Per-request realm selector — alias of `X-Hoody-Realm` (read only when the header is absent): `"global"` or a 24-hex id. Rejected on active-only routes. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. Required by routes that resolve a cwd. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). Rejected on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector: `"global"` or a 24-hex id. Rejected on active-only routes. |

### Request Body

This endpoint does not declare body fields. The request is forwarded to the daemon `hooks.test` RPC; reserved `_`-prefixed keys are ignored and the request scope (cwd/config_dir) is applied automatically. All other keys are passed through. Pass `session_id` to identify the live session.

```json
{}
```

### Responses



```json
{
  "ok": true,
  "exit_code": 0,
  "stdout": "main.go\nutils.go\n",
  "stderr": "",
  "duration_ms": 47
}
```


```json
{
  "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. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | 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. |


```json
{
  "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. |


```json
{
  "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. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |


```json
{
  "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. |


```json
{
  "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. |


```json
{
  "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). | Honor `Retry-After` and retry. |



### SDK Usage



```bash
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/test" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{}'
```


```ts
await client.agent.hooks.testHook({});
```



---

### `POST /api/v1/agent/hooks/trust/ack`

Acknowledges the hook-trust prompt (`hooks.trust_ack`). Requires a live `session_id` (hooks are session-scoped).

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `realm` | query | string | No | Per-request realm selector — alias of `X-Hoody-Realm` (read only when the header is absent): `"global"` or a 24-hex id. Rejected on active-only routes. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. Required by routes that resolve a cwd. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). Rejected on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector: `"global"` or a 24-hex id. Rejected on active-only routes. |

### Request Body

This endpoint does not declare body fields. The request is forwarded to the daemon `hooks.trust_ack` RPC; reserved `_`-prefixed keys are ignored and the request scope (cwd/config_dir) is applied automatically. All other keys are passed through. Pass `session_id` to identify the live session.

```json
{}
```

### Responses



```json
{
  "ok": true,
  "acknowledged": true,
  "session_id": "sess_8f2c1a"
}
```


```json
{
  "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. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | 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. |


```json
{
  "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. |


```json
{
  "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. | Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests. |


```json
{
  "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. |


```json
{
  "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. |


```json
{
  "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). | Honor `Retry-After` and retry. |



### SDK Usage



```bash
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/trust/ack" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{}'
```


```ts
await client.agent.hooks.ackHookTrust({});
```