Agent: Jobs
Section titled “Agent: Jobs”Async jobs are gateway-minted records for work that does not complete within a single request, including dispatch turns, workflow runs, long tool calls, and todo message, run, and triage dispatches. Use these endpoints to poll a job’s status, fetch its terminal result, and either cancel a pending or running job or delete a finished record.
GET /api/v1/agent/jobs/{id}
Section titled “GET /api/v1/agent/jobs/{id}”Get an async job’s status. Returns the status of an async job, covering dispatch turns, workflow runs, and long tool calls. run_id is null during the brief dispatch window for workflow runs. A dispatch or workflow-run job carries the turn_id of the turn it started. Cancelling a dispatch job through the DELETE operation below cancels only that turn.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | The job id. |
Request
Section titled “Request”curl -X GET "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/jobs/{id}" \ -H "Authorization: Bearer $HOODY_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.jobs.get(id);Response
Section titled “Response”Returns the current job status.
{ "job_id": "01HXY5J7C2P3V4R5T6S7U8W9X0", "kind": "session.input", "session_id": "01HXY5J7C2P3V4R5T6S7U8W9Y1", "run_id": null, "status": "running", "turn_id": "01HXY5J7C2P3V4R5T6S7U8W9Z2", "created_at": "2025-01-15T10:30:00.123Z", "updated_at": "2025-01-15T10:30:05.456Z"}| Field | Type | Description |
|---|---|---|
job_id | string | Gateway-minted job id. |
kind | string | What minted the job. One of session.input, session.workflow, session.question_assist, headless.run, tool.run_gated, todos.message, todos.run, todos.triage. |
session_id | string | Owning session id. Omitted for a sessionless tool or headless job. |
run_id | string | Workflow run id. Null until correlated during the dispatch window. |
status | string | Job state. One of pending, running, succeeded, failed, canceled. |
turn_id | string | The turn this job dispatched. Present on dispatch and workflow-run jobs; omitted on a sessionless tool or headless job. |
error | string | Failure or cancel message when terminal with error. Omitted otherwise. |
result | object | Terminal result payload when present, for example an answer:assist suggestion. Dispatch jobs carry status only. |
created_at | string | RFC3339 creation time. |
updated_at | string | RFC3339 last-transition time. |
The request was malformed or carried invalid parameters, or a per-request realm header was supplied to a route that has no realm dimension.
{ "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 or 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. |
Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only.
{ "code": "forbidden", "message": "request must arrive through the Hoody proxy"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
forbidden | Forbidden (Source IP Guard) | The request did not come through the program’s URL. Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
The job id is unknown.
{ "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. |
The per-client request rate limit was exceeded; the gateway throttled the request before dispatch.
{ "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. |
An unexpected error occurred while handling the request.
{ "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. |
GET /api/v1/agent/jobs/{id}/result
Section titled “GET /api/v1/agent/jobs/{id}/result”Get an async job’s result. Returns the result of a completed job, or the running status for a job that is still in flight. Dispatch jobs are observed on the session stream, and the result endpoint returns terminal status only.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | The job id. |
Request
Section titled “Request”curl -X GET "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/jobs/{id}/result" \ -H "Authorization: Bearer $HOODY_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.jobs.getResult(id);Response
Section titled “Response”For a terminal job, the status, result, and error are returned together. For a pending or running job, only the status and session_id are returned. Read status first to select which shape you got.
{ "status": "succeeded", "result": { "answer": "The capital of France is Paris." }, "error": ""}| Field | Type | Description |
|---|---|---|
status | string | Job state. One of pending, running, succeeded, failed, canceled. Read this first to select which body shape you got. |
result | object | The terminal payload, present on every terminal body and null when the job produced none. A dispatch job always returns null here even on success. Absent on a pending or running body. |
error | string | The failure or cancel message, present on every terminal body and empty on success. Absent on a pending or running body. |
session_id | string | Owning session id. Surfaced on the pending or running body so a caller can go watch the stream; absent from the terminal body. |
The request was malformed or carried invalid parameters, or a per-request realm header was supplied to a route that has no realm dimension.
{ "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 or 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. |
Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only.
{ "code": "forbidden", "message": "request must arrive through the Hoody proxy"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
forbidden | Forbidden (Source IP Guard) | The request did not come through the program’s URL. Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
The job id is unknown.
{ "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. |
The per-client request rate limit was exceeded; the gateway throttled the request before dispatch.
{ "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. |
An unexpected error occurred while handling the request.
{ "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. |
DELETE /api/v1/agent/jobs/{id}
Section titled “DELETE /api/v1/agent/jobs/{id}”Cancel a pending or running job, or delete a finished record. Cancels a pending or running async job, or deletes a terminal (succeeded, failed, or canceled) job’s historical record. A pending or running job transitions to canceled and its work is stopped at the source: a sessionless run (headless or long tool call) has its bounded context cancelled, and a session dispatch or workflow turn is stopped by cancelling the session’s active turn (the session and its background tasks are spared). A terminal job’s record is removed. The cancel is authoritative, so a late terminator never flips a canceled job back to succeeded or failed.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | The job id. |
Request
Section titled “Request”curl -X DELETE "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/jobs/{id}" \ -H "Authorization: Bearer $HOODY_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.jobs.delete(id);Response
Section titled “Response”For a cancel, canceled is present and deleted is absent. For a record delete, deleted is present and canceled is absent. Read them for truthiness; do not test either against false.
{ "status": "ok", "canceled": true}| Field | Type | Description |
|---|---|---|
status | string | Always ok on success. |
canceled | boolean | Present and true when a pending or running job was transitioned to canceled. Absent on a record delete. |
deleted | boolean | Present and true when a terminal job’s historical record was removed. Absent on a cancel. |
The request was malformed or carried invalid parameters, or a per-request realm header was supplied to a route that has no realm dimension.
{ "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 or 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. |
Refused by the Source IP Guard: Hoody Kit programs are reached through their URLs only.
{ "code": "forbidden", "message": "request must arrive through the Hoody proxy"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
forbidden | Forbidden (Source IP Guard) | The request did not come through the program’s URL. Hoody Kit programs are reached through their URLs only. | Call the agent through its URL, for example with hoody agent …. |
The job id is unknown.
{ "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. |
The job is not independently cancellable. The daemon helper is bound to a question lifecycle that has no per-job cancel path, so the gateway cannot stop it at source.
{ "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 or poll the job), or cancel it indirectly by answering the question or cancelling the session turn (POST /sessions/{id}/cancel). |
The per-client request rate limit was exceeded; the gateway throttled the request before dispatch.
{ "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. |
An unexpected error occurred while handling the request.
{ "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. |