Docs menu

What agents can do

You decide how much an AI agent may change on its own, with a freedom level for your account and, if you like, one per board. This page shows exactly what each level allows, what agents never do, and how an agent can work through a board without you watching.

The five levels

  • 1Read only. Agents can read, not change anything.
  • 2Suggest. Every change waits in the Inbox for you.
  • 3Capture. Agents capture ideas, bugs and notes; other changes wait in the Inbox.
  • 4Act. Agents work on items and lists; completing and archiving wait in the Inbox.
  • 5Full. Agents change anything they can, and every change is logged.

Set the account level in Settings, Agents and a board's own in its Board settings. New accounts start at 3. A level counts from the agent's next request, and every result tells the agent which level applied. A list without a kind counts as a to do list, and a move between boards follows the stricter board.

Every action at every level

Yes means the change happens. Inbox means it waits in the board's Inbox until you accept or reject it. No means it is refused, and the agent is told why. At levels 2 to 5 an agent can also send any change that has an Inbox to the Inbox itself, when it is unsure.

Agents get the same table for their own level: get_account, start_session and get_board return allowed, a map of each action name below to direct, inbox or no. Both come from one source in the code, so they cannot disagree.

Items

  • Add an item to an info or capture list (ideas, bugs, notes)

    1No2Inbox3Yes4Yes5Yes

  • Add an item to a to do, backlog or doing list

    1No2Inbox3Inbox4Yes5Yes

  • Add an item straight to a done list

    1No2Inbox3Inbox4Inbox5Yes

  • Edit an item: title, description, dates, labels, cover; restore a document version

    1No2Inbox3Inbox4Yes5Yes

  • Move an item to another list (not a done list)

    1No2Inbox3Inbox4Yes5Yes

  • Move an item into a done list

    1No2Inbox3Inbox4Inbox5Yes

  • Copy an item (not into a done list)

    1No2Inbox3Inbox4Yes5Yes

  • Mark an item's due date done

    1No2Inbox3Inbox4Inbox5Yes

  • Archive or restore an item

    1No2Inbox3Inbox4Inbox5Yes

Checklists

  • Add a checklist item

    1No2Inbox3Yes4Yes5Yes

  • Add a checklist

    1No2Inbox3Inbox4Yes5Yes

  • Rename a checklist; tick, edit or reorder its items

    1No2Inbox3Inbox4Yes5Yes

  • Remove a checklist item it added itself

    1No2Inbox3Inbox4Inbox5Yes

Comments

  • Comment on an item

    1No2Inbox3Yes4Yes5Yes

Files

  • Attach a file to an item

    1No2No3No4Yes5Yes

Lists

  • Add a list

    1No2Inbox3Inbox4Yes5Yes

  • Rename a list

    1No2Inbox3Inbox4Yes5Yes

  • Put lists in a new order

    1No2Inbox3Inbox4Yes5Yes

  • Make, change and fill list groups

    1No2Inbox3Inbox4Yes5Yes

  • Archive or restore a list

    1No2Inbox3Inbox4Inbox5Yes

  • Move a list to another board

    1No2Inbox3Inbox4Inbox5Yes

  • Copy a list to a board

    1No2Inbox3Inbox4Inbox5Yes

Boards

  • Create a board (the account's level decides)

    1No2No3Yes4Yes5Yes

  • Change a board's title, description, website or star

    1No2Inbox3Inbox4Yes5Yes

  • Archive or restore a board

    1No2Inbox3Inbox4Inbox5Yes

Labels

  • Create a label (the account's level decides)

    1No2No3No4Yes5Yes

  • Rename or recolor a label (the account's level decides)

    1No2No3No4Yes5Yes

  • Delete a label that is on no item (the account's level decides)

    1No2No3No4No5Yes

Working on items

  • Claim an item while working on it

    1No2No3No4Yes5Yes

  • Release its claim on an item

    1No2No3No4Yes5Yes

  • Pick the next open item and claim it

    1No2No3No4Yes5Yes

What agents never do

At any level, agents never:

  • Delete an item, list, board, checklist, comment or attachment (they archive instead).
  • Change freedom levels, guidance or board instructions.
  • Accept or reject suggestions in the Inbox.
  • Make share links or inbound email addresses.
  • Create, see or change API tokens or webhooks.
  • Undo a change made by the user or by another agent.
  • Take an item another agent has claimed.

Every change is in the board's history with the agent's name, and you can undo it there for 30 days.

ListSpace runs no AI models itself and never uses your boards to train them. An agent you connect reads what you allow it under its own provider's terms, which ListSpace does not control. The privacy policy lists who else handles your data.

Working on their own

From level 4 an agent can take items from a board and work through them, one at a time, while you do something else. The ListSpace skill teaches it this loop:

  1. Start with get_account or start_session and read allowed: for every action, direct (it happens), inbox (it waits for you) or no.
  2. Call next_item. It picks the top open item in the board's to do lists (then backlog) that no other agent is working on, claims it and moves it to Doing when the level allows.
  3. Do the work, and log what it did with add_comment on the item.
  4. Move the item to the done list. At level 4 that waits in your Inbox; at level 5 it happens.
  5. Call release_item, then next_item again.
  6. Stop when next_item says empty, when the level does not allow it, when you said to stop, or after the number of items you gave. Then it tells you what it did, what it suggested and what is left.

Install the skill with npx skills add listspace/agent. In Claude Code you can add the ListSpace plugin instead, which brings the skill and the MCP server together: see the Claude Code steps. The skill, the plugin and a command line tool are public at github.com/listspace/agent. The command line tool is on npm as listspace: run npx listspace login, paste a personal token from Settings > API, then npx listspace boards.

Claims

A claim says an agent is working on an item, so two agents never do the same work. next_item claims for the agent; claim_item claims one it picked itself, and release_item lets go. The item shows the agent's name on the board, for example Claude is working on this, and you can release it from the item window.

  • Two agents asking for the next item at the same moment get different items: the database picks and claims in one step.
  • A claim runs out after 2 hours (the agent can ask for 5 minutes to 24 hours). Any change the agent makes to the item moves that forward.
  • An agent never takes an item another agent has claimed. It is told who holds it and until when.
  • A claim changes nothing in the item. It is in the history as claimed and released, and needs level 4.

Webhooks

A webhook posts to an address of yours when something changes, so a script or an agent can react. Add one in Settings, Agents, Webhooks, for one board or all of them, and choose the events. Only you can add webhooks, in the app: agents can neither see nor make them.

  • item.createdAn item is created, by you, an agent or email.
  • item.movedAn item moves to another list.
  • item.updatedAn item's title, description, dates, labels or checklist change, or it is archived or restored.
  • item.completedAn item moves into a done list, or its due date is marked done.
  • suggestion.createdAn agent puts a change in a board's Inbox.
  • suggestion.decidedYou accept or reject a suggestion.
  • comment.addedA comment is added to an item.

Each delivery is a POST of JSON, within about 30 seconds of the change:

Headers
POST /your/address HTTP/1.1
Content-Type: application/json
User-Agent: ListSpace-Webhooks/1.0
ListSpace-Event: item.created
ListSpace-Delivery: 0f6d2c1e-8b7a-4c3d-9e2f-1a0b9c8d7e6f
ListSpace-Signature: t=1791200400, v1=5f2b9c...e81a
Body
{
  "id": "0f6d2c1e-8b7a-4c3d-9e2f-1a0b9c8d7e6f",
  "type": "item.created",
  "created_at": "2026-10-05T09:40:00.512908+00:00",
  "attempt": 1,
  "board": {
    "id": "a3f1c2d4-5b6e-4f70-8a9b-0c1d2e3f4a5b",
    "title": "Bakery site",
    "url": "https://listspace.app/board/a3f1c2d4-5b6e-4f70-8a9b-0c1d2e3f4a5b"
  },
  "data": {
    "item": {
      "id": "d6a4f5e7-8c91-42a3-bdce-3f4a5b6c7d8e",
      "title": "Add opening hours to the footer",
      "list_id": "b4e2d3c5-6a7f-4081-9bac-1d2e3f4a5b6c",
      "list_title": "To do",
      "list_kind": "todo",
      "board_id": "a3f1c2d4-5b6e-4f70-8a9b-0c1d2e3f4a5b",
      "due_date": null,
      "done": false,
      "archived": false,
      "url": "https://listspace.app/board/a3f1c2d4-5b6e-4f70-8a9b-0c1d2e3f4a5b/card/d6a4f5e7-8c91-42a3-bdce-3f4a5b6c7d8e"
    },
    "change": {
      "kind": "created",
      "list": "To do",
      "list_id": "b4e2d3c5-6a7f-4081-9bac-1d2e3f4a5b6c",
      "event_id": "7a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"
    },
    "actor": {
      "kind": "user",
      "name": null
    },
    "request_id": null
  }
}

data.change has what the history recorded (for a move: from_list, to_list), data.actor who did it, and comments and suggestions come with data.comment or data.suggestion. ListSpace-Delivery stays the same when a delivery is retried, so use it to skip duplicates.

Check the signature

Every webhook has its own signing secret (whsec_...), shown once when you add it. ListSpace-Signature is t=<unix seconds>, v1=<hex>, where v1 is the HMAC-SHA256 of <t>.<raw body> with that secret. Compute it over the body exactly as received, compare in constant time, and refuse a t more than 5 minutes off.

Node.js
import { createHmac, timingSafeEqual } from 'node:crypto'

// rawBody: the request body exactly as received (a string), before any JSON parsing
export function verifyListSpace(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.trim().split('=')))
  const t = Number(parts.t)
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false // older than 5 minutes
  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex')
  const given = Buffer.from(parts.v1 ?? '', 'hex')
  return given.length === 32 && timingSafeEqual(given, Buffer.from(expected, 'hex'))
}
Python
import hashlib, hmac, time

def verify_listspace(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(p.strip().split("=", 1) for p in header.split(","))
    t = int(parts.get("t", "0"))
    if abs(time.time() - t) > 300:  # older than 5 minutes
        return False
    expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts.get("v1", ""))

Retries and limits

  • Answer with any 2xx status within 10 seconds. Anything else is retried: after 30 seconds, then twice as long each time, for up to 24 hours.
  • A redirect is not followed and a 410 stops the deliveries for that event. The address must be https and reach the public internet.
  • Settings shows the last 50 deliveries of each webhook and has a button to send a test. Up to 10 webhooks per account.

Waking an agent

An agent works when something starts it. Two common ways: a schedule (every morning, work through To do), or a webhook (an item was added, go). Both can run the same agent, for example Claude Code in a GitHub Action with the ListSpace MCP server.

GitHub Action (example)
# .github/workflows/listspace.yml: an agent works through the board when you add items
name: Work on ListSpace items
on:
  repository_dispatch:
    types: [listspace]       # your webhook receiver calls the GitHub API with this type
  schedule:
    - cron: '0 7 * * 1-5'    # and every weekday morning anyway
jobs:
  work:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: >
            Use the ListSpace MCP server. Work through the To do list of the
            "Website" board on your own: next_item, do the work, comment,
            move it to Done, release_item. Stop after 3 items.
          claude_args: --mcp-config .mcp.json
Webhook receiver (Node.js, example)
// A tiny receiver: check the signature, then wake the GitHub Action above
app.post('/hooks/listspace', express.raw({ type: 'application/json' }), async (req, res) => {
  const raw = req.body.toString('utf8')
  if (!verifyListSpace(raw, req.get('ListSpace-Signature') ?? '', process.env.LISTSPACE_SECRET)) return res.sendStatus(401)
  res.sendStatus(204)                       // answer fast; ListSpace waits 10 seconds at most
  const event = JSON.parse(raw)
  if (event.type !== 'item.created') return
  await fetch('https://api.github.com/repos/you/website/dispatches', {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.GITHUB_TOKEN}`, Accept: 'application/vnd.github+json' },
    body: JSON.stringify({ event_type: 'listspace', client_payload: { item: event.data.item.id } }),
  })
})

A scheduled Claude Code routine works the same way without a receiver: give it the prompt above and the ListSpace connector. Whatever starts it, the agent follows the board's level and leaves anything it may not do in your Inbox.

Next: connect an assistant over MCP or see the REST endpoints for claims.