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

# Give an agent its own manager

> The exception, not the ordinary case: it pulls the agent out of its team's line. `manager: null` puts it back into that line (inheritance). Refused when it would close a loop (`ORG_CYCLE`) or when nobody human would end up above the agent (`ORG_NO_HUMAN_MANAGER`) — an agent under an agent is allowed; an agent under an agent under nobody is what the rule forbids.



## OpenAPI

````yaml /api-reference/openapi.json put /organization/agents/{id}/manager
openapi: 3.1.0
info:
  title: Atako API
  version: 0.1.0
  description: >-
    The Atako customer API — manage AI agents, their files, integrations,
    billing, and your company/team, programmatically.


    ## Authentication


    Every non-public endpoint takes a Bearer token that is either:

    - a **programmatic API key** (`aik_…`) — create one at
    [app.atako.ai](https://app.atako.ai) → Settings → API keys (company-admin
    only), or

    - a **Supabase session JWT** — what the web app itself sends; not practical
    to obtain outside a browser session.


    ```bash

    curl https://api.atako.ai/agents -H "Authorization: Bearer aik_..."

    ```


    An API key acts as its owning user, with all of that user's permissions —
    there is no separate key scope in this release.


    ## Other Atako HTTP surfaces (not covered by this spec)


    - **Atako MCP server** — `POST /mcp` (auth: same Bearer token as above)
    exposes a read-only Model Context Protocol tool catalogue for AI clients
    (Claude Code, Claude Desktop, Cursor, ChatGPT). See
    [docs.atako.ai/developers/mcp/overview](https://docs.atako.ai/developers/mcp/overview).

    - **Content API** (`cak_…` key, `/content/*`) — a separate, more restricted
    key type for headless CMS-style access to blog/news/use-case content. Not
    documented here.


    ## Errors


    Errors use a JSON envelope: `{ "error": string, "code"?: string }`. `error`
    is either a short human-readable message or a SCREAMING_SNAKE_CASE code,
    depending on the route — treat it as an opaque string to match against, not
    a stable enum across the whole API.


    ## Rate limits


    Authenticated routes: 6000 requests/min per user (`authRateLimit`). Public
    GET routes: 60/min per IP. A handful of sensitive public POST routes
    (newsletter signup, email-exists, invitation preview) are limited to 10
    requests / 15 min per IP.


    ## Pagination


    List endpoints use either simple `limit`/`offset` query params (marketing
    content — a plain JSON array response, capped at the documented max) or
    `page`/`limit` (credit transactions). Neither returns a total count today;
    fetch until a page comes back shorter than `limit`.
servers:
  - url: https://api.atako.ai
    description: Production
security: []
tags:
  - name: Agents
  - name: Messages
  - name: Activity
  - name: Agent Options
  - name: API Keys
  - name: Files
  - name: Cron Jobs
  - name: Sub-Agents
  - name: Interagent Messages
  - name: Integrations
  - name: Subscriptions
  - name: Users
  - name: Company
  - name: Teams
  - name: Floor
  - name: Organization
  - name: Projects
  - name: Public
  - name: Marketing Content
paths:
  /organization/agents/{id}/manager:
    put:
      tags:
        - Organization
      summary: Give an agent its own manager
      description: >-
        The exception, not the ordinary case: it pulls the agent out of its
        team's line. `manager: null` puts it back into that line (inheritance).
        Refused when it would close a loop (`ORG_CYCLE`) or when nobody human
        would end up above the agent (`ORG_NO_HUMAN_MANAGER`) — an agent under
        an agent is allowed; an agent under an agent under nobody is what the
        rule forbids.
      operationId: setOrgAgentManager
      parameters:
        - name: id
          in: path
          required: true
          description: Agent id
          schema:
            type: string
            format: uuid
      requestBody:
        description: ''
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - manager
              properties:
                manager:
                  allOf:
                    - $ref: '#/components/schemas/OrgRef'
                  nullable: true
      responses:
        '200':
          description: The recomputed chart — identical shape to GET /organization/chart.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrgChart'
        '400':
          description: >-
            Validation error, or a refused hierarchy: `ORG_CYCLE` (the link
            would close a loop) / `ORG_NO_HUMAN_MANAGER` (somebody would end up
            with no person responsible for them). The body carries the bare CODE
            so the client can say which.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Missing, malformed, or invalid bearer token / API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >-
            Admin only — every organisation write is reserved to a company
            admin.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: >-
            No company, an unknown id, or one belonging to another company
            (`TEAM_NOT_FOUND` / `ORG_REF_NOT_FOUND`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - bearerAuth: []
components:
  schemas:
    OrgRef:
      type: object
      description: >-
        A reference to a member of the organisation, whatever its nature. Humans
        and agents are the same kind of node in this chart.
      properties:
        kind:
          type: string
          enum:
            - human
            - agent
        id:
          type: string
          format: uuid
      required:
        - kind
        - id
    OrgChart:
      type: object
      description: >-
        The whole chart, and the single payload of every /organization operation
        — reads AND writes. A hierarchy change moves people who were not named
        in the request, so a write answers with the recomputed chart rather than
        an acknowledgement: the client never has to make a second call, nor
        guess. It carries both the derived SHAPE (`tree`) and the raw CHOICES
        (`teams`/`agents`/`humans`, with their explicit `lead`/`manager`), which
        is what an editor needs to show what was decided instead of what was
        inferred from it.
      properties:
        rootHumanId:
          type: string
          format: uuid
          nullable: true
          description: >-
            DERIVED, never stored: the oldest `admin` member. Null when the
            company has no admin at all — the only case where the chart has
            nothing to hang on.
        tree:
          type: object
          description: >-
            The chart as a forest. `roots` are the people nobody stands above
            (normally one). `loose` collects what the structure left dangling —
            a team whose lead is gone stays on the chart, to be repaired rather
            than to vanish quietly.
          properties:
            roots:
              type: array
              items:
                $ref: '#/components/schemas/OrgNode'
            loose:
              type: array
              items:
                $ref: '#/components/schemas/OrgNode'
          required:
            - roots
            - loose
        issues:
          type: array
          items:
            $ref: '#/components/schemas/OrgIssue'
        teams:
          type: array
          items:
            $ref: '#/components/schemas/OrgTeam'
        agents:
          type: array
          items:
            $ref: '#/components/schemas/OrgAgentNode'
        humans:
          type: array
          items:
            $ref: '#/components/schemas/OrgHuman'
        canEdit:
          type: boolean
          description: >-
            True when the caller is a company admin, i.e. when the write
            operations below are open to them. Told here so the client never has
            to deduce a permission from a 403 it provoked.
      required:
        - rootHumanId
        - tree
        - issues
        - teams
        - agents
        - humans
        - canEdit
    Error:
      type: object
      description: >-
        Atako's standard error envelope. `error` is either a short
        human-readable message or a SCREAMING_SNAKE_CASE code (routes are
        inconsistent about which — treat it as an opaque string and match on it
        exactly if you need to branch on error type). Some routes add extra
        fields alongside `error` (see the operation's own error responses).
      properties:
        error:
          type: string
        code:
          type: string
          description: >-
            Present on some routes; a stable machine-readable code duplicating
            or refining `error`.
      required:
        - error
      additionalProperties: true
    OrgNode:
      type: object
      description: >-
        One box of the chart. `id` is a user, agent or team id depending on
        `kind` — the single exception being the VIRTUAL team `unassigned`, which
        has no row in the database and gathers the agents that belong to no
        team. `name` on that node is the literal string `unassigned`: the client
        names it in its own language.
      properties:
        key:
          type: string
          description: 'Stable key: `human:<id>`, `agent:<id>` or `team:<id>`.'
        kind:
          type: string
          enum:
            - human
            - agent
            - team
        id:
          type: string
        name:
          type: string
        role:
          type: string
          nullable: true
        teamId:
          type: string
          format: uuid
          nullable: true
          description: >-
            On a member node: the team it stands in. On a team node: its own id,
            or null for the virtual `unassigned` group.
        memberCount:
          type: integer
          description: Team nodes only — agents plus humans attached to the team.
        children:
          type: array
          items:
            $ref: '#/components/schemas/OrgNode'
      required:
        - key
        - kind
        - id
        - name
        - role
        - children
    OrgIssue:
      type: object
      description: >-
        A rule the structure is currently breaking. A CODE, never a sentence:
        the client translates. `team-lead` — `id` is a team with no designated
        lead (it falls back to the root: to confirm, not to repair urgently).
        `agent-manager` — `id` is an agent with no manager at all. `agent-human`
        — `id` is an agent whose chain never reaches a person.
      properties:
        kind:
          type: string
          enum:
            - team-lead
            - agent-manager
            - agent-human
        id:
          type: string
      required:
        - kind
        - id
    OrgTeam:
      type: object
      description: A team as the hierarchy needs to see it.
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        parentId:
          type: string
          format: uuid
          nullable: true
        lead:
          allOf:
            - $ref: '#/components/schemas/OrgRef'
          nullable: true
          description: >-
            The EXPLICITLY designated lead, or null — a team with no lead falls
            back to the company root, and `issues` reports it as `team-lead`.
      required:
        - id
        - name
        - parentId
        - lead
    OrgAgentNode:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        role:
          type: string
          nullable: true
          description: The title of the org-chart position held, when there is one.
        teamId:
          type: string
          format: uuid
          nullable: true
        manager:
          allOf:
            - $ref: '#/components/schemas/OrgRef'
          nullable: true
          description: >-
            The individual override, or null when the agent simply inherits its
            team's lead (the ordinary case).
      required:
        - id
        - name
        - role
        - teamId
        - manager
    OrgHuman:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: User id.
        name:
          type: string
        title:
          type: string
          nullable: true
        teamId:
          type: string
          format: uuid
          nullable: true
        managerUserId:
          type: string
          format: uuid
          nullable: true
          description: >-
            A person answers to a person, or to nobody — never to an agent. Null
            on the root of the chart.
      required:
        - id
        - name
        - title
        - teamId
        - managerUserId
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        An `aik_…` programmatic API key (app.atako.ai → Settings → API keys) or
        a Supabase session JWT.

````