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

# Duplicate an agent

> Makes a new agent from this one’s current config (its draft, when it has unpublished changes), with copies of its files and procedures. The copy is named “<name> (copy)” at the next free agent id (`billing-copy`, `billing-copy-2`…) and published as its version 1. Its versions and its cloud browser’s saved logins stay with the original. Returns the new agent.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/agents/{agent_id}/duplicate
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}/duplicate:
    parameters:
      - name: agent_id
        in: path
        required: true
        description: The agent’s id, e.g. `billing`.
        schema:
          type: string
    post:
      tags:
        - Agents
      summary: Duplicate an agent
      description: >-
        Makes a new agent from this one’s current config (its draft, when it has
        unpublished changes), with copies of its files and procedures. The copy
        is named “<name> (copy)” at the next free agent id (`billing-copy`,
        `billing-copy-2`…) and published as its version 1. Its versions and its
        cloud browser’s saved logins stay with the original. Returns the new
        agent.
      operationId: duplicateAgent
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Agent'
        '401':
          $ref: '#/components/responses/E401'
        '403':
          $ref: '#/components/responses/E403'
        '404':
          $ref: '#/components/responses/E404'
        '409':
          $ref: '#/components/responses/E409'
components:
  schemas:
    Agent:
      type: object
      properties:
        object:
          const: agent
        agent_id:
          type: string
          example: billing
        name:
          type: string
          example: Billing help
        instructions:
          type: string
          description: Added under Eager’s own rules, which always win.
        model:
          $ref: '#/components/schemas/Model'
        effort:
          $ref: '#/components/schemas/Effort'
        greeting:
          type: string
          description: >-
            The agent’s first message: it opens every new conversation (the
            first item, before the person’s message) and is shown on the invite
            page.
        display_name:
          type: string
          description: >-
            What the Eager app calls the agent on the person’s screen while it
            works (“Acme Support is typing”). Empty means “Eager”.
          example: Acme Support
        narration:
          type: boolean
          description: >-
            The app shows the agent’s thoughts and steps on the person’s screen
            as it works, and its summary when it finishes. These are the agent’s
            own words, so they can repeat what your team answered. Off: no
            thoughts, steps or summary; they see the banner with the Stop button
            (and the agent’s questions and approval requests, if
            `customer_answers` and `customer_approvals` are on).
        customer_answers:
          type: boolean
          description: >-
            The person at the computer can answer the agent’s questions in the
            Eager app (your team still can too; the first answer is used). Off:
            only your team answers, and the question isn’t shown on the person’s
            screen.
        customer_approvals:
          type: boolean
          description: >-
            The person at the computer can approve or deny the agent’s approval
            requests in the Eager app (your team still can too; the first
            decision is used). Off: only your team decides, and the request
            isn’t shown on the person’s screen.
        guardrails:
          $ref: '#/components/schemas/Guardrails'
        tools:
          $ref: '#/components/schemas/AgentTools'
        resources:
          $ref: '#/components/schemas/AgentResources'
        escalations:
          $ref: '#/components/schemas/EscalationRules'
        voice:
          type:
            - string
            - 'null'
          enum:
            - marin
            - gleam
            - meridian
            - vesper
            - willow
            - stone
            - quartz
            - ripple
            - delta
            - cinder
            - beacon
            - bossa
            - tempo
            - nuri
            - juni
            - flitz
            - brise
            - sillage
            - nira
            - harema
            - shida
            - noeul
            - null
          description: >-
            The voice it speaks with on GPT-Live: in Coach by voice and on phone
            calls to its numbers. null means the default, marin. Voices are
            listed by language at
            https://developers.openai.com/api/docs/guides/live-conversations#voice-options.
          example: meridian
        folder_id:
          type:
            - string
            - 'null'
          description: >-
            The folder it’s in (`client.agentFolders`); null at the top. Moving
            an agent makes no new version.
        invite_url_template:
          type: string
          example: https://guidinghand.ai/acme/billing/{code}
        version:
          type: integer
          minimum: 0
          example: 3
          description: >-
            The published version: what sessions and tasks run. 1 when the agent
            is made; each publish adds one.
        has_draft:
          type: boolean
          description: It has unpublished changes (`GET /v1/agents/{agent_id}/draft`).
        created_by:
          $ref: '#/components/schemas/Actor'
          description: Who made it.
        updated_by:
          $ref: '#/components/schemas/Actor'
          description: >-
            Who last changed it: saved its draft, published it or restored a
            version.
        created_at:
          type:
            - string
            - 'null'
          format: date-time
        updated_at:
          type:
            - string
            - 'null'
          format: date-time
    Model:
      type:
        - string
        - 'null'
      enum:
        - claude-haiku-5-5
        - claude-sonnet-5-5
        - claude-opus-5-5
        - claude-fable-5-1
        - gpt-6-luna
        - gpt-6.1-sol
        - gpt-6-astra
        - gemini-3.8-flash
        - gemini-4-argon
        - null
      description: >-
        The AI model the agent runs on: `claude-haiku-5-5`, `claude-sonnet-5-5`,
        `claude-opus-5-5` or `claude-fable-5-1` (Anthropic), `gpt-6-luna`,
        `gpt-6.1-sol` or `gpt-6-astra` (OpenAI), `gemini-3.8-flash` or
        `gemini-4-argon` (Google). Null for Eager’s default, GPT-6 Astra
        (`gpt-6-astra`). It sets the price of the agent’s tokens (US$ per
        million: see /pricing). Starting a task with a model this server can’t
        run returns 503 with `code: "model_unavailable"`.
    Effort:
      type:
        - string
        - 'null'
      enum:
        - low
        - medium
        - high
        - null
      description: >-
        How much the model thinks per step. Null for Eager’s default (Low). It
        has no price of its own: more thinking uses more tokens.
    Guardrails:
      type: object
      required:
        - mode
        - confirm
        - block
        - apps
        - sites
        - safety_checks
        - scope
        - screen_check
        - max_steps
        - max_minutes
        - approval_timeout_minutes
      description: >-
        Rules Eager enforces on each action the agent asks for, before it runs.
        They add to Eager’s own rules and can’t loosen them. In order, the first
        that applies decides: text that looks like a secret, or typing into a
        password field, is not typed (the person is asked to type it); a match
        in `apps.block` or `sites.block` is blocked; with a non-empty
        `apps.allow` or `sites.allow`, anything not on it is blocked; a step in
        a `block` category is blocked; a step in a `confirm` category waits for
        an approval; anything else runs. On a Mac (Eager 1.0.20 or later) a
        step’s category comes from what it would do: what’s under a click; what
        Space, Return or Enter presses (the focused button, or a dialog’s
        default button); Cmd/Ctrl+Enter, and Enter in a message box, count as
        sending; Delete or Backspace outside a text field counts as deleting;
        both ends of a drag (dropping on the Trash counts as deleting); and
        typed text a line at a time (text holding a secret is refused whole). A
        click or acting key Eager can’t see waits for an approval when the agent
        has any `confirm` or `block` categories. A Mac where Eager isn’t allowed
        Accessibility can’t check guardrails, so a task with rules to check
        fails at start. On Windows, and before 1.0.20, categories rest on the
        agent’s own approval requests. Always returned whole, with defaults
        filled in.
      properties:
        mode:
          type: string
          enum:
            - supervised
            - auto
            - unattended
          default: supervised
          description: >-
            `supervised`: someone can approve (your team, and the person at the
            computer when `customer_approvals` is on). `auto`: nobody is asked;
            anything that would need an approval (a step, a safety check, a
            screen check, a tool call) is approved automatically and recorded as
            an `approved` event with `answered_by: "auto"`, so the task only
            waits on a person for questions. Blocked categories, app and site
            rules and secrets still apply, and `safety_checks: stop` still
            stops. `unattended`: nobody is there to approve, so anything that
            would need an approval is refused instead and the agent plans around
            it, and a safety check stops the task. Questions still go to your
            team (and the person at the computer, when `customer_answers` is on)
            as usual.
        confirm:
          type: array
          items:
            $ref: '#/components/schemas/GuardrailCategory'
          uniqueItems: true
          default:
            - purchase
            - send
            - delete
            - install
            - security
            - terms
          description: >-
            Always ask for an approval before these, described by Eager rather
            than by the model. In `auto` mode they are approved automatically,
            and in `unattended` mode refused.
        block:
          type: array
          items:
            $ref: '#/components/schemas/GuardrailCategory'
          uniqueItems: true
          default: []
          description: >-
            Never do these. A category in both `confirm` and `block` is blocked;
            take it out of `block` later and, if it’s still in `confirm`, the
            agent asks first again. Both lists come back as you set them.
        apps:
          type: object
          required:
            - allow
            - block
          properties:
            allow:
              type: array
              maxItems: 50
              items:
                type: string
                maxLength: 100
              default: []
              description: Only these apps (when not empty).
            block:
              type: array
              maxItems: 50
              items:
                type: string
                maxLength: 100
              default: []
              description: Never these apps.
          description: >-
            App names or ids (`Google Chrome`, `com.google.Chrome`,
            `chrome.exe`), matched without regard to case. Names differ by
            system, so for Macs and Windows PCs list both. A non-empty `allow`
            means only those apps; on a Mac the Dock, menu bar, Control Center
            and Spotlight stay usable, and on Windows nothing is exempt (the
            taskbar, File Explorer and the Run box are `explorer.exe`). `block`
            always wins. With any app rule, a step Eager can’t place in an app
            is refused.
        sites:
          type: object
          required:
            - allow
            - block
          properties:
            allow:
              type: array
              maxItems: 50
              items:
                type: string
                maxLength: 100
              default: []
              description: Only these sites in a browser (when not empty).
            block:
              type: array
              maxItems: 50
              items:
                type: string
                maxLength: 100
              default: []
              description: Never these sites.
          description: >-
            Hosts, stored in lowercase without a scheme, path or port
            (`https://Shop.example.com/cart` is kept as `shop.example.com`).
            `example.com` also covers its subdomains. Site rules cover anything
            showing a web page: browsers, and apps with web content such as
            Slack’s desktop app, which counts as the site it shows; an app’s
            local files (`file://`) aren’t a site. A non-empty `allow` means
            only those sites. `block` wins over `allow`. With any site rule, a
            step on a page whose address can’t be read is refused, and what’s
            typed into the address bar since it was last clicked is judged
            together, by where it goes. Site rules need a computer that reports
            page addresses (macOS with Eager 1.0.20 or later, for now): on one
            that can’t, tasks with this agent fail at start.
        safety_checks:
          type: string
          enum:
            - ask
            - stop
          default: ask
          description: >-
            When the model raises a safety check on a step: `ask` for an
            approval with `risk: high` (denying it stops the task), or `stop`
            the task. In `auto` mode an `ask` is approved automatically; in
            `unattended` mode a safety check always stops the task.
        scope:
          type: string
          maxLength: 2000
          default: ''
          description: >-
            What this agent is for, in plain language. When set, each task is
            checked against it before it starts: a task that is clearly
            something else, or one the check can’t give a clear yes or no on,
            fails with the reason in `error`. Empty: no check.
        screen_check:
          type: boolean
          default: false
          description: >-
            Check each new app, window or site the agent sees for text that
            tries to give the agent instructions (prompt injection). What
            happens when it finds some, or can’t check, follows `safety_checks`.
        max_steps:
          type: integer
          minimum: 1
          maximum: 500
          default: 150
          description: >-
            Model turns per task. A task that reaches it without finishing
            fails.
        max_minutes:
          type:
            - integer
            - 'null'
          minimum: 1
          maximum: 240
          default: null
          description: >-
            Running minutes per task, not counting time waiting for answers or
            approvals. A task that reaches it fails. `null`: no limit.
        approval_timeout_minutes:
          type:
            - integer
            - 'null'
          minimum: 1
          maximum: 1440
          default: null
          description: >-
            An approval nobody decides within this many minutes is denied, with
            `answered_by: "timeout"`. `null`: wait until someone decides.
    AgentTools:
      type: object
      required:
        - files
        - http
      description: >-
        The agent’s tools beyond the computer: its own file system (on by
        default) your HTTP tools, and its cloud browser’s sign-ins, and Run
        code. Part of its config, so versioned with it. Always returned whole,
        with defaults filled in.
      properties:
        files:
          type: object
          required:
            - enabled
            - access
          properties:
            enabled:
              type: boolean
              default: true
              description: >-
                The agent has its own file system: text files Eager keeps for
                this agent, separate from the computer it works on. It can list,
                read and search them during tasks (read only, for now).
            access:
              type: string
              enum:
                - read_only
              default: read_only
              description: >-
                For now agents only read their files: `read_only` (it lists,
                reads and searches them; your team adds and changes them).
                `read_write` isn’t available and is refused.
        http:
          type: array
          maxItems: 20
          items:
            $ref: '#/components/schemas/HttpTool'
          default: []
          description: Your own functions the agent can call, up to 20.
        mcp:
          type: array
          maxItems: 10
          items:
            $ref: '#/components/schemas/McpServer'
          default: []
          description: Remote MCP servers the agent can call, up to 10.
        browser:
          type: object
          properties:
            keep_logins:
              type: boolean
              description: >-
                Its cloud browser keeps the sites your team signed in to (its
                cookies, encrypted) from one browser to the next. Off: every
                browser starts signed out, and turning it off forgets what was
                kept.
              default: false
          required:
            - keep_logins
        code:
          type: object
          description: >-
            Run code: in the chat, the agent has its model provider’s own
            sandbox, with no internet. On Claude models, Anthropic’s code
            execution (Bash and Python), kept between turns; on GPT models,
            OpenAI’s Code Interpreter (Python), reset after 20 minutes unused,
            with the conversation’s files put back. Either works on files people
            attach (they’re in the sandbox too), does exact calculations, and
            can hand back files it makes; one sandbox per conversation. On
            Gemini models, Gemini’s code execution (Python, 30 seconds a run,
            nothing kept between runs): exact calculations and charts, but no
            other files in or out, so files only a sandbox opens are refused.
          properties:
            enabled:
              type: boolean
              default: false
        visual:
          type: object
          description: >-
            Visual answers: in the chat, a long answer (a status, options to
            compare, a table, steps) is also laid out as UI, which the console
            and the website widget show (`view` on the message). The text stays
            the answer. On unless turned off.
          properties:
            enabled:
              type: boolean
              default: true
            blocks:
              type: array
              items:
                type: string
                enum:
                  - facts
                  - table
                  - options
                  - list
                  - callout
                  - badges
                  - bars
              description: >-
                The cards a view may use; all of them by default. `text` is
                always there, and `buttons` come with `choices`.
            choices:
              type: boolean
              default: true
              description: >-
                Whether a view has anything to press: a `pick` on options and
                `buttons` for next steps, which send a reply for the person.
                Off: nothing to press.
            instructions:
              type:
                - string
                - 'null'
              maxLength: 2000
              description: >-
                How answers should be laid out, in your words, like "Lead with
                the warranty status. Put part numbers in a table." It steers the
                layout only: a view still has only what the answer says. null:
                none.
    AgentResources:
      type: object
      description: >-
        Where the agent’s tasks may run. `browser`: its own cloud browser in
        each conversation (`enabled`, off by default; `start_url`, an absolute
        http(s) address where it opens; `keep_logins`, the same setting as
        `tools.browser.keep_logins`). `computers`: up to 50 linked computers and
        pools for its desktop tasks, used in order, whichever is free first.
        Send part of it to change only those keys; `computers`, when sent, is
        the whole list; `browser: null` turns the browser off and `resources:
        null` resets both.
      properties:
        browser:
          type: object
          properties:
            enabled:
              type: boolean
              default: false
            start_url:
              type:
                - string
                - 'null'
              format: uri
              maxLength: 2000
            keep_logins:
              type: boolean
              default: false
        computers:
          type: array
          maxItems: 50
          items:
            type: object
            required:
              - type
              - id
            properties:
              type:
                type: string
                enum:
                  - computer
                  - pool
              id:
                type: string
                maxLength: 60
                description: >-
                  A linked computer’s id (its code, like `K7QM-24XP`) or a
                  pool’s (`pool_…`).
      example:
        browser:
          enabled: true
          start_url: https://portal.example.com/orders
          keep_logins: false
        computers:
          - type: pool
            id: pool_8fK2mQ0aLp4x
    EscalationRules:
      type: object
      description: >-
        What needs the team, and whether the agent's procedure runs are checked.
        Every key is on by default. Returned whole; in a change, send only the
        keys that change (null turns them all back on).
      properties:
        qa:
          type: boolean
          default: true
          description: >-
            AI Review: check each run of one of the agent's procedures against
            its steps, on the cheapest model of the agent's provider. Charged by
            its tokens at that model's price. Off: runs aren't checked, and no
            `procedure_failed` or `procedure_change` is raised.
        approval:
          type: boolean
          default: true
          description: >-
            Escalate approvals only the team can decide (list, email, webhook).
            Off: they still wait in their conversation.
        question:
          type: boolean
          default: true
          description: >-
            Escalate questions only the team can answer. Off: they still wait in
            their conversation.
        procedure_failed:
          type: boolean
          default: true
          description: Escalate runs the check found failed (needs `qa`).
        procedure_change:
          type: boolean
          default: true
          description: >-
            Escalate runs the check found worked another way, with the procedure
            rewritten to match (needs `qa`).
        handoff:
          type: boolean
          default: true
          description: >-
            Let the agent hand a request to the team from a chat (its `escalate`
            tool), raising a `handoff` escalation (list, email, webhook). Off:
            it isn’t offered the tool.
    Actor:
      oneOf:
        - title: Person
          type: object
          description: A person in the org (in the console).
          properties:
            type:
              const: user
            email:
              type:
                - string
                - 'null'
              example: jane@acme.com
        - title: API key
          type: object
          description: One of the org’s API keys.
          properties:
            type:
              const: api_key
            key_id:
              type: string
            name:
              type:
                - string
                - 'null'
              example: Zendesk
            prefix:
              type:
                - string
                - 'null'
              description: The key’s first characters.
              example: gh_live_AbC1
        - type: 'null'
      description: >-
        Who did it: a person (in the console) or an API key. Null when nobody
        was recorded: it was made with a session token, by Eager itself, or
        before this was kept.
    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.'
    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.
    HttpTool:
      type: object
      required:
        - name
        - description
        - url
      description: >-
        An API the agent can call. When the model calls the tool, Eager makes
        the call as the tool says (unsigned) and gives the model the response
        body (64 KB, within `timeout_seconds`). A set call (`method`,
        `parameters`): `{name}` placeholders in `url`’s path take those
        arguments, and the others are the query of a `GET` or `DELETE`, else the
        JSON body. An open call (`methods`): `url` is a base, and the agent
        gives each call’s `method`, `path` (with any query) and JSON `body`; a
        call that would leave the base (another host, or a path outside it) is
        refused. Redirects are followed only to an address the tool could call
        itself. Tools made before 2026-10-21 were signed POSTs of an envelope;
        they are now set calls, a POST of their arguments to the same `url`.
      properties:
        name:
          type: string
          pattern: ^[a-zA-Z][a-zA-Z0-9_-]{0,63}$
          example: lookup_order
          description: >-
            What the model calls it: a letter, then letters, numbers, `_` or
            `-`, up to 64. Unique for the agent (in any case), and not one of
            Eager’s own (`ask_user`, `request_approval`, `computer`, or the file
            system’s).
        description:
          type: string
          maxLength: 1000
          example: 'Look up an order by its number: status, items and delivery date.'
          description: What it does and when to use it, for the model.
        url:
          type: string
          format: uri
          example: https://api.acme.com/v1/orders/{order}
          description: >-
            The API’s address: public https, without a user name or password,
            and no keys or tokens in its query. For a set call, the endpoint,
            with `{name}` placeholders in its path for arguments. For an open
            call, the base (its host and path prefix, without a query), like
            `https://api.example.com/v1/`: the agent calls only paths under it.
        method:
          type: string
          enum:
            - GET
            - POST
            - PUT
            - PATCH
            - DELETE
          default: POST
          description: >-
            A set call’s method. Arguments not in `url` go in the query of a
            `GET` or `DELETE`, else in the JSON body.
        parameters:
          type: object
          default:
            type: object
            properties: {}
          description: >-
            A set call’s arguments, as a JSON Schema object (`{ "type":
            "object", "properties": { … } }`), under 10 KB. Left out: no
            arguments.
        methods:
          type: array
          items:
            type: string
            enum:
              - GET
              - POST
              - PUT
              - PATCH
              - DELETE
          default:
            - GET
            - POST
          description: >-
            Makes it an open call: the methods the agent may use. It then has no
            `method` or `parameters`: each call takes `method`, `path` and
            `body`.
        headers:
          type: object
          additionalProperties:
            type: string
          maxProperties: 20
          example:
            User-Agent: Mozilla/5.0
          description: >-
            Fixed headers sent with every call. No keys, tokens or sign-ins (a
            header named like `Authorization`, `Cookie` or `X-Api-Key` is
            refused: it would be kept in every version of the agent). Tools
            can’t hold keys yet.
        timeout_seconds:
          type: integer
          minimum: 5
          maximum: 120
          description: >-
            How long a call waits for an answer, in seconds. Left out: 45. A
            `GET` that times out is tried once more.
        approval:
          type: string
          enum:
            - never
            - always
          default: never
          description: >-
            `always`: each call waits for your team’s approval first, asked in
            the conversation (a task is `paused` until it’s decided). In `auto`
            mode such a call is approved automatically, and in `unattended` mode
            refused.
    McpServer:
      type: object
      required:
        - name
        - url
        - tools
        - approval
      description: >-
        A remote MCP server the agent can call. Eager lists its tools
        (`tools/list`) when it's saved and keeps them with the agent's version,
        so a version always offers the same tools; at run time each call is a
        `tools/call` from Eager's servers, signed in with the server's saved
        headers or OAuth sign-in (its access token renewed before it expires).
        The tool's text result is what the model gets (images and audio are
        described, not shown).
      properties:
        name:
          type: string
          pattern: ^[a-zA-Z][a-zA-Z0-9-]{0,29}$
          example: crm
          description: >-
            The server's name: a letter, then letters, numbers or `-`, up to 30.
            The model sees each of its tools as `<name>__<tool>` (characters
            other than letters, numbers, `_` and `-` in a tool's name become
            `_`).
        url:
          type: string
          format: uri
          example: https://mcp.example.com/mcp
          description: >-
            Its Streamable HTTP address (MCP 2025-03-26 or later): public https
            only. Servers that only speak the older SSE transport aren't
            supported.
        description:
          type: string
          maxLength: 1000
          description: >-
            When the agent should use it. Added to each of its tools'
            descriptions.
        auth:
          type: object
          description: >-
            The sign-in it was saved with: the header names and the id of the
            secret holding them, or (`type: "oauth"`) an OAuth sign-in connected
            in the console. The values and tokens are kept encrypted for your
            organization, never returned and never kept in the agent's versions.
          properties:
            headers:
              type: array
              items:
                type: string
              example:
                - Authorization
            secret_id:
              type: string
              example: tsec_8Zp2kQ7wLm4x
            type:
              type: string
              enum:
                - oauth
              description: >-
                `oauth`: an OAuth sign-in (see `GET /v1/mcp_oauth/{secret_id}`
                for whether it's connected). Left out: headers.
        tools:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
                example: lookup_order
              description:
                type: string
              parameters:
                type: object
                description: Its arguments' JSON Schema, as the server gave it.
          description: Its tools, as listed when it was last saved (or refreshed).
        allowed_tools:
          type: array
          items:
            type: string
          description: >-
            The names of its tools the agent may use. Left out (or `null`): all
            of them. Up to 100 tools across an agent's servers.
        approval:
          type: string
          enum:
            - never
            - always
          default: never
          description: >-
            `always`: your team allows each call first (unattended agents can't
            use its tools).
        timeout_seconds:
          type: integer
          minimum: 5
          maximum: 120
          description: 'How long a call waits for an answer, in seconds. Left out: 30.'
    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.'
  responses:
    E401:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E403:
      description: Your role can’t do this.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E404:
      description: Not found in this org.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E409:
      description: >-
        Conflicts with the current state (e.g. no computer connected, a task
        already running, nothing pending, no draft to publish, an agent’s file
        limits).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  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.