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

# Send a message to an agent

> One turn: the agent reads `input` (and any `attachments`) and answers, using its tools, showing a form when it needs details, and running browser tasks (on the conversation’s cloud browser) or desktop tasks (on its linked computers) when it needs a website or a desktop app. Without `conversation_id` a new conversation starts. Waits up to 55 seconds; a turn still running then comes back `in_progress` (poll GET /v1/responses/{id}). With `stream: true` the answer is server-sent events: `response.created`; `output_text.delta` (`text`: the next piece of the reply as the model writes it; `output_text.reset` takes back what a failed try streamed); `message.delta` (each whole message once written); `tool_call.started`, `tool_call.completed` (a code run’s has `files`: what the code made); `ui` (a form: `surface_id`, `title`, `fields`, `a2ui`; the turn ends after it); `task.started` (`task_id`, `goal`, `kind`: `browser` or `desktop`, `computer` for a desktop task, `plan`: the steps the person sees as its progress, the browser’s `session_id`, and `live_url`: its live view in the console), `task.step` (`text`: what it says it's doing now, and with a plan `plan_step`: the step it's on), `task.completed`; `input.delivered` (messages sent meanwhile, read); with visual answers on, `answer.layout` first (its answer may be laid out as UI) and `message.view` (`seq`, `view`: that answer laid out as cards, before the reply ends; its text is still the answer); then `response.completed`, `response.failed`, `response.cancelled`, or `response.requires_action` (`response`: the reply, paused on a request in its `output`). A message sent while a reply is still running is queued for that reply instead: `202` at once (streamed or not), with the reply as it is now and `queued_message` (your message’s item, `queued: true`). The reply reads it at its next step, after the tool or task it’s running (a task it’s running reads it at its next step too), or carries on after its answer to answer it as well, so the one reply answers both: follow it on its own stream or with GET /v1/responses/{id}. Its stream has `input.delivered` (`seqs`: the items read, `to`: `reply` or `task`) when it reads them. A reply cancelled or failed before it read one leaves it in the conversation for the next turn. A failed turn still answers 200, with `status: failed`. If a deploy hands a streamed turn to another server, the stream can close without a `response.*` event: follow it with GET /v1/responses/{id}. A reply that reaches something needing approval (a procedure whose Approval is on, an HTTP tool with `approval: "always"`, or a step one of its tasks hands back: the task is `paused` until it’s decided, then carries on) pauses: `status: requires_action`, with the request (an `approval` item) in `output`. Decide it with `conversation_id` and `approval` (or an A2UI `action` on its surface), and no `input`; a question is answered the same way with `answer`. Your team decides, as the API key or the member signed in. The same reply carries on (same `id`), streamed with `stream: true`; it still waits while another request is open. With no paused reply (a task started directly) the answer is the decision: `{ object: "decision", approval | question }`. To decide without naming an agent (a task run without one) or streaming, use POST /v1/conversations/{conversation_id}/decisions. Someone deciding first: 409 with `code: already_decided` and `decided_by`.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/agents/{agent_id}/responses
openapi: 3.1.0
info:
  title: Eager API
  version: 1.0.0
  description: >-
    Train AI agents like new hires: hand an agent your files and coach it, and
    it writes its own procedures and works in any software, even without an API.
    Talk to your agents one message at a time (POST
    /v1/agents/{agent_id}/responses): they answer from their files, procedures
    and your HTTP tools, and run tasks on their own cloud browser or your linked
    computers when an answer needs a website or a desktop app. Manage agents
    (versioned: save a draft, publish it), their procedures, browser and
    computers; follow conversations and tasks, answer approvals, and fetch
    history and recordings. Run tasks yourself on a session: a customer’s
    computer through an invite link, or a cloud browser. Test agents with evals:
    chat, browser and desktop test cases, run several times against your agents
    and judged on the answer. Every change is in the org’s audit log.
servers:
  - url: https://guidinghand.ai
    description: Production
  - url: https://dev.guidinghand.ai
    description: Development (Stripe test mode)
security:
  - bearerAuth: []
tags:
  - name: Agents
  - name: Agent files
  - name: Agent tools
  - name: Agent folders
  - name: Computers
    description: >-
      Computers your org links with the Eager app, and pools of them, for
      agents’ desktop tasks. Attach them to an agent in its
      `resources.computers`.
  - name: Phone numbers
    description: >-
      Bring your own Twilio numbers: connect the account, add its numbers, and
      pick the agent that answers each. Calls are answered by the agent's
      published version.
  - name: Sessions
  - name: Tasks
  - name: Webhooks
  - name: Audit log
  - name: Test cases
  - name: Test sets
  - name: Test runs
  - name: Start states
  - name: Runners
  - name: Responses
    description: >-
      Talk to an agent: each call is one turn of a conversation. The agent
      answers with its files, procedures and tools (and, with Run code, its own
      sandbox), asks for details with forms, and runs browser and desktop tasks
      when an answer needs a website or a desktop app.
  - name: Conversations
    description: >-
      The history of each conversation: messages, tool calls and the tasks the
      agent started, in order.
  - name: Uploads
    description: >-
      Files for conversations: attach them to a message, and download what the
      agent’s code made. Kept as long as their conversation.
  - name: Procedures
    description: >-
      An agent’s playbooks: when to use each and its steps. The agent finds and
      follows them; ones it writes from a first run are marked written_by:
      agent.
  - name: Categories
    description: The kinds of request an org’s procedures and test cases are sorted into.
  - name: Escalations
    description: >-
      What needs your team: an approval only the team can give or a question
      only it can answer, in a real conversation; a procedure run that failed;
      and one that worked another way, with the procedure rewritten to match (a
      proposed change). Test chats never escalate; evals do, without webhooks.
  - name: Schedules
    description: >-
      Run an agent’s procedure on a cron expression, in a time zone, with the
      inputs it needs. Each run is a conversation of its own with nobody in it
      (`channel` `schedule` in its variables): the procedure’s steps without AI
      run outright when it has them, else the model follows it to its end. Its
      record says how it ended, what the agent said last and what it cost; the
      team hears by webhook (`schedule.run_completed`, `schedule.run_failed`),
      email and Slack or Teams, as the schedule says.
paths:
  /v1/agents/{agent_id}/responses:
    parameters:
      - name: agent_id
        in: path
        required: true
        description: The agent’s id, e.g. `billing`.
        schema:
          type: string
    post:
      tags:
        - Responses
      summary: Send a message to an agent
      description: >-
        One turn: the agent reads `input` (and any `attachments`) and answers,
        using its tools, showing a form when it needs details, and running
        browser tasks (on the conversation’s cloud browser) or desktop tasks (on
        its linked computers) when it needs a website or a desktop app. Without
        `conversation_id` a new conversation starts. Waits up to 55 seconds; a
        turn still running then comes back `in_progress` (poll GET
        /v1/responses/{id}). With `stream: true` the answer is server-sent
        events: `response.created`; `output_text.delta` (`text`: the next piece
        of the reply as the model writes it; `output_text.reset` takes back what
        a failed try streamed); `message.delta` (each whole message once
        written); `tool_call.started`, `tool_call.completed` (a code run’s has
        `files`: what the code made); `ui` (a form: `surface_id`, `title`,
        `fields`, `a2ui`; the turn ends after it); `task.started` (`task_id`,
        `goal`, `kind`: `browser` or `desktop`, `computer` for a desktop task,
        `plan`: the steps the person sees as its progress, the browser’s
        `session_id`, and `live_url`: its live view in the console), `task.step`
        (`text`: what it says it's doing now, and with a plan `plan_step`: the
        step it's on), `task.completed`; `input.delivered` (messages sent
        meanwhile, read); with visual answers on, `answer.layout` first (its
        answer may be laid out as UI) and `message.view` (`seq`, `view`: that
        answer laid out as cards, before the reply ends; its text is still the
        answer); then `response.completed`, `response.failed`,
        `response.cancelled`, or `response.requires_action` (`response`: the
        reply, paused on a request in its `output`). A message sent while a
        reply is still running is queued for that reply instead: `202` at once
        (streamed or not), with the reply as it is now and `queued_message`
        (your message’s item, `queued: true`). The reply reads it at its next
        step, after the tool or task it’s running (a task it’s running reads it
        at its next step too), or carries on after its answer to answer it as
        well, so the one reply answers both: follow it on its own stream or with
        GET /v1/responses/{id}. Its stream has `input.delivered` (`seqs`: the
        items read, `to`: `reply` or `task`) when it reads them. A reply
        cancelled or failed before it read one leaves it in the conversation for
        the next turn. A failed turn still answers 200, with `status: failed`.
        If a deploy hands a streamed turn to another server, the stream can
        close without a `response.*` event: follow it with GET
        /v1/responses/{id}. A reply that reaches something needing approval (a
        procedure whose Approval is on, an HTTP tool with `approval: "always"`,
        or a step one of its tasks hands back: the task is `paused` until it’s
        decided, then carries on) pauses: `status: requires_action`, with the
        request (an `approval` item) in `output`. Decide it with
        `conversation_id` and `approval` (or an A2UI `action` on its surface),
        and no `input`; a question is answered the same way with `answer`. Your
        team decides, as the API key or the member signed in. The same reply
        carries on (same `id`), streamed with `stream: true`; it still waits
        while another request is open. With no paused reply (a task started
        directly) the answer is the decision: `{ object: "decision", approval |
        question }`. To decide without naming an agent (a task run without one)
        or streaming, use POST /v1/conversations/{conversation_id}/decisions.
        Someone deciding first: 409 with `code: already_decided` and
        `decided_by`.
      operationId: createResponse
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                input:
                  type: string
                  maxLength: 8000
                  description: >-
                    What the person says, up to 8,000 characters. Can be empty
                    when the message has attachments or answers a form
                    (`action`), and is left out with a decision (`approval`,
                    `answer`).
                conversation_id:
                  type: string
                opening:
                  type: string
                  maxLength: 500
                  description: >-
                    For a new conversation (no conversation_id), the agent's
                    first message, shown as said before the person wrote and
                    recorded as the agent's. Used only when the agent has no
                    first message of its own.
                variables:
                  type: object
                  maxProperties: 50
                  additionalProperties:
                    type:
                      - string
                      - number
                      - boolean
                    maxLength: 1000
                  description: >-
                    For a new conversation (no conversation_id): what it starts
                    knowing, like `{ "customer_name": "Ana", "account_id":
                    "A-77" }`. Names are lowercase letters, numbers and _ (up to
                    40), values text up to 1,000 characters. The agent reads
                    them with Eager's own (`current_date`, `current_time`,
                    `day_of_week`, `time_zone`, `language`, `channel`,
                    `conversation_id`, `agent_name`, and where known
                    `caller_number`, `agent_number`, `page_url`, `user_name`,
                    `user_email`) and doesn't ask for them; a procedure's input
                    of the same name is taken as given. Eager's own names can't
                    be passed, except `time_zone` (an IANA zone; the date and
                    time are where the person is) and `language`. Sent with a
                    conversation_id, it's a 400.
                stream:
                  type: boolean
                version:
                  description: >-
                    `draft`, or a version number, for this turn only. Default:
                    the published version.
                  oneOf:
                    - const: draft
                    - type: integer
                metadata:
                  type: object
                  description: >-
                    Your own values for a new conversation (a JSON object, up to
                    4,000 characters). Only used when the conversation is
                    created.
                attachments:
                  type: array
                  maxItems: 10
                  items:
                    type: string
                  description: >-
                    Files the person attached: upload ids (`upl_…`) from POST
                    /v1/uploads, up to 10. Images and PDFs the model sees, text
                    files it reads; any other file needs Run code (`tools.code`,
                    Claude or GPT models). A file sent in one conversation can’t
                    be sent in another.
                action:
                  type: object
                  description: >-
                    Answers a form the agent showed (a `ui` item): `{ name:
                    "submit", surfaceId, context: { <field id>: value } }`, or
                    the same wrapped as `{ version: "v0.9", action }`. Needs
                    `conversation_id`. The answers reach the agent as the
                    person’s message; `input`, if sent too, is added after them.
                    404 for an unknown form, 409 if it was answered already. Or
                    decides a request, as `approval` and `answer` do: on an
                    `approval` item’s surface (`surface_id`), `name` is
                    `approve` or `deny`; on a `question` item’s, its form’s
                    `submit` (`context: { answer: ["<option>"] }`, or `{ answer:
                    "<text>" }` with no options).
                  properties:
                    name:
                      type: string
                      enum:
                        - submit
                        - approve
                        - deny
                    surfaceId:
                      type: string
                    context:
                      type: object
                  required:
                    - surfaceId
                approval:
                  type: object
                  description: >-
                    Decides an `approval` item of the conversation (its
                    `approval_id`): needs `conversation_id`, and no `input`. The
                    reply that paused for it carries on.
                  required:
                    - approval_id
                    - decision
                  properties:
                    approval_id:
                      type: string
                    decision:
                      type: string
                      enum:
                        - approve
                        - deny
                    note:
                      type: string
                      maxLength: 500
                      description: 'For the agent: why, or what to do instead.'
                answer:
                  type: object
                  description: >-
                    Answers a `question` item of the conversation (its
                    `question_id`): needs `conversation_id`, and no `input`.
                  required:
                    - question_id
                    - answer
                  properties:
                    question_id:
                      type: string
                    answer:
                      type: string
                      maxLength: 4000
      responses:
        '200':
          description: >-
            The turn (or, streamed, its events). A decision: the reply it
            carries on, or with no paused reply, the decision.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/Response'
                  - $ref: '#/components/schemas/Decision'
        '202':
          description: >-
            Your message was queued for the reply still running in the
            conversation: that reply as it is now (`in_progress`), with
            `queued_message`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Response'
        '400':
          description: >-
            Invalid request, or an attachment this agent can’t open (`code`:
            `attachment_not_supported`; turn on Run code, on a Claude or GPT
            model, for files other than images, PDFs and text).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: >-
            The org’s balance can’t pay for the reply: it’s empty
            (`insufficient_balance`), or auto top-up can’t add funds
            (`auto_topup_limit_reached`, `card_needs_attention`). A reply is
            paid from the balance for the tokens it uses, at the model’s price;
            free credit is part of the balance. Add funds in Usage & billing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            A form was answered while the conversation is still answering, an
            attachment was already sent in another conversation, or someone
            decided (or answered) the request first: `code: already_decided`,
            with `decided_by`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: The agent’s model isn’t available right now.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Response:
      type: object
      properties:
        object:
          const: response
        id:
          type: string
          example: resp_…
        conversation_id:
          type: string
        status:
          type: string
          enum:
            - in_progress
            - requires_action
            - completed
            - failed
            - cancelled
          description: >-
            `requires_action`: paused on a request in `output` (an `approval` or
            `question` item) until someone decides it. Send the decision to POST
            /v1/agents/{agent_id}/responses (`approval`, `answer`, or an A2UI
            `action` on its surface), and this same response carries on.
        error:
          type:
            - string
            - 'null'
        output:
          type: array
          items:
            $ref: '#/components/schemas/ConversationItem'
          description: This turn’s items.
        usage:
          description: >-
            What the reply used, set when it ends (empty until then). Its tokens
            are paid from the balance at the model’s price, rounded up to a
            whole cent per reply. The browser and desktop tasks it started are
            charged as tasks.
          allOf:
            - $ref: '#/components/schemas/TokenUsage'
            - type: object
              properties:
                tasks:
                  type: array
                  description: The tasks the reply started, with what each cost.
                  items:
                    type: object
                    properties:
                      task_id:
                        type: string
                      cost_cents:
                        type:
                          - integer
                          - 'null'
                        description: The task’s `cost_cents`.
                code_runs:
                  type: integer
                  description: >-
                    Times the agent ran code in its sandbox. Left out when it
                    ran none.
        created_at:
          type: string
          format: date-time
        ended_at:
          type:
            - string
            - 'null'
          format: date-time
        queued_message:
          $ref: '#/components/schemas/ConversationItem'
          description: 'Only when your message was queued (`202`): its item.'
    Decision:
      type: object
      description: >-
        A request decided (POST /v1/conversations/{conversation_id}/decisions,
        or the responses route when no reply was paused for it): the approval or
        question as it is now.
      properties:
        object:
          const: decision
        approval:
          $ref: '#/components/schemas/Approval'
        question:
          $ref: '#/components/schemas/Question'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - type
            - message
          properties:
            type:
              type: string
              enum:
                - invalid_request
                - authentication
                - payment_required
                - permission
                - not_found
                - conflict
                - rate_limit
                - server_error
            message:
              type: string
            code:
              type: string
              description: >-
                Why it was refused, when there’s more to say than the status.
                Starting a task or a chat reply: `insufficient_balance`,
                `auto_topup_limit_reached` or `card_needs_attention` (402: the
                balance is empty and auto top-up can’t add funds; add funds,
                raise the auto top-up limit, or update the card),
                `concurrency_limit` (429), `model_unavailable` (503: the agent’s
                `model` can’t run on this server; choose another). Deciding a
                conversation’s request: `already_decided` (409: someone decided
                or answered it first; see `decided_by`) or `not_pending` (409:
                its task has ended, so nothing would act on it). POST
                /v1/tasks/{task_id}/respond: `decide_in_conversation` (409:
                decide it in the task’s conversation; see `conversation_id`,
                `agent_id`, and `approval_id` or `question_id`). Deleting a
                start state that test cases use: `in_use` (409, with
                `test_case_ids`).
            test_case_ids:
              type: array
              items:
                type: string
              description: 'With `in_use`: the test cases that use the start state.'
            decided_by:
              description: 'With `already_decided`: who decided first.'
              allOf:
                - $ref: '#/components/schemas/Decider'
            conversation_id:
              type: string
              description: >-
                With `decide_in_conversation`: the conversation to decide it in
                (POST /v1/conversations/{conversation_id}/decisions).
            agent_id:
              type:
                - string
                - 'null'
              description: >-
                With `decide_in_conversation`: the task’s agent (null for a task
                run without one).
            approval_id:
              type: string
              description: 'With `decide_in_conversation`: the approval to decide.'
            question_id:
              type: string
              description: 'With `decide_in_conversation`: the question to answer.'
    ConversationItem:
      type: object
      description: One item of a conversation. `type` says which fields it has.
      properties:
        object:
          const: conversation_item
        seq:
          type: integer
        response_id:
          type: string
        at:
          type: string
          format: date-time
        type:
          type: string
          enum:
            - user_message
            - assistant_message
            - tool_call
            - tool_result
            - task
            - ui
            - approval
            - question
            - speech
        text:
          type: string
          description: user_message, assistant_message, speech.
        speaker:
          type: string
          enum:
            - caller
            - agent
          description: 'speech: who said the line on a phone call.'
        queued:
          type: boolean
          description: >-
            user_message: sent while a reply was running, and not read by the
            agent yet. Absent once it is.
        view:
          type: object
          description: >-
            assistant_message: the answer laid out as UI, when that reads better
            than text (visual answers, `tools.visual`): sections, each a card
            when it has a `title` (and maybe a `badge`), of blocks. Block types:
            `text` (text), `facts` (items: label, value), `table` (columns,
            rows), `options` (items: title, label, price, detail, points, pick:
            what the person says by choosing it), `list` (style bullet, check or
            number; items), `callout` (tone, text), `badges` (items: text,
            tone), `bars` (items: label, value), `buttons` (items: label,
            message: what the person says by pressing it). Tones: neutral, good,
            warning, bad, info. Every figure in it is one of the text’s; the
            text stays the answer.
          properties:
            version:
              type: integer
              const: 1
            sections:
              type: array
              items:
                type: object
                properties:
                  title:
                    type: string
                  badge:
                    type: object
                    properties:
                      text:
                        type: string
                      tone:
                        type: string
                        enum:
                          - neutral
                          - good
                          - warning
                          - bad
                          - info
                  blocks:
                    type: array
                    items:
                      type: object
                      required:
                        - type
                      properties:
                        type:
                          type: string
                          enum:
                            - text
                            - facts
                            - table
                            - options
                            - list
                            - callout
                            - badges
                            - bars
                            - buttons
                      additionalProperties: true
                required:
                  - blocks
        call_id:
          type: string
          description: tool_call, tool_result.
        name:
          type: string
          description: >-
            tool_call, tool_result: the tool. Code runs (Run code) are
            `bash_code_execution` (`arguments.command`) or
            `text_editor_code_execution` (`arguments.command`, `path`,
            `file_text`…) on Claude models, `code_interpreter`
            (`arguments.code`) on GPT models and `code_execution`
            (`arguments.code`) on Gemini models.
        arguments:
          type: object
        label:
          type:
            - string
            - 'null'
          description: 'tool_call: what it did, in plain words.'
        output:
          type: string
          description: tool_result.
        task:
          type: object
          description: 'task: a browser or computer task the agent started.'
          properties:
            task_id:
              type: string
            kind:
              type: string
              enum:
                - browser
                - desktop
              description: >-
                Where it ran: the conversation's cloud browser, or one of the
                agent's computers.
            status:
              $ref: '#/components/schemas/TaskStatus'
            result:
              type:
                - string
                - 'null'
            goal:
              type:
                - string
                - 'null'
            computer:
              type: string
              description: 'Desktop tasks: the session code of the computer it ran on.'
            plan:
              type: array
              items:
                type: string
              description: >-
                Its progress as the person sees it: the short steps the agent
                wrote for them when it started the task (its procedure's, said
                simply, when it followed one). Left out when it gave none.
            plan_step:
              type: integer
              minimum: 1
              description: >-
                With `plan`: the step it's on (1 is the first). It only moves
                forward; once the task is `completed`, every step is done.
        files:
          type: array
          items:
            $ref: '#/components/schemas/FileRef'
          description: >-
            user_message: the files the person attached. tool_result of a code
            run: the files the agent’s code made.
        error:
          type: boolean
          description: 'tool_result: it didn’t work.'
        surface_id:
          type: string
          description: >-
            ui: the form’s id (`srf_…`). Answer it with `action` on the next
            message.
        title:
          type: string
          description: 'ui: the form’s title.'
        fields:
          type: array
          items:
            type: object
          description: >-
            ui: up to 8 fields, each `{ id, label, kind, options?, allow_other?,
            min?, max?, step?, unit?, default? }`; `kind` is `choice`,
            `multi_choice`, `yes_no`, `text`, `number`, `slider` or `date`.
        a2ui:
          type: array
          items:
            type: object
          description: 'ui: the same form as A2UI v0.9 messages.'
        answer:
          type:
            - object
            - 'null'
          description: 'ui: `{ values, text, at }` once answered, else null.'
        approval:
          description: >-
            approval: a request the reply paused on, or one decided as it was
            asked (guardrails in `auto` or `unattended` mode).
          allOf:
            - $ref: '#/components/schemas/Approval'
        question:
          description: 'question: a question a task asks.'
          allOf:
            - $ref: '#/components/schemas/Question'
    TokenUsage:
      type: object
      description: >-
        Tokens used by model calls, as the provider counts them. Each kind is
        billed at the model’s price for it (see /pricing).
      properties:
        input_tokens:
          type: integer
          description: All input, `cached_tokens` and `cache_write_tokens` included.
        cached_tokens:
          type: integer
          description: >-
            Input read from the prompt cache, billed at the model’s cached
            price.
        cache_write_tokens:
          type: integer
          description: >-
            Input written to the prompt cache, billed at the cache-write price
            (1.25x input). Claude models only; 0 on the others.
        output_tokens:
          type: integer
          description: Output, the model’s thinking included.
        reasoning_tokens:
          type: integer
          description: >-
            How much of `output_tokens` was thinking, where the provider reports
            it (OpenAI, Gemini). 0 on Claude models.
    Approval:
      type: object
      description: >-
        A request for a yes before something runs: a task from a procedure whose
        Approval is on (`scope: run`), an HTTP tool with `approval: "always"`,
        or one guarded step of a task (`scope: step`). Described by Eager, never
        by the model. Open while `decision` is null; the first decision counts.
      properties:
        approval_id:
          type: string
          example: apr_…
        scope:
          type: string
          enum:
            - run
            - step
          description: '`run`: a whole task (or a tool call). `step`: one step of a task.'
        action:
          type: string
          description: What will happen, in Eager’s words.
        source:
          type:
            - string
            - 'null'
          enum:
            - guardrail
            - safety_check
            - screen_check
            - tool
            - agent
            - null
          description: >-
            What asked for a step’s approval: the agent’s guardrails, its model
            maker’s safety check, the screen check, a tool, or `agent` (the
            task’s own model asked, so `action` is in its words). Null for a
            run’s.
        site:
          type:
            - string
            - 'null'
        app:
          type:
            - string
            - 'null'
        category:
          type:
            - string
            - 'null'
          description: A step’s "Ask first" category (see `GuardrailCategory`).
        risk:
          type:
            - string
            - 'null'
        task_id:
          type:
            - string
            - 'null'
          description: The task it’s for, once there is one.
        procedure_id:
          type:
            - string
            - 'null'
          description: The procedure whose Approval asked for it.
        by:
          type: string
          enum:
            - anyone
            - team
          description: >-
            `anyone`: the person in the chat (when the agent lets them approve)
            or your team. `team`: only your team.
        who:
          type:
            - string
            - 'null'
          description: Who signs off, as the procedure says (a label, not a permission).
        note:
          type:
            - string
            - 'null'
          description: What to check or bring, from the procedure.
        covers:
          type: array
          items:
            $ref: '#/components/schemas/GuardrailCategory'
          description: >-
            A run’s: the "Ask first" categories its task may then do without
            asking again, as they were when it was asked. The surface says so.
        surface_id:
          type: string
          description: Its A2UI surface’s id (`srf_…`), for an `action` that decides it.
        a2ui:
          type: array
          items:
            type: object
          description: >-
            The request as A2UI v0.9 messages: what will happen, what else it
            allows, who signs off, the note, and Approve and Deny buttons (their
            actions are named `approve` and `deny`).
        decision:
          type:
            - object
            - 'null'
          description: Null while it’s open.
          properties:
            decision:
              type: string
              enum:
                - approve
                - deny
            note:
              type: string
              description: The decider’s note to the agent, if any.
            by:
              $ref: '#/components/schemas/Decider'
            at:
              type: string
              format: date-time
    Question:
      type: object
      description: >-
        A question a task asks, drawn as a form: a choice from `options` (or
        something else), or short text. Open while `answer` is null; the first
        answer counts.
      properties:
        question_id:
          type: string
          example: qst_…
        task_id:
          type:
            - string
            - 'null'
        question:
          type: string
        options:
          type: array
          items:
            type: string
        surface_id:
          type: string
          description: Its form’s id (`srf_…`), for an `action` that answers it.
        a2ui:
          type: array
          items:
            type: object
          description: >-
            The form as A2UI v0.9 messages; its one field is `answer` (and
            `answer_other`, for something else).
        answer:
          type:
            - object
            - 'null'
          description: Null while it’s open.
          properties:
            text:
              type: string
            by:
              $ref: '#/components/schemas/Decider'
            at:
              type: string
              format: date-time
    Decider:
      type: object
      description: Who decided a request, or answered a question.
      required:
        - type
      properties:
        type:
          type: string
          enum:
            - person
            - team
            - auto
            - refused
            - timeout
            - operator
            - moved_on
          description: >-
            `person`: the person in the chat (in the Eager app, or a visitor to
            your website’s widget), when the agent lets them
            (`customer_approvals`, `customer_answers`) and the request isn’t for
            your team only. `team`: a member in the console (`email`) or an API
            key (`key_id`). `auto`: the agent’s guardrails approve without
            asking (`mode: auto`). `refused`: its guardrails refuse (`mode:
            unattended`). `timeout`: nobody decided within its
            `approval_timeout_minutes`. `operator`: an eval case’s operator.
            `moved_on`: the person sent a new message instead, so it was
            declined.
        email:
          type: string
          description: '`team`: the member who decided.'
        key_id:
          type: string
          description: '`team`: the API key that decided.'
    TaskStatus:
      type: string
      description: >-
        `paused`: waiting on a request in its conversation (an `approval` or
        `question` item) to be decided there.
      enum:
        - queued
        - running
        - paused
        - completed
        - failed
        - stopped
    FileRef:
      type: object
      description: >-
        A file in a conversation: one a person attached to a message, or one the
        agent’s code made. Download it from GET /v1/uploads/{id}/content.
      properties:
        id:
          type: string
          description: The upload’s id, `upl_…`.
        filename:
          type: string
        content_type:
          type: string
        kind:
          type: string
          enum:
            - image
            - pdf
            - text
            - other
          description: >-
            How the model gets it: `image` (PNG, JPEG, GIF or WebP) and `pdf` it
            sees; `text` it reads (long files are cut); `other` only its code
            sandbox opens (Run code).
        bytes:
          type: integer
    GuardrailCategory:
      type: string
      enum:
        - purchase
        - send
        - delete
        - install
        - security
        - terms
      description: >-
        `purchase`: buying or paying. `send`: sending, posting or submitting.
        `delete`: deleting or removing. `install`: installing software.
        `security`: security and account settings. `terms`: accepting terms or
        agreements.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: An org API key (`gh_live_…`) from Settings → API keys in the console.

````

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