Skip to content

Commit 6d758b6

Browse files
committed
Update email skill for lazy reply workflow
1 parent da7a49b commit 6d758b6

File tree

1 file changed

+75
-40
lines changed

1 file changed

+75
-40
lines changed

skills/clickui-email/SKILL.md

Lines changed: 75 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
---
22
name: clickui-email
3-
description: Use this skill when you have finished writing an email draft and need the user to review it before sending.
3+
description: Use this skill when the user needs to review, triage, read, or reply to email in AgentClick UI before anything is sent.
44
---
55

66
# ClickUI Email Review
77

88
## Trigger Conditions (high priority)
99

10-
Use this skill by default when the user asks you to draft an email and review it before sending.
10+
Use this skill by default when the user asks to review an inbox, read email in UI, triage email, or draft a reply in browser before sending.
1111

1212
Common trigger phrases include (Chinese or English):
1313
- "写好后让我审阅"
@@ -18,7 +18,7 @@ Common trigger phrases include (Chinese or English):
1818
- "before sending, let me review"
1919
- "draft it and I will approve"
2020

21-
If the request is an email draft + human review, prefer this skill over generic chat drafting.
21+
If the request is email work plus human review in UI, prefer this skill over generic chat drafting.
2222

2323
## Do Not Use These Alternatives
2424

@@ -27,16 +27,16 @@ For email review requests handled by this skill:
2727
- Do NOT use the `canvas` tool to manually render a draft
2828
- Do NOT ask the user to review the draft directly in chat first
2929

30-
Always submit to AgentClick via `POST /api/review` and let the user review in the AgentClick UI.
31-
Submission opens the email review page for the active session.
30+
Always submit to AgentClick via `POST /api/review` and let the user work inside the AgentClick UI.
31+
Submission opens the email review page for the active session. Treat that page as the user's email client for this task.
3232

3333
---
3434

3535
## Main Agent: Two Steps Only
3636

37-
The main agent submits the draft and immediately hands off to a sub-agent. It does NOT poll.
37+
The main agent submits the email session and immediately hands off to a sub-agent. It does NOT poll.
3838

39-
### Step 1: Submit draft for review
39+
### Step 1: Submit the email session
4040

4141
```bash
4242
RESPONSE=$(curl -s -X POST "${AGENTCLICK_URL:-http://localhost:${AGENTCLICK_PORT:-38173}}/api/review" \
@@ -49,41 +49,44 @@ RESPONSE=$(curl -s -X POST "${AGENTCLICK_URL:-http://localhost:${AGENTCLICK_PORT
4949
{
5050
"id": "e1",
5151
"from": "SENDER_EMAIL",
52+
"to": "RECIPIENT_EMAIL",
5253
"subject": "ORIGINAL_SUBJECT",
53-
"preview": "ORIGINAL_EMAIL_PREVIEW_TEXT",
54-
"category": "Work",
55-
"isRead": false,
54+
"preview": "SHORT_SIDEBAR_SNIPPET_ONLY",
55+
"body": "FULL_ORIGINAL_EMAIL_BODY",
56+
"headers": [
57+
{"label": "Message-ID", "value": "<[email protected]>"},
58+
{"label": "Thread", "value": "THREAD_SUBJECT"}
59+
],
60+
"category": "Updates",
61+
"unread": true,
5662
"timestamp": UNIX_MS_TIMESTAMP
5763
}
5864
],
5965
"draft": {
60-
"replyTo": "e1",
66+
"replyTo": "SENDER_EMAIL",
6167
"to": "RECIPIENT_EMAIL",
6268
"subject": "Re: ORIGINAL_SUBJECT",
63-
"paragraphs": [
64-
{"id": "p1", "content": "PARAGRAPH_1"},
65-
{"id": "p2", "content": "PARAGRAPH_2"},
66-
{"id": "p3", "content": "PARAGRAPH_3"}
67-
],
68-
"intentSuggestions": [
69-
{"id": "i1", "text": "Agree to the proposal"},
70-
{"id": "i2", "text": "Schedule a follow-up meeting"}
71-
]
69+
"paragraphs": []
7270
}
7371
}
7472
}')
7573
SESSION_ID=$(echo "$RESPONSE" | grep -o '"sessionId":"[^"]*"' | cut -d'"' -f4)
7674
echo "Session: $SESSION_ID"
7775
```
7876

79-
Replace placeholders with actual content. Split body into 2–4 logical paragraphs.
77+
Rules for the initial payload:
78+
- Include the full original email in `body`. Do not rely on `preview` for review.
79+
- `preview` is only a short list snippet for the sidebar.
80+
- Do not generate a reply draft up front unless the user explicitly asked for one before opening the UI.
81+
- Default to `draft.paragraphs: []` until the user clicks `Reply`.
82+
- Normalize categories to Gmail-style values when possible: `Primary`, `Social`, `Promotions`, `Updates`, `Forums`.
8083

8184
### Step 2: Spawn a monitor sub-agent
8285

8386
Use the Task tool to spawn a sub-agent. Pass it:
8487
- The `SESSION_ID`
8588
- The full inbox array (exactly as submitted)
86-
- The original paragraphs array (exactly as submitted)
89+
- The current draft object (which may start empty)
8790

8891
Tell the sub-agent to follow the **Sub-Agent Instructions** section below.
8992

@@ -100,10 +103,14 @@ You are a dedicated monitor for an AgentClick email review session. You own the
100103

101104
You have been given:
102105
- `SESSION_ID` — the active session
103-
- `inbox` — the inbox array (never changes)
104-
- `paragraphs` — the current draft paragraphs (update this in memory after each rewrite)
106+
- `inbox` — the inbox array
107+
- `draft` — the current reply draft object, which may be empty until the user clicks `Reply`
105108

106109
Maintain a `ROUND` counter starting at 0 and a `LOG` list of actions taken each round.
110+
Maintain per-email UI state in memory:
111+
- `reply_loading[emailId]` — true while you are generating a reply draft
112+
- `reply_ready[emailId]` — true when the draft has arrived
113+
- `reply_unread[emailId]` — true when a newly generated reply draft is ready but the user has not opened it yet
107114

108115
### Your loop
109116

@@ -131,28 +138,38 @@ echo "$RESULT"
131138

132139
#### C. Rewrite and PUT (only when STATUS is `rewriting`)
133140

134-
Read `result.actions` and `result.userIntention` from the `/wait` response.
141+
Read the full `result` object from the `/wait` response.
142+
143+
The UI is an email client, not only a final approval page:
144+
- The user may open multiple emails while you work.
145+
- The user may click `Reply` on one email while continuing to read others.
146+
- Do not block the user from browsing other emails while a reply is being prepared.
147+
- When a reply is requested, update the session payload promptly so the UI can show loading state for that email.
148+
- When the reply draft is ready, update the same email row so the UI can show a ready ring and an unread red dot for that email.
135149

136150
Rewrite rules:
137-
- Apply the **minimum** change needed to satisfy the feedback
138-
- Only modify paragraphs referenced in `result.actions`
139-
- Keep all other paragraph text exactly unchanged
140-
- Keep `inbox`, `draft.subject`, `draft.to`, and `draft.replyTo` unchanged
151+
- If `result.readMore` is true, fetch more emails for the requested categories and PUT an updated inbox payload. Keep existing email IDs and append or merge new ones.
152+
- If the user marked emails as read, reflect that in your local state and sync that status back to the real email system if you control it.
153+
- If the user requested `Reply` for an email and no draft exists yet, generate the draft then PUT it into the payload for that email.
154+
- If `result.actions` contains paragraph edits, apply the minimum change needed to satisfy the feedback.
155+
- Only modify paragraphs referenced in `result.actions` unless the user explicitly requested a full rewrite.
156+
- Keep all other paragraph text exactly unchanged.
157+
- Keep `inbox`, `draft.subject`, `draft.to`, and `draft.replyTo` unchanged unless the user explicitly edited them in UI-supported fields.
141158

142159
Write the payload to a temp file (required for stability with special characters), then PUT:
143160

144161
```bash
145162
cat > /tmp/clickui_payload.json <<'JSON'
146163
{
147164
"payload": {
148-
"inbox": [SAME_INBOX_AS_SUBMITTED],
149-
"draft": {
150-
"replyTo": "e1",
151-
"to": "RECIPIENT_EMAIL",
152-
"subject": "Re: ORIGINAL_SUBJECT",
153-
"paragraphs": [
154-
{"id": "p1", "content": "UPDATED_OR_UNCHANGED_PARAGRAPH_1"},
155-
{"id": "p2", "content": "UPDATED_OR_UNCHANGED_PARAGRAPH_2"},
165+
"inbox": [SAME_INBOX_AS_SUBMITTED],
166+
"draft": {
167+
"replyTo": "SENDER_EMAIL",
168+
"to": "RECIPIENT_EMAIL",
169+
"subject": "Re: ORIGINAL_SUBJECT",
170+
"paragraphs": [
171+
{"id": "p1", "content": "UPDATED_OR_UNCHANGED_PARAGRAPH_1"},
172+
{"id": "p2", "content": "UPDATED_OR_UNCHANGED_PARAGRAPH_2"},
156173
{"id": "p3", "content": "UPDATED_OR_UNCHANGED_PARAGRAPH_3"}
157174
]
158175
}
@@ -170,15 +187,18 @@ cat /tmp/clickui_put_response.txt
170187

171188
If HTTP is not `200`, fix the JSON and retry the PUT. Do not loop back to A with a failed PUT.
172189

173-
If HTTP is not `200`, fix the JSON and retry the PUT. Do not loop back to A with a failed PUT.
190+
When preparing a first reply draft after the user clicks `Reply`, use the same PUT path:
191+
- First PUT a lightweight state update as soon as possible so the UI can show loading for that email.
192+
- Then generate the draft.
193+
- Then PUT the completed draft so the UI shows it as ready.
174194

175195
#### D. Report to main agent after each rewrite round
176196

177197
After a successful PUT, the server automatically notifies the main agent via webhook with a progress summary. You do not need to call the webhook yourself.
178198

179199
However, you must update your local state before looping:
180200
- Increment `ROUND`
181-
- Update your in-memory `paragraphs` to the new content
201+
- Update your in-memory `draft` to the new content
182202
- Append to `LOG`: `"Round N: rewrote [paragraph IDs] — [user instruction]"`
183203

184204
Then **go back to step A**. The user will see the updated draft in the same browser tab.
@@ -193,6 +213,8 @@ Extract from the final `/wait` response:
193213
- `result.actions` — deletions and rewrites the user marked
194214
- `result.confirmed` — should be `true`
195215
- The final paragraph list from the session payload
216+
- Any emails marked read by the user
217+
- Any reply draft fields edited by the user in UI
196218

197219
Output a structured report for the main agent:
198220

@@ -210,9 +232,22 @@ FINAL_DRAFT:
210232
- p1: <final content>
211233
- p2: <final content>
212234
- p3: <final content>
213-
INSTRUCTION_TO_MAIN_AGENT: Send the email using the FINAL_DRAFT above. Do not ask the user again.
235+
EMAIL_STATE_CHANGES:
236+
marked_read:
237+
- <email id>
238+
INSTRUCTION_TO_MAIN_AGENT: Send the email using the FINAL_DRAFT above, and sync any marked-read state. Do not ask the user again.
214239
```
215240

241+
## UI Behavior Requirements
242+
243+
Follow these UI assumptions when preparing or updating payloads:
244+
- The main email view should show the full email body, not only a preview snippet.
245+
- The sidebar snippet is only for compact scanning.
246+
- Reply draft generation is lazy: do not send a ready draft before the user clicks `Reply`, unless the user explicitly asked for an immediate draft.
247+
- While a reply is being generated, the UI should be able to show loading for that email and still let the user browse other emails.
248+
- When a reply draft becomes ready, the corresponding email row should show a visible ready state and an unread red dot until the user opens that reply.
249+
- Fast updates matter. Prefer sending an immediate "loading" payload update, then a second payload update with the completed draft.
250+
216251
---
217252

218253
### Exit: Timeout (HTTP 408 or empty STATUS)

0 commit comments

Comments
 (0)