inbox-triage
Skill4 starsChanged 14 days agoMITView on GitHub
Work the inbound replies: surface the conversations that matter first, give the user compact thread context, draft responses together, send only what was explicitly approved, and record the outcome of each conversation. Use when the user asks about replies, inbox triage, responding to prospects, or finding the interested leads.
52 other projects use a version of this.
Adopted by
Most recently taken up by
- chatmaxima-com/chatmaxima-skillstheir own version, first seen Nov 8, 2026
- itsryanarmani/skillstheir own version, first seen Nov 8, 2026
- pooriaarab/skillstheir own version, first seen Nov 7, 2026
- digitalgym/aipathway-standardstheir own version, first seen Nov 4, 2026
- kesslernity/awesome-copilot-cowork-skillstheir own version, first seen Nov 3, 2026
- cwhited26/pocket-agent-starter-skillstheir own version, first seen Nov 1, 2026
Used with
Projects with it also use aeon-update, auto-workflow and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
aaronjmarsSkillaeon-update
Pull framework updates from the upstream Aeon repo into this instance - 3-way merges canon's new commits into a PR, never clobbering operator config.
Also in 4 projects that use this
aaronjmarsSkillauto-workflow
Two-mode aeon.yml workflow builder - analyze inspects URLs and emits a tiered, signal-verified skill-enablement plan plus an aeon.yml diff; enable flips slugs to enabled:true and opens a PR.
Also in 4 projects that use this
- +10 more from aaronjmars
Other versions52 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 52
- gnekt/My-Brain-Is-Full-Crew★ 3.9ksame name
- aaronjmars/aeon★ 789same name
- aeonfun/aeon★ 789same name
- QuixiAI/agi-memory★ 623same name
- QuixiAI/Hexis★ 623same name
- microsoft/cat-agent-skills★ 101same name
- latour-ai/skills★ 69same name
- kesslernity/awesome-copilot-cowork-skills★ 45same name
- GTMify/aigtm★ 25same name
- aaronjmars/miroshark-aeon★ 20same name
42 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository16 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- approval-boundariesSkill
- audience-buildingSkill
- campaign-launchSkill
- campaign-planningSkill
- linkedin-guardrailsSkill
- performance-analysisSkill
- sdr-operationsSkill
- sending-guardrailsSkill
- approvals-and-questionsSkill
- managed-campaign-workSkill
- operating-the-installationSkill
- planner-in-sessionSkill
- reporting-outside-effectsSkill
- researcher-in-sessionSkill
- troubleshooting-jasonSkill
The file
We split this skill into the rules it gives an agent
6 rules. 0 are common, 2 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 45 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 29
Use for reviewing replies, drafting and sending responses, routing or deferring a thread, and recording what came of each conversation.
- Very specific: line 31
Do NOT use for bulk campaign changes — that is campaign-launch or performance-analysis.
- Very specific: line 32
Do NOT use for the calendar hand-off after a prospect says yes.
- Very specific: line 191
Batch-sending drafts: Every message to a real person is its own confirm_each.
- Very specific: line 196
Switching channel silently: when the original channel is unavailable.
- Distinctive: line 218
Greeting by the provider's name for the thread's contact: instead of the person's own record, or choosing between the two without saying …
“Common” is measured: kept by at least 6 in 10 of the 45 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Inbox triage
Knowledge, not the enforced contract. This skill names operations from the vendor-neutral catalogue in
sdr-operations, which says what an SDR operation is. What this runtime validates and executes is the smaller set of JSON documents underdocs/contracts/operations/; where the two disagree, the contract is what decides.
Partly an expert skeleton. The triage procedure and the sending gate are complete. Reply strategy — how to answer an objection, when to push for a meeting, how long to keep a thread alive — is marked
TODO(expert)and needs validation by outbound experts before this skill leavesdraft.
Purpose
A campaign that generates replies nobody works is a campaign that generated nothing. This skill keeps the pipeline moving: find the conversations that deserve attention today, give the user enough context to decide quickly, draft the response with them, send exactly what they approved, and record what came of it so the next person or session knows.
When to use / when NOT to use
- Use for reviewing replies, drafting and sending responses, routing or deferring a thread, and recording what came of each conversation.
- Do NOT use for bulk campaign changes — that is
campaign-launchorperformance-analysis. - Do NOT use for the calendar hand-off after a prospect says yes. That is no longer a gap in
the contract:
meeting.propose,meeting.bookandhandoff.createexist, along with the rest of their families. What is missing is a playbook — no skill in this pack carries the judgement for proposing times, qualifying, or handing a person on. Take the thread as far as the classification, name the operations, and say that the judgement around them is unwritten rather than improvising it here.
Prerequisites
- Conversations exist — i.e. something has been sent (
campaign-launch). - Operations used:
- find and read —
conversation.list,conversation.get; - decide what it means —
conversation.classify; - answer —
message.draft, thenmessage.send; - record what came of it —
disposition.set, andactivity.logwhen the exchange happened somewhere we do not send from; - move it through the queue —
conversation.assign,conversation.snooze,conversation.close,conversation.reopen; - when the reply names somebody else —
referral.record.
- find and read —
- Everything above is
readorcontroland derivesauto, with two exceptions.message.sendis reachactand irreversible, so it derivesconfirm_each.referral.recordis raised toconfirm_once, and the reason stated at the operation is what you act on.
Why confirm_each and not confirm_once. The distinction is not size, it is whether one
call is one decision. confirm_once covers a release — one decision over a body of work that
already exists, approved against a preview that names the population. A reply is a
composition: distinct words, written for this thread, going to one named person on one
channel. There is no population a preview could name, and no summary that can stand in for
reading the text, so the approval is the rendered text, once per message. Twelve replies
are twelve approvals, and collapsing them into one yes is the exact inversion
approval-boundaries exists to prevent.
With Jason, the replies have usually been worked before you open the inbox
Unless the installation switched it off, Jason raises a responder for each thread that moved, without anybody asking. It reads the thread, records one verdict on the reply — a category, how sure it is, and what it decided to do — and then acts, drafts an answer or asks a person. So triage starts from what the responder left, not from a raw queue, and a person triaging works with that:
- A verdict that says draft has its draft already, parked for the person's approval. Read it with them as it stands, at the rendered text. Never write a second draft beside it: one reply has one verdict and one draft, for a person as for a role, and a person who wants different words says so on the decision, which is then theirs to settle.
- A verdict that says escalate is a question waiting for the person, in their own words.
- A verdict that says act has been acted on: a request to stop is already on the register, an out-of-office is already waiting for its return date. Check that it was done; do not do it again.
- A verdict is a role's reading, not the person's decision. Where it looks wrong, say so to the person, with the verdict's line id, and leave the correction to them.
- A draft may have gone out without a question where the person set a standing approval for that category in
that campaign. Which one let it go is in the record, and
approval-boundariessays what a standing approval is.
jason journal list --campaign cmp_01JB6K8TQ2W9V4MZ0C3Y7H5NRD --kind reply_classified
jason approval list --campaign cmp_01JB6K8TQ2W9V4MZ0C3Y7H5NRD
jason decision list --campaign cmp_01JB6K8TQ2W9V4MZ0C3Y7H5NRD
jason approval list-standing cmp_01JB6K8TQ2W9V4MZ0C3Y7H5NRDPlanning guidance
Agree the scope before opening anything: everything, or a slice — one campaign, one meaning, one owner, one time window? An inbox reviewed without a scope tends to be reviewed half-way.
The queue arrives ordered (H10). conversation.list returns threads by how overdue they
are, and that ordering is part of the result rather than something to reconstruct. Do not
re-sort by created date.
Where the business wants a different order, filter — do not re-rank. conversation.list
filters by meaning, channel, owner and campaign, so "meeting intent first" is a filtered read,
not a hand-sorted copy of the whole queue. The distinction matters because a re-ranked list
silently drops the waiting time that made a thread urgent.
- TODO(expert): the signals that reliably mark meeting intent versus polite interest, and the order of the remaining categories.
- TODO(expert): how quickly a reply must go out before the interest goes cold, per channel.
The account's own answer to the second one is a policy value rather than a contract value:
response_policy.get reads what this operator holds itself to, and response_policy.define
sets it. Read it before asserting any number.
Execution guidance
- Get the shape of the work (
conversation.list). Counts by meaning and how long each has been waiting, so the user knows how big the job is before starting it. - Present a triage list — person, company, subject, current meaning, how long it has waited — in the order it arrived in. Let the user pick, or confirm working through in order.
- Open the conversation (
conversation.get). Present the exchange compactly: who said what, when. Note the channel and the sending identity that owns the thread — a reply goes out from that identity (H5), not from whichever sender has capacity. Decide what the reply means (
conversation.classify) — before drafting, because the meaning decides whether a reply is the right next act at all. Three cases are not replies:- a request to stop is not a meaning (
A2). It goes tooptout.recordandoutreach.hold, which areautoand go first; thensuppression.add, which isautofor the person's own identifier andconfirm_oncefor a domain or a pattern; thenenrollment.stop, which isconfirm_onceand is asked for. Nothing is sent back (H4), and the protective half is never held up waiting for the gated half; - an out-of-office or other automatic message is answered by
message.schedulefor their stated return date, which is a new outbound message rather than a reply (H4); - a reply naming somebody else goes to
referral.record, which is raised toconfirm_onceand never guesses an address.
The branch each remaining meaning produces is written out as a worked chain in
sdr-operations. Read it there rather than reconstructing it here.- a request to stop is not a meaning (
- Draft with the user (
message.draft). Ground the draft in the actual thread and in the user's stored preferences — tone, sign-off, hard constraints — if those are available. Iterate. Then show the final rendered text, which is what the approval binds to.- Greet the person by the name you hold for them, from their own contact record
(
contact.get; in Jason,jason contact get), never from the name the thread carries. A provider that already held a contact for the address keeps its own name for it, so the thread can name the person differently from the record the campaign was built on, and a draft that opens with the thread's name greets somebody the user never chose. Compare the two before drafting. Where they match, say nothing. Where they differ, greet by the record's name and tell the user, beside the draft and before they approve it — "the thread calls them B; our record says A; I greeted them as A" — so that the choice is theirs and not made silently. Where the record holds no first name, leave the name out of the greeting and say so. - TODO(expert): response patterns for the recurring cases — not interested, wrong person, not now, price objection, "send me info".
- Greet the person by the name you hold for them, from their own contact record
(
- Confirm and send (
message.send). The user approves the literal rendered text, to this person, on this channel —confirm_each, every message, no batching. One call carries one person and one channel, so switching channel is an argument to the call, and therefore a different decision needing its own approval rather than a silent fallback. Then verify the send landed on the thread and report it. - Record what came of the participation (
disposition.set), from the account's declared vocabulary —vocabulary.listsays what values this account allows. The disposition is a different axis from the reply's meaning and from the execution state (G3): the meaning was already recorded at step 4, and the disposition is the business outcome. Confirm it when it is ambiguous. - Move the thread out of the queue.
conversation.closewhen it is worked;conversation.snoozewhen it should come back on a date;conversation.assignwhen it belongs in someone else's inbox, which routes it and promises nothing;conversation.reopenwhen it was closed too early. Closing carries no business outcome and stops no outreach (H9) —disposition.setandenrollment.stopare what do those two things. - Log what happened elsewhere (
activity.log) — a reply that arrived in someone's personal mailbox, a call back, a message on a channel we do not send from. Logging records; it never sends and never advances a cadence (H6). - Continue through the remaining conversations as the user wants.
Validation
The send is confirmed by the created message appearing in the thread — re-read with
conversation.get if in doubt, never assume, and recover a timed-out send through
invocation.get under the key it went out with rather than sending again. After
disposition.set, the participation carries the outcome; after conversation.close, the
thread is out of the queue and the cadence is unchanged, which is the correct result rather
than a bug. At the end, the count of conversations reviewed plus those still waiting adds up to
what you started with.
Reporting
Conversations reviewed, replies sent (with recipients, channels and thread identifiers, and the
idempotency key each went out under), meanings classified, dispositions assigned, threads
closed, snoozed or assigned, and what is still waiting on attention. Then the useful part:
interested people with no meeting yet, and the follow-up that should exist for them —
task.create is how that follow-up becomes real rather than a line in a report.
Failure modes
- Batch-sending drafts. Every message to a real person is its own
confirm_each. There is no bulk mode for this, by design, and no standing approval covers "the replies" as a class: where one exists it is a person's own decision for one category of reply in one campaign, and it is never one you set. - Drafting again for a reply that already has a draft. Where a responder's verdict named a draft, one is parked or has gone out; a second beside it sends two answers to one person.
- Switching channel silently when the original channel is unavailable.
message.sendcarries one channel per call, so the switch is a visible argument change and a new decision; tell the user instead of falling back. - Answering from whichever sender has capacity. Load-balancing is right nearly everywhere
else and wrong here: a reply is sent from the identity that owns the thread (
H5). - Replying to an automatic message because the thread is open and it looks like a reply
(
H4). - Classifying a request to stop as the nearest-looking meaning, because it keeps the
reporting axis tidy (
A2). It is an obligation. Recording it —optout.record,outreach.hold— is protective, derivesautoand is never delayed for a confirmation. The rest of the branch is not:suppression.addover a domain or a pattern isconfirm_once, andenrollment.stopisconfirm_oncewith no conditional at all, because an enrolment's position is evidence of what the person actually received (G8). Perform the protective half immediately and ask for the other half — treating the whole branch asautois how a stop turns into an unapproved domain-wide exclusion. - Treating do-not-contact as a disposition value. Suppression is
suppression.addandoptout.record, not a label on a thread, and recording a disposition the user did not agree with is a separate mistake worth avoiding on its own. - Closing the thread to stop the cadence, because closing feels like finishing. It stops
nothing (
H9). - Re-sorting the queue by timestamp and burying the interested reply under twenty automated bounces — or re-ranking it by hand and losing the waiting time that made a thread urgent.
- Greeting by the provider's name for the thread's contact instead of the person's own record, or choosing between the two without saying that they differ.
- Losing thread context by summarising away the specific thing the prospect asked.
Safety
Sending a reply to a real prospect is confirm_each: the user confirms the exact rendered
text, for this person, on this channel, every time — no exceptions, no batching. Where the
draft was machine-generated, the moment the user approves that rendered text is the moment a
human editorial review exists; record it with editorial_review.record then, or the send
carries the disclosure obligation instead (A21).
Recording that somebody asked to stop is the opposite case and must not be reasoned about the
same way. It is protective, derives auto, and is never held back for a confirmation, never
inferred from silence, and never inferred from a lukewarm reply.
Conversations contain personal data; keep quotes to what the decision requires. Full rules:
approval-boundaries.
Related skills
sdr-operations— the conversation operations, their five properties, and the worked chain for a morning inbox and for a reply that names somebody else.performance-analysis— when reply volume or quality suggests a campaign problem rather than an inbox problem.approval-boundaries— whereconfirm_eachcomes from, why a composition is never covered by one yes, and what a valid confirmation looks like.
Changelog
- 3.1.0 (2026-11-02): with Jason, a reply has usually been worked before the inbox is opened: a responder records a verdict and acts, drafts or asks. Triage reads what it left and never writes a second draft beside one; a standing approval is a person's own decision for one category in one campaign.
- 3.0.0 (2026-08-10): migrated onto contract 2.0.0.
conversation.read→conversation.get;conversation.reply→message.send, which is a different family and the point of the move — a reply is a message, and switching channel is an argument change rather than a silent fallback. Bothexact-textgates becomeconfirm_each, with the composition-versus-release reasoning stated rather than assumed. Addsconversation.assign,conversation.snooze,conversation.close,conversation.reopen,referral.recordandactivity.log, and with them the rule that closing a thread stops no outreach. Classification and disposition are now two steps on two axes instead of one; a request to stop is no longer offered as a classification value. The meeting-booking gap is closed — family 11 exists; what is missing is a playbook, and the skill now says so. Reply-strategy gaps remain marked for expert validation. - 2.0.0 (2026-07-30): renamed from
manage-repliesand rewritten vendor-neutral for the business pack — provider inbox endpoints and scopes moved out to the provider's own skills. Reply-strategy gaps marked for expert validation; safety now defers toapproval-boundaries. - 1.0.0 (2026-07-27): ported from the prototype workflow as
manage-replies.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

