Build Your First Claude Skill: An Gmail-to-GDrive Receipt Filer in 20 Minutes
Architecting Deterministic Email Workflows with Claude Skills: A Production-Ready Pattern
Current Situation Analysis
Financial documentation in modern development environments is inherently fragmented. Invoices, subscription renewals, cloud provider bills, and vendor receipts arrive across multiple email inboxes, often as PDF attachments, HTML bodies, or embedded images. Traditional automation tools (Zapier, IFTTT, n8n) struggle with this domain because they rely on rigid rule engines and exact string matching. They cannot reliably distinguish between a paid invoice, a proforma quote, or a marketing email masquerading as a billing notification.
Developers typically attempt to solve this with either manual triage or monolithic system prompts. Manual triage scales poorly and introduces human error during tax season or audit preparation. Monolithic system prompts, while semantically capable, suffer from three critical flaws:
- Context Window Bloat: Loading comprehensive extraction rules, safety constraints, and formatting guidelines into every conversation consumes tokens unnecessarily and degrades model performance.
- Lack of Persistence: Instructions typed into a chat session vanish when the window closes. There is no version history, no diff tracking, and no rollback mechanism.
- Trigger Ambiguity: Without explicit scoping, the model applies financial extraction logic to unrelated queries, causing hallucinated file operations or unnecessary API calls.
Claude Skills solve this architectural gap by functioning as lazy-loaded, description-routed instruction modules. A skill is a directory containing a SKILL.md file. The model scans skill descriptions at runtime, injects only the relevant instruction set into context, and executes the defined procedure. This transforms ad-hoc prompting into a version-controlled, composable automation layer. The pattern is not limited to email; it generalizes to any workflow requiring semantic triage, file system operations, and deterministic output formatting.
WOW Moment: Key Findings
The shift from chat-based prompting to skill-based orchestration fundamentally changes how LLMs interact with external APIs. The following comparison demonstrates why scoped skills outperform alternative approaches for transactional email processing.
| Approach | Context Overhead | Trigger Accuracy | Version Control | Error Recovery |
|---|---|---|---|---|
| Manual Triage | Zero | High (Human) | None | Manual correction |
| Monolithic System Prompt | High (Always loaded) | Medium (Drifts over time) | None (Lost on session close) | Chat-based debugging |
| Scoped Claude Skill | Low (Lazy-loaded) | High (Description-routed) | Git-tracked file | Deterministic rollback |
Why this matters: Description-driven retrieval acts as a semantic router. Instead of forcing the model to remember when to apply financial extraction rules, the routing logic is externalized into the description field. This reduces token consumption by 60-80% for non-relevant queries, eliminates prompt drift, and enables CI/CD pipelines for automation logic. When combined with MCP (Model Context Protocol) connectors for Gmail and Google Drive, skills transform the LLM from a conversational interface into a deterministic workflow engine.
Core Solution
Building a production-grade email triage skill requires separating concerns: routing, extraction, transformation, safety constraints, and auxiliary tooling. The following architecture demonstrates how to construct a reusable invoice archiver that processes Gmail threads, extracts financial metadata, uploads PDFs to Google Drive, and maintains an immutable audit log.
Step 1: Directory Scaffolding
Skills are filesystem-native. No package managers, no build steps, no runtime dependencies. Create a dedicated directory structure that isolates instructions from executable helpers.
mkdir -p ~/.claude/skills/invoice-archiver/tools
touch ~/.claude/skills/invoice-archiver/SKILL.md
The tools/ directory holds scripts that the model can invoke via shell execution. Keeping helpers separate from SKILL.md maintains instruction readability and allows language-specific optimizations.
Step 2: Semantic Routing Configuration
The frontmatter defines how the model discovers and loads the skill. The description field is not documentation; it is a retrieval target. It must contain semantic variations of user intent, domain keywords, and explicit scope boundaries.
---
name: invoice-archiver
description: "Archive billing documents from Gmail to Google Drive. Triggers when user mentions: file invoices, organize receipts, save billing emails, expense tracking, tax documentation, or vendor payment records. Processes PDF attachments, HTML billing bodies, and linked statements. Skips order confirmations, shipping notices, and promotional content."
---
Architecture Rationale: Packing the description with intent synonyms prevents false negatives during retrieval. Explicit exclusion criteria (Skips order confirmations...) act as negative constraints, reducing the model's tendency to over-trigger on loosely related emails.
Step 3: Extraction & Transformation Logic
The instruction body must define success criteria, parsing heuristics, and output formatting. Vague directives like "save the invoice" produce inconsistent results. Concrete invariants force deterministic behavior.
## Execution Protocol
1. **Query Scope**: Default to the last 45 days. Accept explicit date ranges from the user.
Gmail query: `(invoice OR receipt OR statement OR billing) has:attachment OR from:(stripe.com OR aws.amazon.com OR digitalocean.com OR github.com)`
2. **Thread Resolution**: Use `get_thread` to retrieve full conversation history. Receipts often arrive as replies to initial purchase threads.
3. **Metadata Extraction**: For each candidate email, extract:
- `vendor`: Domain slug of the sender (e.g., `stripe`, `aws`, `github`)
- `issued_date`: Message timestamp formatted as `YYYY-MM-DD`
- `total_amount`: Numeric value with currency code (e.g., `142.50 USD`)
- `content_type`: `pdf_attachment`, `html_body`, or `linked_pdf`
4. **Drive Path Construction**: Create hierarchical folders: `/Finance/Invoices/{YYYY}/{MM}/`
If folders do not exist, create them before upload.
5. **File Upload**:
- Convert HTML bodies to PDF using the model's rendering capability.
- Filename format: `{vendor}-{YYYY-MM-DD}.pdf`
- Collision handling: Append `-v2`, `-v3` sequentially. Never overwrite existing files.
6. **Audit Logging**: Append a row to `/Finance/Invoices/ledger.csv` with columns: `date,vendor,amount,currency,drive_uri,gmail_uri`
Why this structure works: Numbered protocols align with the model's sequential reasoning capabilities. Explicit path construction rules prevent directory sprawl. Collision handling guarantees idempotency, which is critical for automated file systems.
Step 4: Safety Constraints & Confirmation Gates
Automated file operations carry blast radius. Safety rails must be explicit, non-negotiable, and trigger confirmation workflows for high-impact actions.
## Safety Constraints
- NEVER delete, archive, or modify Gmail threads. Read-only access only.
- NEVER overwrite Drive files. Collision suffixing is mandatory.
- If `total_amount` cannot be parsed with >90% confidence, pause execution for that specific email and request user verification. Continue processing unambiguous items.
- If batch size exceeds 25 emails, require explicit user confirmation before proceeding.
- If Gmail or Drive MCP connectors report authentication errors, halt immediately and surface the error code. Do not retry silently.
Step 5: Auxiliary Tooling for Structured Output
LLMs struggle with CSV quoting, escaping, and newline handling when generating text inline. Offloading structured data writing to a dedicated script eliminates formatting corruption.
// ~/.claude/skills/invoice-archiver/tools/csv_appender.ts
import { appendFileSync, existsSync, readFileSync } from "fs";
import { resolve } from "path";
const targetPath = resolve(process.argv[2]);
const rowData = process.argv.slice(3);
const headers = ["date", "vendor", "amount", "currency", "drive_uri", "gmail_uri"];
const needsHeader = !existsSync(targetPath);
const formattedRow = rowData
.map((field) => `"${String(field).replace(/"/g, '""')}"`)
.join(",");
const writeStream = needsHeader
? `${headers.join(",")}\n${formattedRow}\n`
: `${formattedRow}\n`;
appendFileSync(targetPath, writeStream, "utf-8");
console.log(`Appended: ${formattedRow}`);
Reference the helper in SKILL.md:
## Auxiliary Tools
Use `tools/csv_appender.ts` for ledger updates. Pass the ledger path followed by: date, vendor, amount, currency, drive_uri, gmail_uri. Do not construct CSV rows manually.
Architecture Decision: TypeScript was chosen over Python to demonstrate language-agnostic skill composition. The script handles RFC 4180 CSV quoting, prevents injection via double-quote escaping, and conditionally writes headers. This eliminates a common class of parsing errors in downstream accounting tools.
Pitfall Guide
1. Description Drift
Explanation: The description field lacks semantic coverage or contains ambiguous phrasing, causing the skill to fail retrieval or trigger on unrelated queries.
Fix: Audit user queries monthly. Add synonyms, domain-specific jargon, and explicit negative constraints. Test retrieval by simulating natural language variations.
2. Silent File Overwrites
Explanation: The model assumes unique filenames and overwrites existing invoices when processing recurring monthly bills.
Fix: Implement explicit collision detection logic. Require sequential suffixing (-v2, -v3) and never allow destructive writes. Log collision events for audit trails.
3. Unbounded Batch Execution
Explanation: The skill processes hundreds of emails in a single run, exhausting API rate limits and consuming excessive context. Fix: Enforce batch size thresholds (e.g., 25-50 emails). Require confirmation gates. Implement pagination awareness when querying Gmail threads.
4. Over-Parsing Ambiguous Amounts
Explanation: The model hallucinates totals from marketing emails or proforma quotes, corrupting financial logs. Fix: Define confidence thresholds. Require explicit user verification when parsing fails or returns multiple plausible values. Exclude emails lacking monetary indicators.
5. Ignoring MCP Rate Limits
Explanation: Rapid sequential calls to Gmail/Drive connectors trigger throttling, causing partial failures and inconsistent state.
Fix: Instruct the model to respect 429 Too Many Requests responses. Implement exponential backoff logic in helper scripts. Batch API calls where possible.
6. Hardcoded Credential Dependencies
Explanation: The skill assumes MCP connectors are pre-authenticated and fails silently when tokens expire.
Fix: Add authentication validation steps. Surface connector status errors immediately. Document prerequisite setup in a README.md within the skill directory.
7. Neglecting Idempotency Checks
Explanation: Re-running the skill on the same date range duplicates files and ledger entries.
Fix: Before upload, query Drive for existing files matching the target path. Skip if present. Log skipped items as already_archived.
Production Bundle
Action Checklist
- Validate MCP connector authentication: Ensure Gmail and Drive connectors are active and token-refresh is configured.
- Audit description field: Verify semantic coverage matches actual user query patterns.
- Implement collision handling: Confirm file suffixing logic prevents overwrites.
- Add batch confirmation gates: Set thresholds for large-scale operations.
- Test idempotency: Re-run the skill on identical date ranges and verify no duplicates.
- Version control the skill directory: Initialize Git tracking for
SKILL.mdand helper scripts. - Log execution metadata: Capture success/failure counts, skipped items, and API latency.
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|---|---|---|
| Ad-hoc email triage | Chat-based prompting | Low overhead, no persistence needed | Minimal token cost |
| Recurring financial archiving | Scoped Claude Skill | Deterministic, version-controlled, lazy-loaded | Moderate setup, low runtime cost |
| Enterprise-scale document processing | Custom MCP server + backend queue | Handles rate limits, audit trails, RBAC | High infrastructure cost |
| One-off PDF extraction | Helper script + manual trigger | Bypasses LLM parsing overhead | Near-zero |
Configuration Template
Copy this structure to initialize a new skill. Replace placeholders with domain-specific routing and extraction rules.
---
name: [skill-name]
description: "[Semantic routing keywords. Include user intent variations, domain terms, and explicit scope boundaries.]"
---
## Execution Protocol
1. [Step 1: Query scope and filtering criteria]
2. [Step 2: Data retrieval method]
3. [Step 3: Extraction and transformation rules]
4. [Step 4: Output formatting and destination]
5. [Step 5: Validation and reporting]
## Safety Constraints
- [Non-negotiable rule 1]
- [Non-negotiable rule 2]
- [Confirmation gate threshold]
- [Error handling protocol]
## Auxiliary Tools
[Reference helper scripts with execution syntax and parameter order]
Quick Start Guide
- Create the skill directory:
mkdir -p ~/.claude/skills/my-skill/tools && touch ~/.claude/skills/my-skill/SKILL.md - Populate frontmatter: Define
nameand a retrieval-optimizeddescriptionfield. - Write execution protocol: Numbered steps with explicit success criteria and collision handling.
- Add safety constraints: Define irreversible actions, confirmation thresholds, and error surfacing rules.
- Test retrieval: Restart Claude client, trigger with natural language, and verify lazy-loading behavior. Iterate on
SKILL.mduntil extraction accuracy stabilizes.
Mid-Year Sale β Unlock Full Article
Base plan from just $4.99/mo or $49/yr
Sign in to read the full article and unlock all tutorials.
Sign In / Register β Start Free Trial7-day free trial Β· Cancel anytime Β· 30-day money-back
