用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/majiayu000/claude-skill-registry --skill ops-inbox命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | ops-inbox |
| description | Process pending Brikette customer emails and generate draft responses using MCP tools |
Process customer emails for Hostel Brikette, generating intelligent draft responses using the knowledge base and MCP tools.
Run this skill when you want to process customer inquiry emails for Brikette:
scripts/ops/create-brikette-drafts.pyBefore any inbox processing, run:
health_check({ strict: false })
Then enforce these rules:
Tool not found, unknown tool, or MCP disconnect), stop immediately.gmail_organize_inbox or any other MCP call in that session.claude
Then rerun /ops-inbox.status: "unhealthy", stop and show the failing checks/remediation.status: "degraded", continue only with explicit user approval.After health_check passes, run the reconcile step:
gmail_reconcile_in_progress({ dryRun: false, staleHours: 2 })
Handle the result as follows:
⚠️ Reconcile failed: <error message> — continuing) and proceed. This step is fail-open and must never block the inbox run.counts.routedRequeued > 0: surface this line in the preflight output:
♻️ N stuck email(s) recovered and re-queued.
(where N is the value of counts.routedRequeued)If the user wants dry-run fallback (or MCP remains unavailable), queue drafts locally instead of writing Gmail drafts:
python3 scripts/ops/create-brikette-drafts.py \
--input <path-to-drafts.json> \
--dry-run \
--queue-file data/email-fallback-queue/<timestamp>-ops-inbox.jsonl
NOTE: Dry-run and Python-fallback sessions produce no signal events. This is expected — those sessions are excluded from calibration data and will not appear in
draft_signal_statscounts.
First, run an inbox organize pass for unread emails. This does a garbage/sort cycle:
Brikette/Queue/Needs-ProcessingOrganizing unread inbox...
Call the tool:
gmail_organize_inbox({ limit: 500 })
Then briefly report the result:
Use the gmail_list_pending MCP tool to fetch pending emails:
gmail_list_pending({ limit: 20 })
If no pending emails, inform the user:
No pending emails in your queue. You're all caught up!
Present emails in a summary table:
## Pending Emails (N total)
| # | From | Subject | Received | Type |
|---|------|---------|----------|------|
| 1 | maria@example.com | Availability June 15-18? | 2h ago | Inquiry |
| 2 | john@example.com | RE: Booking confirmation | 4h ago | Reply |
...
Actions:
- "Process all" - work through queue in order
- "Process #1" - handle specific email
- "Skip #3" - mark as spam/not-customer
- "Defer #5" - move to deferred manual-review label
- "Done" - finish session
Classify emails by type:
Needs Draft Response:
No Draft Needed:
Special Handling:
When user selects an email to process:
Fetch full details using gmail_get_email:
gmail_get_email({ emailId: "...", includeThread: true })
Run Interpretation stage using draft_interpret:
draft_interpret({
body: email.body.plain,
subject: email.subject,
threadContext: email.thread_context
})
Output: EmailActionPlan (intents, scenario, agreement status, workflow triggers).
Review the Action Plan:
scenario.categoryescalation_required: if true, do NOT proceed to draft_generate. Instead, move the email to Brikette/Queue/Deferred via gmail_mark_processed({ emailId, action: "deferred" }) and stop the pipeline for this email. Inform the user that the email requires human review before a draft can be generated.deferred (manual review)Run Composition stage using draft_generate:
draft_generate({
actionPlan,
subject: email.subject,
recipientName: email.from.name,
prepaymentStep: "first" | "second" | "third" | ,
: |
})
Create draft (for Inquiry/Reply/FAQ):
gmail_create_draft({
emailId: "original_email_id",
subject: "RE: Original Subject",
bodyPlain: "Plain text version",
bodyHtml: "HTML version with branding"
})
gmail_mark_processed({ emailId: "...", action: "drafted" })
Create draft (dry-run fallback queue):
Use this path when:
Steps:
emailId, to, subject, recipientName, bodyPlain).python3 scripts/ops/create-brikette-drafts.py \
--input <path-to-drafts.json> \
--dry-run \
--queue-file data/email-fallback-queue/<timestamp>-ops-inbox.jsonl
gmail_mark_processed in dry-run mode.Edit request:
Acknowledge (for Informational emails - no draft needed):
gmail_mark_processed({ emailId: "...", action: "acknowledged" })
Use when customer provides info but no reply is needed:
Promotional (for marketing/newsletters):
gmail_mark_processed({ emailId: "...", action: "promotional" })
Archives email and labels Brikette/Outcome/Promotional for batch review later.
Use for:
When a promotional/spam false-positive appears in queue:
promotional or spam immediately.packages/mcp-server/src/tools/gmail.ts (NON_CUSTOMER_* constants) so future organize runs stop queueing it.Skip (not relevant/not customer):
gmail_mark_processed({ emailId: "...", action: "skipped" })
Spam (suspicious/unwanted):
gmail_mark_processed({ emailId: "...", action: "spam" })
Defer (complex/needs more info):
gmail_mark_processed({ emailId: "...", action: "deferred" })
Moves it out of the active queue and labels it Brikette/Queue/Deferred for manual follow-up.
Agreement detection is high-stakes:
confirmed only for explicit agreement phrases (EN/IT/ES).likely or unclear requires human confirmation before any payment workflow.agreement.requires_human_confirmation.If the email includes agreement and questions, treat as mixed response:
likely/unclear.Marking agreement_received — reservation code required:
When marking an email as agreement_received, you must extract the booking reservation code and pass it as reservationCode. This writes activity code 21 to Firebase for all occupants on that booking.
How to extract the reservation code:
#XXXXXX or plain numbers in subject lines like "Booking confirmation #456789".gmail_mark_processed without reservationCode (labels will still be applied), and note in the session summary that the Firebase activity write was skipped.// When agreement is confirmed and reservation code is found:
gmail_mark_processed({
emailId: "...",
action: "agreement_received",
reservationCode: "456789" // extracted from email thread
})
// When agreement is confirmed but no reservation code found:
gmail_mark_processed({
emailId: "...",
action: "agreement_received"
// No reservationCode — labels applied, Firebase write skipped
})
When an email is classified as Informational (customer providing info, no reply needed):
## Email #3: Customer Information
**From:** John Smith <john@example.com>
**Subject:** RE: Booking confirmation
**Received:** 1 hour ago
### Content:
> Thanks for confirming! Just to let you know, we'll be arriving
> around 3pm. See you then!
### Classification:
- **Type:** Informational (arrival time notification)
- **Action Needed:** Note arrival time
- **Draft Required:** No
### Extracted Information:
- **Arrival time:** 3pm (approximately)
- **Guest:** John Smith
### Suggested Action:
Note arrival time in booking system if applicable.
**Mark as acknowledged?** (y/n)
Common informational patterns:
When user requests batch processing ("Process all FAQ emails"):
## Batch Processing: 4 FAQ Emails
1. "Check-in time question" -> Draft created
2. "Breakfast included?" -> Draft created
3. "Pet policy" -> Draft created
4. "Luggage storage" -> Draft created
4 drafts created. Review them in Gmail.
Remaining in queue: 2 emails
When user says "Done" or queue is empty:
draft_signal_stats to retrieve event counts for this session.draft_template_review with action: "list" to get pending proposal count.gmail_audit_labels to check the Brikette label namespace health.
orphaned.length > 0: include an Orphaned labels warning in the summary listing each orphaned label name. These are unrecognised Brikette/* labels that should be reviewed or migrated.orphaned.length === 0: omit the label health section entirely (silent pass).## Session Complete
**Processed this session:**
- 3 drafts created
- 2 emails acknowledged (no reply needed)
- 1 promotional archived
- 1 email deferred
**Drafts ready for review:**
1. RE: Availability June 15-18? (maria@example.com)
2. RE: Check-in time question (guest@hotel.com)
3. RE: Breakfast options (traveler@email.com)
**Acknowledged (info noted):**
- Arrival time 3pm (john@example.com)
- Dietary: vegetarian (jane@example.com)
Remember to review and send drafts in Gmail!
**Deferred for manual review:** 1 email
**Signal health:**
- N selection events · N refinement events · N joined signals this session
- N template proposals pending review
- [one-line summary per pending proposal, e.g. "T05 check-in: wrong-template (2026-02-20)"]
> ⚠️ **Backlog warning:** >10 pending proposals — run `draft_template_review list` and review.
> _(Remove this line if ≤10 proposals pending.)_
> 💡 **Calibration prompt:** ≥20 joined signals since last calibration — consider running `draft_ranker_calibrate`.
> _(Remove this line if events_since_last_calibration < 20.)_
<!-- Include the following block only when gmail_audit_labels returns orphaned.length > 0: -->
> ⚠️ **Orphaned Gmail labels:** The following unrecognised `Brikette/*` labels exist in Gmail and should be reviewed or removed:
> - [list each orphaned label name on its own line]
Graceful fallback: If draft-signal-events.jsonl or template-proposals.jsonl are missing, show "0 events" / "0 proposals pending" — do not error. If gmail_audit_labels fails, omit the label health section.
NOTE: Dry-run and Python-fallback sessions produce no signal events. Show
"0 events"for those sessions.
Use these patterns to correctly classify incoming emails:
Inquiry - Customer asking a question:
Reply - Continuing a conversation that needs response:
FAQ - Common questions with standard answers:
Informational - Customer providing info (acknowledge, no reply):
Promotional - Marketing (archive to Brikette/Outcome/Promotional):
Not-Customer - Skip without reply:
Complex - Defer for careful handling:
Spam - Mark as spam:
Is it from a real person about Brikette?
├─ No → Is it promotional?
│ ├─ Yes → PROMOTIONAL
│ └─ No → Is it spam?
│ ├─ Yes → SPAM
│ └─ No → SKIP (not-customer)
└─ Yes → Does it contain a question or need a response?
├─ Yes → Is it a complaint or complex?
│ ├─ Yes → DEFER (complex)
│ └─ No → DRAFT (inquiry/faq/reply)
└─ No → Is it providing useful information?
├─ Yes → ACKNOWLEDGE (informational)
└─ No → ACKNOWLEDGE (no action needed)
Availability inquiry:
Price question:
Directions/Location:
Policy questions:
Complaints:
## Gmail API Error
Unable to fetch emails: [Error message]
Options:
1. "Retry" - try again
2. "Done" - end session and try later
## Draft Generation Issue
I'm having trouble with this email because:
- [Reason]
Options:
1. "Flag for manual" - you'll handle this directly
2. "Use template" - generic acknowledgment response
3. "Give context" - tell me more to help
When user needs to stop:
Before creating each draft, verify:
docs/guides/brikette-email-workflow.mddocs/plans/email-autodraft-workflow-design.mddocs/business-os/cards/BRIK-ENG-0020.user.md| URI | Content |
|---|---|
brikette://faq | 29 FAQ items |
brikette://rooms | Room details and config |
brikette://pricing/menu | Bar and breakfast prices |
brikette://policies | Check-in, age restrictions, etc. |
brikette://draft-guide | Draft quality framework |
brikette://voice-examples | Voice/tone examples |
brikette://email-examples | Classification examples |
| Tool | Action/Params | Purpose |
|---|---|---|
draft_signal_stats | (none) | Returns {selection_count, refinement_count, joined_count, events_since_last_calibration} — used in Session Summary |
draft_template_review | action: "list" | Lists pending template improvement proposals with one-line summaries |
draft_template_review | action: "approve", proposal_id, expected_file_hash | Approves a proposal and writes to email-templates.json (optimistic concurrency) |
draft_template_review | action: "reject", proposal_id | Rejects and archives a proposal |
draft_ranker_calibrate | dry_run?: boolean | Computes and persists ranker priors from ≥20 joined events; use when events_since_last_calibration ≥ 20 |
Pre-written templates are available in packages/mcp-server/data/email-templates.json for common response scenarios. Use these as a starting point and personalize for each customer.
| Category | Templates | Use For |
|---|---|---|
| check-in | Arriving before check-in, Arrival Time, Out of hours | Check-in timing questions |
| access | Inner/Outer Building Main Door | Door code and access questions |
| transportation | Transportation to Hostel | How to get here questions |
| payment | Change Credit Card Details | Payment method updates |
| prepayment | 1st/2nd/3rd Attempt, Cancelled, Successful | Payment processing status |
| cancellation | Non-Refundable Booking, No Show | Cancellation requests |
| policies | Alcohol, Age Restriction | Policy explanations |
| activities | Path of the Gods Hike | Activity recommendations |
| booking-issues | Why cancelled | Booking troubleshooting |
When handling prepayment chase emails, apply these mappings:
When updating Gmail labels, use gmail_mark_processed with:
prepayment_chase_1, prepayment_chase_2, or prepayment_chase_3.
When an incoming email is a T&C agreement reply:
action: "awaiting_agreement".action: "agreement_received" and pass reservationCode (see Agreement Detection section above). This triggers Firebase activity code 21 write for all occupants — required to prevent the booking from being auto-cancelled despite the guest having agreed.When drafting a response:
Templates provide consistent messaging for common scenarios while maintaining the professional, warm tone expected by guests.
Output: draft (plain + HTML), template_used, answered_questions, knowledge_sources.
Run Quality Gate using draft_quality_check:
draft_quality_check({ actionPlan, draft })
Capture the full result including quality.question_coverage[].
Gap-Patch Loop — run this before presenting to the user:
a. Inspect every entry in quality.question_coverage[]:
status: "covered" → no action needed for that question.status: "missing" → the question received zero keyword matches; a patch is required.status: "partial" → the question was touched but under the required match threshold; a patch attempt is required.b. For each missing or partial entry, look up the question text against
knowledge_summaries returned by draft_generate.
knowledge_summaries: rewrite the relevant
paragraph to include a source-backed answer. Cite the snippet URI inline
if helpful. NEVER invent an answer that has no source snippet."For this specific question we want to give you the most accurate answer — Pete or Cristiana will follow up with you directly." Do not attempt to paraphrase, guess, or approximate the missing information.
c. Hard-rule categories — do NOT modify under any circumstance:
prepayment category text (1st/2nd/3rd attempt, cancelled, successful templates)cancellation category text (non-refundable, no-show templates)
These paragraphs are legally and operationally fixed. If a missing/partial
entry belongs to a question about prepayment or cancellation policy, escalate
using the sentence above rather than touching the template wording.d. Partial-subset rule: When an email contains multiple questions and only some can be source-backed, patch what can be sourced and escalate the rest individually. Do not withhold the draft because one question lacks a snippet — produce the best partial draft and flag each unanswered question explicitly in the user-facing summary.
e. After applying all patches (or escalation insertions), re-render bodyPlain
and bodyHtml.
LLM Refinement Stage — after gap-patching, Claude (not a tool call) assesses
the draft holistically and optionally rewrites it to improve tone, flow, and coverage.
Then call draft_refine to submit and attest the result:
draft_refine({
actionPlan,
draft_id: draftGenerateResult.draft_id, // links this refinement to the selection signal event
rewrite_reason: "<reason>", // "none" | "style" | "language-adapt" | "light-edit" | "heavy-rewrite" | "missing-info" | "wrong-template"
originalBodyPlain: patchedBodyPlain, // post-gap-patch plain text
refinedBodyPlain: claudeRefinedBodyPlain, // Claude's rewrite (or same text if no improvement)
})
Refinement rules:
draft_refine is the commit
step only. Never invoke an external model from inside this skill.refinedBodyPlain === originalBodyPlain —
draft_refine will return refinement_applied: false, refinement_source: 'none'.refinement_applied: true, refinement_source: 'claude-cli'.prepayment category text (1st/2nd/3rd attempt, cancelled, successful templates)cancellation category text (non-refundable, no-show templates)knowledge_summaries.quality.passed: false after refinement: inspect failed_checks. If resolvable
by a targeted patch, patch and call draft_refine again (max one retry). If still
failing, escalate to the user with failed_checks listed and ask how to proceed.refinement_source: 'codex' is reserved for future CLI-based LLMs; it is
not an active path in this workflow.Mandatory delivery_status gate — always check before creating the Gmail draft.
draft_generate returns a delivery_status field: "ready" | "needs_patch" | "blocked".
"ready" — quality passed with no warnings: proceed to gmail_create_draft."needs_patch" — quality passed but warnings exist (e.g. partial coverage): review
warnings, apply any needed patches via draft_refine, then proceed."blocked" — quality failed (quality.passed: false): inspect quality.failed_checks,
patch and call draft_refine (max one retry). If still "blocked", escalate to the
user with failed_checks listed and ask how to proceed. Do not call gmail_create_draft
while delivery_status === "blocked". This is a hard gate, not advisory.partial_question_coverage warnings after patching are acceptable to proceed
if the escalation sentence has been inserted; note them in the session summary.Present to user:
## Email #1: Availability Inquiry
**From:** Maria Santos <maria@example.com>
**Subject:** Availability June 15-18?
**Received:** 2 hours ago
### Content:
> [Customer's email content]
### Classification:
- **Scenario:** [from EmailActionPlan]
- **Language:** [from EmailActionPlan]
- **Agreement:** confirmed / likely / unclear / none
- **Workflow triggers:** prepayment / terms_and_conditions / booking_monitor
### Relevant Knowledge:
- [Knowledge sources used]
### Draft Response:
---
[Generated draft]
---
Actions:
- "Create draft" - save to Gmail drafts
- "Edit" - modify the response
- "Regenerate" - try a different approach
- "Skip" - don't respond
- "Flag" - mark for manual handling