Skip to main content
POST
JavaScript
When an agent reaches for a tool marked requiresApproval, the objective parks. The call sits at TOOL_CALL_STATUS_WAITING_FOR_APPROVAL and nothing runs until you approve it or deny it. Approve takes no body. Deny takes an optional memo, which is the interesting one.
The response body of approve and deny carries little more than the ID. Its status and executionStatus read UNSPECIFIED, because the decision resolves asynchronously. Read the call back with Get a tool call when you need the settled state.

Denying steers, it does not stop

A denial is not a failure. Cadenya hands the agent the rejected call back as its tool result, wrapping your memo:
The agent reads that, and picks another path. In a live run, denying a GetFakerOptions call produced this timeline: The objective stayed in STATE_RUNNING throughout. Write the memo as an instruction to the agent, not as an audit note to yourself: it is prompt text, and it steers the next attempt.
The memo reaches the agent through the tool result, but the toolDenied event’s own memo field comes back empty. Read the memo from the toolResult that follows, or store it yourself when you send the denial.

Find the parked call

Three ways, depending on how your system is shaped. A webhook, when you want to be told. The objective_event.tool_approval_requested delivery carries toolCallId, and the approval guide walks the full handler including signature verification. The event stream, when a person is already watching. A toolApprovalRequested event arrives with a toolApprovalRequested.toolCallId and nothing else. Polling, when you want no inbound plumbing at all. The list endpoint takes a status filter:
Everything a reviewer needs to make the decision is on that record: the tool through data.callable, and the exact data.arguments the agent proposed.
status and executionStatus sit on the tool call itself, not on data. Reach for call.status, not call.data.status.

The two status fields

A tool call tracks approval and execution separately, and both matter. Approve a parked call and it walks WAITING_FOR_APPROVAL to APPROVED, while execution walks PENDING to COMPLETED.

What marks a tool for approval

One field decides at run time: requiresApproval on the tool. Nothing else is consulted. You set it two ways. By hand, when you define a tool. Or through the tool set adapter’s toolApprovals filter, which stamps requiresApproval onto tools as they sync:
Swap always for only with a filter to mark a subset. The filter runs on every sync, so a hand-edited requiresApproval gets overwritten the next time the tool set syncs, unless the adapter carries no toolApprovals at all.
Only tools can require approval. An agent-as-tool (sub-agent) and Cadenya’s built-in tools never park.

The 24-hour clock

A parked call waits 24 hours. Nothing approves or denies it for you: the wait expires, the call fails, and the objective surfaces an error. The window is fixed and takes no configuration. Do not confuse it with two other 24-hour timers:
  • contentTimeout on a bare adapter also defaults to 24 hours, but it resolves gracefully, writing a synthesized result that says no content arrived. The objective survives.
  • inactivityTimeout on a variation’s constraints finalizes an idle objective as STATE_TIMED_OUT. It counts objective activity, not approvals.
An approval that expires is the only one of the three that fails the run. Notify your reviewer quickly, and treat an expired approval like any other failed objective.

Approving a tool

The end-to-end tutorial: webhook, signature check, Slack button, decision.

Deny a tool call

The sibling endpoint, with the memo that steers the agent.

Bare tools

Park a call and fulfill it from your own infrastructure with setContent.

Stream objective events

Watch approval requests arrive in real time.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

workspaceId
string
required
Example:

"workspace_01HXKD2E5NQM3T9AYWCF133E3Q"

objectiveId
string
required

The ID of the objective. Supports "external_id:" prefix for external IDs.

Example:

"obj_01HXKD2E5NQM3T9AYWCFQAZGFV"

toolCallId
string
required

The ID of the tool call to approve

Example:

"toolcall_01HXKD2E5NQM3T9AYWCFTANFGV"

Body

application/json

The body is of type object.

Response

OK

ObjectiveToolCall is a record of a tool call made during an objective's execution. Tool calls are mutable — their status changes as they are approved, denied, or executed.

metadata
object
required

Metadata for ephemeral operations and activities (e.g., objectives, executions, runs)

data
object
required
status
enum<string>
required

Current status of the tool call

Available options:
TOOL_CALL_STATUS_UNSPECIFIED,
TOOL_CALL_STATUS_AUTO_APPROVED,
TOOL_CALL_STATUS_WAITING_FOR_APPROVAL,
TOOL_CALL_STATUS_APPROVED,
TOOL_CALL_STATUS_DENIED
executionStatus
enum<string>
required
read-only
Available options:
TOOL_CALL_EXECUTION_STATUS_UNSPECIFIED,
TOOL_CALL_EXECUTION_STATUS_PENDING,
TOOL_CALL_EXECUTION_STATUS_RUNNING,
TOOL_CALL_EXECUTION_STATUS_COMPLETED,
TOOL_CALL_EXECUTION_STATUS_ERRORED,
TOOL_CALL_EXECUTION_STATUS_WAITING_FOR_CONTENT
info
object