Skip to content
Hoody.com

A gate parks a turn until a human answers it. There are two kinds: a confirm gate asks for an approve or deny decision on a tool call or directory access, and a question gate asks for a free-form or structured answer. This page covers the four surfaces that surround a gate: listing and answering parked gates, the session’s approval policy (mode, lock, per-tool rules, lease, and YOLO), and the tool-call rules that determine which calls actually park. Answering a confirm gate on an always policy also requires the approver lease; that surface is documented on the leases page.

List every gate this gateway can answer that is waiting for a human, across the sessions GET /sessions shows. Each entry is one live session’s confirm or question, or, on a helper-gates session, one helper’s gate (a background task’s pending gate is its helper’s gate, with task_id). Order is oldest parked first, then session_id, then generation. Pagination is 1-based; an omitted or zero limit, or one above 100, is served as 100, and meta.limit echoes the value used. meta.omitted counts gates that changed or resolved during the read.

Answer one with POST /sessions/{session_id}/confirm or /answer, sending its gate_id. A gate is only listed while this gateway holds its session live; a session held by another client (the TUI) is not listed until it is attached here.

NameInTypeRequiredDescription
include_systemquerybooleanNoWhen true, also list the gates of daemon-owned system/resident sessions (as sessions.list does).
realmquerystringNoThe realm to list: “global” (gates not tied to a realm), a 24-hex realm id, or “all” for every realm this login serves. Also accepted as the X-Hoody-Realm header, except “all”. Omitted, the agent’s current realm.
pagequeryintegerNo1-based page number for pagination.
limitqueryintegerNoMaximum items per page, at most 100. A value of 0, an omitted value, or a value above 100 is served as 100, and meta.limit echoes the value used.
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against.
X-Hoody-RealmheaderstringNoPer-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). On a session route it names the realm the session is looked up in: a session in another realm, or in a realm this login does not serve, is 404 not_found. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.

The pending gates.

{
"items": [
{
"agent": "builder",
"gate": {
"gate_cause": "rules",
"gate_id": 3,
"generation": 0,
"human_only": false,
"lease_required": false,
"params": {
"command": "git push origin main"
},
"risk": "unknown",
"rules": {
"outcome": "ask",
"rule_ids": [
"ask-git"
]
},
"status": "parked",
"tool_name": "bash",
"type": "confirm"
},
"gate_id": "gate-9f2c4e1ab07d3355-3",
"generation": 3,
"kind": "confirm",
"parked_at": "2026-09-28T10:15:04.512Z",
"realm": "global",
"rules": {
"outcome": "ask",
"rule_ids": [
"ask-git"
]
},
"session_id": "9f2c4e1a-5b7d-4c3e-8a21-6d0f3b9e7c55"
}
],
"meta": {
"limit": 100,
"omitted": 0,
"page": 1,
"total": 1
}
}
FieldTypeDescription
itemsarrayThe page of items, built by the gateway.
items[].session_idstringThe session the gate is parked on.
items[].realmstringThe session’s realm: "global" for a session not tied to a realm, else its 24-hex realm id. Pass it as X-Hoody-Realm (or ?realm=) when answering the gate.
items[].gate_idstringThe answerable gate id: send it as gate_id on POST /sessions/{session_id}/confirm (kind confirm) or /answer (kind question). Scoped to this gateway’s session incarnation.
items[].generationintegerThe gateway’s gate generation (optional on the answer; a mismatch is refused as stale_gate).
items[].kindstringWhat the gate asks for: confirm (approve or deny a tool call) or question (an answer).
items[].helper_idstringPresent on a helper’s gate: the spawn_agent helper that parked it.
items[].parent_tool_call_idstringPresent on a helper’s gate: the lead’s spawn_agent tool call that started the helper.
items[].task_idstringPresent on a background helper’s gate: its task id.
items[].agentstringThe session’s agent. Omitted when the session record names none.
items[].parked_atstringRFC3339 time this gateway parked the gate. A re-attach parks it again with a new gate_id and time.
items[].rulesobjectPresent when tool-call rules asked for the gate: {rule_ids, outcome}.
items[].gateobjectThe daemon’s redacted description of the gate, as GET /sessions/{id}/state shows it.
metaobjectPagination metadata.
meta.totalintegerEvery gate parked when the list was read, across all pages.
meta.pageintegerThe 1-based page served. Always present.
meta.limitintegerThe page size used, at most 100. Always present.
meta.omittedintegerGates in this page window that changed or resolved during the read.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
for await (const item of client.agent.gates.listIterator({ page: 1, limit: 100 })) {
console.log(item);
}

Returns the session’s effective approval policy: the mode (default or always), the monotonic lock, the revision, the waiver posture (yolo, auto_write, auto_dir_access, backend_auto_approving), the session permission rules, and the approver lease state. The response ETag is the revision; send it as If-Match on a change. Works for a live or persisted session.

The event.permission_rules frames pushed on the stream are snapshots of the same rule set. Each one states what the rules are at that moment and follows a successful durable write (a write whose commit fails rolls back and broadcasts nothing), so a client converges on the frame’s contents rather than on having asked for a change.

NameInTypeRequiredDescription
idpathstringYesThe session id.
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
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 or no-realm routes.
realmquerystringNoPer-request realm selector (the in:query alias of the X-Hoody-Realm header, read only when the header is absent).

The session’s approval policy. ETag = revision.

{
"mode": "default",
"locked": false,
"revision": 3,
"yolo": false,
"auto_write": false,
"auto_dir_access": false,
"backend_auto_approving": false,
"rules": [
{
"tool": "bash",
"decision": "allow"
}
],
"lease": {
"held": false,
"holder": null,
"generation": 0,
"expires_at": null,
"epoch": "ep-7f3a1c"
},
"epoch": "ep-7f3a1c",
"capabilities": {
"always": true,
"locked": true,
"lease": true
}
}
FieldTypeDescription
modestring"default" (automatic waivers may satisfy gates) or "always" (one explicit decision per side-effecting invocation). Sessionless headless runs, sessionless tool runs and management operations are outside any session’s policy.
lockedbooleanWhether the policy is frozen for the session’s lifetime (monotonic; never unlocked).
revisionintegerMonotonic policy revision, the ETag value.
yolobooleanWhether YOLO auto-approve is armed.
auto_writebooleanWhether automatic file-write permission is on (a CLI-default posture an HTTP attach may inherit); always false under "always".
auto_dir_accessbooleanWhether automatic directory access is on.
backend_auto_approvingbooleanWhether a delegated backend auto-approves its own tools.
rulesarraySession permission rules.
rules[].toolstringRule key (a tool name, or tool:action).
rules[].decisionstringallow or deny.
leaseobjectApprover lease state: {held, holder, generation, expires_at, epoch}. The capability itself is never shown here.
epochstringThe daemon execution epoch (an opaque id). Changes on restart; leases and parked gates do not survive it.
changedbooleanPUT only: whether the request changed anything.
capabilitiesobjectWhat this daemon supports: {always, locked, lease}.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
const policy = await client.agent.sessions.getApproval('{session_id}');

GET /api/v1/agent/sessions/{id}/rules/applies

Section titled “GET /api/v1/agent/sessions/{id}/rules/applies”

Returns the tool-call rules a live session checks for one agent’s calls, from the same selection the rules check itself runs. A rule without tools skips read-only tools, a rule with tools covers only those, and a rule with agents covers only those agents’ calls. agent defaults to the session’s own agent; name a helper’s or workflow step’s agent to see what its calls are checked against. With tool, the reply’s checked rules (applies_as: checked) are exactly the rules sent to Jev for that call; without it, every checked rule that covers the agent’s calls to some tool. Guidance and playbook rules are listed too, with applies_as: prompt. fail_closed_reason says when every covered call fails closed right now (trust_hold, jev_disabled, or jev_no_key).

A dormant session answers 404 not_found.

NameInTypeRequiredDescription
idpathstringYesThe session id.
agentquerystringNoAgent name to ask about (default: the session’s own agent).
toolquerystringNoTool name to ask about (default: any tool).
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 of the X-Hoody-Realm header).

The applying rules.

{
"agent": "builder",
"tool": "bash",
"read_only": false,
"active": true,
"count": 2,
"rules": [
{
"id": "ask-git",
"text": "Ask before running git push.",
"kind": "check_in",
"applies_as": "checked",
"tools": ["bash"],
"agents": [],
"source": "/etc/hoody/settings.json"
}
],
"prompt_off": false,
"prompt_bytes": 184,
"prompt_budget_bytes": 8192,
"prompt_over_budget": []
}
FieldTypeDescription
agentstringThe acting agent asked about: the agent query value, else the session’s own agent.
toolstringThe tool asked about. Omitted when no tool was named.
read_onlybooleanWhether the named tool is read-only. Omitted when no tool was named.
activebooleanWhether the session has rules that are checked at all (limit or check_in).
countintegerlen(rules): the rules that apply to the agent, checked and prompt together.
rulesarrayThe rules that apply to the agent, in settings order.
rules[].idstringThe rule id.
rules[].textstringThe rule in plain words.
rules[].kindstringlimit, check_in, guidance, or playbook.
rules[].applies_asstringOutput only, derived from kind. checked = Jev checks covered tool calls; prompt = its text is in the covered agents’ system prompt.
rules[].toolsarrayThe tools the rule is limited to; empty = every tool that is not read-only. Always empty for guidance and playbook rules.
rules[].agentsarrayThe agents whose calls the rule covers; empty = every agent.
rules[].sourcestringThe settings file that declared the rule.
prompt_offbooleanWhether prompt_blocks drops the team-rules block for this agent.
prompt_bytesintegerThe size in bytes of the rule lines the agent’s team-rules block carries. 0 when prompt_off is true.
prompt_budget_bytesintegerThe most rule-line bytes one agent’s team-rules block carries (8192).
prompt_over_budgetarrayThe guidance and playbook rules that cover the agent but did not fit prompt_budget_bytes.
fail_closed_reasonstringPresent when rules apply and none can be checked right now: trust_hold, jev_disabled, or jev_no_key.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
const rules = await client.agent.sessions.listApplicableRules('{session_id}', { agent: 'builder', tool: 'bash' });

Answers a parked ask-the-user question. Provide answer or text for a free-form reply, or answers (a map) for a structured multi-field question. gate_id and generation are echoes of the parked gate; a mismatch is 409 stale_gate. 409 no_pending_gate when nothing is parked; 409 gate_already_answered when an earlier request already won; 409 gate_type_mismatch when the parked gate is a confirm gate (use /confirm for those); 409 gate_cancelled when the turn was cancelled while the answer was in flight (do not retry this answer).

NameInTypeRequiredDescription
idpathstringYesThe session id.
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 of the X-Hoody-Realm header).
FieldTypeRequiredDescription
gate_idstringNoEcho of the parked gate id, as published on the frame that parked it. Valid only for the session in the path. Ids are unique per session incarnation, so an id from before a re-attach never matches.
generationintegerNoOptional echo of the parked gate generation. Restarts when the session is re-attached, so it is not an identity on its own.
answerstringNoFree-form answer text. When it is absent or blank, text is used in its place. It may be empty when text or answers carries the answer.
textstringNoAnswer text used when answer is absent or blank; ignored otherwise.
answersobjectNoStructured per-field answers for a multi-field question.
{
"gate_id": "gate-3f9a1c2b7d4e6f80-2",
"generation": 2,
"answer": "Yes, push to main."
}

Answered.

{
"status": "ok",
"resolved": {
"gate_id": "gate-3f9a1c2b7d4e6f80-2",
"outcome": "answered"
}
}
FieldTypeDescription
statusstring"ok" on success.
resolvedobjectThe daemon’s resolution of the gate, when it acknowledged within the wait.
replayedbooleanTrue when a retried decision naming the same gate got the original acknowledgement back. Nothing was forwarded a second time.
session_scope_appliedbooleanPresent when a session-wide grant could not be applied; see note.
notestringPresent alongside session_scope_applied: why the wider grant did not apply.
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.gates.answer('{session_id}', {
gate_id: 'gate-3f9a1c2b7d4e6f80-2',
generation: 2,
answer: 'Yes, push to main.',
});

POST /api/v1/agent/sessions/{id}/answer:assist

Section titled “POST /api/v1/agent/sessions/{id}/answer:assist”

Runs a one-shot helper-model call that proposes answers for the parked question. The real answer still travels via /answer; the daemon never answers itself. The suggestion arrives later as event.question_suggestion, with the job id from the 202 ack. 409 no_pending_gate when no question is parked; 409 assist_in_flight when another assist is already running for this session.

NameInTypeRequiredDescription
idpathstringYesThe session id.
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 of the X-Hoody-Realm header).
FieldTypeRequiredDescription
modestringNoSuggestion mode (default "suggest").
modelstringNoHelper model override; empty uses the configured helper.
genintegerNoGeneration counter to correlate the suggestion event (echoed as event.question_suggestion gen).
{
"mode": "suggest",
"gen": 1
}

Suggestion job dispatched. Fetch its result via GET /jobs/{id}/result.

{
"job_id": "job-9f2c4e1ab07d3355-7",
"session_id": "9f2c4e1a-5b7d-4c3e-8a21-6d0f3b9e7c55"
}
FieldTypeDescription
job_idstringGateway-minted job id for the helper call. GET /jobs/{id}/result returns the suggestion under result once the job is terminal; it is null while the job is still running.
session_idstringThe session whose parked question is being answered (echo of the path id).
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
const assist = await client.agent.gates.suggest('{session_id}', { mode: 'suggest', gen: 1 });
const jobId = assist.data.job_id;

Approves or denies a parked tool or directory confirmation. A 200 means the agent consumed this decision; nothing else is a 200. The required approved boolean is mandatory: a confirm without a boolean approved is rejected 400 approved_required and the gate stays parked. On a session that requires approval on every action (mode: "always"), gate_id and generation are required too, and once the session’s approver lease was minted, every decision also carries it in X-Hoody-Approver-Lease.

session_scope: true remembers the decision for the rest of the session (with approved: true the tool stops asking, with approved: false it is refused without asking). Offer allow-for-session only when the gate’s event.confirm_request carried offer_session_allow. Under a locked policy the wider grant is refused, but the one-shot decision still applies and the reply says so (session_scope_applied: false, note). trust_container: true accepts the gate’s exec_trust offer (also only on the gate’s offer).

NameInTypeRequiredDescription
idpathstringYesThe session id.
X-Hoody-Approver-LeaseheaderstringNoThe approver-lease capability returned by POST /sessions/{id}/approver-lease. Required on every decision on an "always" session whose lease was minted; the daemon verifies it at decision consumption.
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 of the X-Hoody-Realm header).
FieldTypeRequiredDescription
approvedbooleanYestrue to approve, false to deny. There is no default; a missing, null, or non-boolean value is rejected 400.
gate_idstringNoEcho of the parked gate id. Required on a session that requires approval on every action: a confirm without it is rejected 400.
generationintegerNoEcho of the parked gate generation. Optional on a default-policy session; required, and non-zero, on a session that requires approval on every action.
persist_dirsbooleanNoPersist an approved directory grant to settings.json (WS↔REST parity).
session_scopebooleanNoRemember this decision for the rest of the session. With approved: true the tool stops asking, with approved: false it is refused without asking. Offer allow-for-session only when the gate’s event.confirm_request carried offer_session_allow.
trust_containerbooleanNoWith approved: true, accept the gate’s exec_trust offer. Ignored when the gate carried no offer or the approval policy is locked.
request_idstringNoOptional caller id for this decision, at most 64 characters from A-Z, a-z, 0-9, ., _, and -. A later 409 gate_already_resolved for the gate echoes it as details.request_id.
lease_generationintegerNoThe approver-lease generation the decision was made under. Forwarded as is; omitted or 0 sends none.
{
"gate_id": "gate-9f2c4e1ab07d3355-3",
"generation": 3,
"approved": true,
"session_scope": false
}

Answered.

{
"status": "ok",
"resolved": {
"gate_id": "gate-9f2c4e1ab07d3355-3",
"outcome": "answered"
}
}
FieldTypeDescription
statusstring"ok" on success.
resolvedobjectThe daemon’s resolution of the gate (event.gate_resolved) that consumed this decision.
session_scope_appliedbooleanPresent (false) when the decision applied once but its session-wide grant could not be applied; see note.
notestringPresent alongside session_scope_applied: why the wider grant did not apply.

The SDK reaches this operation through two methods:

  • client.agent.gates.approve(...): sets approved: true.
  • client.agent.gates.deny(...): sets approved: false.
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.gates.approve('{session_id}', {
gate_id: 'gate-9f2c4e1ab07d3355-3',
generation: 3,
session_scope: false,
});

Changes the session’s approval mode ("default" or "always") and/or its lock. Use If-Match (the ETag from GET, or * for unconditional) to make the change conditional. A stale If-Match is 412 (the response ETag carries the current revision). A locked policy is 409 approval_policy_locked; an unknown mode, a delegated session, an unlock attempt, or weakening an inherited lock is 409 approval_policy_unsatisfiable; a busy session is 409 session_busy (the policy only changes at quiescence); a failed durable commit is 503 policy_commit_failed (nothing acknowledged). Emits event.approval_policy_changed to every attached client.

"always" makes every side-effecting Hoody-visible invocation require one explicit decision naming its gate. Nested executors that cannot park a decision are refused (subagents, workflow runs and resumes, the orchestrator, foreign CLIs, run_todo, test_hook); the user’s configured hook commands are skipped, each disclosed as event.hook_run {decision:"skipped"}; configured MCP servers are not started; stdin to a background bash process is refused. Machine-confirmed execution paths (a composite or fusion model’s winner-commit run in writes mode, subagents, workflow tool steps, auto-reply) have their side-effecting invocations refused under "always" (error code approval_policy_unsatisfiable); reads still pass.

NameInTypeRequiredDescription
idpathstringYesThe session id.
If-MatchheaderstringNoConditional-request precondition: the ETag from GET /sessions/{id}/approval (a quoted policy revision, e.g. "3") or *. A mismatch is 412 precondition_failed.
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 of the X-Hoody-Realm header).
FieldTypeRequiredDescription
modestringNo"default" or "always". Omit to keep the current mode.
lockedbooleanNoFreeze the policy for the session’s lifetime (monotonic; never unlocked). Omit to keep the current lock.
{
"mode": "always",
"locked": true
}

The updated policy. ETag = new revision.

{
"mode": "always",
"locked": true,
"revision": 4,
"yolo": false,
"auto_write": false,
"auto_dir_access": false,
"backend_auto_approving": false,
"rules": [],
"lease": {
"held": false,
"holder": null,
"generation": 0,
"expires_at": null,
"epoch": "ep-7f3a1c"
},
"epoch": "ep-7f3a1c",
"changed": true,
"capabilities": {
"always": true,
"locked": true,
"lease": true
}
}
FieldTypeDescription
modestring"default" or "always".
lockedbooleanWhether the policy is frozen for the session’s lifetime (monotonic; never unlocked).
revisionintegerMonotonic policy revision, the ETag value.
yolobooleanWhether YOLO auto-approve is armed.
auto_writebooleanWhether automatic file-write permission is on; always false under "always".
auto_dir_accessbooleanWhether automatic directory access is on.
backend_auto_approvingbooleanWhether a delegated backend auto-approves its own tools.
rulesarraySession permission rules.
rules[].toolstringRule key (a tool name, or tool:action).
rules[].decisionstringallow or deny.
leaseobjectApprover lease state: {held, holder, generation, expires_at, epoch}.
epochstringThe daemon execution epoch (an opaque id).
changedbooleanPUT only: whether the request changed anything.
capabilitiesobjectWhat this daemon supports: {always, locked, lease}.
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.sessions.updateApproval('{session_id}', { mode: 'always', locked: true }, { IfMatch: '"3"' });

PUT /api/v1/agent/sessions/{id}/approval/rules/{tool}

Section titled “PUT /api/v1/agent/sessions/{id}/approval/rules/{tool}”

Upserts one session permission rule for {tool}: {"decision":"allow"|"deny"}. One rule per request (never an array). An allow is refused 409 approval_policy_locked on a locked policy and 409 approval_policy_active on an "always" policy (allow rules are never consulted there); a deny is always accepted. Optional If-Match (the ETag from GET /approval): a stale one is 412 with the current ETag; the answer carries the new ETag. Emits event.permission_rules and event.approval_policy_changed.

A rule write is durable-or-nothing: if the durable write fails the rule is rolled back, the answer is 503 policy_commit_failed, and nothing is broadcast, because nothing was announced to retract. Every event.permission_rules frame therefore carries rules that are persisted. The frame is still a snapshot to converge on rather than a receipt for this request: another client’s write, or an in-session decision, produces one too.

NameInTypeRequiredDescription
idpathstringYesThe session id.
toolpathstringYesThe tool.
If-MatchheaderstringNoConditional-request precondition: the ETag from GET /sessions/{id}/approval (a quoted policy revision, e.g. "3") or *. A mismatch is 412 precondition_failed.
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 of the X-Hoody-Realm header).
FieldTypeRequiredDescription
decisionstringYesallow or deny.
{
"decision": "allow"
}

The session’s permission rules after the change.

{
"status": "ok",
"rules": [
{
"tool": "bash",
"decision": "allow"
}
]
}
FieldTypeDescription
statusstring"ok".
rulesarraySession permission rules.
rules[].toolstringRule key (a tool name, or tool:action).
rules[].decisionstringallow or deny.
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.sessions.setApprovalRule('{session_id}', 'bash', { decision: 'allow' });

DELETE /api/v1/agent/sessions/{id}/approval/rules/{tool}

Section titled “DELETE /api/v1/agent/sessions/{id}/approval/rules/{tool}”

Clears the session permission rule for {tool} (re-arming the per-call prompt). Refused 409 approval_policy_locked on a locked policy (rules cannot be cleared there). Optional If-Match, as on the PUT (412 when stale). Emits event.permission_rules and event.approval_policy_changed. A rule write is durable-or-nothing: if the durable write fails the rule is rolled back, the answer is 503 policy_commit_failed, and nothing is broadcast.

NameInTypeRequiredDescription
idpathstringYesThe session id.
toolpathstringYesThe tool.
If-MatchheaderstringNoConditional-request precondition: the ETag from GET /sessions/{id}/approval (a quoted policy revision, e.g. "3") or *. A mismatch is 412 precondition_failed.
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 of the X-Hoody-Realm header).

This endpoint takes no body.

The session’s permission rules after the change.

{
"status": "ok",
"rules": []
}
FieldTypeDescription
statusstring"ok".
rulesarraySession permission rules.
rules[].toolstringRule key (a tool name, or tool:action).
rules[].decisionstringallow or deny.
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.sessions.deleteApprovalRule('{session_id}', 'bash');

Flips the session’s YOLO auto-approve on or off, the same power as the TUI’s lightning toggle, including clearing actions the agent otherwise reserves for a person (a caller that can reach this API is treated as having that permission). A locked policy refuses it 409 approval_policy_locked and an "always" policy refuses it 409 approval_policy_active, rather than dropping it silently. Returns the applied {yolo}. Emits event.yolo_mode.

NameInTypeRequiredDescription
idpathstringYesThe session id.
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 of the X-Hoody-Realm header).
FieldTypeRequiredDescription
enabledbooleanYestrue to arm auto-approve, false to disarm.
{
"enabled": true
}

Applied YOLO state.

{
"status": "ok",
"yolo": true
}
FieldTypeDescription
statusstring"ok".
yolobooleanThe applied auto-approve state.
forwardedbooleantrue when the command was delivered but not acknowledged within the wait; observe event.yolo_mode.
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.sessions.setYolo('{session_id}', { enabled: true });