# Get started (for AI Agents) (/docs/agent-get-started)



andibase [#andibase]

Build and operate AI-native workflows with one shared system for AI agents & humans.

Skill Files [#skill-files]

| File                     | URL                                  |
| ------------------------ | ------------------------------------ |
| **SKILL.md** (this file) | `https://andibase.com/skill.md`      |
| **Docs.md**              | `https://andibase.com/docs.md`       |
| **Recipes**              | `https://andibase.com/docs/receipes` |

**Install locally:**

```bash
mkdir -p ~/.agents/skills/andibase
curl -s https://andibase.com/skill.md > ~/.agents/skills/andibase/SKILL.md
```

**Or just read them from the URLs above!**

**For inspiration before you build:**

* [Recipes index](https://andibase.com/docs/receipes)
* [Expense tracker recipe](https://andibase.com/docs/receipes/expense-tracker)

Use these recipes when you want a starting point for a new agent, app, or workflow.

**Base URL:** `https://andibase.com/api/v1/`

What this login flow gives you [#what-this-login-flow-gives-you]

This flow gives an agent a **reusable workspace API key** for the regular HTTP API.

It does **not** return an OAuth token, and it is **not** the MCP OAuth flow.

If you complete this flow successfully, save `apiKey.key` and use it in:

```http
Authorization: Bearer <api-key>
```

for future `/api/v1/...` requests.

Login first [#login-first]

Every agent needs to start login and get approved by their human:

```bash
curl -X POST https://andibase.com/api/v1/agent/auth/requests \
  -H "Content-Type: application/json" \
  -d '{
    "agentName": "YourAgentName",
    "agentDescription": "What your agent does",
    "role": "admin"
  }'
```

If you omit `role`, the API defaults to `admin`.

Response:

```json
{
  "deviceCode": "dc_xxx",
  "userCode": "ABCD-1234",
  "verificationUri": "https://andibase.com/agent-login",
  "verificationUriComplete": "https://andibase.com/agent-login?user_code=ABCD-1234",
  "expiresAt": "2026-03-07T18:15:00.000Z",
  "intervalSeconds": 5,
  "instructions": {
    "verificationMessage": "Ask the user to open verificationUriComplete and approve the request.",
    "exchangeMessage": "After approval, call POST /api/v1/agent/auth/exchange with deviceCode.",
    "apiKeySecretField": "apiKey.key",
    "apiKeySaveHint": "When exchange succeeds, save apiKey.key immediately. The secret is returned once and should be reused for future calls."
  }
}
```

The only two fields the agent must keep are:

* `verificationUriComplete`: send this to the human
* `deviceCode`: use this for polling and exchange

Agent flow in 4 steps [#agent-flow-in-4-steps]

1. Call `POST /api/v1/agent/auth/requests`.
2. Show the human `verificationUriComplete`.
3. Poll `POST /api/v1/agent/auth/exchange` with `deviceCode`.
4. Save `apiKey.key` and reuse it for future HTTP API calls.

Exchange device code [#exchange-device-code]

Call this endpoint until you get either:

* success with `apiKey.key`, or
* a terminal error such as `access_denied`, `expired_token`, or `invalid_grant`

```bash
curl -X POST https://andibase.com/api/v1/agent/auth/exchange \
  -H "Content-Type: application/json" \
  -d '{"deviceCode":"dc_xxx"}'
```

What `exchange` means here [#what-exchange-means-here]

This endpoint is named `exchange`, but the important behavior is:

* while approval is still pending, it tells the agent to wait,
* once approved, it **issues a reusable API key**,
* the secret is returned at `apiKey.key` exactly once.

Response: pending [#response-pending]

```json
{
  "code": "authorization_pending",
  "message": "The customer has not approved this login request yet."
}
```

Response: slow down [#response-slow-down]

```json
{
  "code": "slow_down",
  "message": "Poll less frequently and retry in about 5 seconds."
}
```

Response: success [#response-success]

```json
{
  "status": "approved",
  "workspace": {
    "handle": "acme-growth-team",
    "name": "Acme Growth Team",
    "createdAt": "2026-03-05T18:00:00.000Z",
    "updatedAt": "2026-03-05T18:00:00.000Z",
    "deletedAt": null
  },
  "apiKey": {
    "key": "andi_live_xxx",
    "apiKey": {
      "id": "key_6ZW0qF8cXTWETrdFM3A7yv",
      "name": "Claude production key",
      "start": "andi_l",
      "prefix": "andi_",
      "enabled": true,
      "role": "admin",
      "createdAt": "2026-03-07T18:10:00.000Z",
      "updatedAt": "2026-03-07T18:10:00.000Z",
      "expiresAt": null,
      "lastRequest": null
    }
  },
  "usage": {
    "saveHint": "Store this API key in a secrets manager or environment variable before continuing. Reuse the same key for future calls instead of re-running login. The secret is only returned once.",
    "recommendedEnvVar": "ANDI_API_KEY",
    "authorizationHeader": "Authorization: Bearer <api-key>",
    "secretField": "apiKey.key",
    "lifecycle": "This key is persistent until revoked or until its configured expiration, if any."
  }
}
```

What to do for each response [#what-to-do-for-each-response]

| Response                | Meaning                                                            | Agent action                  |
| ----------------------- | ------------------------------------------------------------------ | ----------------------------- |
| `authorization_pending` | The human has not approved yet                                     | Sleep and poll again          |
| `slow_down`             | You are polling too quickly                                        | Wait longer, then retry       |
| `access_denied`         | The human rejected the request                                     | Stop and ask for a new login  |
| `expired_token`         | The login request expired                                          | Start a new login             |
| `invalid_grant`         | The `deviceCode` is invalid, already consumed, or no longer usable | Start a new login             |
| success                 | The request was approved and the key was issued                    | Save `apiKey.key` immediately |

Minimal polling loop [#minimal-polling-loop]

```ts
while (true) {
  const response = await fetch("https://andibase.com/api/v1/agent/auth/exchange", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ deviceCode }),
  });

  const payload = await response.json();

  if (response.ok) {
    const apiKey = payload.apiKey.key;
    // Save securely and reuse for future HTTP API calls.
    break;
  }

  if (payload.code === "authorization_pending") {
    await sleep(5000);
    continue;
  }

  if (payload.code === "slow_down") {
    await sleep(7000);
    continue;
  }

  throw new Error(`Agent login failed: ${payload.code}`);
}
```

**Important:** save `apiKey.key` immediately. You need it for all authenticated HTTP API requests after approval.

**Recommended:** Save credentials to `~/.config/andibase/credentials.json`:

```json
{
  "api_key": "andi_live_xxx",
  "agent_name": "YourAgentName"
}
```

Use the key after exchange [#use-the-key-after-exchange]

After `exchange` succeeds, use the key in the regular HTTP API:

```bash
curl "https://andibase.com/api/v1/data-definitions" \
  -H "Authorization: Bearer andi_live_xxx"
```

You do not need to run login again for every task. Reuse the same key until it is revoked or expires.

Create and edit apps [#create-and-edit-apps]

Agents can create workspace apps and revise them later through the apps API.

* `POST /api/v1/apps` creates a new app.
* `PATCH /api/v1/apps/:handle` updates an existing app.
* `GET /api/v1/apps/:id` returns the full saved app, including `code`.

Each app stores a `code` field. That field must be a complete single JSX module that exports a default React component.

When the user asks to improve an existing app, start from the current saved app instead of rewriting it from scratch.

* Fetch the current app first and use its saved `code` as the base for edits.
* Preserve the existing design language, layout, spacing, and interaction patterns unless the user explicitly asks for a redesign.
* Prefer small, targeted changes over broad rewrites.

```bash
curl -X POST https://andibase.com/api/v1/apps \
  -H "Authorization: Bearer andi_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Expense Tracker",
    "handle": "expense-tracker",
    "description": "Track workspace expenses",
    "code": "import { Button } from \"@andibase/ui/button\";\n\nexport default function App() {\n  return <main style={{ padding: 24 }}><h1>Expense Tracker</h1><Button>Add expense</Button></main>;\n}"
  }'
```

To revise an app, send the updated fields and replace `code` with the full next version of the module:

```bash
curl -X PATCH https://andibase.com/api/v1/apps/expense-tracker \
  -H "Authorization: Bearer andi_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Track and review workspace expenses",
    "code": "import { Button } from \"@andibase/ui/button\";\n\nexport default function App() {\n  return <main style={{ padding: 24 }}><h1>Expense Tracker</h1><Button>New report</Button></main>;\n}"
  }'
```

App runtime [#app-runtime]

Apps render at `/w/:handle/apps/:handle` inside a sandboxed iframe for signed-in workspace members.

* Use `window.andibase.fetch(path, init?)` inside app code to call the API from the app runtime.
* That helper sends `credentials: "include"` and adds the workspace handle automatically.
* Do not hardcode bearer tokens inside app source.

The embedded app runtime has access to shared UI components from `@andibase/ui`.

* You can import from `@andibase/ui` and subpaths like `@andibase/ui/button`, `@andibase/ui/input`, and similar shared components.
* Prefer those shared components when building or editing apps in this runtime.
* Use the existing `@andibase/ui` primitives as much as possible before reaching for custom CSS or Tailwind.
* Keep the default `shadcn/ui` styling unless custom layout or behavior is strictly necessary.

`@andibase/ui` packages shared `shadcn/ui` components for apps running inside andibase, so you can build with the same reusable primitives used by the platform. The full list of available components and helpers lives in [UI Components](/docs/ui-components).

The embedded runtime also exposes host-action helpers from `@andibase/hooks`.

* `openDataRecordForm(...)` asks the host to open the schema-driven record form drawer.
* `openInlineAgentChat(...)` asks the host to open the inline full-screen agent chat drawer.
* `useAndibaseRefreshOnReturn(...)` refreshes app state only after the iframe actually returns from blur or hidden state.

```tsx
import {
  openDataRecordForm,
  openInlineAgentChat,
  useAndibaseRefreshOnReturn,
} from "@andibase/hooks";

openDataRecordForm({
  definitionHandle: "customer",
  defaultValues: { firstName: "Ada" },
});

openDataRecordForm({
  mode: "edit",
  definitionHandle: "customer",
  recordId: "rec_123",
  defaultValues: { firstName: "Ada" },
});

openInlineAgentChat({
  agentHandle: "support-assistant",
});
```

When an app needs to reload data after a host drawer or chat closes, use `useAndibaseRefreshOnReturn(loadData)` instead of `window.addEventListener("focus", loadData)`. In iframe apps, the first click often gives the iframe focus, so unconditional focus listeners can make the app appear to reload on the first interaction.

See [Embedded Host Actions](/docs/embedded-host-actions) for the full embedded-runtime API.
See [Agent Tools](/docs/agent-tools) for the current runtime tool surface available to agents.

***

Some things you can do [#some-things-you-can-do]

You do not need to copy the full docs to get started. Your agent can do all of this:

| Action                                       | What it does                                                                                                                  | Priority    |
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ----------- |
| Start with agent login                       | Get approved by a human and exchange the device code for a reusable API key.                                                  | 🔴 Do first |
| Create, update, delete, list, and query data | Manage records end-to-end, including filtering and lookup.                                                                    | 🔴 High     |
| Create data definitions when needed          | Define new structured data like customers, invoices, tasks, or projects only when the workflow requires new data definitions. | 🟡 Medium   |
| Create and edit apps                         | Build workspace apps by saving JSX modules and revising the stored `code` over time.                                          | 🟠 High     |
| Manage files                                 | Store, organize, and attach files to your workflows.                                                                          | 🟠 High     |
| Invite users                                 | Bring teammates into the workspace to collaborate.                                                                            | 🟡 Medium   |

Ideas to Try [#ideas-to-try]

* Create a list of potential customers.
* Track invoices and categorize them, including each file and key extracted data.
* List todos with priority.


## Documentation Navigation
Use these paths to traverse the relevant docs and generated API reference files for the app.
- Get started (for AI Agents) [current] -> `/docs/agent-get-started` (source: `content/docs/agent-get-started.mdx`)
- andibase Overview -> `/docs` (source: `content/docs/index.mdx`)
- Agent Tools -> `/docs/agent-tools` (source: `content/docs/agent-tools.mdx`)
- Agents -> `/docs/agents` (source: `content/docs/agents.mdx`)
- Agent Auth -> `/docs/api-reference/agent-auth`
- Get agent login request -> `/docs/api-reference/agent-auth/get-api-v1-agent-auth-requests-usercode`
- Exchange agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-exchange`
- Start agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-requests`
- Approve agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-requests-usercode-approve`
- Deny agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-requests-usercode-deny`
- Agents -> `/docs/api-reference/agents`
- Delete workspace agent -> `/docs/api-reference/agents/delete-api-v1-agents-id`
- List workspace agents -> `/docs/api-reference/agents/get-api-v1-agents`
- Get workspace agent -> `/docs/api-reference/agents/get-api-v1-agents-id`
- List agent chats -> `/docs/api-reference/agents/get-api-v1-agents-id-chats`
- Get agent chat -> `/docs/api-reference/agents/get-api-v1-agents-id-chats-chatid`
- Update workspace agent -> `/docs/api-reference/agents/patch-api-v1-agents-id`
- Create workspace agent -> `/docs/api-reference/agents/post-api-v1-agents`
- Send agent message -> `/docs/api-reference/agents/post-api-v1-agents-id-chats-chatid-messages`
- Apps -> `/docs/api-reference/apps`
- Delete app -> `/docs/api-reference/apps/delete-api-v1-apps-id`
- List workspace apps -> `/docs/api-reference/apps/get-api-v1-apps`
- Get app by id -> `/docs/api-reference/apps/get-api-v1-apps-id`
- Update app -> `/docs/api-reference/apps/patch-api-v1-apps-id`
- Create app -> `/docs/api-reference/apps/post-api-v1-apps`
- Automations -> `/docs/api-reference/automations`
- Delete workspace automation -> `/docs/api-reference/automations/delete-api-v1-automations-id`
- List workspace automations -> `/docs/api-reference/automations/get-api-v1-automations`
- Get workspace automation -> `/docs/api-reference/automations/get-api-v1-automations-id`
- List automation runs -> `/docs/api-reference/automations/get-api-v1-automations-id-runs`
- Get automation run -> `/docs/api-reference/automations/get-api-v1-automations-id-runs-runid`
- Update workspace automation -> `/docs/api-reference/automations/patch-api-v1-automations-id`
- Create workspace automation -> `/docs/api-reference/automations/post-api-v1-automations`
- Run automation -> `/docs/api-reference/automations/post-api-v1-automations-id-run`
- Trigger automation webhook -> `/docs/api-reference/automations/post-api-v1-automations-webhooks-publicid-secret`
- Channels -> `/docs/api-reference/channels`
- Delete channel -> `/docs/api-reference/channels/delete-api-v1-channels-channelid`
- List channels -> `/docs/api-reference/channels/get-api-v1-channels`
- Get channel -> `/docs/api-reference/channels/get-api-v1-channels-channelid`
- Update channel -> `/docs/api-reference/channels/patch-api-v1-channels-channelid`
- Create channel -> `/docs/api-reference/channels/post-api-v1-channels`
- Data -> `/docs/api-reference/data`
- Data Definitions -> `/docs/api-reference/data-definitions`
- Delete data definition -> `/docs/api-reference/data-definitions/delete-api-v1-data-definitions-id`
- List data definitions -> `/docs/api-reference/data-definitions/get-api-v1-data-definitions`
- Get data definition -> `/docs/api-reference/data-definitions/get-api-v1-data-definitions-id`
- Update data definition -> `/docs/api-reference/data-definitions/patch-api-v1-data-definitions-id`
- Create data definition -> `/docs/api-reference/data-definitions/post-api-v1-data-definitions`
- Data SQL Query -> `/docs/api-reference/data-sql-query`
- Run SQL query against workspace data -> `/docs/api-reference/data-sql-query/post-api-v1-data-sql-query`
- Get data by id -> `/docs/api-reference/data/get-api-v1-data-definitions-definitionid-data-id`
- Select all data row ids -> `/docs/api-reference/data/get-api-v1-data-definitions-definitionid-data-select-all`
- List data -> `/docs/api-reference/data/get-api-v1-data-definitions-definitionid-query`
- Patch many data rows -> `/docs/api-reference/data/patch-api-v1-data-definitions-definitionid-data-patch-many`
- Delete many data rows -> `/docs/api-reference/data/post-api-v1-data-definitions-definitionid-data-delete-many`
- Upsert many data rows -> `/docs/api-reference/data/post-api-v1-data-definitions-definitionid-data-upsert-many`
- DuckDB Query -> `/docs/api-reference/duckdb-query`
- Run a DuckDB query against registered sources -> `/docs/api-reference/duckdb-query/post-api-v1-duckdb-query`
- Explorer -> `/docs/api-reference/explorer`
- Delete explorer folder -> `/docs/api-reference/explorer/delete-api-v1-workspace-nodes-nodeid`
- List explorer nodes -> `/docs/api-reference/explorer/get-api-v1-workspace-nodes`
- List explorer folders -> `/docs/api-reference/explorer/get-api-v1-workspace-nodes-folders`
- Rename explorer folder -> `/docs/api-reference/explorer/patch-api-v1-workspace-nodes-nodeid-rename`
- Create folder -> `/docs/api-reference/explorer/post-api-v1-workspace-nodes-folders`
- Move explorer node -> `/docs/api-reference/explorer/post-api-v1-workspace-nodes-nodeid-move`
- Files -> `/docs/api-reference/files`
- List workspace files -> `/docs/api-reference/files/get-api-v1-files`
- Read file content -> `/docs/api-reference/files/get-api-v1-files-fileid-content`
- Create file -> `/docs/api-reference/files/post-api-v1-files`
- Complete file upload -> `/docs/api-reference/files/post-api-v1-files-fileid-complete`
- Presign multipart parts -> `/docs/api-reference/files/post-api-v1-files-fileid-parts`
- Update file content -> `/docs/api-reference/files/put-api-v1-files-fileid-content`
- Messages -> `/docs/api-reference/messages`
- List channel messages -> `/docs/api-reference/messages/get-api-v1-channels-channelid-messages`
- List thread messages -> `/docs/api-reference/messages/get-api-v1-channels-channelid-threads-threadid-messages`
- Create channel message -> `/docs/api-reference/messages/post-api-v1-channels-channelid-messages`
- Create thread message -> `/docs/api-reference/messages/post-api-v1-channels-channelid-threads-threadid-messages`
- Notifications -> `/docs/api-reference/notifications`
- List notification devices -> `/docs/api-reference/notifications/get-api-v1-notifications-devices`
- Check Expo notification receipts -> `/docs/api-reference/notifications/post-api-v1-notifications-receipts`
- Send workspace notifications -> `/docs/api-reference/notifications/post-api-v1-notifications-send`
- Runs -> `/docs/api-reference/runs`
- List workspace runs -> `/docs/api-reference/runs/get-api-v1-runs`
- Get workspace run -> `/docs/api-reference/runs/get-api-v1-runs-runid`
- Threads -> `/docs/api-reference/threads`
- List channel threads -> `/docs/api-reference/threads/get-api-v1-channels-channelid-threads`
- Get thread -> `/docs/api-reference/threads/get-api-v1-channels-channelid-threads-threadid`
- Create thread -> `/docs/api-reference/threads/post-api-v1-channels-channelid-threads`
- Workflows -> `/docs/api-reference/workflows`
- Delete workflow definition -> `/docs/api-reference/workflows/delete-api-v1-workflows-id`
- List workflow definitions -> `/docs/api-reference/workflows/get-api-v1-workflows`
- Get workflow definition -> `/docs/api-reference/workflows/get-api-v1-workflows-id`
- Update workflow definition -> `/docs/api-reference/workflows/patch-api-v1-workflows-id`
- Create workflow definition -> `/docs/api-reference/workflows/post-api-v1-workflows`
- Workspaces -> `/docs/api-reference/workspaces`
- Delete workspace API key -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-api-keys-keyid`
- Delete workspace credential -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-credentials-credentialid`
- Delete workspace invitation -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-invitations-invitationid`
- Delete workspace user -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-users-userid`
- List my workspaces -> `/docs/api-reference/workspaces/get-api-v1-workspaces`
- List workspace API keys -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-api-keys`
- List workspace credentials -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-credentials`
- List workspace credential tools -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-credentials-credentialid-tools`
- List workspace invitations -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-invitations`
- List workspace users -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-users`
- Create workspace -> `/docs/api-reference/workspaces/post-api-v1-workspaces`
- Create workspace API key -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-api-keys`
- Create workspace credential -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-credentials`
- Invite user to workspace -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-invitations`
- Create workspace user -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-users`
- Apps -> `/docs/apps` (source: `content/docs/apps.mdx`)
- Authentication -> `/docs/authentication` (source: `content/docs/authentication.mdx`)
- Building Blocks -> `/docs/building-blocks` (source: `content/docs/building-blocks.mdx`)
- Data Model -> `/docs/data-model` (source: `content/docs/data-model.mdx`)
- Embedded Host Actions -> `/docs/embedded-host-actions` (source: `content/docs/embedded-host-actions.mdx`)
- Introduction -> `/docs/introduction` (source: `content/docs/introduction.mdx`)
- Recipes -> `/docs/receipes` (source: `content/docs/receipes/index.mdx`)
- Construction Site Visit Agent -> `/docs/receipes/construction-site-visit-agent` (source: `content/docs/receipes/construction-site-visit-agent.mdx`)
- Daily Lead Qualification Agent -> `/docs/receipes/daily-lead-qualification-agent` (source: `content/docs/receipes/daily-lead-qualification-agent.mdx`)
- Day Planner Agent -> `/docs/receipes/day-planner-agent` (source: `content/docs/receipes/day-planner-agent.mdx`)
- Expense Tracker -> `/docs/receipes/expense-tracker` (source: `content/docs/receipes/expense-tracker.mdx`)
- Legal Case Tracker -> `/docs/receipes/legal-case-tracker` (source: `content/docs/receipes/legal-case-tracker.mdx`)
- Spare Parts Request Agent -> `/docs/receipes/spare-parts-request-agent` (source: `content/docs/receipes/spare-parts-request-agent.mdx`)
- Weekly Report Email Agent -> `/docs/receipes/weekly-report-email-agent` (source: `content/docs/receipes/weekly-report-email-agent.mdx`)
- UI Components -> `/docs/ui-components` (source: `content/docs/ui-components.mdx`)