> ## Documentation Index
> Fetch the complete documentation index at: https://ara-90a60a07.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Message a Reason

> Messaging a Reason is the primary way to give it work. The message goes into the Reason's long-running conversation, which this call opens the first time (as openReasonConversation does); the Reason then decides how to do the work: it answers, starts Sessions, or sets up Loops. Sessions it starts are filed under it.

The message is delivered exactly as sendSessionMessage delivers a follow-up to the conversation Session: the same body, admission, usage and safeguards. A message sent while the Reason is working steers its running turn (or waits for the next one with `delivery` queue). The call returns once the message is accepted, not when the Reason answers: poll listReasonMessages with the last `end_cursor` for its reply, or follow the Session (`session_id`) with getSession and listSessionEvents. Send a `client_message_id` to make retries safe: resending with it returns the accepted message instead of adding another. Anyone the Reason is shared with may message it; each turn acts as the person who sent it.

<sub>Scope: `run`</sub>



## OpenAPI

````yaml /openapi.json post /v3/organizations/{orgId}/reasons/{reasonId}/messages
openapi: 3.1.0
info:
  title: Reason API
  version: 3.0.0
  description: >-
    The Reason HTTP API. Drive cloud software-engineering agents: open sessions
    against your repositories, stream their work, and manage the secrets,
    skills, and automations they run with.


    Authenticate with a Reason API key sent as a bearer token. New keys use
    `reason_`; legacy `ara_` keys remain accepted. Every resource is scoped to
    an organization; resolve your `org_id` once with `GET /v3/self`.
servers:
  - url: https://api.reasonmachines.com
security:
  - reasonApiKey: []
tags:
  - name: Account
    description: Verify a key and resolve the organization it belongs to.
  - name: Reasons
    description: >-
      Start here. A Reason is the long-running agent a person keeps: their main
      Reason and named ones, each with its own instructions, default model and
      repositories, conversation, Loops and Sessions. Give a Reason work by
      messaging it (sendReasonMessage) and read its replies with
      listReasonMessages.
  - name: Loops
    description: >-
      Standing work a Reason does, woken by a schedule or an event: a webhook, a
      GitHub event or a Slack message. Each wake opens or continues a Session of
      the Reason; webhook events that share a correlation key continue one
      Session.
  - name: Memory
    description: >-
      What Reasons remember across Sessions. Each Session starts by reading
      MEMORY.md (a short index) and the list of topic notes, and reads a note
      when its topic comes up. `personal` memory belongs to one person (the API
      key's owner) and only their Sessions read it; `team` memory belongs to the
      Workspace and every member's Sessions read it. memory:read lists, reads
      and searches; memory:write writes and deletes, in team memory only for a
      Workspace owner or admin.
  - name: Sessions
    description: >-
      A Session is one run of work inside a Reason: every Reason message and
      Loop wake runs in one, and createSession starts one directly for a single
      unattended task with a pass/fail outcome. Its transcript, events, result
      and pull request are read here.
  - name: Skills
    description: >-
      Reusable instruction bundles Reason selects semantically from their
      descriptions for matching agent tasks.
  - name: Secrets
    description: >-
      Encrypted credentials injected into the agent's sandbox. Write-only:
      values can be set but never read back.
  - name: Attachments
    description: >-
      Files uploaded to the organization and shared with sessions, downloaded
      via short-lived signed URLs.
  - name: Repositories
    description: Connected repositories, their indexing state, and generated wikis.
  - name: Git Connections
    description: Linked source-control accounts and the repositories they expose.
  - name: Machines
    description: >-
      Named Workspace queues served by headless workers. Sessions target a
      Machine by name and wait for a free worker; more workers serve more
      Sessions concurrently.
  - name: Devices
    description: >-
      Owned Mac and headless Device identity, bounded enrollment and root
      grants.
  - name: Cloud Access
    description: >-
      Keyless cloud sign-in for sessions: Reason's OIDC issuer facts and the
      AWS, Google Cloud and Azure connections a workspace trusts, including
      which run triggers each one signs in.
  - name: MCP Servers
    description: >-
      Org-level Model Context Protocol servers exposed to the agent. Secret
      values are write-only.
  - name: Change Request Reviews
    description: >-
      Automated senior-engineer reviews posted on pull requests and merge
      requests.
  - name: Consumption
    description: 'Billing-aligned usage: daily consumption and billing cycles.'
  - name: Metrics
    description: Aggregate analytics over sessions, change requests, and usage.
  - name: Audit Logs
    description: An append-only record of changes made within the organization.
  - name: Organizations
    description: The top-level tenant. Create, read, update, and delete organizations.
  - name: Members
    description: People in an organization and their pending invites.
  - name: Roles
    description: Role assignments that govern what each member can do.
  - name: Settings
    description: 'Organization configuration: namespaced settings and the run tag policy.'
  - name: Provider credentials
    description: >-
      Configure Bring-Your-Own-Key (BYOK) API keys and subscription credentials
      for model providers. Secret values are write-only.
  - name: Feedback
    description: Report problems with the API or these docs to the Reason team.
  - name: Projects
    description: >-
      Deprecated: a project is a Reason with the same id. Use the Reasons
      operations; these remain for existing clients.
  - name: Automations
    description: >-
      The older form of Loops. Prefer the Loops under a Reason (listReasonLoops,
      createReasonLoop), which take every wake: schedule, webhook, GitHub,
      Slack. Use these for what Loops do not carry yet: a run's MCP and app
      tools, and automations not filed under a Reason.
paths:
  /v3/organizations/{orgId}/reasons/{reasonId}/messages:
    parameters:
      - $ref: '#/components/parameters/orgId'
      - name: reasonId
        description: The Reason id, returned as `id` by `listReasons` and `createReason`.
        in: path
        required: true
        schema:
          type: string
          format: uuid
    post:
      tags:
        - Reasons
      summary: Message a Reason
      description: >-
        Messaging a Reason is the primary way to give it work. The message goes
        into the Reason's long-running conversation, which this call opens the
        first time (as openReasonConversation does); the Reason then decides how
        to do the work: it answers, starts Sessions, or sets up Loops. Sessions
        it starts are filed under it.


        The message is delivered exactly as sendSessionMessage delivers a
        follow-up to the conversation Session: the same body, admission, usage
        and safeguards. A message sent while the Reason is working steers its
        running turn (or waits for the next one with `delivery` queue). The call
        returns once the message is accepted, not when the Reason answers: poll
        listReasonMessages with the last `end_cursor` for its reply, or follow
        the Session (`session_id`) with getSession and listSessionEvents. Send a
        `client_message_id` to make retries safe: resending with it returns the
        accepted message instead of adding another. Anyone the Reason is shared
        with may message it; each turn acts as the person who sent it.


        <sub>Scope: `run`</sub>
      operationId: sendReasonMessage
      parameters:
        - in: header
          name: X-Reason-Agent
          required: false
          schema:
            type: string
            maxLength: 80
          description: >-
            Optional self-reported caller agent name. If absent, the server uses
            the User-Agent for external callers.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                message:
                  type: string
                  description: >-
                    The follow-up instruction for the agent. It reaches the
                    running turn or starts the next one; the response's
                    `delivery` says which.
                attachments:
                  type: array
                  items:
                    anyOf:
                      - type: object
                        properties:
                          id:
                            type: string
                            description: >-
                              Caller-chosen identifier for this file, kept with
                              the stored attachment. Omitted, the file is
                              numbered by its position: att-1, att-2 and so on.
                          name:
                            type: string
                            description: >-
                              File name shown with the attachment, for example
                              screenshot.png. It also supplies the content type
                              when none is given; an empty name becomes
                              attachment-1, attachment-2 and so on.
                          content_type:
                            type: string
                            description: >-
                              MIME type of the file, for example image/png.
                              Omitted, the data URL's media type is used; when
                              that is empty or application/octet-stream, the
                              type is inferred from the name's extension.
                          contentType:
                            description: Legacy alias of content_type.
                            type: string
                          data_url:
                            type: string
                            description: >-
                              Base64 data URL. Stored privately with the Session
                              before dispatch.
                        required:
                          - name
                          - data_url
                      - type: object
                        properties:
                          id:
                            type: string
                            description: >-
                              Caller-chosen identifier for this file, kept with
                              the stored attachment. Omitted, the file is
                              numbered by its position: att-1, att-2 and so on.
                          name:
                            type: string
                            description: >-
                              File name shown with the attachment, for example
                              screenshot.png. It also supplies the content type
                              when none is given; an empty name becomes
                              attachment-1, attachment-2 and so on.
                          content_type:
                            type: string
                            description: >-
                              MIME type of the file, for example image/png.
                              Omitted, the data URL's media type is used; when
                              that is empty or application/octet-stream, the
                              type is inferred from the name's extension.
                          contentType:
                            description: Legacy alias of content_type.
                            type: string
                          dataUrl:
                            type: string
                            description: Legacy alias of data_url.
                        required:
                          - name
                          - dataUrl
                  description: >-
                    Up to 10 attachments; maximum 64 MiB per file and 80 MiB
                    total decoded bytes. The endpoint's request-body limit also
                    applies to the encoded payload.
                client_message_id:
                  type: string
                  minLength: 1
                  maxLength: 160
                  description: >-
                    Caller-generated idempotency key. Reusing it for the same
                    Session returns the original accepted turn.
                model:
                  type: string
                  description: >-
                    Optional model id from `GET /agent-auth/models` to retry
                    this session on. A model override always starts a new
                    continuation run, because a run's model is fixed at its
                    first execution. Omit or use `auto` to keep the session's
                    current model.
                reasoning_effort:
                  type: string
                  enum:
                    - minimal
                    - low
                    - medium
                    - high
                    - xhigh
                    - max
                  description: >-
                    How much reasoning the model should use for the follow-up
                    turn. Higher effort trades time and token usage for more
                    deliberation; supported levels depend on the selected model.
                    Omit to retain the Session's effort setting.
                allow_model_rollover:
                  type: boolean
                  description: >-
                    Same as the create field, for this and later turns: the
                    follow-up goes on with the provider's other accounts, then
                    Reason, when the Session's subscription or key runs out. A
                    Session that already rolls over keeps doing so.
                delivery:
                  type: string
                  enum:
                    - steer
                    - queue
                  description: >-
                    While a turn runs: steer (the default) hands the message to
                    the running turn; queue holds it until the turn ends and
                    then runs it as the next one. A queued message can be sent
                    at once or withdrawn with its message_id (POST
                    .../messages/{messageId}/steer, DELETE
                    .../messages/{messageId}/queued). Not combinable with
                    target.
                target:
                  oneOf:
                    - type: object
                      properties:
                        kind:
                          type: string
                          const: cloud
                          description: Run on Reason-managed cloud compute.
                        computer_id:
                          description: >-
                            Start on this cloud computer of the Session's Reason
                            (project_id, else your main Reason), from
                            createReasonComputer. It keeps its own size. 409
                            computer_unavailable when that Reason's Sessions
                            each keep their own computer; 404 computer_not_found
                            when it is not one of the Reason's computers you may
                            use.
                          type: string
                          format: uuid
                          pattern: >-
                            ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
                      required:
                        - kind
                      additionalProperties: false
                    - type: object
                      properties:
                        kind:
                          type: string
                          const: mac
                          description: Run on a connected Mac.
                        device_id:
                          type: string
                          format: uuid
                          pattern: >-
                            ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
                          description: Connected Mac ID returned by listDevices.
                        root_id:
                          description: >-
                            Optional: a Mac Device is the whole machine. Omit it
                            to run in the Mac's own Reason workspace; older
                            clients send the exact root id, which is still
                            honored.
                          type: string
                          format: uuid
                          pattern: >-
                            ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
                        cwd:
                          description: >-
                            Absolute folder on the Mac the Session works in,
                            like a terminal's working directory. Nothing is
                            granted or locked. It runs on the deepest folder the
                            Mac granted Reason that holds it (an older Reason
                            Device: only a folder inside its home folder); 409
                            local_device_cwd_not_granted when no granted folder
                            holds it. Not combinable with root_id.
                          type: string
                          minLength: 1
                          maxLength: 4096
                          pattern: ^\/[^\x00-\x1f\x7f]*$
                        isolation:
                          description: >-
                            With cwd: worktree (the default for repository work)
                            gives the Session its own git worktree at
                            ~/.reason/workspace/sessions/<id>/<repository> on
                            branch reason/<id>; in_place works directly in cwd.
                          type: string
                          enum:
                            - worktree
                            - in_place
                      required:
                        - kind
                        - device_id
                      additionalProperties: false
                    - type: object
                      properties:
                        kind:
                          type: string
                          const: headless
                          description: >-
                            Run on a CLI-connected computer or externally
                            provisioned worker.
                        device_id:
                          type: string
                          format: uuid
                          pattern: >-
                            ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
                          description: >-
                            Connected computer or worker ID returned by
                            listDevices.
                        root_id:
                          description: >-
                            Optional on your own computer (`reason connect`):
                            omit it to run on the deepest granted folder holding
                            the cwd, else on its home grant (the folder you last
                            used for the repository there, else a managed
                            checkout), or on a worker's only folder. Required
                            when the worker holds several folders, none is its
                            home folder and no cwd is named (409
                            local_device_root_ambiguous otherwise).
                          type: string
                          format: uuid
                          pattern: >-
                            ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
                        workspace_mode:
                          description: >-
                            Defaults to a stable Session-managed checkout.
                            project_root explicitly operates the selected
                            existing root.
                          type: string
                          enum:
                            - managed
                            - project_root
                        workspace_path:
                          description: >-
                            Absolute path of the project_root on the Device, as
                            the client sees it (for example /app). Read only
                            with workspace_mode project_root, as the working
                            directory the default C2 harness names in its model
                            prompt; ignored otherwise, and rejected when the
                            request names experimental_runtime_profile
                            runtime/reason-c2-tools-v7. It grants nothing and
                            never selects a directory.
                          type: string
                          maxLength: 4096
                          pattern: ^\/[^\u0000\r\n]*$
                        cwd:
                          description: >-
                            Your own computer (`reason connect`) only: the
                            absolute folder the Session works in, as for a Mac,
                            in a folder the computer granted Reason (root_id
                            when named, else the deepest one holding it; an
                            older `reason connect`: only inside its home
                            folder). Not combinable with workspace_mode or
                            workspace_path.
                          type: string
                          minLength: 1
                          maxLength: 4096
                          pattern: ^\/[^\x00-\x1f\x7f]*$
                        isolation:
                          description: >-
                            With cwd: worktree (the default for repository work)
                            gives the Session its own git worktree at
                            ~/.reason/workspace/sessions/<id>/<repository> on
                            branch reason/<id>; in_place works directly in cwd.
                          type: string
                          enum:
                            - worktree
                            - in_place
                      required:
                        - kind
                        - device_id
                      additionalProperties: false
                    - type: object
                      properties:
                        kind:
                          type: string
                          const: machine
                          description: >-
                            Queue this Session on a worker belonging to a named
                            Machine.
                        name:
                          description: Machine name (case-insensitive).
                          type: string
                          minLength: 1
                          maxLength: 63
                          pattern: ^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?$
                        id:
                          description: Machine id.
                          type: string
                          format: uuid
                          pattern: >-
                            ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
                      required:
                        - kind
                      additionalProperties: false
                  description: >-
                    Moves the Session: this message's turn, and every later one,
                    runs on this target instead of the one the Session was on.
                    Same shape and admission as the create `target` (`cloud`, a
                    Device and root, or a named Machine). Only the conversation
                    moves; files on the previous machine do not, unless they
                    were pushed to the Session branch. A move starts a new
                    continuation run, so the Session must have finished its
                    current turn. Any target other than `cloud` needs the
                    `devices:use` scope.
              required:
                - message
            example:
              message: Also bump the timeout to 30s while you're in there.
              client_message_id: follow-up-018f6f3a
      responses:
        '200':
          description: Message accepted and delivered or queued.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendReasonMessageResponse'
        '400':
          description: >-
            The message was empty, a `model` / `reasoning_effort` override was
            not valid, or admission refused the conversation's create as
            invalid; the body names why.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          description: >-
            Usage is unavailable for this message or for a new conversation; the
            body names why.
        '403':
          description: >-
            A required scope or workspace permission is missing, or admission
            refused the message; the body names why.
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: >-
            The conversation's Session is briefly unavailable or a
            `client_message_id` was used for a different message (as
            sendSessionMessage answers), or this is an ephemeral benchmark
            workspace (`reasons_unavailable_in_ephemeral_workspace`).
        '413':
          description: >-
            Message limit exceeded (`message_too_large`), or the JSON request is
            over 116042412 bytes (`request_too_large`).
        '422':
          description: >-
            Admission refused the create as unsupported here; the body names
            why.
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          description: Session writes are disabled.
      security:
        - reasonApiKey:
            - run
components:
  parameters:
    orgId:
      name: orgId
      in: path
      required: true
      description: Organization id or slug. Resolve it with `GET /v3/self`.
      schema:
        type: string
  schemas:
    SendReasonMessageResponse:
      type: object
      properties:
        ok:
          type: boolean
          description: 'True: the message was accepted.'
        delivery:
          type: string
          description: >-
            How the message was delivered: steered_live (into the running turn),
            queued_for_next_turn or held_in_queue (waits for the turn to end),
            started_continuation_run or reattached_warm_session (started a new
            turn), applied_to_queued_run, saved_for_follow_up (saved; see
            held_reason), queue_cancelled or continuation_blocked.
        continuation_session_id:
          description: >-
            The stable logical Session id after an accepted follow-up. Continue
            polling this id; Reason may run the turn in a hidden execution
            Attempt.
          type:
            - string
            - 'null'
        message_id:
          type: string
          description: >-
            Set for a message sent with delivery queue: the id to send it at
            once or withdraw it while it waits.
        client_message_id:
          type: string
          description: >-
            The message's idempotency key: the client_message_id sent, or the
            one the server gave it. Resending the message with it returns this
            accepted turn instead of adding another.
        held_reason:
          type: string
          description: >-
            Present when delivery is saved_for_follow_up and the message is
            waiting instead of starting. session_machine_transition_pending: the
            Session's machine is changing; the message is delivered when the
            change settles, so do not send it again. If the change has not
            settled after 10 minutes the message is marked not delivered
            instead.
        reason_id:
          type: string
          format: uuid
          description: The Reason the message went to.
        session_id:
          type: string
          description: >-
            The Reason's conversation Session the message was added to.
            getSession and listSessionEvents read it; listReasonMessages reads
            the replies.
        conversation_created:
          type: boolean
          description: >-
            True when this message opened the Reason's conversation for the
            first time.
      required:
        - ok
        - reason_id
        - session_id
        - conversation_created
    Error:
      type: object
      properties:
        error:
          oneOf:
            - type: string
            - type: object
              required:
                - type
                - message
              properties:
                type:
                  type: string
                message:
                  type: string
                request_id:
                  type:
                    - string
                    - 'null'
        message:
          type: string
        required_scope:
          type: string
          description: >-
            The capability required when the request was denied for a missing
            scope.
  responses:
    Unauthorized:
      description: Missing, invalid, or expired key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: missing_bearer
            message: Authorization required
    NotFound:
      description: Resource not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: session_not_found
    RateLimited:
      description: >-
        Too many requests. Retry after the number of seconds in the
        `Retry-After` response header.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
            minimum: 1
          required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: rate_limited
              message: This API key exceeded its request-rate limit
  securitySchemes:
    reasonApiKey:
      type: http
      scheme: bearer
      bearerFormat: 'reason_<hex> (legacy: ara_<hex>)'
      description: >-
        Your Reason API key from Settings › API keys. New keys use `reason_`;
        legacy `ara_` keys remain accepted. Keys are capability-scoped: run,
        mcp:read, mcp:write, secrets:read, secrets:write, sessions:read,
        sessions:debug, knowledge:read, memory:read, memory:write, skills:read,
        skills:write, repos:read, repos:write, reviews:read, reviews:write,
        deployment:read, analytics:read, org:read, org:write, attachments:read,
        attachments:write, guardrails:read, guardrails:write, network:read,
        network:write, automations:read, automations:write, agent_auth:read.
        network:read and network:write are opt-in, excluded from default keys.
        network:read reads the saved workspace network policy; network:write
        replaces custom allowed hosts and requires a current organization
        owner/admin. Legacy project PATCH requests containing
        network_allowed_hosts also require network:write plus their existing run
        scope and project management permission; saved project hosts do not
        affect current session egress. Only owners/admins can mint or manage
        keys with network:write; keys cannot grant themselves more authority.
        See /docs/network-policies for replacement semantics and runtime
        applicability. mcp:write manages MCP server configuration only; it does
        not authorize remote MCP-tool execution. sessions:read reads sessions,
        including the assistant, reasoning and tool activity in their events.
        sessions:debug is privileged: only for organization owners/admins, it
        expands session events to the full diagnostic projection (diagnostic
        event kinds, status text and raw event metadata).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.