> ## Documentation Index
> Fetch the complete documentation index at: https://cadenya.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Approve a tool call

> Release a tool call that is parked waiting for human approval. Deny it instead, with a memo, and the agent reads the memo and picks another path.

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](/docs/api-reference/objectiveservice/deny-a-tool-call).

Approve takes no body. Deny takes an optional `memo`, which is the interesting one.

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Approve: the tool runs as the agent wrote it.
  await client.objectives.toolCalls.approve(toolCallId, { workspaceId, objectiveId });

  // Deny: the agent reads the memo and tries something else.
  await client.objectives.toolCalls.deny(toolCallId, {
    workspaceId,
    objectiveId,
    memo: 'Do not charge the full balance. Offer a payment plan instead.',
  });
  ```

  ```go Go theme={null}
  _, err := client.Objectives.ToolCalls.Approve(ctx, objectiveID, toolCallID,
  	cadenya.ObjectiveToolCallApproveParams{WorkspaceID: cadenya.String(workspaceID)})

  _, err = client.Objectives.ToolCalls.Deny(ctx, objectiveID, toolCallID,
  	cadenya.ObjectiveToolCallDenyParams{
  		WorkspaceID: cadenya.String(workspaceID),
  		Memo:        cadenya.String("Do not charge the full balance. Offer a payment plan instead."),
  	})
  ```

  ```ruby Ruby theme={null}
  # Approve: the tool runs as the agent wrote it.
  cadenya.objectives.tool_calls.approve(
    tool_call_id,
    workspace_id: workspace_id,
    objective_id: objective_id
  )

  # Deny: the agent reads the memo and tries something else.
  cadenya.objectives.tool_calls.deny(
    tool_call_id,
    workspace_id: workspace_id,
    objective_id: objective_id,
    memo: "Do not charge the full balance. Offer a payment plan instead."
  )
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.cadenya.com/v1/workspaces/${WORKSPACE_ID}/objectives/${OBJECTIVE_ID}/tool_calls/${TOOL_CALL_ID}:approve" \
    -H "Authorization: Bearer ${CADENYA_API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{}'

  curl -X POST "https://api.cadenya.com/v1/workspaces/${WORKSPACE_ID}/objectives/${OBJECTIVE_ID}/tool_calls/${TOOL_CALL_ID}:deny" \
    -H "Authorization: Bearer ${CADENYA_API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{"memo": "Do not charge the full balance. Offer a payment plan instead."}'
  ```
</CodeGroup>

<Warning>
  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](/docs/api-reference/objectiveservice/get-an-objective-tool-call-by-id) when you need the settled state.
</Warning>

## 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:

```
<tool_call_result>denied: Do not charge the full balance. Offer a payment plan instead.</tool_call_result>
```

The agent reads that, and picks another path. In a live run, denying a `GetFakerOptions` call produced this timeline:

| Event                   | What happened                             |
| ----------------------- | ----------------------------------------- |
| `toolApprovalRequested` | The agent wanted `GetFakerOptions`.       |
| `toolDenied`            | You denied it.                            |
| `toolResult`            | The agent received `denied: <your memo>`. |
| `assistantMessage`      | The agent reconsidered.                   |
| `toolApprovalRequested` | It asked for `GenerateFake` instead.      |

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.

<Note>
  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.
</Note>

## 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](/docs/guides/callbacks/approving-a-tool) 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:

```typescript theme={null}
const parked = await client.objectives.toolCalls.list(objectiveId, {
  workspaceId,
  status: 'TOOL_CALL_STATUS_WAITING_FOR_APPROVAL',
});

for await (const call of parked) {
  if (call.data.callable.type !== 'tool') continue;
  console.log(call.metadata.id, call.data.callable.tool.name, call.data.arguments);
  // toolcall_01KX19RCAJ7MHXSNNCNR7ANFDV  GetFakerOptions  { filter: 'company name' }
}
```

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.

<Warning>
  `status` and `executionStatus` sit on the tool call itself, not on `data`. Reach for `call.status`, not `call.data.status`.
</Warning>

## The two status fields

A tool call tracks approval and execution separately, and both matter.

| `status` (approval)                     | Meaning                      |
| --------------------------------------- | ---------------------------- |
| `TOOL_CALL_STATUS_AUTO_APPROVED`        | The tool needed no approval. |
| `TOOL_CALL_STATUS_WAITING_FOR_APPROVAL` | Parked. Waiting on you.      |
| `TOOL_CALL_STATUS_APPROVED`             | Released.                    |
| `TOOL_CALL_STATUS_DENIED`               | Refused. The agent was told. |

| `executionStatus`                                | Meaning                                                                               |
| ------------------------------------------------ | ------------------------------------------------------------------------------------- |
| `TOOL_CALL_EXECUTION_STATUS_PENDING`             | Not started. A parked call sits here.                                                 |
| `TOOL_CALL_EXECUTION_STATUS_RUNNING`             | The tool is running.                                                                  |
| `TOOL_CALL_EXECUTION_STATUS_COMPLETED`           | It returned.                                                                          |
| `TOOL_CALL_EXECUTION_STATUS_ERRORED`             | It failed.                                                                            |
| `TOOL_CALL_EXECUTION_STATUS_WAITING_FOR_CONTENT` | A [bare tool](/docs/api-reference/toolservice/create-a-new-tool-set) waiting on your code. |

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](/docs/api-reference/toolservice/create-a-new-tool-set#define-tools-by-hand). Or through the tool set adapter's `toolApprovals` filter, which stamps `requiresApproval` onto tools as they sync:

```typescript theme={null}
await client.toolSets.create({
  workspaceId,
  metadata: { name: 'Faker' },
  spec: {
    adapter: {
      type: 'mcp',
      mcp: {
        url: 'https://free.cadenya.com/faker-mcp',
        toolApprovals: { type: 'always', always: true },
      },
    },
  },
});
// Every tool the sync finds comes back with requiresApproval: true.
```

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.

<Note>
  Only tools can require approval. An agent-as-tool ([sub-agent](/docs/guides/delegate-to-sub-agents)) and Cadenya's built-in tools never park.
</Note>

## 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.

## Related

<CardGroup cols={2}>
  <Card title="Approving a tool" icon="hand" href="/docs/guides/callbacks/approving-a-tool">
    The end-to-end tutorial: webhook, signature check, Slack button, decision.
  </Card>

  <Card title="Deny a tool call" icon="ban" href="/docs/api-reference/objectiveservice/deny-a-tool-call">
    The sibling endpoint, with the `memo` that steers the agent.
  </Card>

  <Card title="Bare tools" icon="plug" href="/docs/api-reference/toolservice/create-a-new-tool-set">
    Park a call and fulfill it from your own infrastructure with `setContent`.
  </Card>

  <Card title="Stream objective events" icon="tower-broadcast" href="/docs/api-reference/objectiveeventstreamsservice/stream-objective-events">
    Watch approval requests arrive in real time.
  </Card>
</CardGroup>


## OpenAPI

````yaml post /v1/workspaces/{workspaceId}/objectives/{objectiveId}/tool_calls/{toolCallId}:approve
openapi: 3.1.0
info:
  title: Cadenya API
  description: API for the Cadenya Agent Runtime platform.
  version: '1.0'
servers:
  - url: https://api.cadenya.com
    description: Production server
security:
  - bearerAuth: []
tags:
  - name: AIProviderKeyService
  - name: APIKeyService
    description: |-
      Issue, rotate, disable, and revoke a workspace's API keys. Every key
       belongs to exactly one workspace; the system-managed global account key is
       managed via GlobalAPIKeyService instead.
  - name: AccountService
    description: >-
      Manage the authenticated account. Accounts are the top-level
      organizational
       unit and contain one or more workspaces.
  - name: AgentScheduleService
    description: >-
      Manage recurring schedules attached to agents. Schedules trigger
      objectives
       on a cadence defined by AgentScheduleSpec.Schedule.
  - name: AgentService
    description: >-
      Manage AI agents within a workspace. Agents define AI behavior and tool
      access.
  - name: AgentVariationService
    description: >-
      Manage variations of an agent and their tool, sub-agent, and memory layer
      assignments.
  - name: GlobalAPIKeyService
    description: |-
      Manage the account's system-provisioned global API key. The global key is
       the only key that spans every workspace; it is created by the system and
       cannot be deleted, so the surface is retrieve, rotate, and the
       disable/enable kill switch.
  - name: MemoryService
    description: >-
      Manage memory layers and their entries. Layers are named containers that
      can
       be composed into an objective's memory cascade; entries are the keyed values
       within a layer. System-managed layers (e.g., episodic layers created by the
       runtime) cannot be mutated through this API.
  - name: ModelService
    description: |-
      Manage LLM models available to a workspace. Models represent provider and
       family pairs (e.g., "anthropic/claude-sonnet-4.6"). Workspaces are seeded
       with the supported models and you can enable or disable each one.
  - name: ObjectiveEventStreamsService
  - name: ObjectiveService
  - name: ProfilesService
    description: |-
      Operations on profiles, the account-level principals (users, API keys,
       system) that authenticate against the API.
  - name: SearchService
  - name: TenantService
    description: >-
      Read and erase tenants and the subjects under them. Tenants and subjects
      are
       created by assertion — on objective creation or widget session mint — never
       directly, so this service has no create or update: it exists to enumerate what
       assertions have produced, and to destroy it on request.
  - name: ToolService
    description: >-
      Manage tool sets and the tools they contain. Tool sets group related
      tools,
       and tools define specific capabilities available to agents.

       When a tool set is managed, only API key actors can modify its tools; human
       (profile) actors cannot.
  - name: UploadService
    description: |-
      Issue short-lived presigned URLs for direct client-to-object-storage
       uploads. Created uploads can be referenced by id when creating or updating
       resources that accept binary content (e.g., MemoryEntry).
  - name: WidgetService
    description: |-
      Manage embeddable chat widgets. A widget binds an agent to a globally
       unique hostname with a per-widget origin allowlist; browsers reach it with
       session tokens minted via WidgetSessionService.
  - name: WidgetSessionService
    description: >-
      Mint and manage widget sessions. Session creation is server-to-server
      only:
       the customer's backend authenticates its visitor, asserts tenant/subject
       context, attaches any per-visitor secrets, and receives a short-lived
       bearer token the browser uses against the widget host.
  - name: WorkspaceAdminService
    description: >-
      Administer workspaces across the account: create and archive workspaces
      and
       manage their membership. These operations are account-scoped and require the
       admin role (a token whose profile holds the WorkOS admin role); they live
       under /v1/account/workspaces rather than the workspace-scoped /v1/workspaces
       tree so an admin can manage any workspace in the account, including ones they
       are not themselves a member of.
  - name: WorkspaceSecretService
  - name: WorkspaceService
    description: |-
      Manage workspaces within an account. Workspaces provide organizational
       grouping and isolation for resources such as agents, tools, and API keys.

       This is the workspace-scoped, end-user surface. Administrative operations
       (create / archive workspaces, manage members) live in WorkspaceAdminService
       under /v1/account/workspaces and require the admin role.
paths:
  /v1/workspaces/{workspaceId}/objectives/{objectiveId}/tool_calls/{toolCallId}:approve:
    post:
      tags:
        - ObjectiveService
        - Objectives
      summary: Approve a tool call
      description: >-
        When an agent attempts to use a tool that requires approval, use this
        endpoint to mark it as approved.
      operationId: ObjectiveService_ApproveToolCall
      parameters:
        - name: workspaceId
          in: path
          required: true
          schema:
            type: string
            example: workspace_01HXKD2E5NQM3T9AYWCF133E3Q
        - name: objectiveId
          in: path
          description: >-
            The ID of the objective. Supports "external_id:" prefix for external
            IDs.
          required: true
          schema:
            example: obj_01HXKD2E5NQM3T9AYWCFQAZGFV
            type: string
        - name: toolCallId
          in: path
          description: The ID of the tool call to approve
          required: true
          schema:
            example: toolcall_01HXKD2E5NQM3T9AYWCFTANFGV
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApproveToolCallRequest'
        required: true
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObjectiveToolCall'
        default:
          description: Default error response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Status'
      x-codeSamples:
        - lang: JavaScript
          source: |-
            import Cadenya from '@cadenya/cadenya';

            const client = new Cadenya({
              apiKey: process.env['CADENYA_API_KEY'], // This is the default and can be omitted
            });

            const objectiveToolCall = await client.objectives.toolCalls.approve(
              'obj_01HXKD2E5NQM3T9AYWCFQAZGFV',
              'toolcall_01HXKD2E5NQM3T9AYWCFTANFGV',
              { workspaceId: 'workspace_01HXKD2E5NQM3T9AYWCF133E3Q' },
            );

            console.log(objectiveToolCall.data);
        - lang: Python
          source: |-
            import os
            from cadenya import Cadenya

            client = Cadenya(
                api_key=os.environ.get("CADENYA_API_KEY"),  # This is the default and can be omitted
            )
            objective_tool_call = client.objectives.tool_calls.approve(
                objective_id="obj_01HXKD2E5NQM3T9AYWCFQAZGFV",
                tool_call_id="toolcall_01HXKD2E5NQM3T9AYWCFTANFGV",
                workspace_id="workspace_01HXKD2E5NQM3T9AYWCF133E3Q",
            )
            print(objective_tool_call.data)
        - lang: Go
          source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"go.cadenya.com/cadenya-go\"\n\t\"go.cadenya.com/cadenya-go/option\"\n)\n\nfunc main() {\n\tclient := cadenya.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\tobjectiveToolCall, err := client.Objectives.ToolCalls.Approve(\n\t\tcontext.TODO(),\n\t\t\"obj_01HXKD2E5NQM3T9AYWCFQAZGFV\",\n\t\t\"toolcall_01HXKD2E5NQM3T9AYWCFTANFGV\",\n\t\tcadenya.ObjectiveToolCallApproveParams{\n\t\t\tWorkspaceID: cadenya.String(\"workspace_01HXKD2E5NQM3T9AYWCF133E3Q\"),\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", objectiveToolCall.Data)\n}\n"
        - lang: Ruby
          source: |-
            require "cadenya"

            cadenya = Cadenya::Client.new(api_key: "My API Key")

            objective_tool_call = cadenya.objectives.tool_calls.approve(
              "obj_01HXKD2E5NQM3T9AYWCFQAZGFV",
              "toolcall_01HXKD2E5NQM3T9AYWCFTANFGV",
              workspace_id: "workspace_01HXKD2E5NQM3T9AYWCF133E3Q"
            )

            puts(objective_tool_call)
        - lang: CLI
          source: |-
            cadenya objectives:tool-calls approve \
              --api-key 'My API Key' \
              --workspace-id workspace_01HXKD2E5NQM3T9AYWCF133E3Q \
              --objective-id obj_01HXKD2E5NQM3T9AYWCFQAZGFV \
              --tool-call-id toolcall_01HXKD2E5NQM3T9AYWCFTANFGV
components:
  schemas:
    ApproveToolCallRequest:
      type: object
      properties:
        workspaceId:
          readOnly: true
          example: workspace_01HXKD2E5NQM3T9AYWCF133E3Q
          type: string
        objectiveId:
          readOnly: true
          example: obj_01HXKD2E5NQM3T9AYWCFQAZGFV
          type: string
          description: >-
            The ID of the objective. Supports "external_id:" prefix for external
            IDs.
        toolCallId:
          readOnly: true
          example: toolcall_01HXKD2E5NQM3T9AYWCFTANFGV
          type: string
          description: The ID of the tool call to approve
    ObjectiveToolCall:
      required:
        - metadata
        - data
        - status
        - executionStatus
      type: object
      properties:
        metadata:
          $ref: '#/components/schemas/OperationMetadata'
        data:
          $ref: '#/components/schemas/ObjectiveToolCallData'
        status:
          enum:
            - TOOL_CALL_STATUS_UNSPECIFIED
            - TOOL_CALL_STATUS_AUTO_APPROVED
            - TOOL_CALL_STATUS_WAITING_FOR_APPROVAL
            - TOOL_CALL_STATUS_APPROVED
            - TOOL_CALL_STATUS_DENIED
          type: string
          description: Current status of the tool call
          format: enum
        info:
          $ref: '#/components/schemas/ObjectiveToolCallInfo'
        executionStatus:
          readOnly: true
          enum:
            - 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
          type: string
          format: enum
      description: >-
        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.
    Status:
      type: object
      properties:
        code:
          type: integer
          description: >-
            The status code, which should be an enum value of
            [google.rpc.Code][google.rpc.Code].
          format: int32
        message:
          type: string
          description: >-
            A developer-facing error message, which should be in English. Any
            user-facing error message should be localized and sent in the
            [google.rpc.Status.details][google.rpc.Status.details] field, or
            localized by the client.
        details:
          type: array
          items:
            $ref: '#/components/schemas/GoogleProtobufAny'
          description: >-
            A list of messages that carry the error details.  There is a common
            set of message types for APIs to use.
      description: >-
        The `Status` type defines a logical error model that is suitable for
        different programming environments, including REST APIs and RPC APIs. It
        is used by [gRPC](https://github.com/grpc). Each `Status` message
        contains three pieces of data: error code, error message, and error
        details. You can find out more about this error model and how to work
        with it in the [API Design
        Guide](https://cloud.google.com/apis/design/errors).
    OperationMetadata:
      required:
        - id
        - accountId
        - workspaceId
        - profileId
        - createdAt
      type: object
      properties:
        id:
          readOnly: true
          type: string
          description: >-
            Unique identifier for the operation (prefixed ULID, e.g.,
            "obj_01HXK...")
        accountId:
          readOnly: true
          example: account_01HXKD2E5NQM3T9AYWCFTJHJVF
          type: string
          description: >-
            Account this operation belongs to for multi-tenant isolation
            (prefixed ULID)
        workspaceId:
          readOnly: true
          example: workspace_01HXKD2E5NQM3T9AYWCF133E3Q
          type: string
          description: >-
            Workspace this operation belongs to for organizational grouping
            (prefixed ULID)
        labels:
          type: object
          additionalProperties:
            type: string
          description: |-
            Key-value pairs for categorization and filtering. Values are 0-63
             alphanumeric characters with "-", "_", or "." allowed between; keys
             follow the same shape and additionally accept an optional DNS-subdomain
             prefix (e.g. "cadenya.com/") of at most 253 characters.
             Examples: {"priority": "high", "source": "api", "workflow": "onboarding"}
        createdAt:
          readOnly: true
          type: string
          description: |-
            Timestamp when this operation was created
             ULID includes timestamp information, but this explicit field enables easier querying
          format: date-time
        externalId:
          type: string
          description: >-
            External ID for the operation (e.g., a workflow ID from an external
            system)
        profileId:
          readOnly: true
          example: profile_01HXKD2E5NQM3T9AYWCFS0AP08
          type: string
          description: >-
            ID of the actor (user or service account) that created this
            operation
      description: >-
        Metadata for ephemeral operations and activities (e.g., objectives,
        executions, runs)
    ObjectiveToolCallData:
      required:
        - callable
      type: object
      properties:
        callable:
          allOf:
            - $ref: '#/components/schemas/CallableTool'
          description: The tool that was called
        arguments:
          type: object
          additionalProperties: true
          description: The arguments passed to the tool
        memo:
          type: string
          description: A memo supplied by the reviewer when denying the tool call
        statusChangedBy:
          readOnly: true
          allOf:
            - $ref: '#/components/schemas/Profile'
          description: >-
            The profile that changed the status of this tool call. Set when the
            status is changed to APPROVED or DENIED by a user.
        resolvedSecrets:
          readOnly: true
          type: array
          items:
            $ref: '#/components/schemas/ResolvedSecret'
          description: List of resolved secrets used by the tool call
    ObjectiveToolCallInfo:
      type: object
      properties:
        objective:
          $ref: '#/components/schemas/OperationMetadata'
        createdBy:
          $ref: '#/components/schemas/Profile'
        tool:
          $ref: '#/components/schemas/BareMetadata'
        toolSet:
          $ref: '#/components/schemas/BareMetadata'
    GoogleProtobufAny:
      type: object
      properties:
        '@type':
          type: string
          description: The type of the serialized message.
      additionalProperties: true
      description: >-
        Contains an arbitrary serialized message along with a @type that
        describes the type of the serialized message.
    CallableTool:
      oneOf:
        - $ref: '#/components/schemas/CallableTool_Tool'
        - $ref: '#/components/schemas/CallableTool_Agent'
        - $ref: '#/components/schemas/CallableTool_CadenyaProvidedTool'
      discriminator:
        propertyName: type
        mapping:
          tool:
            $ref: '#/components/schemas/CallableTool_Tool'
          agent:
            $ref: '#/components/schemas/CallableTool_Agent'
          cadenyaProvidedTool:
            $ref: '#/components/schemas/CallableTool_CadenyaProvidedTool'
      description: >-
        CallableTool is a union that represents a tool that can be called by an
        agent. In Cadenya, a tool that is used within an agent objective
         might be a user-defined tool (IE: MCP, HTTP), another Agent (useful to separate context), or a Cadenya Tool (one Cadenya provides).
    Profile:
      required:
        - metadata
        - spec
      type: object
      properties:
        metadata:
          $ref: '#/components/schemas/AccountResourceMetadata'
        spec:
          $ref: '#/components/schemas/ProfileSpec'
      description: |-
        A profile identifies a user or non-human principal (such as an API key)
         at the account level. Profiles are account-scoped and can be granted access
         to multiple workspaces.
    ResolvedSecret:
      type: object
      properties:
        key:
          type: string
        source:
          enum:
            - RESOLVED_SECRET_SOURCE_UNSPECIFIED
            - RESOLVED_SECRET_SOURCE_WORKSPACE
            - RESOLVED_SECRET_SOURCE_TOOLSET
            - RESOLVED_SECRET_SOURCE_OBJECTIVE
          type: string
          format: enum
      description: >-
        ResolvedSecret is a resolved secret value from the workspace, toolset,
        or objective. When a tool is called, it will rely
         on secrets in the order of:
         - Objective
         - Toolset
         - Workspace
    BareMetadata:
      type: object
      properties:
        id:
          readOnly: true
          type: string
        name:
          readOnly: true
          type: string
          description: >-
            Human-readable name of the referenced resource, populated by the
            server
             on reads for convenience. Absent on references to resources that do not
             have a name (e.g., objective tasks).
      description: |-
        BareMetadata contains the minimal metadata for a resource: the ID and an
         optional human-readable name. These are used for reference fields where the
         full metadata (account scoping, timestamps, labels, external IDs) is not
         needed — e.g., the tool references inside an agent variation spec or the
         tools assigned to an objective. Both fields are server-populated; clients
         provide IDs through sibling fields rather than by constructing a
         BareMetadata themselves.
    CallableTool_Tool:
      type: object
      required:
        - type
        - tool
      properties:
        type:
          type: string
          enum:
            - tool
        tool:
          $ref: '#/components/schemas/ResourceMetadata'
    CallableTool_Agent:
      type: object
      required:
        - type
        - agent
      properties:
        type:
          type: string
          enum:
            - agent
        agent:
          $ref: '#/components/schemas/ResourceMetadata'
    CallableTool_CadenyaProvidedTool:
      type: object
      required:
        - type
        - cadenyaProvidedTool
      properties:
        type:
          type: string
          enum:
            - cadenyaProvidedTool
        cadenyaProvidedTool:
          $ref: '#/components/schemas/ResourceMetadata'
    AccountResourceMetadata:
      required:
        - id
        - accountId
        - name
        - profileId
      type: object
      properties:
        id:
          readOnly: true
          type: string
          description: >-
            Unique identifier for the resource (prefixed ULID, e.g.,
            "apikey_01HXK...")
        accountId:
          readOnly: true
          example: account_01HXKD2E5NQM3T9AYWCFTJHJVF
          type: string
          description: >-
            Account this resource belongs to for multi-tenant isolation
            (prefixed ULID)
        name:
          type: string
          description: >-
            Human-readable name for the resource (e.g., "Customer Support
            Agent", "Email Tool")
             Required for resources that users interact with directly
        externalId:
          type: string
          description: >-
            External ID for the resource (e.g., a workflow ID from an external
            system)
        labels:
          type: object
          additionalProperties:
            type: string
          description: |-
            Key-value pairs for categorization and filtering. Values are 0-63
             alphanumeric characters with "-", "_", or "." allowed between; keys
             follow the same shape and additionally accept an optional DNS-subdomain
             prefix (e.g. "cadenya.com/") of at most 253 characters.
             Examples: {"environment": "production", "team": "platform", "version": "v2"}
        profileId:
          readOnly: true
          example: profile_01HXKD2E5NQM3T9AYWCFS0AP08
          type: string
        createdAt:
          readOnly: true
          type: string
          format: date-time
      description: >-
        AccountResourceMetadata is used to represent a resource that is
        associated to an account but not to a workspace.
    ProfileSpec:
      required:
        - type
      type: object
      properties:
        email:
          type: string
          description: >-
            Email address of the profile. Required and unique within an account
            for
             user profiles.
        name:
          type: string
          description: Display name (e.g., "Bobby Tables").
        type:
          enum:
            - PROFILE_TYPE_UNSPECIFIED
            - PROFILE_TYPE_USER
            - PROFILE_TYPE_API_KEY
            - PROFILE_TYPE_SYSTEM
          type: string
          description: >-
            Whether this profile represents a human user, an API key, or a
            system
             principal.
          format: enum
      description: Configuration for a profile.
    ResourceMetadata:
      required:
        - id
        - accountId
        - workspaceId
        - name
        - profileId
        - createdAt
      type: object
      properties:
        id:
          readOnly: true
          type: string
          description: >-
            Unique identifier for the resource (prefixed ULID, e.g.,
            "agent_01HXK...")
        accountId:
          readOnly: true
          example: account_01HXKD2E5NQM3T9AYWCFTJHJVF
          type: string
          description: >-
            Account this resource belongs to for multi-tenant isolation
            (prefixed ULID)
        workspaceId:
          readOnly: true
          example: workspace_01HXKD2E5NQM3T9AYWCF133E3Q
          type: string
          description: >-
            Workspace this resource belongs to for organizational grouping
            (prefixed ULID)
        name:
          type: string
          description: >-
            Human-readable name for the resource (e.g., "Customer Support
            Agent", "Email Tool")
             Required for resources that users interact with directly
        externalId:
          type: string
          description: >-
            External ID for the resource (e.g., a workflow ID from an external
            system)
        labels:
          type: object
          additionalProperties:
            type: string
          description: |-
            Key-value pairs for categorization and filtering. Values are 0-63
             alphanumeric characters with "-", "_", or "." allowed between; keys
             follow the same shape and additionally accept an optional DNS-subdomain
             prefix (e.g. "cadenya.com/") of at most 253 characters.
             Examples: {"environment": "production", "team": "platform", "version": "v2"}
        profileId:
          readOnly: true
          example: profile_01HXKD2E5NQM3T9AYWCFS0AP08
          type: string
          description: ID of the actor (user or service account) that created this resource
        createdAt:
          readOnly: true
          type: string
          description: Timestamp when this resource was created
          format: date-time
        updatedAt:
          readOnly: true
          type: string
          description: Timestamp when this resource was last updated
          format: date-time
      description: >-
        Standard metadata for persistent, named resources (e.g., agents, tools,
        prompts)
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````