Skip to content
Hoody.com

A session exposes two independent, renewable lease resources, both in-memory and both restart-resilient only insofar as the gateway still recognises them.

The approver lease grants the exclusive right to answer a session’s approval gates. Every decision on an “always” session whose lease was minted (/confirm, a WS confirm frame, or a gated tool-run confirmation) must present the current capability. The capability is returned once, on acquire. A capability minted for another session, a fenced generation, or no capability at all is rejected; an expired capability also fails closed, the requirement persists until someone re-acquires.

The attachment lease keeps a live session, and especially a parked approval gate, alive against the 5-minute idle reaper, so a client that dispatched a turn and disconnected can reconnect and still answer. It is a separate resource with its own expiry, and renewing it does not renew the approver lease.

When a lease expires without renewal the consequence is fail-closed in both cases, but the meaning differs:

  • An expired approver lease keeps the requirement active. No holder has the right to answer; the gate stays parked until some caller acquires a new capability. Expiry never lets anyone answer.
  • An expired attachment lease no longer suppresses the idle reaper. The session, and any gate parked on it, may be torn down at the next reaper sweep. Re-acquire to resume protection.

Leases are in-memory on the daemon. After a daemon restart GET /sessions/{id}/approval reports held:false, and a client must acquire again. Holder strings are never compared; only capabilities authorise.

All endpoints below live on the agent gateway of the bound container. The base URL takes the form https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com.

The approver lease is the only thing that lets you answer a parked gate on an “always” session. Acquire, renew, and release act on the session’s single approver lease.

POST /api/v1/agent/sessions/{id}/approver-lease

Section titled “POST /api/v1/agent/sessions/{id}/approver-lease”

Acquire the right to answer this session’s gates.

The response carries the capability exactly once. The daemon verifies the capability at every decision consumption: /confirm, a WS confirm frame, and the confirmed re-issue of a gated tool run. While a gate is parked and a lease change happens, the daemon broadcasts event.decision_requirements { gate_id, generation, lease_required } so peers can re-arm.

NameInTypeRequiredDescription
idpathstringYesSession identifier.
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (the in-query alias of X-Hoody-Realm, read only when the header is absent).
FieldTypeRequiredDescription
holderstringYesOpaque per-caller id (1 to 64 printable ASCII, no spaces) that identifies this client as the holder (reported as holder on the event.gate_resolved stream event). Never a credential; an empty holder is 400.
ttl_msintegerNoRequested lifetime in milliseconds (the daemon clamps to its bounds).
replacebooleanNoDocumentation only. A live lease is taken over ONLY by presenting its current capability as proof; replace:true without the proof is still 409 approver_lease_held. After expiry or release an acquire needs no proof.
leasestringNoThe capability, used as proof an acquire presents to take over a live lease (alternative to the X-Hoody-Approver-Lease header).
Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/sessions/{id}/approver-lease" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"holder": "ops-console-7a3"}'
{
"lease": "alc_01HF3ZP7MX8HQ6VYJK5R2N9C4D",
"held": true,
"holder": "ops-console-7a3",
"generation": 1,
"expires_at": "2025-03-19T14:22:08.314Z",
"epoch": "ep_01HF3ZP5T7K9M2X8V4N6YQB1RA"
}
FieldTypeDescription
leasestringThe capability to present as X-Hoody-Approver-Lease on /confirm (acquire only).
heldbooleanWhether a lease is currently held.
holderstringThe holder identity (this gateway connection, plus the optional body holder).
generationintegerLease generation; a decision echoes it, and a replacement bumps it (fencing the previous holder).
expires_atstringRFC3339 expiry; renew before it.
epochstringThe daemon execution epoch the lease is bound to; a restart starts a new one and every lease must be re-acquired.

PATCH /api/v1/agent/sessions/{id}/approver-lease

Section titled “PATCH /api/v1/agent/sessions/{id}/approver-lease”

Renew the approver lease.

Extends the presented lease (X-Hoody-Approver-Lease header or body.lease). A capability that does not verify returns 409 approver_lease_invalid; a lease that has already lapsed returns 410 approver_lease_expired (re-acquire).

NameInTypeRequiredDescription
idpathstringYesSession identifier.
X-Hoody-Approver-LeaseheaderstringNoThe approver-lease capability returned by POST /sessions/{id}/approver-lease. On renew/release it names the lease to act on.
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container.
X-Hoody-RealmheaderstringNoPer-request realm selector.
realmquerystringNoPer-request realm selector (in-query alias).
FieldTypeRequiredDescription
ttl_msintegerNoRequested lifetime in milliseconds (the daemon clamps to its bounds).
leasestringNoThe capability (alternative to the X-Hoody-Approver-Lease header).
Terminal window
curl -X PATCH "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/sessions/{id}/approver-lease" \
-H "Authorization: Bearer <token>" \
-H "X-Hoody-Approver-Lease: alc_01HF3ZP7MX8HQ6VYJK5R2N9C4D" \
-H "Content-Type: application/json" \
-d '{"ttl_ms": 900000}'
{
"held": true,
"holder": "ops-console-7a3",
"generation": 1,
"expires_at": "2025-03-19T14:37:08.314Z",
"epoch": "ep_01HF3ZP5T7K9M2X8V4N6YQB1RA"
}
FieldTypeDescription
leasestringThe capability. Present ONLY on acquire and never shown again; store it.
heldbooleanWhether a lease is currently held.
holderstringThe holder identity.
generationintegerLease generation; a decision echoes it, and a replacement bumps it (fencing the previous holder).
expires_atstringRFC3339 expiry; renew before it.
epochstringThe daemon execution epoch.

DELETE /api/v1/agent/sessions/{id}/approver-lease

Section titled “DELETE /api/v1/agent/sessions/{id}/approver-lease”

Release the approver lease.

Releases the presented lease (X-Hoody-Approver-Lease). A capability that does not verify returns 409 approver_lease_invalid; a lease that has already lapsed returns 410 approver_lease_expired.

NameInTypeRequiredDescription
idpathstringYesSession identifier.
X-Hoody-Approver-LeaseheaderstringNoThe approver-lease capability. On release it names the lease to act on.
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container.
X-Hoody-RealmheaderstringNoPer-request realm selector.
realmquerystringNoPer-request realm selector (in-query alias).

This endpoint accepts no request body.

Terminal window
curl -X DELETE "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/sessions/{id}/approver-lease" \
-H "Authorization: Bearer <token>" \
-H "X-Hoody-Approver-Lease: alc_01HF3ZP7MX8HQ6VYJK5R2N9C4D"
{
"held": false,
"holder": "ops-console-7a3",
"generation": 1,
"expires_at": "2025-03-19T14:22:08.314Z",
"epoch": "ep_01HF3ZP5T7K9M2X8V4N6YQB1RA"
}
FieldTypeDescription
leasestringThe capability. Present ONLY on acquire and never shown again; store it.
heldbooleanWhether a lease is currently held.
holderstringThe holder identity.
generationintegerLease generation.
expires_atstringRFC3339 expiry.
epochstringThe daemon execution epoch.

The attachment lease keeps a live session, and especially a parked gate, alive across client disconnects. The acquire is decided atomically against the reaper: a session whose close is already committed answers 404. The attachment lease only keeps the session alive; the approver lease is a separate resource with its own expiry, so an expired approver lease still fails closed even while an attachment lease is live.

POST /api/v1/agent/sessions/{id}/attachments

Section titled “POST /api/v1/agent/sessions/{id}/attachments”

Hold a live session (and its parked gate) alive.

Returns { lease_id, expires_at }. Renew with PATCH before expiry, release with DELETE. Default lifetime is 15 minutes, capped at 60 minutes.

NameInTypeRequiredDescription
idpathstringYesSession identifier.
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container.
X-Hoody-RealmheaderstringNoPer-request realm selector.
realmquerystringNoPer-request realm selector (in-query alias).
FieldTypeRequiredDescription
ttl_msintegerNoRequested lifetime in milliseconds (default 15m, capped at 60m).
Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/sessions/{id}/attachments" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"ttl_ms": 900000}'
{
"lease_id": "atl_01HF3ZQ4MX9JQ7WZK6S3OAE5E2",
"expires_at": "2025-03-19T14:37:08.314Z"
}
FieldTypeDescription
lease_idstringThe lease id (send it on PATCH/DELETE to renew/release).
expires_atstringRFC3339 expiry; renew before it or the session may be reaped once idle.

PATCH /api/v1/agent/sessions/{id}/attachments/{lease_id}

Section titled “PATCH /api/v1/agent/sessions/{id}/attachments/{lease_id}”

Renew an attachment lease.

Extends the lease’s expiry, decided atomically against the reaper’s close (404 once closing). A lapsed lease is refused with 410 attachment_expired (acquire a new one). 404 is also returned when the lease is unknown, not this session’s, or not this owner’s. Renewals are re-authorized against the session’s current owner and realm, so a lease never outlives a changed pin or a credential switch.

NameInTypeRequiredDescription
idpathstringYesSession identifier.
lease_idpathstringYesAttachment lease identifier.
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container.
X-Hoody-RealmheaderstringNoPer-request realm selector.
realmquerystringNoPer-request realm selector (in-query alias).
FieldTypeRequiredDescription
ttl_msintegerNoNew lifetime in milliseconds from now (default 15m, capped at 60m).
Terminal window
curl -X PATCH "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/sessions/{id}/attachments/{lease_id}" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"ttl_ms": 900000}'
{
"lease_id": "atl_01HF3ZQ4MX9JQ7WZK6S3OAE5E2",
"expires_at": "2025-03-19T14:52:08.314Z"
}
FieldTypeDescription
lease_idstringThe lease id.
expires_atstringRFC3339 expiry; renew before it or the session may be reaped once idle.

DELETE /api/v1/agent/sessions/{id}/attachments/{lease_id}

Section titled “DELETE /api/v1/agent/sessions/{id}/attachments/{lease_id}”

Release an attachment lease.

Drops the lease; the session resumes ordinary idle-reap behaviour. 404 is returned when the lease is unknown, not this session’s, or not this owner’s.

NameInTypeRequiredDescription
idpathstringYesSession identifier.
lease_idpathstringYesAttachment lease identifier.
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container.
X-Hoody-RealmheaderstringNoPer-request realm selector.
realmquerystringNoPer-request realm selector (in-query alias).

This endpoint accepts no request body.

Terminal window
curl -X DELETE "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/sessions/{id}/attachments/{lease_id}" \
-H "Authorization: Bearer <token>"
{
"status": "ok",
"released": true
}
FieldTypeDescription
statusstring"ok" on success.
releasedbooleanAlways true on a 200.