diff --git a/skills/email/email-inbox-triage/SKILL.md b/skills/email/email-inbox-triage/SKILL.md index f35cb4e4e8..2aefee45e2 100644 --- a/skills/email/email-inbox-triage/SKILL.md +++ b/skills/email/email-inbox-triage/SKILL.md @@ -1,7 +1,7 @@ --- name: email-inbox-triage description: "Triage an inbox: prioritize threads, draft replies safely." -version: 0.1.0 +version: 0.2.0 author: Ben Barclay (benbarclay), Hermes Agent license: MIT platforms: [linux, macos, windows] @@ -50,9 +50,11 @@ Use these dispositions: Extract sender request, deadline, commitments already made, attachments, and missing information. Done when every surfaced thread has a disposition and a stated reason. -### 4. Draft replies in thread context +### 4. Calibrate the user's voice, then draft replies in thread context -Answer every material question, preserve the user's tone, avoid invented commitments, and state uncertainty. Resolve attachment/link facts before referencing them. Done when each sentence can be checked against the thread or an explicit user preference. +Before drafting the first reply of a run, calibrate on evidence rather than guessing tone (inspired by Energy's reply agent, which studies ~100 of the user's past replies before writing): pull a bounded sample of the user's own recent sent replies from the Sent folder — 20-50 where available, preferring replies to the same recipients or thread types being drafted. Extract the observable style facts: greeting and sign-off habits (and per-audience differences), typical reply length, formality and warmth, sentence rhythm, emoji/exclamation use, and how the user says no or pushes back. Keep the calibration as working notes for this run; if the Sent folder is empty or inaccessible, say so and fall back to matching the incoming thread's register. + +Then draft: answer every material question, match the calibrated voice (not a generic-professional one), avoid invented commitments, and state uncertainty. Resolve attachment/link facts before referencing them. Done when each sentence can be checked against the thread or an explicit user preference, and each draft's tone can be traced to the calibration notes. ### 5. Present an approval batch @@ -75,6 +77,7 @@ Send, label, archive, or create follow-ups only within approval. For ambiguous s - Treating unread as synonymous with important. - Missing earlier unanswered questions in a long thread. +- Drafting in a generic-professional voice instead of calibrating against the user's own sent replies. - Retrying after SMTP succeeded but save-to-Sent failed, causing duplicate mail. - Claiming inbox zero when pagination or another folder was omitted. @@ -82,6 +85,7 @@ Send, label, archive, or create follow-ups only within approval. For ambiguous s - [ ] The requested folders and time window were fully covered, or gaps are stated. - [ ] Every disposition has a reason traceable to thread content. +- [ ] Drafts were calibrated against the user's sent replies, or the fallback was stated. - [ ] No send/delete/archive happened outside the approved batch. - [ ] Every approved mutation was read back from the provider. - [ ] The final response separates completed actions, drafts awaiting approval, and blockers. diff --git a/tests/skills/test_email_inbox_triage_skill.py b/tests/skills/test_email_inbox_triage_skill.py index 7298b0aecc..634537dfbe 100644 --- a/tests/skills/test_email_inbox_triage_skill.py +++ b/tests/skills/test_email_inbox_triage_skill.py @@ -87,3 +87,13 @@ def test_mutation_boundary_is_default_safe(): _, body = _frontmatter_and_body() assert "read + draft" in body, "scope step must default to read+draft, not send/delete" assert "does not imply permission" in body + + +def test_voice_calibration_is_evidence_based(): + """Drafting must calibrate against the user's own sent replies (Energy-inspired), + with an explicit fallback when the Sent folder is unavailable.""" + _, body = _frontmatter_and_body() + assert "Calibrate the user's voice" in body + assert "sent replies" in body.lower() + assert "fall back to matching the incoming thread's register" in body + assert "generic-professional" in body diff --git a/website/docs/user-guide/skills/bundled/email/email-email-inbox-triage.md b/website/docs/user-guide/skills/bundled/email/email-email-inbox-triage.md index 3c68833eec..dfb79508a5 100644 --- a/website/docs/user-guide/skills/bundled/email/email-email-inbox-triage.md +++ b/website/docs/user-guide/skills/bundled/email/email-email-inbox-triage.md @@ -15,8 +15,8 @@ Triage an inbox: prioritize threads, draft replies safely. | | | |---|---| | Source | Bundled (installed by default) | -| Path | `skills/email\email-inbox-triage` | -| Version | `0.1.0` | +| Path | `skills/email/email-inbox-triage` | +| Version | `0.2.0` | | Author | Ben Barclay (benbarclay), Hermes Agent | | License | MIT | | Platforms | linux, macos, windows | @@ -68,9 +68,11 @@ Use these dispositions: Extract sender request, deadline, commitments already made, attachments, and missing information. Done when every surfaced thread has a disposition and a stated reason. -### 4. Draft replies in thread context +### 4. Calibrate the user's voice, then draft replies in thread context -Answer every material question, preserve the user's tone, avoid invented commitments, and state uncertainty. Resolve attachment/link facts before referencing them. Done when each sentence can be checked against the thread or an explicit user preference. +Before drafting the first reply of a run, calibrate on evidence rather than guessing tone (inspired by Energy's reply agent, which studies ~100 of the user's past replies before writing): pull a bounded sample of the user's own recent sent replies from the Sent folder — 20-50 where available, preferring replies to the same recipients or thread types being drafted. Extract the observable style facts: greeting and sign-off habits (and per-audience differences), typical reply length, formality and warmth, sentence rhythm, emoji/exclamation use, and how the user says no or pushes back. Keep the calibration as working notes for this run; if the Sent folder is empty or inaccessible, say so and fall back to matching the incoming thread's register. + +Then draft: answer every material question, match the calibrated voice (not a generic-professional one), avoid invented commitments, and state uncertainty. Resolve attachment/link facts before referencing them. Done when each sentence can be checked against the thread or an explicit user preference, and each draft's tone can be traced to the calibration notes. ### 5. Present an approval batch @@ -93,6 +95,7 @@ Send, label, archive, or create follow-ups only within approval. For ambiguous s - Treating unread as synonymous with important. - Missing earlier unanswered questions in a long thread. +- Drafting in a generic-professional voice instead of calibrating against the user's own sent replies. - Retrying after SMTP succeeded but save-to-Sent failed, causing duplicate mail. - Claiming inbox zero when pagination or another folder was omitted. @@ -100,6 +103,7 @@ Send, label, archive, or create follow-ups only within approval. For ambiguous s - [ ] The requested folders and time window were fully covered, or gaps are stated. - [ ] Every disposition has a reason traceable to thread content. +- [ ] Drafts were calibrated against the user's sent replies, or the fallback was stated. - [ ] No send/delete/archive happened outside the approved batch. - [ ] Every approved mutation was read back from the provider. - [ ] The final response separates completed actions, drafts awaiting approval, and blockers.