# Agent: Jobs

**Page:** api/agent/jobs

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

---

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



The Agent Jobs endpoints let you poll the status and result of async work dispatched through the agent (session inputs, workflow runs, long tool calls, headless runs), and cancel a still-active job or delete a terminal record. Use `GET /jobs/{id}` for the full job record, `GET /jobs/{id}/result` for a lean status-and-payload view, and `DELETE /jobs/{id}` to stop a pending or running job, or purge a finished one.


A `run_id` is `null` during the brief dispatch window for workflow runs (§7.4). Dispatch jobs surface their events on the session stream — `getJobResult` returns terminal status only for those.


---

## Get a job

`GET /api/v1/agent/jobs/{id}`

Returns the gateway-minted job record for an async dispatch, workflow run, or long tool call.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1): the .hoody project layer / record cwd / tool+workflow cwd. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1) selecting which on-disk .hoody install a stateless read/write resolves. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. Rejected (400 `realm_scope_unsupported`) on active-only / no-realm routes. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the query-string alias of the `X-Hoody-Realm` header, read only when the header is absent. |

### Request body

This endpoint accepts no body.

### Response




```json
{
  "job_id": "job_5f3c1a7b9d2e4f6a8b0c1d2e",
  "kind": "session.workflow",
  "session_id": "sess_8a7b6c5d4e3f2a1b0c9d8e7f",
  "run_id": "run_2a3b4c5d6e7f8a9b0c1d2e3f",
  "status": "running",
  "created_at": "2025-11-14T09:32:18.512Z",
  "updated_at": "2025-11-14T09:32:24.118Z"
}
```




```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 arrive through `hoody-proxy`: its source IP is private/local (in-container loopback, the bridge, the host, or a sibling container). The gateway has no service-level auth — authorization is owned by `hoody-proxy`, which is the only party that can reach it. | 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. |




### SDK usage

```ts
const job = await client.agent.jobs.getJob({
  id: "job_5f3c1a7b9d2e4f6a8b0c1d2e",
});
```

### cURL

```bash
curl -X GET "https://api.hoody.ai/api/v1/agent/jobs/job_5f3c1a7b9d2e4f6a8b0c1d2e" \
  -H "Authorization: Bearer $HOODY_TOKEN"
```

---

## Get a job's result

`GET /api/v1/agent/jobs/{id}/result`

Returns the terminal status and payload of a completed job, or the running status if the job is still in flight. Dispatch jobs are observed on the session stream — the result body carries terminal status only for those.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the query-string alias of the `X-Hoody-Realm` header. |

### Request body

This endpoint accepts no body.

### Response




```json
{
  "status": "succeeded",
  "result": {
    "answer_id": "ans_4f2a1b3c5d6e7f8a9b0c1d2e",
    "summary": "Reviewed the 3 pending TODOs and ranked them by impact."
  },
  "session_id": "sess_8a7b6c5d4e3f2a1b0c9d8e7f"
}
```




```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 arrive through `hoody-proxy`: its source IP is private/local. The gateway has no service-level auth — authorization is owned by `hoody-proxy`. | 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. |




### SDK usage

```ts
const result = await client.agent.jobs.getJobResult({
  id: "job_5f3c1a7b9d2e4f6a8b0c1d2e",
});
```

### cURL

```bash
curl -X GET "https://api.hoody.ai/api/v1/agent/jobs/job_5f3c1a7b9d2e4f6a8b0c1d2e/result" \
  -H "Authorization: Bearer $HOODY_TOKEN"
```

---

## Cancel or delete a job

`DELETE /api/v1/agent/jobs/{id}`

Cancels a `pending` or `running` async job, or deletes a terminal (`succeeded` / `failed` / `canceled`) job's immutable historical record.

- A pending/running job transitions to `canceled` and its work is stopped at the source: a sessionless run (headless / long tool call) has its bounded context cancelled; a session dispatch / workflow turn is stopped via `session.cancel` (the active turn is cancelled, the session and its background tasks are spared).
- A terminal job's record is removed.
- Returns `{status:"ok", canceled:true}` on a cancel and `{status:"ok", deleted:true}` on a terminal-record delete; `404` when the job id is unknown.
- The cancel is authoritative — a late terminator never flips a canceled job back to `succeeded` / `failed`.


An in-flight `answer:assist` job is not independently cancellable: the daemon helper is bound to the question lifecycle with no per-assist cancel on the wire. `DELETE` returns `409 job_not_cancellable` rather than falsely reporting a cancel. Let it complete, or cancel it indirectly by answering the question / cancelling the session turn.


### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (§6.1). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override (§6.1). |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (§6.1; omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (§6.1): `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector (§6.1) — the query-string alias of the `X-Hoody-Realm` header. |

### Request body

This endpoint accepts no body.

### Response




```json
{
  "status": "ok",
  "canceled": true
}
```

```json
{
  "status": "ok",
  "deleted": 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 arrive through `hoody-proxy`: its source IP is private/local. The gateway has no service-level auth — authorization is owned by `hoody-proxy`. | 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": "job_not_cancellable",
  "message": "this job is not independently cancellable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `job_not_cancellable` | Job not cancellable | This async job is not independently cancellable: an `answer:assist` helper runs bound to the question lifecycle and has no per-job cancel path, so the gateway cannot stop it at source. | Let it complete (its suggestion arrives on the session stream / poll the job), or cancel it indirectly by answering the question or cancelling the session turn (`POST /sessions/{id}/cancel`). |




```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

```ts
// Cancel a still-active job
const result = await client.agent.jobs.deleteJob({
  id: "job_5f3c1a7b9d2e4f6a8b0c1d2e",
});

// result: { status: "ok", canceled: true }  — for pending/running
// result: { status: "ok", deleted:  true }  — for terminal
```

### cURL

```bash
curl -X DELETE "https://api.hoody.ai/api/v1/agent/jobs/job_5f3c1a7b9d2e4f6a8b0c1d2e" \
  -H "Authorization: Bearer $HOODY_TOKEN"
```