Open source / Rust / MIT Field guide / indexed
Field guide / Agents APIReviewable source / main

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 classCredentialScoping
publicNo 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

NameTypeRequirementDescription
traceparentstringOptionalOptional 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

StatusDescriptionBody
200OKValue

200 response body

Structure: Value.

NameTypeRequirementDescription
public_keyJSON valueRequiredValue of public_key returned in the response body.
protocol_versionJSON valueRequiredValue 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 classCredentialScoping
publicNo 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

NameTypeRequirementDescription
traceparentstringOptionalOptional 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

StatusDescriptionBody
200OKValue

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 classCredentialScoping
publicNo 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

NameTypeRequirementDescription
Content-TypestringRequiredRequired by the resolved Axum Json<T> request extractor; send application/json.
x-ryuki-protocol-versionintegerRequiredRequired CP↔agent wire-schema version. The extractor rejects absent, duplicate, malformed, or unsupported values.
traceparentstringOptionalOptional 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.

NameTypeRequirementDescription
enrollment_challenge_idstring (uuid)RequiredValue of enrollment_challenge_id in the JSON request body.
enrollment_challengestringRequiredValue of enrollment_challenge in the JSON request body.
agent_idstringRequiredValue of agent_id in the JSON request body.
platformstringRequiredValue of platform in the JSON request body.
capabilitiesobject (Capabilities)RequiredValue of capabilities in the JSON request body.
public_keystringRequiredValue of public_key in the JSON request body.
enrollment_proofstringRequiredValue of enrollment_proof in the JSON request body.

Response

StatusDescriptionBody
200OKValue

For 200, the known response body type is Value. Its field schema is unavailable, so no JSON shape is inferred.

200 response headers

NameTypeRequirementDescription
Cache-ControlstringRequiredThe 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 classCredentialScoping
agentAn 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

NameTypeRequirementDescription
agent_idstringRequiredIdentifier of the target resource in the request path.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
AuthorizationstringRequiredRequired agent credential: Bearer rya_...; this route bypasses human-session authentication and validates the agent token in the handler.
Content-TypestringRequiredRequired by the resolved Axum Json<T> request extractor; send application/json.
x-ryuki-protocol-versionintegerRequiredRequired CP↔agent wire-schema version. The extractor rejects absent, duplicate, malformed, or unsupported values.
traceparentstringOptionalOptional 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.

NameTypeRequirementDescription
running_job_idstring (uuid)OptionalRunning job whose lease should be renewed. Omit together with every other lease field for an idle heartbeat.
attempt_idstring (uuid)OptionalExact lease attempt identifier issued with running_job_id.
lease_generationintegerOptionalExact lease generation issued by the control plane.
fencing_tokenstringOptionalExact opaque fencing token issued for this attempt. Partial or stale four-field fences are rejected.

Response

StatusDescriptionBody
200OKAgentHeartbeatResponse

200 response body

Structure: AgentHeartbeatResponse.

NameTypeRequirementDescription
agent_idstringRequiredIdentifier of the authenticated enrolled agent.
last_seen_atstring (date-time)RequiredControl-plane timestamp recorded for this heartbeat.
lease_deadlinestring (date-time)OptionalRenewed 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 classCredentialScoping
agentAn 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

NameTypeRequirementDescription
agent_idstringRequiredIdentifier of the target resource in the request path.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
AuthorizationstringRequiredRequired agent credential: Bearer rya_...; this route bypasses human-session authentication and validates the agent token in the handler.
x-ryuki-protocol-versionintegerRequiredRequired CP↔agent wire-schema version. The extractor rejects absent, duplicate, malformed, or unsupported values.
traceparentstringOptionalOptional 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

StatusDescriptionBody
200OKValue
204No ContentNo 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 classCredentialScoping
agentAn 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

NameTypeRequirementDescription
agent_idstringRequiredIdentifier of the target resource in the request path.
job_idstringRequiredIdentifier of the target resource in the request path.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
AuthorizationstringRequiredRequired agent credential: Bearer rya_...; this route bypasses human-session authentication and validates the agent token in the handler.
Content-TypestringRequiredRequired by the resolved Axum Json<T> request extractor; send application/json.
x-ryuki-protocol-versionintegerRequiredRequired CP↔agent wire-schema version. The extractor rejects absent, duplicate, malformed, or unsupported values.
traceparentstringOptionalOptional 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.

NameTypeRequirementDescription
attempt_idstring (uuid)RequiredValue of attempt_id in the JSON request body.
fencing_tokenstringRequiredValue of fencing_token in the JSON request body.

Response

StatusDescriptionBody
200OKValue

200 response body

Structure: Value.

NameTypeRequirementDescription
job_idJSON valueRequiredValue of job_id returned in the response body.
statusstringRequiredCurrent 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 classCredentialScoping
agentAn 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

NameTypeRequirementDescription
agent_idstringRequiredIdentifier of the target resource in the request path.
job_idstringRequiredIdentifier of the target resource in the request path.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
AuthorizationstringRequiredRequired agent credential: Bearer rya_...; this route bypasses human-session authentication and validates the agent token in the handler.
Content-TypestringRequiredRequired by the resolved Axum Json<T> request extractor; send application/json.
x-ryuki-protocol-versionintegerRequiredRequired CP↔agent wire-schema version. The extractor rejects absent, duplicate, malformed, or unsupported values.
traceparentstringOptionalOptional 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.

NameTypeRequirementDescription
job_resultobject (JobResult)RequiredValue of job_result in the JSON request body.
evidencearray<integer>OptionalRaw 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_jsonJSON valueOptionalOptional structured evidence parsed from the evidence bytes. Stored as JSONB for query convenience; never trusted for authz.

Response

StatusDescriptionBody
200OKserde_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'
Last updated 2026-07-16 · Generated from the API route registrations.