You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: chat-agent/plans/016-draft-write-mode.md
+13-11Lines changed: 13 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,7 @@ readiness: draft
9
9
10
10
There's a usability gap between the two "write-capable" modes today:
11
11
12
-
-**`ask`** — the agent can call write tools, but every write pauses on a confirmation dialog (`needsApproval: true`, see `tools.ts:594-606`). Good for high-trust operations, but the round-trip is painful when a user is iterating on content and wants the agent to just _do the work_ — especially on long tasks that involve many small edits (e.g. *"rewrite the intro of all 20 blog posts in the 'news' category"*).
12
+
-**`ask`** — the agent can call write tools, but every write pauses on a confirmation dialog (`needsApproval: true`, see `tools.ts:594-606`). Good for high-trust operations, but the round-trip is painful when a user is iterating on content and wants the agent to just _do the work_ — especially on long tasks that involve many small edits (e.g. _"rewrite the intro of all 20 blog posts in the 'news' category"_).
13
13
-**`read-write`** — writes execute instantly, but they hit production data directly. Fine for superuser-style maintenance; too sharp for content iteration where the user wants a safety net.
14
14
15
15
What users actually want for iterative content work: **instant writes with a safety net**. The agent writes freely, no confirmation dialogs, but the result lands as a draft version — nothing is published until the user reviews and publishes it in the admin panel.
@@ -25,11 +25,13 @@ Understanding Payload's draft model is essential for this plan. There are **two
25
25
2.**The `_status` field** (document field) — holds the actual status of the document: `'draft'` or `'published'`. This is a regular field on the document, not a query flag.
26
26
27
27
What `draft: true` does on a write:
28
+
28
29
- Writes to the **versions table**, not the main table — so the published version is untouched.
29
30
- Relaxes required-field validation, allowing the agent to save work-in-progress content.
30
31
- Sets `_status: 'draft'` on the new version.
31
32
32
33
What this means for `draft-write` mode:
34
+
33
35
- Forcing `draft: true` on every create/update ensures the agent's changes land in the versions table and never overwrite the published document.
34
36
- The user reviews the draft in the admin panel's version history and publishes when ready.
35
37
- Collections/globals without `versions.drafts` don't have a versions table, so `draft: true` is a no-op — this is why we must refuse writes to non-drafts-enabled targets (see below).
@@ -40,13 +42,13 @@ What this means for `draft-write` mode:
|`superuser`| yes | none | published (bypass ACL) |
50
52
51
53
In `draft-write`:
52
54
@@ -93,7 +95,7 @@ Add a mode-specific block to `buildSystemPrompt` mirroring the existing per-mode
93
95
> - Some collections/globals may not have drafts enabled; writes to those will fail with a clear error. Relay the error and suggest switching modes.
94
96
> - You do not need to set `draft: true` yourself — it is forced on every write. Required-field validation is relaxed, so partial saves are fine.
95
97
96
-
Also skip the line *"Always confirm with the user before creating, updating, or deleting documents"* in this mode, since the whole point is that the user has _already_ opted in to instant writes.
98
+
Also skip the line _"Always confirm with the user before creating, updating, or deleting documents"_ in this mode, since the whole point is that the user has _already_ opted in to instant writes.
97
99
98
100
## Implementation
99
101
@@ -114,7 +116,7 @@ Two changes in `filterToolsByMode`:
114
116
if (mode==='draft-write') {
115
117
const result:Record<string, ExecutableTool> = {}
116
118
for (const [name, tool] ofObject.entries(tools)) {
117
-
if (name==='delete') continue// destructive, no draft equivalent
119
+
if (name==='delete') continue// destructive, no draft equivalent
@@ -154,7 +156,7 @@ Add a branch to the `mode === …` chain in `buildSystemPrompt` with the bullets
154
156
### 5. `index.ts`
155
157
156
158
- Pass `req.payload.config` into `filterToolsByMode` (the `allTools` call at `index.ts:272-280` already has it).
157
-
- No change to the `overrideAccess` logic — `draft-write` uses the default `overrideAccess: false`, so user ACL still applies to every write. It's *reversible*, not *privileged*.
159
+
- No change to the `overrideAccess` logic — `draft-write` uses the default `overrideAccess: false`, so user ACL still applies to every write. It's _reversible_, not _privileged_.
0 commit comments