Agents API
Routes for Agents.
7 routes
Response metadata: x-api-version, x-request-id, and traceresponse apply to normal routed responses and are omitted from the per-operation header tables below.
GET/api/agents/cp-public-key
public accessno bearer auth required
Return the CP's Ed25519 public key as base64.
Auth posture
Unauthenticated — intentionally. A public key is not a secret; any agent (or observer) may fetch it. Agents use this to pin the CP public key for verifying [VerifiedLiveContext] grants. This endpoint is mounted via agent_routes(), which sits OUTSIDE the human auth_middleware layer in main.rs, so no session or agent-token is required.
Returns 503 if the CP signing key was not initialised at startup (e.g. the key file was unreadable and the server continued in degraded mode).
Permissions
| Access class | Credential | Scoping |
|---|---|---|
public | No user or agent bearer token is required. Operation-specific proof, when present, is documented below. | No authenticated-principal scope is applied to this operation. |
HTTP request
GET https://<your-host>/api/agents/cp-public-key
Path parameters
This operation has no path parameters.
Query parameters
This operation has no query parameters.
Request headers
| Name | Type | Requirement | Description |
|---|---|---|---|
traceparent | string | Optional | Optional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation. |
Request body
This operation does not accept a request body.
Response
| Status | Description | Body |
|---|---|---|
200 | OK | Value |
200 response body
Structure: Value.
| Name | Type | Requirement | Description |
|---|---|---|---|
public_key | JSON value | Required | Value of public_key returned in the response body. |
protocol_version | JSON value | Required | Value of protocol_version returned in the response body. |
Errors
JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.
Examples
Request
curl --silent --show-error --globoff \
--request GET \
'https://<your-host>/api/agents/cp-public-key'
Schematic response body
Illustrative shape generated from the extracted field types, not a recorded live response. Values are placeholders; null marks a field whose type could not be resolved.
Success status: 200
{
"public_key": null,
"protocol_version": null
}
GET/api/agents/openapi.json
public accessno bearer auth required
Thin handler wrapping [openapi_document] for GET /api/agents/openapi.json.
Permissions
| Access class | Credential | Scoping |
|---|---|---|
public | No user or agent bearer token is required. Operation-specific proof, when present, is documented below. | No authenticated-principal scope is applied to this operation. |
HTTP request
GET https://<your-host>/api/agents/openapi.json
Path parameters
This operation has no path parameters.
Query parameters
This operation has no query parameters.
Request headers
| Name | Type | Requirement | Description |
|---|---|---|---|
traceparent | string | Optional | Optional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation. |
Request body
This operation does not accept a request body.
Response
| Status | Description | Body |
|---|---|---|
200 | OK | Value |
For 200, the known response body type is Value. Its field schema is unavailable, so no JSON shape is inferred.
Errors
JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.
Examples
Request
curl --silent --show-error --globoff \
--request GET \
'https://<your-host>/api/agents/openapi.json'
POST/api/agents/register
public accessno bearer auth required
Enrolls a new agent in 'pending' status.
Generates a bearer token, stores its SHA-256 hash, and returns the plaintext token ONCE. A pending agent cannot poll for jobs until an admin approves it.
Permissions
| Access class | Credential | Scoping |
|---|---|---|
public | No user or agent bearer token is required. Operation-specific proof, when present, is documented below. | No authenticated-principal scope is applied to this operation. |
HTTP request
POST https://<your-host>/api/agents/register
Path parameters
This operation has no path parameters.
Query parameters
This operation has no query parameters.
Request headers
| Name | Type | Requirement | Description |
|---|---|---|---|
Content-Type | string | Required | Required by the resolved Axum Json<T> request extractor; send application/json. |
x-ryuki-protocol-version | integer | Required | Required CP↔agent wire-schema version. The extractor rejects absent, duplicate, malformed, or unsupported values. |
traceparent | string | Optional | Optional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation. |
Request body
JSON structure: RegisterBody.
| Name | Type | Requirement | Description |
|---|---|---|---|
enrollment_challenge_id | string (uuid) | Required | Value of enrollment_challenge_id in the JSON request body. |
enrollment_challenge | string | Required | Value of enrollment_challenge in the JSON request body. |
agent_id | string | Required | Value of agent_id in the JSON request body. |
platform | string | Required | Value of platform in the JSON request body. |
capabilities | object (Capabilities) | Required | Value of capabilities in the JSON request body. |
public_key | string | Required | Value of public_key in the JSON request body. |
enrollment_proof | string | Required | Value of enrollment_proof in the JSON request body. |
Response
| Status | Description | Body |
|---|---|---|
200 | OK | Value |
For 200, the known response body type is Value. Its field schema is unavailable, so no JSON shape is inferred.
200 response headers
| Name | Type | Requirement | Description |
|---|---|---|---|
Cache-Control | string | Required | The handler directly marks this response no-store, preventing persistence or idempotency replay of the returned value. |
Errors
JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.
Examples
Request
curl --silent --show-error --globoff \
--request POST \
--header 'Content-Type: application/json' \
--header 'x-ryuki-protocol-version: 2' \
--data '{"enrollment_challenge_id":"<uuid>","enrollment_challenge":"<string>","agent_id":"<string>","platform":"<string>","capabilities":{},"public_key":"<string>","enrollment_proof":"<string>"}' \
'https://<your-host>/api/agents/register'
POST/api/agents/{agent_id}/heartbeat
agent access
Heartbeat.
Permissions
| Access class | Credential | Scoping |
|---|---|---|
agent | An enrolled agent bearer token beginning with rya_ is required. | The credential represents the enrolled agent; request-path identifiers must address that agent's operation. |
HTTP request
POST https://<your-host>/api/agents/{agent_id}/heartbeat
Path parameters
| Name | Type | Requirement | Description |
|---|---|---|---|
agent_id | string | Required | Identifier of the target resource in the request path. |
Query parameters
This operation has no query parameters.
Request headers
| Name | Type | Requirement | Description |
|---|---|---|---|
Authorization | string | Required | Required agent credential: Bearer rya_...; this route bypasses human-session authentication and validates the agent token in the handler. |
Content-Type | string | Required | Required by the resolved Axum Json<T> request extractor; send application/json. |
x-ryuki-protocol-version | integer | Required | Required CP↔agent wire-schema version. The extractor rejects absent, duplicate, malformed, or unsupported values. |
traceparent | string | Optional | Optional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation. |
Request body
JSON structure: AgentHeartbeat.
| Name | Type | Requirement | Description |
|---|---|---|---|
running_job_id | string (uuid) | Optional | Running job whose lease should be renewed. Omit together with every other lease field for an idle heartbeat. |
attempt_id | string (uuid) | Optional | Exact lease attempt identifier issued with running_job_id. |
lease_generation | integer | Optional | Exact lease generation issued by the control plane. |
fencing_token | string | Optional | Exact opaque fencing token issued for this attempt. Partial or stale four-field fences are rejected. |
Response
| Status | Description | Body |
|---|---|---|
200 | OK | AgentHeartbeatResponse |
200 response body
Structure: AgentHeartbeatResponse.
| Name | Type | Requirement | Description |
|---|---|---|---|
agent_id | string | Required | Identifier of the authenticated enrolled agent. |
last_seen_at | string (date-time) | Required | Control-plane timestamp recorded for this heartbeat. |
lease_deadline | string (date-time) | Optional | Renewed database-clock lease deadline; present only for a valid running job fence and omitted for an idle heartbeat. |
Errors
JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.
Examples
Request
curl --silent --show-error --globoff \
--request POST \
--header 'Authorization: Bearer rya_<agent-token>' \
--header 'Content-Type: application/json' \
--header 'x-ryuki-protocol-version: 2' \
--data '{}' \
'https://<your-host>/api/agents/<agent_id>/heartbeat'
Schematic response body
Illustrative shape generated from the extracted field types, not a recorded live response. Values are placeholders; null marks a field whose type could not be resolved.
Success status: 200
{
"agent_id": "<string>",
"last_seen_at": {},
"lease_deadline": {}
}
GET/api/agents/{agent_id}/jobs
agent access
Poll job.
Permissions
| Access class | Credential | Scoping |
|---|---|---|
agent | An enrolled agent bearer token beginning with rya_ is required. | The credential represents the enrolled agent; request-path identifiers must address that agent's operation. |
HTTP request
GET https://<your-host>/api/agents/{agent_id}/jobs
Path parameters
| Name | Type | Requirement | Description |
|---|---|---|---|
agent_id | string | Required | Identifier of the target resource in the request path. |
Query parameters
This operation has no query parameters.
Request headers
| Name | Type | Requirement | Description |
|---|---|---|---|
Authorization | string | Required | Required agent credential: Bearer rya_...; this route bypasses human-session authentication and validates the agent token in the handler. |
x-ryuki-protocol-version | integer | Required | Required CP↔agent wire-schema version. The extractor rejects absent, duplicate, malformed, or unsupported values. |
traceparent | string | Optional | Optional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation. |
Request body
This operation does not accept a request body.
Response
| Status | Description | Body |
|---|---|---|
200 | OK | Value |
204 | No Content | No response body |
For 200, the known response body type is Value. Its field schema is unavailable, so no JSON shape is inferred.
Errors
JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.
Examples
Request
curl --silent --show-error --globoff \
--request GET \
--header 'Authorization: Bearer rya_<agent-token>' \
--header 'x-ryuki-protocol-version: 2' \
'https://<your-host>/api/agents/<agent_id>/jobs'
POST/api/agents/{agent_id}/jobs/{job_id}/ack
agent access
Transitions Leased → Running.
The caller must supply the fencing_token and attempt_id that match the current lease. A mismatch returns 409.
Permissions
| Access class | Credential | Scoping |
|---|---|---|
agent | An enrolled agent bearer token beginning with rya_ is required. | The credential represents the enrolled agent; request-path identifiers must address that agent's operation. |
HTTP request
POST https://<your-host>/api/agents/{agent_id}/jobs/{job_id}/ack
Path parameters
| Name | Type | Requirement | Description |
|---|---|---|---|
agent_id | string | Required | Identifier of the target resource in the request path. |
job_id | string | Required | Identifier of the target resource in the request path. |
Query parameters
This operation has no query parameters.
Request headers
| Name | Type | Requirement | Description |
|---|---|---|---|
Authorization | string | Required | Required agent credential: Bearer rya_...; this route bypasses human-session authentication and validates the agent token in the handler. |
Content-Type | string | Required | Required by the resolved Axum Json<T> request extractor; send application/json. |
x-ryuki-protocol-version | integer | Required | Required CP↔agent wire-schema version. The extractor rejects absent, duplicate, malformed, or unsupported values. |
traceparent | string | Optional | Optional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation. |
Request body
JSON structure: AckBody.
| Name | Type | Requirement | Description |
|---|---|---|---|
attempt_id | string (uuid) | Required | Value of attempt_id in the JSON request body. |
fencing_token | string | Required | Value of fencing_token in the JSON request body. |
Response
| Status | Description | Body |
|---|---|---|
200 | OK | Value |
200 response body
Structure: Value.
| Name | Type | Requirement | Description |
|---|---|---|---|
job_id | JSON value | Required | Value of job_id returned in the response body. |
status | string | Required | Current operation or resource status. |
Errors
JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.
Examples
Request
curl --silent --show-error --globoff \
--request POST \
--header 'Authorization: Bearer rya_<agent-token>' \
--header 'Content-Type: application/json' \
--header 'x-ryuki-protocol-version: 2' \
--data '{"attempt_id":"<uuid>","fencing_token":"<string>"}' \
'https://<your-host>/api/agents/<agent_id>/jobs/<job_id>/ack'
Schematic response body
Illustrative shape generated from the extracted field types, not a recorded live response. Values are placeholders; null marks a field whose type could not be resolved.
Success status: 200
{
"job_id": null,
"status": "<string>"
}
POST/api/agents/{agent_id}/jobs/{job_id}/result
agent access
Verifies and records the signed JobResult from an agent.
The full 9-step verifier runs FAIL-CLOSED: every check that fails returns 4xx and mutates nothing. The terminal UPDATE is a single atomic conditional statement guarded on (id, attempt_id, lease_generation, status IN ('Leased','Running'), unexpired database-clock lease). A repeat POST with the same (job_id, attempt_id, result_id) returns idempotent 200.
Permissions
| Access class | Credential | Scoping |
|---|---|---|
agent | An enrolled agent bearer token beginning with rya_ is required. | The credential represents the enrolled agent; request-path identifiers must address that agent's operation. |
HTTP request
POST https://<your-host>/api/agents/{agent_id}/jobs/{job_id}/result
Path parameters
| Name | Type | Requirement | Description |
|---|---|---|---|
agent_id | string | Required | Identifier of the target resource in the request path. |
job_id | string | Required | Identifier of the target resource in the request path. |
Query parameters
This operation has no query parameters.
Request headers
| Name | Type | Requirement | Description |
|---|---|---|---|
Authorization | string | Required | Required agent credential: Bearer rya_...; this route bypasses human-session authentication and validates the agent token in the handler. |
Content-Type | string | Required | Required by the resolved Axum Json<T> request extractor; send application/json. |
x-ryuki-protocol-version | integer | Required | Required CP↔agent wire-schema version. The extractor rejects absent, duplicate, malformed, or unsupported values. |
traceparent | string | Optional | Optional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation. |
Request body
JSON structure: ResultBody.
| Name | Type | Requirement | Description |
|---|---|---|---|
job_result | object (JobResult) | Required | Value of job_result in the JSON request body. |
evidence | array<integer> | Optional | Raw evidence bytes (the payload whose SHA-256 is evidence_digest).
May be empty for modes that produce no evidence (e.g. OfflineDryRun
without a plan artifact), but the digest must still match. |
evidence_json | JSON value | Optional | Optional structured evidence parsed from the evidence bytes. Stored as JSONB for query convenience; never trusted for authz. |
Response
| Status | Description | Body |
|---|---|---|
200 | OK | serde_json::Value |
For 200, the known response body type is serde_json::Value. Its field schema is unavailable, so no JSON shape is inferred.
Errors
JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.
Examples
Request
curl --silent --show-error --globoff \
--request POST \
--header 'Authorization: Bearer rya_<agent-token>' \
--header 'Content-Type: application/json' \
--header 'x-ryuki-protocol-version: 2' \
--data '{"job_result":{}}' \
'https://<your-host>/api/agents/<agent_id>/jobs/<job_id>/result'