Skip to main content
POST
JavaScript
A tool behind approval parks at TOOL_CALL_STATUS_WAITING_FOR_APPROVAL and the objective waits. Denying it tells the agent the action is off the table.
The tool never runs. The agent keeps working.

The memo is the difference between a wall and a hint

Deny with no memo and the agent knows only that it may not do that. It shrugs and tries something else:
Deny with a memo and the agent reads it, in the same run:
Both are real runs of the same agent on the same message. The memo is the steering wheel: it lands in the agent’s context as the reason, so it can pick a different approach rather than guess at your policy. Write the memo as an instruction to the agent, not a note to your audit log. “Refund exceeds the $500 limit; escalate to a human instead” gives the agent somewhere to go. “Denied” does not.

The response reports the state before the decision

Denial resolves asynchronously, and the response body carries almost nothing:
Read the call back for the settled state:
executionStatus stays PENDING forever. That is the tell: a denied call is one that was never executed, not one that failed.

Deciding twice

A tool call can be decided once. A second decision, in either direction, comes back 404:
That 404 does not mean the tool call is missing. It means someone already decided, or the objective moved on. The message says so; the status code does not.An approval queue with two reviewers hits this on day one. Treat a 404 on :deny as “refresh and show the outcome”, not as “this does not exist.”

Finding the calls waiting on you

The toolApprovalRequested event fires on the stream the moment a call parks, so a UI does not have to poll. toolDenied fires when you decide, carrying the toolCallId and the memo.

Putting a tool behind approval

Approval is a property of the tool, and a synced tool set does not let you edit its tools:
Set it on the adapter instead, and every synced tool inherits it:
Use an only filter in toolApprovals to gate a subset. For bare and HTTP tools, which you define by hand, set requiresApproval on the tool directly.

Approve a tool call

The other decision, and the same 404 on a second one.

List tool calls

Filter by WAITING_FOR_APPROVAL to build the queue.

Create a tool set

toolApprovals, and why synced tools reject edits.

Set tool call content

When you want the human to be the tool, not only gate it.

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 deny

Example:

"toolcall_01HXKD2E5NQM3T9AYWCFTANFGV"

Body

application/json
memo
string

A memo to associate to the tool call denial. Use a memo to steer the LLM to a different decision or usage of the tool.

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