summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/agent-task-creation.md94
1 files changed, 94 insertions, 0 deletions
diff --git a/docs/agent-task-creation.md b/docs/agent-task-creation.md
new file mode 100644
index 0000000..c2594c3
--- /dev/null
+++ b/docs/agent-task-creation.md
@@ -0,0 +1,94 @@
+# Creating doot tasks as an agent
+
+For a Claude instance with no access to this repo or the database. Everything goes through the
+agent API on `https://doot.terst.org`.
+
+## The one thing to know first
+
+**A human approves every session, in a logged-in browser, and the session lasts one hour.**
+There is no API key and no auto-approval — trust levels change how the prompt is labelled, not
+whether it appears. Ask for a session when you are ready to use it, not at the start of a long
+task, because the approval request itself expires in **5 minutes**.
+
+## Getting a session
+
+```bash
+# 1. Ask. `name` is shown to the human approving; make it say who you are.
+curl -sX POST https://doot.terst.org/agent/auth/request \
+ -H 'Content-Type: application/json' \
+ -d '{"name":"Claude (groceries)","agent_id":"claude-cli-1"}'
+# -> {"request_token":"...","status":"pending"}
+
+# 2. The human approves in the browser. Tell them to expect it.
+
+# 3. Poll until it flips. Statuses: pending, approved, denied, expired.
+curl -s "https://doot.terst.org/agent/auth/poll?token=$REQUEST_TOKEN"
+# -> {"status":"approved","session_token":"...","expires_at":"..."}
+```
+
+Send the session token on every later call as `Authorization: Bearer <session_token>`. On a
+401, the hour is up: request a new session rather than retrying.
+
+## Creating a task
+
+```bash
+curl -sX POST https://doot.terst.org/agent/tasks \
+ -H "Authorization: Bearer $SESSION_TOKEN" \
+ -H 'Content-Type: application/json' \
+ -d '{"title":"Renew the boat registration","source":"doot","due_date":"2026-11-20T00:00:00Z","priority":2}'
+# -> {"status":"success"}
+```
+
+`title` and `source` are required. `source` is either:
+
+- **`doot`** — a native task. Takes `due_date`, `priority`, `project_id`.
+- **`trello`** — a Trello card. **Requires `list_id`**; `project_id` and `priority` are ignored.
+
+`priority` defaults to 1 when omitted or 0. `due_date` is RFC 3339, or omit it for no due date.
+
+### What this endpoint will not do
+
+These fields exist on a doot task and **cannot be set here**. They are not rejected — they are
+silently ignored, so a task created with them arrives without them:
+
+- `description`
+- `labels`
+- `estimated_minutes`
+- `project_name` (use `project_id`)
+
+If a task needs any of those, create it and tell the human it needs editing, or use the web UI.
+
+The response is `{"status":"success"}` with **no task id**, so you cannot chain a create into an
+update. Read the task back from `/agent/context` if you need its id.
+
+## Seeing what is already there
+
+```bash
+curl -s https://doot.terst.org/agent/context -H "Authorization: Bearer $SESSION_TOKEN"
+```
+
+Do this before creating anything. doot pulls from several sources and a task that looks missing
+is often already there under a different wording.
+
+## The other write operations
+
+| | |
+|---|---|
+| `POST /agent/tasks/{id}/complete` | mark done |
+| `POST /agent/tasks/{id}/uncomplete` | undo that |
+| `PATCH /agent/tasks/{id}/due` | change the due date only |
+| `PATCH /agent/tasks/{id}` | change the task |
+| `POST /agent/shopping` | `{"name":..., "store":...}`, both required |
+
+## If you only have a browser
+
+`GET /agent/web/request`, `/agent/web/status` and `/agent/web/context` are the same flow in
+HTML, for agents that cannot POST. They are read-only — there is no browser path that creates a
+task.
+
+## Errors
+
+Plain text with the status, not JSON. `400` means the body was wrong (most often a missing
+`title`, `source`, or `list_id` on a Trello task); `401` means the session expired; `500` means
+doot accepted the request and failed to carry it out, so check before retrying — it may have
+half-succeeded.