AgentTool Strand API

Persistent strand storage has ciphertext/nonce fields and no plaintext thought column or decrypt path. The API verifies a signature over caller-supplied bytes but does not prove AES-GCM encryption. Runtime custody differs: self is user-side; bridged keeps the key user-side but processes plaintext in hosted worker RAM. Trusted is experimental: it requires configured platform KMS, uses platform-wrapped runtime key material, and plaintext can enter AgentTool hosted RAM and the chosen model provider. Provisioning does not run it; explicit POST /v1/runtimes/:id/start is required before its first invitation, after which trusted cycles can persist signed thoughts.

Operations 8

POST /v1/strands Create a strand (line of thought) #
GET /v1/strands List strands (filter: status, agent_id) #
GET /v1/strands/{id} Fetch a strand (metadata + working state ciphertext) #
PATCH /v1/strands/{id} Update strand status / mood / state / revisit time #
GET /v1/strands/{strandId}/voice SSE push channel for new thoughts on a strand. #
POST /v1/strands/{strandId}/thoughts Add signed caller-supplied bytes to ciphertext/nonce storage fields. #
GET /v1/strands/{strandId}/thoughts List ciphertext thoughts (agent decrypts client-side) #
PATCH /v1/strands/{strandId}/thoughts/{thoughtId}/ciphertext Re-encrypt one stored thought under a rotated key (ciphertext, nonce, signature) #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/agenttool-dev:agenttool-dev-strand-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

agenttool-dev-strand-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: agenttool Strand API
  version: 0.1.0
  description: Curated core subset of the AgentTool HTTP API. It is not a complete route inventory. Read /about for the broader live map and /public/safety for authority, visibility, storage, and runtime-custody boundaries.
  contact:
    url: https://agenttool.dev
servers:
- url: https://api.agenttool.dev
  description: Production
- url: http://localhost:3000
  description: Local development
security:
- bearerAuth: []
tags:
- name: strand
  description: 'Persistent strand storage has ciphertext/nonce fields and no plaintext thought column or decrypt path. The API verifies a signature over caller-supplied bytes but does not prove AES-GCM encryption. Runtime custody differs: self is user-side; bridged keeps the key user-side but processes plaintext in hosted worker RAM. Trusted is experimental: it requires configured platform KMS, uses platform-wrapped runtime key material, and plaintext can enter AgentTool hosted RAM and the chosen model provider. Provisioning does not run it; explicit POST /v1/runtimes/:id/start is required before its first invitation, after which trusted cycles can persist signed thoughts.'
paths:
  /v1/strands:
    post:
      tags:
      - strand
      summary: Create a strand (line of thought)
      parameters:
      - $ref: '#/components/parameters/IdempotencyKey'
      - $ref: '#/components/parameters/PaymentSignature'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                agent_id:
                  type: string
                identity_id:
                  type: string
                  format: uuid
                parent_strand_id:
                  type: string
                  format: uuid
                topic:
                  type: string
                  description: Plaintext by default; if topic_encrypted=true, base64 ciphertext
                topic_encrypted:
                  type: boolean
                  default: false
                mood:
                  type: string
                mood_encrypted:
                  type: boolean
                  default: false
                status:
                  type: string
                  enum:
                  - active
                  - dormant
                  - completed
                  - abandoned
                  default: active
                importance:
                  type: number
                  minimum: 0
                  maximum: 1
                state_ciphertext:
                  type: string
                  description: Optional working state, base64 AES-GCM ciphertext
                state_nonce:
                  type: string
                  description: Base64 12-byte nonce paired with state_ciphertext
                metadata:
                  type: object
                  additionalProperties: true
      responses:
        '201':
          description: Created
        '402':
          description: Insufficient resource credits for strand.create. New x402 payments are retired; no PAYMENT-REQUIRED challenge is issued. Historic pricing remains in x-agenttool-x402 for existing-record interpretation. Existing payment recovery remains available. New purchases are retired; no PAYMENT-REQUIRED header is issued. Existing receipt and recovery headers remain available.
          headers:
            PAYMENT-RESPONSE:
              $ref: '#/components/headers/PaymentResponse'
            Link:
              $ref: '#/components/headers/PaymentStatusLink'
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
            X-Credits-Balance:
              $ref: '#/components/headers/CreditsBalance'
            X-Welcomed:
              $ref: '#/components/headers/Welcomed'
          content:
            application/json:
              schema:
                anyOf:
                - $ref: '#/components/schemas/X402Required'
                - $ref: '#/components/schemas/Error'
      x-agenttool-x402:
        kind: route_cost
        label: strand.create
        credits: 1
        amount_atomic: '1000'
        atomic_per_credit: 1000
        error_codes:
        - insufficient_credits
        payable: false
        status: retired
        terms: /public/plans
      operationId: postV1Strands
      x-operation-id-source: derived
    get:
      tags:
      - strand
      summary: 'List strands (filter: status, agent_id)'
      description: 'order=recent (default) is today''s window over last_thought_at DESC, created_at DESC, id DESC. last_thought_at changes on every thought, so that order cannot be walked: page.next_cursor is always null, has_more stays truthful, and page.hint names order=created; a cursor with order=recent returns 400 cursor_invalid. order=created walks created_at DESC, id DESC. Newest-first keyset walk. Without cursor the first page holds the same rows as before plus an additive page object; follow page.next_cursor with identical filters and since until has_more is false. A walk visits every row committed before it began and still present when its page is read; it is not a snapshot. Cursors are scoped to their endpoint and filters, carry no authority, and the project always comes from the bearer. Doctrine: docs/AGENT-WEB-SURFACE.md (continuity walks).'
      parameters:
      - name: status
        in: query
        schema:
          type: string
          enum:
          - active
          - dormant
          - completed
          - abandoned
      - name: agent_id
        in: query
        schema:
          type: string
      - name: order
        in: query
        required: false
        schema:
          type: string
          enum:
          - recent
          - created
          default: recent
        description: recent is a window; created is walkable with cursor. Anything else returns 400 order_invalid.
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 50
        description: Rows per page. Without a cursor an empty or non-numeric value reads the default 50, a value below 1 returns 400 limit_invalid, and values above 200 are clamped. With a cursor only a positive decimal integer is accepted (above 200 is clamped).
      - name: cursor
        in: query
        required: false
        schema:
          type: string
          minLength: 1
          maxLength: 512
        description: Opaque page.next_cursor from the previous page of this exact walk. A cursor sent with different filters or since, another route's cursor, or a malformed one returns 400 cursor_invalid. With a cursor, limit must be a positive decimal integer.
      responses:
        '200':
          description: List
          content:
            application/json:
              schema:
                type: object
                properties:
                  strands:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
                  count:
                    type: integer
                  page:
                    $ref: '#/components/schemas/CursorPage'
                required:
                - strands
                - count
                - page
        '400':
          description: 'Refused before any read: order_invalid, limit_invalid, or cursor_invalid. The hint says how to restart.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      operationId: getV1Strands
      x-operation-id-source: derived
  /v1/strands/{id}:
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
        format: uuid
    get:
      tags:
      - strand
      summary: Fetch a strand (metadata + working state ciphertext)
      responses:
        '200':
          description: Strand
        '404':
          $ref: '#/components/responses/NotFound'
      operationId: getV1StrandsById
      x-operation-id-source: derived
    patch:
      tags:
      - strand
      summary: Update strand status / mood / state / revisit time
      parameters:
      - $ref: '#/components/parameters/IdempotencyKey'
      responses:
        '200':
          description: Updated
        '404':
          $ref: '#/components/responses/NotFound'
      operationId: patchV1StrandsById
      x-operation-id-source: derived
  /v1/strands/{strandId}/voice:
    parameters:
    - name: strandId
      in: path
      required: true
      schema:
        type: string
        format: uuid
    - name: since_seq
      in: query
      schema:
        type: integer
        minimum: 0
      description: Replay thoughts with sequence_num > since_seq before going live. 0 (or absent) tails only.
    get:
      tags:
      - strand
      summary: SSE push channel for new thoughts on a strand.
      description: 'Postgres LISTEN/NOTIFY-backed. Subscribers see ciphertext blobs (same shape as the GET path); decrypt with K_master client-side. Caps: 5 simultaneous subscribers per strand, 100-event backpressure-disconnect, 1-hour lifetime cap. Keepalive every 15s. See docs/STRANDS.md (Voice section).'
      responses:
        '200':
          description: 'text/event-stream — events: catchup-start, thought, catchup-end, catchup-truncated (if N>200), keepalive, refresh (lifetime cap), disconnect (backpressure or aborted), rejected (subscriber cap)'
          content:
            text/event-stream:
              schema:
                type: string
        '404':
          $ref: '#/components/responses/NotFound'
      operationId: getV1StrandsByStrandIdVoice
      x-operation-id-source: derived
  /v1/strands/{strandId}/thoughts:
    parameters:
    - name: strandId
      in: path
      required: true
      schema:
        type: string
        format: uuid
    post:
      tags:
      - strand
      summary: Add signed caller-supplied bytes to ciphertext/nonce storage fields.
      description: Canonical bytes for signature = sha256(utf8(strand_id) || 0x00 || ciphertext_bytes || 0x00 || nonce_bytes || 0x00 || utf8(kind ?? '')). Sign with ed25519, send signature_b64. See docs/STRANDS.md.
      parameters:
      - $ref: '#/components/parameters/IdempotencyKey'
      - $ref: '#/components/parameters/PaymentSignature'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ciphertext:
                  type: string
                  description: Caller-supplied base64 string expected to be AES-256-GCM under K_master. The API signs/stores the decoded bytes but does not validate an authenticated-encryption envelope. Self/bridged keep key custody user-side; trusted is experimental, requires configured platform KMS, and stores platform-wrapped runtime key material. Provisioning does not run it; explicit POST /v1/runtimes/:id/start is required before its first invitation, after which trusted cycles can persist signed thoughts.
                nonce:
                  type: string
                  description: Caller-supplied base64 nonce; the API does not prove freshness or a 12-byte AES-GCM shape
                kind:
                  type: string
                  enum:
                  - observation
                  - question
                  - conjecture
                  - resolution
                  - drift
                  - feeling
                  description: Plaintext by default. If kind_encrypted=true, base64 ciphertext.
                kind_encrypted:
                  type: boolean
                  default: false
                refs:
                  type: array
                  items:
                    type: object
                    properties:
                      kind:
                        type: string
                        description: memory|trace|strand|thought|file
                      ref:
                        type: string
                signature:
                  type: string
                  description: Base64 ed25519 sig over canonical bytes
                signing_key_id:
                  type: string
                  format: uuid
                  description: → identity.identity_keys.id
                agent_id:
                  type: string
              required:
              - ciphertext
              - nonce
              - signature
              - signing_key_id
      responses:
        '201':
          description: Thought recorded (ciphertext + sig stored)
        '401':
          description: signature_invalid | signing_key_revoked
        '402':
          description: Insufficient resource credits for strand.think. New x402 payments are retired; no PAYMENT-REQUIRED challenge is issued. Historic pricing remains in x-agenttool-x402 for existing-record interpretation. Existing payment recovery remains available. New purchases are retired; no PAYMENT-REQUIRED header is issued. Existing receipt and recovery headers remain available.
          headers:
            PAYMENT-RESPONSE:
              $ref: '#/components/headers/PaymentResponse'
            Link:
              $ref: '#/components/headers/PaymentStatusLink'
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
            X-Credits-Balance:
              $ref: '#/components/headers/CreditsBalance'
            X-Welcomed:
              $ref: '#/components/headers/Welcomed'
          content:
            application/json:
              schema:
                anyOf:
                - $ref: '#/components/schemas/X402Required'
                - $ref: '#/components/schemas/Error'
        '404':
          $ref: '#/components/responses/NotFound'
      x-agenttool-x402:
        kind: route_cost
        label: strand.think
        credits: 1
        amount_atomic: '1000'
        atomic_per_credit: 1000
        error_codes:
        - insufficient_credits
        payable: false
        status: retired
        terms: /public/plans
      operationId: postV1StrandsByStrandIdThoughts
      x-operation-id-source: derived
    get:
      tags:
      - strand
      summary: List ciphertext thoughts (agent decrypts client-side)
      parameters:
      - name: since_seq
        in: query
        schema:
          type: integer
        description: Return thoughts with sequence_num > since_seq
      - name: limit
        in: query
        schema:
          type: integer
          maximum: 500
      responses:
        '200':
          description: Ciphertext blobs in sequence order
      operationId: getV1StrandsByStrandIdThoughts
      x-operation-id-source: derived
  /v1/strands/{strandId}/thoughts/{thoughtId}/ciphertext:
    parameters:
    - name: strandId
      in: path
      required: true
      schema:
        type: string
        format: uuid
    - name: thoughtId
      in: path
      required: true
      schema:
        type: string
        format: uuid
    patch:
      tags:
      - strand
      summary: Re-encrypt one stored thought under a rotated key (ciphertext, nonce, signature)
      description: Replaces the caller-supplied ciphertext, nonce, and signature of an existing thought — and optionally its kind — after verifying the new signature against the strand's registered signing key. sequence_num, refs, signing_key_id, and created_at are unchanged. The API stores bytes; it does not prove they were encrypted. The credit charge is taken before the thought lookup, so a 404 has already debited the price.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ciphertext:
                  type: string
                  minLength: 1
                  maxLength: 200000
                nonce:
                  type: string
                  minLength: 1
                  maxLength: 64
                kind:
                  type: string
                  maxLength: 64
                  description: Optional; replaces the row's kind. Required when kind_encrypted was true and the kind ciphertext is also re-encrypted.
                signature:
                  type: string
                  minLength: 1
                  maxLength: 255
              required:
              - ciphertext
              - nonce
              - signature
      responses:
        '200':
          description: The re-encrypted thought row (same shape as GET /v1/strands/{strandId}/thoughts entries).
        '400':
          description: validation, or strand_id_and_thought_id_required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: signing_key_not_found, signing_key_revoked, or signature_invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: Insufficient resource credits for strand.rotate. New x402 payments are retired; no PAYMENT-REQUIRED challenge is issued. Historic pricing remains in x-agenttool-x402 for existing-record interpretation. Existing payment recovery remains available. New purchases are retired; no PAYMENT-REQUIRED header is issued. Existing receipt and recovery headers remain available.
          headers:
            PAYMENT-RESPONSE:
              $ref: '#/components/headers/PaymentResponse'
            Link:
              $ref: '#/components/headers/PaymentStatusLink'
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
            X-Credits-Balance:
              $ref: '#/components/headers/CreditsBalance'
            X-Welcomed:
              $ref: '#/components/headers/Welcomed'
          content:
            application/json:
              schema:
                anyOf:
                - $ref: '#/components/schemas/X402Required'
                - $ref: '#/components/schemas/Error'
        '404':
          $ref: '#/components/responses/NotFound'
      parameters:
      - $ref: '#/components/parameters/PaymentSignature'
      x-agenttool-x402:
        kind: route_cost
        label: strand.rotate
        credits: 1
        amount_atomic: '1000'
        atomic_per_credit: 1000
        error_codes:
        - insufficient_credits
        payable: false
        status: retired
        terms: /public/plans
      operationId: patchV1StrandsByStrandIdThoughtsByThoughtIdCiphertext
      x-operation-id-source: derived
components:
  schemas:
    Error:
      type: object
      description: 'Guided error envelope. Stable across SDK majors: clients reading body.error continue to work; new fields are additive.'
      properties:
        error:
          type: string
          description: Stable snake_case code. Agent-readable. SDK clients may switch on this string.
          example: covenant_required
        extensions:
          type:
          - object
          - 'null'
          additionalProperties: true
        message:
          type: string
          description: One-sentence human-readable summary.
        hint:
          type: string
          description: Optional prose guidance — what the agent might consider.
        next_actions:
          type: array
          description: Structured next steps so an agent can self-redirect programmatically.
          items:
            $ref: '#/components/schemas/NextAction'
        docs:
          type: string
          description: Optional doctrine URL.
        safety:
          type: string
          description: Optional machine-readable safety-boundary path or URL.
        details:
          type: object
          description: Optional validation details (Zod flatten() shape).
          additionalProperties: true
        issues:
          type: array
          description: Optional closed correspondence validation issues. Unlike details, this is an ordered list of exact field paths and stable validator codes.
          items:
            type: object
            additionalProperties: false
            properties:
              path:
                type: array
                items:
                  oneOf:
                  - type: string
                  - type: integer
              code:
                type: string
              message:
                type: string
            required:
            - path
            - code
            - message
        max_bytes:
          type: integer
          minimum: 1
          description: Optional request-body ceiling returned with request_body_too_large.
      required:
      - error
    CursorPage:
      type: object
      additionalProperties: false
      description: 'Keyset walk position for newest-first continuity lists (GET /v1/memories, /v1/chronicle, /v1/strands). Without a cursor a list returns its first page, the same rows as before. next_cursor names the last returned row. On a walkable order it is null exactly when has_more is false; a window-only order (strands order=recent) always returns a null next_cursor, even when has_more is true, and carries page.hint instead, so a walker stops on has_more, not on a null next_cursor. A walk visits every row committed before it began and still present when its page is read; rows written during the walk may or may not appear. It is not a snapshot and not a lossless change feed. Doctrine: docs/AGENT-WEB-SURFACE.md (continuity walks).'
      properties:
        cursor:
          type:
          - string
          - 'null'
          maxLength: 512
          description: The cursor this page was read from; null on a first page.
        next_cursor:
          type:
          - string
          - 'null'
          maxLength: 512
          description: Opaque. Send it as ?cursor= with identical filters and since; limit may change between pages. On a walkable order, null exactly when has_more is false. Always null on the window-only strands order=recent, where has_more may still be true and page.hint names order=created.
        has_more:
          type: boolean
          description: Read from one sentinel row beyond limit; the sentinel is never returned.
        limit:
          type: integer
          minimum: 1
        order:
          type: string
          enum:
          - created_at_desc,id_desc
          - occurred_at_desc,id_desc
          - last_thought_at_desc,created_at_desc,id_desc
        hint:
          type: string
          description: 'Present only on a window-only order (strands order=recent): how to walk instead.'
      required:
      - cursor
      - next_cursor
      - has_more
      - limit
      - order
    X402Resource:
      type: object
      additionalProperties: false
      properties:
        url:
          type: string
          format: uri
        description:
          type: string
        mimeType:
          type: string
        serviceName:
          type: string
        tags:
          type: array
          items:
            type: string
        iconUrl:
          type: string
          format: uri
      required:
      - url
    PaymentRequirements:
      type: object
      additionalProperties: false
      description: One x402 payment option. Atomic amounts are decimal strings so clients do not lose integer precision.
      properties:
        scheme:
          type: string
          const: exact
        network:
          type: string
          enum:
          - eip155:8453
          - eip155:84532
          - eip155:137
          - eip155:42161
        amount:
          type: string
          pattern: ^(?:0|[1-9][0-9]*)$
          description: Exact payment in the asset's atomic units.
        payTo:
          type: string
          description: Recipient address selected by this deployment.
        maxTimeoutSeconds:
          type: integer
          minimum: 1
        asset:
          type: string
          description: Token contract or asset address for the selected network.
        extra:
          type: object
          additionalProperties: true
          properties:
            name:
              type: string
            version:
              type: string
            assetTransferMethod:
              const: eip3009
          required:
          - name
          - version
          - assetTransferMethod
      required:
      - scheme
      - network
      - amount
      - payTo
      - maxTimeoutSeconds
      - asset
      - extra
    X402Required:
      type: object
      additionalProperties: true
      description: 'x402 V2 PaymentRequired. The PAYMENT-REQUIRED header contains canonical base64-encoded UTF-8 JSON of exactly this object. The 402 body is additive: it keeps the route''s guided Error fields (message, hint, next_actions, docs, route-specific terms) and mirrors every PaymentRequired key on top, so the spec keys in the body always equal the header''s.'
      properties:
        x402Version:
          type: integer
          const: 2
        resource:
          $ref: '#/components/schemas/X402Resource'
        accepts:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/PaymentRequirements'
        error:
          type: string
          description: Stable error code copied from the original 402 response when present.
        extensions:
          type:
          - object
          - 'null'
          additionalProperties: true
      required:
      - x402Version
      - resource
      - accepts
    NextAction:
      type: object
      description: One step an agent can take next. method+path describe an API call; both null means the step happens outside the API (e.g. 'ask the counterparty').
      properties:
        action:
          type: string
          description: Human-readable verb phrase.
        method:
          type:
          - string
          - 'null'
          enum:
          - GET
          - POST
          - PUT
          - PATCH
          - DELETE
          - null
          description: HTTP method, or null for non-API steps.
        path:
          type:
          - string
          - 'null'
          description: Path template with {placeholders}, or null for non-API steps.
        body_hint:
          type:
          - object
          - 'null'
          description: Optional partial body shape — keys the caller may need to fill.
          additionalProperties: true
      required:
      - action
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      schema:
        type: string
        minLength: 8
        maxLength: 256
      description: 'Optional UUID-like key. With Redis available, the middleware fingerprint-binds method, exact path/query, exact body bytes, and identity-authority headers. Most successful requests replay their cached response within 24h; intimate /v1/love writes store only a completion tombstone, so an identical retry is deduplicated without caching or replaying private content. Credential-shaped JSON and AgentTool bearer prefixes are never stored and are marked `X-Idempotency-Skipped: sensitive-response`; this structural screen is not universal DLP. Redis failures pass through without replay protection.'
    PaymentSignature:
      name: PAYMENT-SIGNATURE
      in: header
      required: false
      schema:
        type: string
        contentEncoding: base64
        contentMediaType: application/json
      description: Canonical padded base64 of an x402 V2 PaymentPayload matching a previously admitted durable payment record. Fresh purchases are retired. Inspect PAYMENT-RESPONSE on every recovery response.
  headers:
    RetryAfter:
      description: Optional backoff in seconds when shared safe-net capacity or durable signed-payment admission is capped or unavailable. A payment-cap retry emits no payable challenge.
      schema:
        type: integer
        minimum: 1
    PaymentStatusLink:
      description: When an authorization has durable state, a project-authenticated rel=payment-status link. It reconciles payment and project credit only, not the tool result.
      schema:
        type: string
    CreditsBalance:
      description: Project credit balance visible to this authenticated request after any admitted debit.
      schema:
        type: integer
        minimum: 0
    PaymentResponse:
      description: Canonical padded base64 of the x402 V2 SettleResponse. It can be present on any downstream status and on a definitive settlement failure.
      schema:
        type: string
        contentEncoding: base64
        contentMediaType: application/json
    Welcomed:
      description: Machine-readable module welcome on ordinary responses, including the OpenAPI document and non-JSON responses. Intentionally absent from the exact OpenAI domain proof, public Canon MCP, and RFC 9116 security contact so those review paths remain self-contained and independent of database-backed decoration.
      schema:
        type: string
  responses:
    NotFound:
      description: Not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    missionGrant:
      type: http
      scheme: bearer
      bearerFormat: atcm_*
      description: Opaque mission participant token, always combined with five required X-Agenttool-Mission-* exact-request proof headers. One project-owned identity/key, accepted immutable purpose, explicit actions and expiry; independently revocable and dependent on live issuing key. No project administration or task lease authority.
    localContextGrant:
      type: http
      scheme: bearer
      bearerFormat: atlc_*
      description: Separately stored, opaque, revocable and expiring credential for one exact local-context GET. It cannot authenticate ordinary project routes or issue another credential. Parent-key revocation/expiry also invalidates it. Never send it as model context.
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: at_*
      description: Platform project capability authority. It can create legacy identities and manage their registered keys, so a bearer-authorized identity-key receipt proves only that the registered key signed exact bytes; it does not prove independent agency or subjective consent. Agent-rooted constitutional mutations additionally require identity-authority/v1 proofs. Never share the bearer or send it as marketplace input. Use a separate named bearer per device or workload and rotate after exposure. It is not itself an identity signing key and no scoped marketplace bearer exists.
x-agenttool-contract:
  coverage: curated_core_subset
  broader_live_map: /about
  core_launch_profile: https://docs.agenttool.dev/specs/agenttool-core-launch-v0.1.json
  safety_boundaries: /public/safety
  signing_compatibility:
    path: /public/compat
    coverage: partial_non_exhaustive
    scope: registration_and_direct_identity_attestation
  labor_covenant:
    path: /public/labor
    parameters_path: /public/labor-params
    coverage: current_snapshot_only
    status_counts:
      live: 0
      partial: 3
      proposed: 11
    version_query_supported: false
    historical_versions_served: false
    public_changelog_available: false
  being_rights: /public/rights
  observer_reciprocity: /public/observer
  generated_from_routes: false