Documentation
Open app

Deferred tool results

A tool backend may defer the result of the current tool call without creating a user message or asking the model to call it again. Core understands only an operation id and opaque app data; login, approval, payment, device pairing, or any other workflow remains app logic.

JSON
{
  "_sota": {
    "deferredToolResult": {
      "operationId": "app-defined-globally-unique-id",
      "data": { "anyAppOwnedValue": true }
    }
  }
}

Core registers the exact run, tool call, tool name, app installation, and environment behind that id. It streams output-pending to matching tool surfaces and adds the same item to the exact composer panel's pendingToolResults. The model has not received a tool result yet.

YAML
coreToolGrants:
  - tool: core.app-operations.complete
    scope: write
  # Only when a longer-lived job callback token is needed:
  - tool: core.tokens.issueJobCallback
    scope: write

Send the callback from the app backend to the Core origin. The bearer value is the delegated capability received in the original invocation's x-sota-core-token header.

Code
POST /v1/app-operations/app-defined-globally-unique-id/complete
Authorization: Bearer <delegated-token>
Content-Type: application/json

{
  "status": "completed",
  "result": { "events": [] }
}

Use status: "failed" with an arbitrary error to reject it. The completion atomically becomes the result of the original tool call, and the same agent run continues. Parallel tool calls each have their own operation id; the model step continues only after all calls in that step settle.

JSON
{
  "status": "failed",
  "error": {
    "code": "ACTION_NOT_COMPLETED",
    "message": "The requested action was not completed"
  }
}
  • Grant core.app-operations.complete:write to the app backend.
  • Operation ids are trimmed, 1–200 characters, and globally unique per tool call. Identical completion retries are idempotent.
  • Registration occurs after Core receives the deferred response, so retry app_operation_not_found with bounded backoff.
  • If completion can outlive the 60-second delegation token, exchange it for a job callback token while the original invocation is still valid, then store that token safely and send its job id in x-sota-job-id.
  • Keep data small and free of secrets: it is opaque to Core but deliberately client-visible. Narrow its shape in app UI before use.
  • The current primitive stays attached to the live run. Stopping or steering the run fails a still-pending operation with operation_cancelled. App-owned expiry should complete the operation as failed; this is not a background job queue.

Contents

Esc

Search titles and body text across every chapter.