diff --git a/plugins/slack/skills/slack-channel-summarization/SKILL.md b/plugins/slack/skills/slack-channel-summarization/SKILL.md index 43f54efb..dfe84823 100644 --- a/plugins/slack/skills/slack-channel-summarization/SKILL.md +++ b/plugins/slack/skills/slack-channel-summarization/SKILL.md @@ -11,7 +11,7 @@ Use this skill to summarize activity from one Slack channel, using a requested t | Workflow | Skill | | --- | --- | -| Draft, send, or rewrite the final Slack update | [../slack-messages/SKILL.md](../slack-messages/SKILL.md) | +| Draft, send, or rewrite the final Slack update | [../slack-outgoing-message/SKILL.md](../slack-outgoing-message/SKILL.md) | ## Start Here @@ -24,29 +24,44 @@ Use this skill to summarize activity from one Slack channel, using a requested t 1. Resolve the named channel with `slack_search_channels`. 2. Collect the initial pass with `slack_read_channel` and `limit: 100`. If the user gave a window, set `oldest` and `latest`. If not, read the latest messages. 3. Read a thread using `slack_read_thread` when the parent message looks important to the summary, for example a decision, blocker, launch, incident, or open question. Default to the last `50` replies unless the request requires more. -4. Consolidate the channel activity into a short summary grouped by topic. The summary should include recurring conversations, key decisions or follow-ups, notable updates, and important threads. -5. Match the delivery format to the request: +4. Read the full `## Formatting Rules` section below. +5. Consolidate the channel activity into a short summary grouped by topic. The summary should include recurring conversations, key decisions or follow-ups, notable updates, and important threads. +6. Match the delivery format to the request: - short recap or brief: reply in chat or draft/send a compact Slack message - summary doc: use `slack_create_canvas` -6. If the user wants the result delivered in Slack, draft by default unless they explicitly asked to send. +7. If the user wants the result delivered in Slack, draft by default unless they explicitly asked to send. -## Formatting +## Formatting Rules + +- For a concise Slack or chat summary, you MUST use exactly this structure unless the user explicitly requests a different format. +- If you use `../slack-outgoing-message/SKILL.md` to draft or send the final message, this output contract remains binding. The downstream skill does not relax or rename these sections. -For a concise Slack or chat summary, format as: ```md -*Channel Summary — * -*Overview:* <1–2 sentence summary of the main themes and biggest updates> +*Channel Summary - * +[ZWSP line] +*Overview* +[ZWSP line] +<1-2 sentence summary> +[blank line] +[ZWSP line] *Topic: * +[ZWSP line] - ... - ... +[blank line] +[ZWSP line] *Topic: * +[ZWSP line] - ... - ... +[blank line] +[ZWSP line] *Notes* +[ZWSP line] - ``` diff --git a/plugins/slack/skills/slack-daily-digest/SKILL.md b/plugins/slack/skills/slack-daily-digest/SKILL.md index 54f556f5..6b70c02c 100644 --- a/plugins/slack/skills/slack-daily-digest/SKILL.md +++ b/plugins/slack/skills/slack-daily-digest/SKILL.md @@ -19,33 +19,55 @@ Use this skill to produce a daily digest of today's important Slack activity fro 3. Named channels: Resolve IDs through `slack_search_channels`, then call `slack_read_channel` for today's window with `limit` at `50` per channel. 4. Named topics: Use `slack_search_public_and_private` for each topic phrase. If channels were also provided, run one search per topic and channel with `query` set to ` in:<#CHANNEL_ID>` so the search stays inside the selected channels. If no channels were provided, set `query` to the topic phrase. Then read the returned channels with `slack_read_channel` or parent threads with `slack_read_thread` when a result looks important. 5. Prioritize decisions, blockers, incidents, asks, ownership changes, deadline changes, and status changes. +6. Read the full `## Formatting Rules` section below. -## Formatting +## Formatting Rules -Format the digest as: +- For a concise Slack or chat summary, you MUST use exactly this structure unless the user explicitly requests a different format. +- If you use `../slack-outgoing-message/SKILL.md` to draft or send the final message, this output contract remains binding. The downstream skill does not relax or rename these sections. ```md -*Daily Slack Digest — YYYY-MM-DD* +*Daily Slack Digest - YYYY-MM-DD* +[ZWSP line] +*Scope* +[ZWSP line] +- +- -*Scope:* -*Summary:* <1–2 line overview of volume + key signals> +[blank line] +[ZWSP line] +*Summary* +[ZWSP line] +<1-2 sentence summary of volume + key signals> -*Details (by )* -** +[blank line] +[ZWSP line] +*Topic: * +[ZWSP line] - ... - ... -** +[blank line] +[ZWSP line] +*Topic: * +[ZWSP line] - ... - ... +[blank line] +[ZWSP line] *Needs attention* +[ZWSP line] - ... +[blank line] +[ZWSP line] *Notes* +[ZWSP line] - ``` +- Group the digest by topic or channel, whichever better matches the request. - Use short group headers and keep each group to 1–3 bullets. - Keep the digest compact; aim for 4–10 bullets total across all sections. - Start each bullet with the key update, then add implication, owner, blocker, or action if relevant. @@ -54,3 +76,4 @@ Format the digest as: - Preserve exact channel names. - Include *Needs attention* only for items requiring user action, decisions, or input. - Include *Notes* for gaps, absences, sparse results, or caveats. +- Between sections, use the exact safe transition required by `../slack-outgoing-message/SKILL.md`: prior content line, true blank line, `U+200B` line, next `*Section*` label, `U+200B` line, section content. diff --git a/plugins/slack/skills/slack-messages/SKILL.md b/plugins/slack/skills/slack-messages/SKILL.md deleted file mode 100644 index 99e4e87d..00000000 --- a/plugins/slack/skills/slack-messages/SKILL.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -name: slack-messages -description: Compose or rewrite standalone Slack messages with correct mrkdwn, destination-aware recipient checks, and explicit mention handling. ---- - -# Slack Messages - -## Overview - -Use this skill to compose, draft, or refine Slack-ready messages and related Slack content. Apply it when the next step involves `slack_send_message`, `slack_send_message_draft`, or `slack_create_canvas`. - -## Reference Notes - -Read this reference **before finalizing any outgoing Slack text**: - -| Task | Reference | -| --- | --- | -| Exact Slack mrkdwn syntax for emphasis, lists, links, code, and mentions | [../slack/references/mrkdwn.md](../slack/references/mrkdwn.md) | - -## Workflow - -1. Identify the **intended destination** before drafting: channel, thread, DM, or group DM. -2. Determine whether the user wants a **draft**, a **send-ready message**, or content for a **Slack canvas**. **Default to a draft** unless the user has approved the wording or explicitly asked to send. -3. Read `../slack/references/mrkdwn.md` and use that syntax directly instead of generic Markdown. - -## Destination Safety - -- If the user wants to **cc, mention, or tag** someone, first check whether that person is already in the destination channel or group DM. If they are not, **warn the user** instead of implying the mention will notify them or that they will see the message. -- Treat `@here`, `@channel`, `@everyone`, and similar broad notifications as **high-impact**. Before posting, **warn the user** that the message will notify a broad audience. - -## Mention Rules - -- Resolve **user mentions** before writing when the message should tag a person, and use canonical Slack mrkdwn syntax: `<@U123456>`. -- Resolve **Slack user groups** before writing when the message should tag a group, and use canonical Slack mrkdwn syntax: ``. -- Do not rely on bare `@name` text in outgoing Slack messages. -- If you cannot resolve the correct user or group, **tell the user** and compose the draft or message without implying the mention will work. diff --git a/plugins/slack/skills/slack-messages/agents/openai.yaml b/plugins/slack/skills/slack-messages/agents/openai.yaml deleted file mode 100644 index 971ec0bc..00000000 --- a/plugins/slack/skills/slack-messages/agents/openai.yaml +++ /dev/null @@ -1,7 +0,0 @@ -interface: - display_name: "Slack Messages" - short_description: "Write Slack messages and drafts" - icon_small: "../slack/assets/slack-small.svg" - icon_large: "../slack/assets/slack.svg" - brand_color: "#611F69" - default_prompt: "Use $slack-messages to write, draft, or rewrite Slack message content for sending, saving as a draft, or creating a canvas with correct mrkdwn and explicit Slack mentions." diff --git a/plugins/slack/skills/slack-notification-triage/SKILL.md b/plugins/slack/skills/slack-notification-triage/SKILL.md index 7a1768c2..41ffa577 100644 --- a/plugins/slack/skills/slack-notification-triage/SKILL.md +++ b/plugins/slack/skills/slack-notification-triage/SKILL.md @@ -20,29 +20,51 @@ Use this skill to produce a priority queue or task list for the user from recent 4. **Named channels:** Resolve IDs through `slack_search_channels`, then call `slack_read_channel` with `limit` at `100` per channel. 5. **Named people or DMs:** Resolve people through `slack_search_users`, then use `slack_search_public_and_private` with several small searches using filters `from:<@USER_ID>`, `to:<@USER_ID>`, or `in:<@USER_ID>` to surface relevant DM or person-specific activity. 6. **Named topics:** Use `slack_search_public_and_private`, and if channels were also provided, keep the search inside those channels. -7. **No explicit scope:** Run several small `slack_search_public_and_private` searches using filters such as `to:me`, `<@USER_ID>`, and `is:thread`, then expand the strongest results with `slack_read_thread` for threads or `slack_read_channel` for surrounding channel context. +7. **No explicit scope:** Search in this order: + - unanswered direct conversations: run `slack_search_public_and_private` over `channel_types="im"`, paging until you have a reasonable set of unique conversations, then dedupe and expand promising DMs with `slack_read_channel` + - unanswered group DMs: repeat over `channel_types="mpim"`, again preferring unique conversations over repeated hits from one chat + - direct mentions: `slack_search_public_and_private` with `query` set to `<@USER_ID>` + - threads with prior user participation: `slack_search_public_and_private` with `query` set to `from:<@USER_ID> is:thread`, then `slack_read_thread` + - threads with prior user mention: `slack_search_public_and_private` with `query` set to `<@USER_ID> is:thread`, then `slack_read_thread` 8. Use `slack_read_thread` when the thread could hold more necessary context. -9. Prioritize messages that likely need a reply or could create a concrete follow-up or task for the user. +9. Prioritize messages that likely need a reply or could create a concrete follow-up or task for the user. Explicit asks, review or approval requests, blockers, and bumps should rank above casual questions, FYIs, or repeated snippets from the same conversation. +10. Read the full `## Formatting Rules` section below. +11. Before sending the final answer, map the findings into the exact structure in **Formatting Rules**. Do not invent alternate section names or top-level layouts. -## Formatting +## Formatting Rules -Format the triage as: +- For a concise Slack or chat summary, you MUST use exactly this structure unless the user explicitly requests a different format. +- If you use `../slack-outgoing-message/SKILL.md` to draft or send the final message, this output contract remains binding. The downstream skill does not relax or rename these sections. ```md -*Slack Notification Triage — YYYY-MM-DD* - -*Summary:* <1–2 line overview of what the user most likely needs to read, reply to, or do next> +*Slack Notification Triage - YYYY-MM-DD* +[ZWSP line] +*Overview* +[ZWSP line] +<1-2 sentence summary of what the user most likely needs to read, reply to, or do next> +[blank line] +[ZWSP line] *Tasks for you* +[ZWSP line] - ... +[blank line] +[ZWSP line] *Worth skimming* +[ZWSP line] - ... +[blank line] +[ZWSP line] *Can ignore for now* +[ZWSP line] - ... +[blank line] +[ZWSP line] *Notes* +[ZWSP line] - ``` diff --git a/plugins/slack/skills/slack-notification-triage/agents/openai.yaml b/plugins/slack/skills/slack-notification-triage/agents/openai.yaml new file mode 100644 index 00000000..49bb09d8 --- /dev/null +++ b/plugins/slack/skills/slack-notification-triage/agents/openai.yaml @@ -0,0 +1,7 @@ +interface: + display_name: "Slack Notification Triage" + short_description: "Triage Slack attention signals" + icon_small: "../slack/assets/slack-small.svg" + icon_large: "../slack/assets/slack.svg" + brand_color: "#611F69" + default_prompt: "Use $slack-notification-triage to triage recent Slack activity into what likely needs my attention, separating items that need a reply from things worth skimming." diff --git a/plugins/slack/skills/slack-outgoing-message/SKILL.md b/plugins/slack/skills/slack-outgoing-message/SKILL.md new file mode 100644 index 00000000..b8367791 --- /dev/null +++ b/plugins/slack/skills/slack-outgoing-message/SKILL.md @@ -0,0 +1,57 @@ +--- +name: slack-outgoing-message +description: Primary skill for composing, drafting, or refining any outbound Slack content. Use this whenever the task will require using `slack_send_message`, `slack_send_message_draft`, or `slack_create_canvas`. Use `slack` to read or analyze Slack context; use this skill to produce the final outgoing message. +--- + +# Slack Outgoing Message + +## Overview + +Use this skill whenever the task involves producing final Slack text for a draft, send, or canvas. +If another Slack skill is used to read or summarize source context, switch to this skill before finalizing outgoing text. +This skill is not complete until you reread the full `## Formatting Rules` section immediately before any outgoing Slack tool call and verify the final text follows every rule. + +## Reference Notes + +Read this reference **before finalizing any outgoing Slack text**: + +| Task | Reference | +| --- | --- | +| Exact Slack mrkdwn syntax for emphasis, lists, links, code, and mentions | [../slack/references/mrkdwn.md](../slack/references/mrkdwn.md) | + +## Formatting Rules + +- Distinguish parser breaks from visible spacing: + - Use a true blank line (`\n\n`) after quotes and also whenever a `*Section*` label follows a numbered list, bulleted list, paragraph, or code block. + - Use a line containing only a zero-width space (`U+200B`) when you need a visible blank line separator, since Slack collapses truly empty lines. + - Do not use vertical tabs (`U+000B`) +- After any section label, insert a line containing only a zero-width space (`U+200B`) before the next bullet, numbered item, or paragraph. +- If a quote should end before the next section, add a true blank line after the quoted line. If you also want visible spacing before the next section label, follow that with a line containing only `\u200B` (`U+200B`). +- Whenever a new `*Section*` label follows a list item, paragraph, or code block, use this safe transition pattern exactly: prior content line, true blank line, `U+200B` line, `*Section*` label, `U+200B` line, section content. +- Prefer labels like `*Section: Foo*` or `*Foo*` instead of numbered sections. + +## Workflow + +1. Identify the **intended destination** before drafting: channel, thread, DM, or group DM. +2. Determine whether the user wants a **draft**, a **send-ready message**, or content for a **Slack canvas**. **Default to a draft** unless the user has approved the wording or explicitly asked to send. +3. Read `../slack/references/mrkdwn.md` and use that syntax directly instead of generic Markdown. +4. Read the full `## Formatting Rules` section above. + +## Tool Guardrails + +- Treat optional Slack tool parameters as absent-by-default. +- `thread_ts` is valid only for replies in an existing thread. For normal channel posts, DMs, and new group DMs, omit the `thread_ts` key entirely. +- `slack_send_message_draft` cannot overwrite an existing attached draft, and do not claim that you verified the destination is draft-free before calling the tool. +- If `slack_send_message_draft` returns `draft_already_exists`, stop immediately. Tell the user there is already an attached draft in that destination and that Slack cannot overwrite it. + +## Destination Safety + +- If the user wants to **cc, mention, or tag** someone, first check whether that person is already in the destination channel or group DM. If they are not, **warn the user** instead of implying the mention will notify them or that they will see the message. +- Treat `@here`, `@channel`, `@everyone`, and similar broad notifications as **high-impact**. Before posting, **warn the user** that the message will notify a broad audience. + +## Mention Rules + +- Resolve **user mentions** before writing when the message should tag a person, and use canonical Slack mrkdwn syntax: `<@U123456>`. +- Resolve **Slack user groups** before writing when the message should tag a group, and use canonical Slack mrkdwn syntax: ``. +- Do not rely on bare `@name` text in outgoing Slack messages. +- If you cannot resolve the correct user or group, **tell the user** and compose the draft or message without implying the mention will work. diff --git a/plugins/slack/skills/slack-outgoing-message/agents/openai.yaml b/plugins/slack/skills/slack-outgoing-message/agents/openai.yaml new file mode 100644 index 00000000..8adf851b --- /dev/null +++ b/plugins/slack/skills/slack-outgoing-message/agents/openai.yaml @@ -0,0 +1,7 @@ +interface: + display_name: "Slack Outgoing Message" + short_description: "Compose final outbound Slack text" + icon_small: "../slack/assets/slack-small.svg" + icon_large: "../slack/assets/slack.svg" + brand_color: "#611F69" + default_prompt: "Use $slack-outgoing-message to turn source context into final Slack-ready text for a draft, send, or canvas with correct mrkdwn and explicit Slack mentions." diff --git a/plugins/slack/skills/slack-reply-drafting/SKILL.md b/plugins/slack/skills/slack-reply-drafting/SKILL.md index d7d5d8f9..8872a553 100644 --- a/plugins/slack/skills/slack-reply-drafting/SKILL.md +++ b/plugins/slack/skills/slack-reply-drafting/SKILL.md @@ -11,7 +11,7 @@ Use this skill to identify messages that likely need a reply and produce Slack-r | Workflow | Skill | | --- | --- | -| Refine, draft, or send the final Slack text | [../slack-messages/SKILL.md](../slack-messages/SKILL.md) | +| Refine, draft, or send the final Slack text | [../slack-outgoing-message/SKILL.md](../slack-outgoing-message/SKILL.md) | ## Start Here @@ -38,30 +38,33 @@ Use this skill to identify messages that likely need a reply and produce Slack-r - named person or DM: `slack_search_users`, then `slack_search_public_and_private` - bounded keyword search: `slack_search_public_and_private` 4. If no scope was provided, search these default categories: - - unanswered direct conversations: `slack_search_public_and_private` across `im,mpim`, then `slack_read_channel` to keep conversations where the latest relevant message is from someone else + - unanswered direct conversations: `slack_search_public_and_private` across `im,mpim` to generate candidate conversations, then `slack_read_channel` for each plausible candidate before deciding whether it needs a reply; do not decide from the search snippet alone - direct mentions: `slack_search_public_and_private` with `query` set to `<@USER_ID>` - threads with prior user participation: `slack_search_public_and_private` with `query` set to `from:<@USER_ID> is:thread`, then `slack_read_thread` for newer replies - threads with prior user mention: `slack_search_public_and_private` with `query` set to `<@USER_ID> is:thread`, then `slack_read_thread` for newer replies after the mention -5. Keep only candidates where the latest relevant message is from someone else, or where newer replies appeared after the user's last reply or mention. +5. Keep only candidates where the latest unresolved ask is from someone else, or where newer replies appeared after the user's last substantive reply or mention. Do not count emoji-only, acknowledgement-only, or other non-answer chatter from the user as a reply. 6. Expand only the threads or surrounding messages needed to answer accurately. Answer the question first, then add clarification or next steps when the context supports it. 7. If the context is incomplete, write the smallest useful clarifying reply instead of pretending the answer is known. -8. Create the draft with `slack_send_message_draft` in the source channel or DM, and include `thread_ts` for thread replies. +8. Create the draft with `slack_send_message_draft` in the source channel or DM. Include `thread_ts` only for thread replies; otherwise omit the parameter entirely. If Slack returns `draft_already_exists`, stop and tell the user you cannot overwrite the existing attached draft via API. ## Drafting Rules -- Use the [../slack-messages/SKILL.md](../slack-messages/SKILL.md) skill to draft outgoing Slack text. +- Use the [../slack-outgoing-message/SKILL.md](../slack-outgoing-message/SKILL.md) skill to draft outgoing Slack text. ## Formatting +- For a concise Slack or chat summary, you MUST use exactly this structure unless the user explicitly requests a different format. +- If you use `../slack-outgoing-message/SKILL.md` to draft or send the final message, this output contract remains binding. The downstream skill does not relax or rename these sections. + Format multiple drafts as: ```md -*Reply Drafts — * +**Reply Drafts — ** -** +**** Draft: -** +**** Draft: ``` diff --git a/plugins/slack/skills/slack/SKILL.md b/plugins/slack/skills/slack/SKILL.md index b6cb99f1..0400a439 100644 --- a/plugins/slack/skills/slack/SKILL.md +++ b/plugins/slack/skills/slack/SKILL.md @@ -8,12 +8,13 @@ description: Summarize Slack conversations and draft channel-ready posts. Use wh ## Overview Use this skill to turn channel and thread context into concise, post-ready Slack communication. Read the conversation first, preserve the intended audience and tone, and format messages with Slack-native mrkdwn. +If the task will produce outgoing Slack text, switch to [../slack-outgoing-message/SKILL.md](../slack-outgoing-message/SKILL.md) before finalizing and reread that file's `## Formatting Rules` section immediately before any draft or send. ## Related Skills | Workflow | Skill | | --- | --- | -| Message composition, rewrites, drafts, and canvas-writing workflows | [../slack-messages/SKILL.md](../slack-messages/SKILL.md) | +| Message composition, rewrites, drafts, and canvas-writing workflows | [../slack-outgoing-message/SKILL.md](../slack-outgoing-message/SKILL.md) | | Bounded channel recaps and thematic Slack summaries | [../slack-channel-summarization/SKILL.md](../slack-channel-summarization/SKILL.md) | | Daily digests across selected channels or topics | [../slack-daily-digest/SKILL.md](../slack-daily-digest/SKILL.md) | | Find messages that likely need a response and prepare reply drafts | [../slack-reply-drafting/SKILL.md](../slack-reply-drafting/SKILL.md) | @@ -46,6 +47,7 @@ Use this skill to turn channel and thread context into concise, post-ready Slack - Prefer a short opener, a few tight bullets, and a clear ask or next step. - Use mrkdwn formatting rules from `references/mrkdwn.md` for emphasis, lists, links, quotes, mentions, and code. +- For any outgoing Slack text, use the `slack-outgoing-message` skill. - Distinguish clearly between a private summary for the user and a post-ready message for Slack. - When summarizing a thread, lead with the latest status and then list blockers, decisions, and owners. - When drafting a reply, match the tone of the channel and avoid over-formatting.