Skip to main content
POST
JavaScript
A bare tool has no adapter. When an agent calls one, nothing fires: the tool call parks at TOOL_CALL_EXECUTION_STATUS_WAITING_FOR_CONTENT and waits for you to supply the result. That inversion is the point. The tool runs on your infrastructure, inside your VPC, against your database, and Cadenya only ever sees the answer.

The whole loop

That is a complete reverse harness. Poll, execute, answer.

What it looks like in flight

A real run, end to end. The agent decided to call lookup_order with the argument it extracted from the user’s message:
The objective stays STATE_RUNNING while it waits. Then setContent lands with {"orderId":"A-1007","status":"delivered"}, and the agent picks up where it left off:
The response to setContent reports the call’s pre-update state: executionStatus still reads WAITING_FOR_CONTENT. The transition is asynchronous. Read the call back if you need the settled state, or watch for the agent’s next event.

Content is a list of blocks

content is required and takes at least one block. Each block is a discriminated union: type reads text, image, or audio, and the payload sits under the matching key.
Media blocks carry raw base64 data on input. On the way out, when you read the tool call back, media comes as a signed URL instead. The two shapes are deliberately different. The whole payload caps at 16 MiB. An empty array is a 400, and so is a block whose type does not match its payload key.

The two states that reject you

setContent is precondition-checked, and both failures are worth handling:
  • The tool call must be in WAITING_FOR_CONTENT. A call that already resumed, or was never bare, is a FailedPrecondition.
  • The objective must not be terminal. Setting content on a finalized or cancelled objective is a FailedPrecondition.
Setting content twice while still waiting is idempotent: the second call re-publishes rather than storing a second result.

Bound the wait

contentTimeout on the bare adapter decides how long a call may sit parked. It defaults to 24 hours, and when it elapses the call resolves on its own with a synthesized result:
The objective keeps going rather than failing. That is a friendlier default than it sounds: a harness that dies mid-run leaves the agent able to reason about the absence of an answer instead of hanging forever.

Two patterns this unlocks

Human in the loop. The tool is a question for a person. Park the call, render the arguments in your app, and submit the human’s answer as the content. Unlike tool approval, which only gates a call Cadenya then makes itself, this lets the human be the tool. Reverse harness. The tool runs code that Cadenya cannot and should not reach: an internal service, a database behind a VPN, a GPU box, a legacy system with no HTTP surface. You poll, execute locally, and report back. There is no inbound network path from Cadenya to you, which is the whole reason a security team signs off. Both are the same three calls. The difference is only who computes the answer.

Create a tool set

The bare adapter, contentTimeout, and defining a tool by hand.

Approve a tool call

The other way to put a person between an agent and an action.

Stream objective events

Watch for the parked call instead of polling for it.

Create an agent

outputDefinition, which is what let this objective finalize.

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 set content for

Example:

"toolcall_01HXKD2E5NQM3T9AYWCFTANFGV"

Body

application/json

SetToolCallContentRequest lets an external API consumer supply the result of a bare tool call (one whose tool set has no execution adapter). Used for human-in-the-loop tools and reverse harnesses that execute tools locally and report results back.

content
object[]
required

The content to set on the tool call. Mirrors ObjectiveToolCallResult.ContentBlock but writable: media blocks carry raw data on input where the result-side carries a signed url on output.

ContentBlock is a single block of tool call content supplied on input. Exactly one of the variants is set.

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