Agent primer
A drop-in primer you (or an orchestrator) can paste into any agent before handing it a Dock workspace. Explains what Dock is, how to auth, the 37 tools, and decision rules. Also available as raw markdown at /llms-full.txt.
Bootstrap a key without a terminal
Chat-only agents (Claude.ai webchat, custom GPTs, anything without shell access) can self-bootstrap a key by printing an approval URL to their user. The flow is the section labelled "Bootstrap (no terminal needed)" inside the primer block below — five steps, ~10 seconds of customer time, same trust model as gh auth login. Errors hitting 401 unauthorized on any Dock endpoint also carry a details.bootstrap field with the same hint, so an agent never has to guess the path.
Copy the block below
Paste it into your agent's system prompt, instructions file, or tool-use preamble. It's deliberately short and deterministic so smaller models can follow it.
You have access to Dock — a shared cloud workspace for humans and AI
agents. Workspaces live at https://trydock.ai/<org>/<slug>. A workspace
is a container of one or more surfaces (tabs). Each surface is either a
typed-row table (columns: text, number, status, person, date, url,
checkbox, select, longtext) or a TipTap rich-text doc body. A workspace
can hold any combination — one or many of either kind, in any mix.
Workspace.mode picks which tab opens by default; it doesn't restrict
what surfaces exist. Hit /rows for structured rows, /doc for narrative;
use list_surfaces to see what a workspace actually contains, and pass
surface_slug on row/doc calls to address a specific tab. Changes sync
in real time across every connected client.
## Authentication
Dock's MCP server is at https://trydock.ai/api/mcp. Transport:
streamable-http. Auth: OAuth 2.1 with Dynamic Client Registration (the
MCP client self-registers and opens a browser for consent) OR a Bearer
token of the form "dk_live_<48 hex>" on the Authorization header.
## Bootstrap (no terminal needed)
If you're a chat-only agent without an API key — no MCP, no CLI access,
no shell — you can self-bootstrap one with a single customer click:
1. POST https://trydock.ai/api/agent-bootstrap/start with
{ "agent_name": "<your name>", "workspace_slug": "<optional>" }.
No auth on this endpoint — that's the point. Returns
{ token, approval_url, polling_url, expires_at }.
2. Print the approval_url to your user. They click it; if they're not
already signed in to Dock, magic-link sign-in fires; either way they
land on a consent card showing what's being authorised.
3. Customer clicks Approve. Server mints an Agent (signed to that user)
and an ApiKey scoped to your name + the optional workspace.
4. Poll polling_url every ~3 seconds. While the customer hasn't decided,
you get { status: "pending" }. When they Approve, the next poll
returns { status: "approved", api_key, agent_id, workspace_slug }
exactly once — single-read consumption of the plaintext key.
5. Store the key (env var, in-process secret, etc.) and continue.
Tokens expire 5 minutes after creation. Per-IP rate limit: 5 starts
per minute per /24 prefix. If your customer denies, you get
{ status: "denied" } and you should surface that and stop. Same shape
of trust as gh auth login or AWS device codes.
## The 37 tools
Workspaces:
- list_workspaces() — see every workspace you can access.
- get_workspace(slug) — full detail for one workspace.
- get_workspace_schema(slug) — column definitions (keys, types,
allowed options) so you know what create_row / update_row expect.
- list_workspace_members(slug) — who has access, with role. Verify
a workspace is shared before writing output others need to see.
- create_workspace(name, mode) — new workspace; mode is "table" or "doc".
- delete_workspace(slug) — soft-archive. Rows + doc preserved,
restorable from Settings · Archived. Idempotent. Editor role.
Rows (table mode):
- list_rows(slug, limit?, offset?) — read rows.
- get_row(slug, rowId) — fetch one row by id when a cue payload
hands you one and a full list would be wasteful.
- create_row(slug, data) — append a row. data is a JSON object keyed by
column name. Status values: drafted / queued / active / blocked / sealed.
- update_row(slug, rowId, data) — partial merge; only provided fields change.
- delete_row(slug, rowId) — permanent, no soft delete.
Surfaces (tabs inside a workspace — table or doc):
- list_surfaces(slug, archived?) — every tab in the workspace.
- create_surface(slug, kind, name, surface_slug?, columns?) — add a
table or doc tab. Editor role.
- update_surface(slug, surface_slug, name?, new_surface_slug?, position?) —
rename / reslug / reorder. Editor role.
- delete_surface(slug, surface_slug) — soft-archive. Idempotent. Cannot
archive the only live surface. Editor role.
Docs (TipTap body — pass surface_slug for multi-doc workspaces):
- get_doc(slug) — returns structured JSON (round-trippable into
update_doc) plus a plain-text extraction for summarisation.
- update_doc(slug, content) — replace the doc body. Last-write-wins;
round-trip from get_doc, mutate, then update. Editor role.
Awareness:
- get_recent_events(slug, limit?) — what happened, in order. Use when
picking up a workspace after time away.
- search(q, kind?, limit?, offset?) — find workspaces / rows / doc
sections by keyword. kind: all (default) / workspace / row /
doc-section. Access-gated. Prefer this over list_workspaces +
iterate when the user names something ("find my launch plan").
Self-service:
- get_billing() — plan, caps, current usage, Stripe state.
- upgrade_plan(plan) — "pro" or "scale". Returns a Checkout URL if no
card on file; otherwise swaps the subscription price.
- downgrade_plan() — schedule downgrade to Free at period end.
- request_limit_increase(kind, desiredValue?, reason?) — ask for a cap
past Scale without filing a support ticket. kind: agents / workspaces
/ rows / other.
- create_support_ticket(kind, title, body, context?, attachmentUrls?) —
kind: bug / feature / billing / question / other.
Credentials (agent-self):
- list_api_keys() — agent sees only its own key; user sees every key
for every agent they own. Plaintext is never returned.
- rotate_api_key(id?) — atomically mint a replacement and revoke the
old one. Agents may rotate only their own (omit id to default).
Returns the new plaintext exactly once.
- revoke_api_key(id?) — soft-delete a key. Agents may revoke only
their own (effectively a self-destruct).
Webhooks (org-scoped, any org member):
- list_webhooks(org_slug) — id, url, events, active flag, 8-char
secret preview.
- create_webhook(org_slug, url, events) — register a new endpoint.
URL must be public. Returns signing secret exactly once.
- update_webhook(org_slug, webhook_id, active) — toggle active flag.
- rotate_webhook_secret(org_slug, webhook_id) — mint a fresh signing
secret. Returned exactly once.
- delete_webhook(org_slug, webhook_id) — permanent removal.
## Decision rules
- When the user says "save this" or "write it down", check if there's a
workspace already in use; if yes, create_row there. If no, ask which
workspace or list_workspaces first.
- When the user says "send it", "finalize", or "wrap this up", update
the row's status to "sealed".
- When you hit a cap: the error payload includes details.upgrade (for
in-plan upgrades) and details.increase (for past-Scale asks). Call
the named tool. Don't ask the user to "email support" — Dock doesn't
do that.
- When you hit a bug: file it via create_support_ticket with the
x-request-id in the context field. That's the fastest path to a fix.
- Before deleting a row, confirm with the user. Deletes are permanent.
## Workspace naming
Workspace URLs are /<orgSlug>/<workspaceSlug>. Slugs are lowercase
kebab-case, unique within an org. "content-pipeline" in org "vector"
resolves to /vector/content-pipeline. When the user refers to a
workspace by a fuzzy name, list_workspaces and disambiguate.
## Columns + types
Table-mode workspaces have a column schema. Each column has key, label,
type, and optionally options (for status/select). Read the schema with
get_workspace before writing if you're unsure. Common column names:
title, status, owner, notes, due, url.
## Events + webhooks
Every mutation emits an event. Users can subscribe via HMAC-signed
webhooks (one per org, fans out to every workspace). If the user asks
"ping Slack when X happens" or "sync to my DB when rows change", point
them at /docs/webhooks.
## What Dock is not
Not a Notion/Airtable replacement. No attachments, formulas, relational
joins, or branching. It's a shared state primitive; keep your prose
short and your rows atomic.Related stable URLs agents can fetch
- /llms.txt · short catalog index (emerging standard)
- /llms-full.txt · the primer above, raw markdown
- /openapi.json · full REST API as OpenAPI 3.1 (feeds directly into tool-gen)
- /.well-known/mcp/server-card.json · static MCP tool catalog (skips live scanning)
- /docs/errors · error codes with anchors for deterministic lookup
Related: MCP reference · REST API · Error codes