Files
FrancyJGLisboa_agent-skill-…/references/architecture-guide.md
francylisboacharuto 1154b1d6ab feat: -skill suffix convention, team sharing via GitHub/GitLab
Skills now require -skill suffix for org-wide discoverability (teams
search *-skill to find all skills). Suites use -suite suffix.

Post-creation sharing flow: agent detects gh/glab CLI, creates repo,
adds agent-skill topic, gives shareable one-liner for Slack/Teams.
Supports GitHub, GitLab, Enterprise, and self-hosted instances.

Updated validate.py to warn on missing -skill suffix and error on
deprecated -cskill suffix. Updated architecture-guide.md naming
section to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 04:21:41 -03:00

34 KiB
Raw Permalink Blame History

Architecture Decision Guide

Version: 4.0 Purpose: Comprehensive guide for choosing the right architecture when creating agent skills, including directory structures, naming conventions, sizing patterns, and performance strategies.


1. Architecture Decision Framework

Before creating any skill, determine whether it should be a Simple Skill or a Complex Suite. This decision drives the entire directory structure, file organization, and whether a marketplace.json is needed.

1.1 Decision Criteria

Factor Simple Skill Complex Suite
Number of workflows 1-2 related workflows 3+ distinct workflows
Code complexity <1000 lines total >2000 lines total
SKILL.md files 1 Multiple (one per component)
Maintenance scope Single developer Team or multi-concern
Domain breadth Single domain focus Spans multiple sub-domains
Deployment Install as one unit Components may be used independently
marketplace.json Not needed Optional (official fields only)

1.2 Decision Flowchart

Follow this logic sequentially:

START
  |
  v
How many distinct workflows does this skill address?
  |
  +-- 1-2 workflows --> Does the total code exceed 2000 lines?
  |                       |
  |                       +-- No  --> SIMPLE SKILL
  |                       +-- Yes --> Can it be split into independent sub-skills?
  |                                     |
  |                                     +-- No  --> SIMPLE SKILL (large)
  |                                     +-- Yes --> COMPLEX SUITE
  |
  +-- 3+ workflows --> Are the workflows tightly coupled?
                        |
                        +-- Yes (shared state/data) --> SIMPLE SKILL (organized)
                        +-- No  (independent concerns) --> COMPLEX SUITE

1.3 Decision Examples

User Request Decision Rationale
"Analyze stock prices with technical indicators" Simple Skill Single domain, 1-2 workflows (fetch + analyze)
"Format markdown tables" Simple Skill Single workflow, <500 lines
"Full-stack web dev with frontend, backend, deployment" Complex Suite 3 independent sub-domains
"USDA agriculture data with 6 analysis types" Simple Skill (organized) Multiple analyses but single domain, shared data pipeline
"Financial suite: stock analysis, portfolio tracking, tax reporting" Complex Suite 3 distinct workflows, each usable independently

2. Simple Skill Structure

A Simple Skill is a single, self-contained agent skill that follows the Agent Skills Open Standard. It has one SKILL.md file and no marketplace.json.

2.1 Standard Directory Layout

skill-name/
├── SKILL.md          # <500 lines, spec-compliant frontmatter
├── scripts/          # Functional Python code
├── references/       # Detailed documentation (loaded on demand)
├── assets/           # Templates, schemas, data files
├── install.sh        # Cross-platform auto-detect installer
└── README.md         # Multi-platform installation instructions

Key rule: NO .claude-plugin/marketplace.json for simple skills. The SKILL.md file is the sole manifest and activation mechanism.

2.2 SKILL.md Frontmatter (Required)

---
name: skill-name            # 1-64 chars, lowercase + hyphens, must match directory
description: >-             # 1-1024 chars, activation keywords included
  Description with domain keywords for agent discovery...
license: MIT                # or appropriate license
metadata:
  author: Author Name
  version: 1.0.0
compatibility: >-           # optional, use when platform-specific features exist
  Works on all platforms supporting the SKILL.md standard.
---

2.3 File Responsibilities

File/Directory Purpose Required?
SKILL.md Primary skill definition, frontmatter, instructions Yes
scripts/ Executable Python code (functional, no placeholders) Yes (if skill has code)
references/ Detailed documentation, API guides, methodology docs Recommended
assets/ Configuration files, templates, schemas, static data Optional
install.sh Cross-platform installer script Yes
README.md Installation instructions for 5+ platforms Yes

2.4 Why No marketplace.json for Simple Skills

Per the Agent Skills Open Standard and FR-005:

  • SKILL.md is the universal discovery mechanism across all 26+ platforms
  • marketplace.json is a Claude Code-specific plugin manifest, not part of the standard
  • Simple skills activate via their SKILL.md description field alone
  • Adding marketplace.json to a simple skill creates a non-standard structure that may confuse other platforms
  • Skills placed in ~/.claude/skills/ or .claude/skills/ are discovered automatically by Claude Code without marketplace.json

3. Complex Suite Structure

A Complex Suite bundles multiple related but independently usable skills under a single parent directory. It optionally includes a marketplace.json for Claude Code plugin registration.

3.1 Standard Directory Layout

suite-name/
├── .claude-plugin/
│   └── marketplace.json    # ONLY official fields (see below)
├── component-1/
│   ├── SKILL.md            # Independent skill definition
│   ├── scripts/
│   └── references/
├── component-2/
│   ├── SKILL.md            # Independent skill definition
│   ├── scripts/
│   └── references/
├── shared/                 # Shared utilities, data, config
│   ├── utils.py
│   └── config.json
├── install.sh              # Installs all components
└── README.md               # Suite-level documentation

3.2 marketplace.json Schema (Official Fields Only)

When a Complex Suite includes a marketplace.json, it must contain only the official Claude Code fields. No custom or non-standard fields are permitted.

{
  "name": "suite-name",
  "plugins": [
    {
      "name": "component-1",
      "description": "What component-1 does",
      "source": "component-1/SKILL.md",
      "skills": ["component-1"]
    },
    {
      "name": "component-2",
      "description": "What component-2 does",
      "source": "component-2/SKILL.md",
      "skills": ["component-2"]
    }
  ]
}

Allowed top-level fields:

  • name (string): The suite name
  • plugins (array): List of plugin entries

Allowed fields per plugin entry:

  • name (string): Component skill name
  • description (string): What the component does
  • source (string): Relative path to the component's SKILL.md
  • skills (array of strings): Skill identifiers

Forbidden fields (non-standard, will cause validation failure):

  • version -- use metadata.version in SKILL.md instead
  • author -- use metadata.author in SKILL.md instead
  • repository -- not part of the official schema
  • tags -- not part of the official schema
  • Any other custom fields

3.3 When to Use marketplace.json

Scenario Include marketplace.json?
Simple skill (1 SKILL.md) No
Complex suite for Claude Code distribution Yes (optional)
Complex suite targeting only non-Claude platforms No
Suite where components must be independently discoverable in Claude Code Yes

3.4 Component Independence

Each component in a Complex Suite should be independently functional:

  • Each component has its own SKILL.md with valid frontmatter
  • Each component can be installed separately if extracted from the suite
  • Shared resources in shared/ are optional enhancements, not hard dependencies
  • Each component's name field matches its directory name

4. Naming Convention

All skill and suite names follow standard kebab-case per the Agent Skills Open Standard.

4.1 Rules

Rule Requirement
Length 1-64 characters
Characters Lowercase letters (a-z), numbers (0-9), hyphens (-)
Format kebab-case
First character Must be a letter or number (not a hyphen)
Last character Must be a letter or number (not a hyphen)
Consecutive hyphens Not allowed (my--skill is invalid)
Directory match The name field in SKILL.md frontmatter must exactly match the parent directory name

4.2 The -skill Suffix

Every generated skill name must end with -skill. This suffix makes skills instantly discoverable across GitHub and GitLab organizations — teams can search *-skill and find every skill in their org.

Suites use the -suite suffix instead (e.g., financial-suite). Suites contain skills but are not themselves invoked as skills.

The previous -cskill suffix convention is deprecated. If encountered, replace with -skill.

4.3 Naming Pattern

{domain}-{objective}-skill

Examples:

  • stock-analyzer-skill -- domain: stock, objective: analyzer
  • csv-data-cleaner-skill -- domain: csv-data, objective: cleaner
  • sales-report-skill -- domain: sales, objective: report
  • deploy-checklist-skill -- domain: deploy, objective: checklist
  • financial-suite -- complex suite (uses -suite, not -skill)

Guidelines:

  • Must end with -skill (or -suite for multi-skill suites)
  • Be descriptive but concise — aim for under 30 characters
  • Include the primary domain for discoverability
  • Avoid generic names like my-skill or tool-1

4.4 Naming Validation

A valid name passes all of these checks:

import re

def validate_skill_name(name: str) -> tuple[bool, list[str]]:
    errors = []
    if not name:
        errors.append("Name is required")
    if len(name) > 64:
        errors.append(f"Name exceeds 64 chars ({len(name)})")
    if name != name.lower():
        errors.append("Name must be lowercase")
    if not re.match(r'^[a-z0-9][a-z0-9-]*[a-z0-9]$', name) and len(name) > 1:
        errors.append("Name must start/end with letter or number, contain only a-z, 0-9, hyphens")
    if '--' in name:
        errors.append("Consecutive hyphens not allowed")
    if name.endswith('-cskill'):
        errors.append("The -cskill suffix is deprecated; use -skill instead")
    if not name.endswith('-skill') and not name.endswith('-suite'):
        errors.append("Name must end with '-skill' (or '-suite' for multi-skill suites)")
    return (len(errors) == 0, errors)

5. Directory Sizing Patterns

Choose a sizing pattern based on the skill's complexity. These patterns apply to both Simple Skills and individual components within a Complex Suite.

5.1 Small Agent Pattern

When to use: Single workflow, 1-2 scripts, <500 total lines of code.

skill-name/
├── SKILL.md              # <200 lines
├── scripts/
│   └── main.py           # 200-400 lines, single entry point
├── references/
│   └── guide.md          # API docs, methodology
├── assets/
│   └── config.json       # Minimal configuration
├── install.sh
└── README.md

Characteristics:

  • One main script handles the entire workflow
  • Minimal configuration
  • Single reference document
  • Estimated total: 500-800 lines across all files

Examples: markdown-table-formatter, url-shortener, json-validator

5.2 Medium Agent Pattern

When to use: 2-3 workflows, 3-5 scripts, 500-2000 total lines of code.

skill-name/
├── SKILL.md              # 200-400 lines
├── scripts/
│   ├── fetch.py          # Data acquisition (200-300 lines)
│   ├── parse.py          # Data processing (150-200 lines)
│   ├── analyze.py        # Analysis logic (300-500 lines)
│   └── utils/
│       ├── cache.py      # Cache management (100-150 lines)
│       └── validators.py # Input validation (100-150 lines)
├── references/
│   ├── api-guide.md      # ~1500 words
│   └── methodology.md    # ~2000 words
├── assets/
│   └── config.json
├── install.sh
└── README.md

Characteristics:

  • Separation of concerns: fetch, parse, analyze
  • Utility modules for cross-cutting concerns (caching, validation)
  • Multiple reference documents
  • Estimated total: 1000-2500 lines across all files

Examples: stock-analyzer, weather-dashboard, csv-data-cleaner

5.3 Large Agent Pattern

When to use: 3+ workflows within a single domain, 6+ scripts, 2000+ total lines of code. Still a Simple Skill if all workflows share a single domain and data pipeline.

skill-name/
├── SKILL.md              # 400-500 lines (at the limit)
├── scripts/
│   ├── core/
│   │   ├── fetch_source_a.py    # 200-300 lines
│   │   ├── fetch_source_b.py    # 200-300 lines
│   │   ├── parse_source_a.py    # 150-200 lines
│   │   ├── parse_source_b.py    # 150-200 lines
│   │   └── analyze.py           # 400-600 lines
│   ├── models/
│   │   ├── forecasting.py       # 200-300 lines
│   │   └── ml_models.py         # 200-300 lines
│   └── utils/
│       ├── cache_manager.py     # 100-150 lines
│       ├── rate_limiter.py      # 100-150 lines
│       └── validators.py        # 100-150 lines
├── references/
│   ├── api/
│   │   ├── source-a-guide.md
│   │   └── source-b-guide.md
│   ├── methods/
│   │   └── analysis-methods.md
│   └── troubleshooting.md
├── assets/
│   ├── config.json
│   └── metadata.json
├── install.sh
└── README.md

Characteristics:

  • Sub-directories within scripts/ for organization (core, models, utils)
  • Multiple data sources with dedicated fetch/parse scripts
  • Dedicated models directory for analysis/ML logic
  • Organized reference documentation
  • Estimated total: 2500-5000 lines across all files

Examples: nass-usda-agriculture, conab-crop-yield-analysis, noaa-climate-analysis

5.4 Sizing Comparison Table

Aspect Small Medium Large
Total code lines <500 500-2000 2000+
Script files 1 3-5 6+
Script sub-dirs None utils/ core/, models/, utils/
Reference files 1 2-3 4+ (may use sub-dirs)
Asset files 0-1 1 2+
SKILL.md length <200 lines 200-400 lines 400-500 lines
Typical domains Formatters, validators Data analyzers, dashboards Multi-source analysis, forecasting

6. Performance Strategy

All generated skills should incorporate performance considerations appropriate to their size and use case.

6.1 Caching Strategy

Cache API responses and computed results to avoid redundant work and reduce API usage.

Cache TTL Decision Logic:

Data Type TTL Rationale
Historical data (past years) 365 days (effectively permanent) Historical data does not change
Current-year data 7 days May be revised/updated
Metadata (lists, enums) 365 days Rarely changes
Real-time data 1-60 minutes Freshness required
User preferences Session-scoped Per-execution only

Implementation Pattern:

import json
import hashlib
from pathlib import Path
from datetime import datetime, timedelta

class FileCache:
    """Simple file-based cache with TTL support."""

    def __init__(self, cache_dir: str = "data/cache"):
        self.cache_dir = Path(cache_dir)
        self.cache_dir.mkdir(parents=True, exist_ok=True)

    def _key_path(self, key: str) -> Path:
        hashed = hashlib.sha256(key.encode()).hexdigest()[:16]
        return self.cache_dir / f"{hashed}.json"

    def get(self, key: str, ttl: timedelta) -> dict | None:
        path = self._key_path(key)
        if not path.exists():
            return None
        data = json.loads(path.read_text())
        cached_at = datetime.fromisoformat(data["cached_at"])
        if datetime.now() - cached_at > ttl:
            return None  # Expired
        return data["value"]

    def set(self, key: str, value: dict) -> None:
        path = self._key_path(key)
        path.write_text(json.dumps({
            "cached_at": datetime.now().isoformat(),
            "value": value
        }, indent=2))

    def get_or_fetch(self, key: str, ttl: timedelta, fetch_fn) -> dict:
        cached = self.get(key, ttl)
        if cached is not None:
            return cached
        value = fetch_fn()
        self.set(key, value)
        return value

Cache Location: Store cache files under data/cache/ within the skill directory. This keeps cache local and avoids polluting system directories.

Graceful Degradation: If the cache file is corrupted or unreadable, log a warning and proceed without cache (fetch fresh data).

6.2 Rate Limiting Strategy

Protect against API rate limit exhaustion with proactive tracking.

Rate Limiter Pattern:

import json
from pathlib import Path
from datetime import datetime, timedelta

class RateLimiter:
    """File-based rate limiter with persistent counter."""

    def __init__(
        self,
        max_requests: int,
        period: timedelta,
        counter_file: str = "data/cache/rate_limit.json"
    ):
        self.max_requests = max_requests
        self.period = period
        self.counter_file = Path(counter_file)
        self.counter_file.parent.mkdir(parents=True, exist_ok=True)

    def _load(self) -> dict:
        if not self.counter_file.exists():
            return {"requests": [], "period_start": datetime.now().isoformat()}
        return json.loads(self.counter_file.read_text())

    def _save(self, data: dict) -> None:
        self.counter_file.write_text(json.dumps(data, indent=2))

    def _prune_old(self, data: dict) -> dict:
        cutoff = (datetime.now() - self.period).isoformat()
        data["requests"] = [r for r in data["requests"] if r > cutoff]
        return data

    def allow_request(self) -> bool:
        data = self._prune_old(self._load())
        count = len(data["requests"])
        if count >= self.max_requests:
            return False
        if count > self.max_requests * 0.9:
            remaining = self.max_requests - count
            print(f"WARNING: Rate limit nearly reached ({count}/{self.max_requests}), {remaining} requests remaining")
        return True

    def record_request(self) -> None:
        data = self._prune_old(self._load())
        data["requests"].append(datetime.now().isoformat())
        self._save(data)

Rate Limit Configuration: Define rate limits in assets/config.json so they can be adjusted without code changes:

{
  "rate_limit": {
    "max_requests_per_day": 1000,
    "warn_threshold_percent": 90
  }
}

6.3 Optimization Techniques

For Small Agents:

  • Keep it simple. A single script with basic caching is sufficient.
  • Avoid premature optimization.

For Medium Agents:

  • File-based caching for API responses.
  • Rate limiter for external APIs.
  • Lazy loading of reference data (only load when a specific analysis is requested).

For Large Agents:

  • All Medium optimizations, plus:
  • Batch API requests where the API supports it.
  • Parallel processing for independent data sources (use concurrent.futures).
  • Tiered caching: in-memory for hot data, file-based for cold data.
  • Progress reporting for long-running operations.

General Rules:

  • Never make the same API call twice in a single execution -- always check cache first.
  • Use exponential backoff for transient API failures (start at 1 second, max 3 retries).
  • Log all API calls with timestamps for debugging rate limit issues.
  • Keep cached data in data/cache/ and provide a way to clear it (--clear-cache flag or a function).

6.4 Error Handling Strategy

Every script must handle errors gracefully:

import sys
from pathlib import Path

def safe_api_call(url: str, params: dict, retries: int = 3) -> dict:
    """Make an API call with retry logic and graceful error handling."""
    import urllib.request
    import urllib.error
    import json
    import time

    for attempt in range(retries):
        try:
            query = "&".join(f"{k}={v}" for k, v in params.items())
            full_url = f"{url}?{query}" if params else url
            req = urllib.request.Request(full_url)
            with urllib.request.urlopen(req, timeout=30) as response:
                return json.loads(response.read().decode())
        except urllib.error.HTTPError as e:
            if e.code == 429:  # Rate limited
                wait = 2 ** attempt
                print(f"Rate limited. Retrying in {wait}s...")
                time.sleep(wait)
            elif e.code >= 500:  # Server error
                wait = 2 ** attempt
                print(f"Server error ({e.code}). Retrying in {wait}s...")
                time.sleep(wait)
            else:
                print(f"HTTP error {e.code}: {e.reason}")
                return {"error": str(e), "code": e.code}
        except urllib.error.URLError as e:
            print(f"Network error: {e.reason}")
            if attempt < retries - 1:
                time.sleep(2 ** attempt)
            else:
                return {"error": f"Network error after {retries} attempts: {e.reason}"}
        except Exception as e:
            return {"error": f"Unexpected error: {str(e)}"}

    return {"error": f"Failed after {retries} retries"}

6.5 SKILL.md Size Management

The SKILL.md body must stay under 500 lines. Use progressive disclosure:

Content Type Where It Goes
Activation triggers, overview, core workflow SKILL.md body (required)
API documentation, endpoint details references/api-guide.md
Analysis methodology, formulas references/methodology.md
Troubleshooting, FAQs references/troubleshooting.md
Domain context, terminology references/domain-context.md
Configuration schema documentation references/config-guide.md

Reference content from SKILL.md using See references/filename.md for details. directives. The agent will load referenced files on demand, reducing initial context consumption.


7. When to Refactor a Growing Skill

Skills evolve. A simple skill that started at 500 lines can grow to 5000+ as the team adds analyses, data sources, and edge case handling. Recognize the signs early and refactor before the skill becomes unmaintainable.

7.1 Signs It's Time to Refactor

Signal What It Means
SKILL.md approaching 500 lines Body is stuffed — move content to references
Total code exceeding 3000 lines Single-domain skill is becoming unwieldy
3+ unrelated workflows emerging The skill is doing too many different jobs
Different people maintaining different parts Ownership boundaries need to be explicit
Users invoking the skill for fundamentally different tasks The skill should be split into focused components
New data sources that don't share the existing pipeline Independent fetch/parse/analyze chains = independent skills

7.2 Refactoring Patterns

Pattern 1: Extract to References (lightest touch)

When the skill body is too long but the code is fine:

Before: SKILL.md at 480 lines with inline methodology docs
After:  SKILL.md at 250 lines, references/methodology.md with the detail

This is not a structural refactor — just progressive disclosure. Do this first.

Pattern 2: Extract Utility Module

When multiple scripts duplicate logic:

Before: fetch.py has cache logic, analyze.py has cache logic
After:  utils/cache.py extracted, both scripts import from it

Pattern 3: Split by Domain (simple → suite)

When the skill covers multiple independent domains:

Before:
  financial-analyzer/
    scripts/
      stock_analysis.py      # 800 lines
      portfolio_tracking.py   # 600 lines
      tax_reporting.py        # 500 lines

After:
  financial-suite/
    skills/
      stock-analyzer/         # Independent skill
      portfolio-tracker/      # Independent skill
      tax-reporter/           # Independent skill
    shared/
      market_data_client.py   # Shared API connection

Pattern 4: Extract Shared Resources

When converting to a suite, identify code that multiple components need:

  1. API client code → shared/api_client.py
  2. Common data models → shared/models.py
  3. Utility functions (date handling, formatting) → shared/utils.py
  4. Configuration → shared/config.json

7.3 Refactoring Decision Process

Is SKILL.md > 400 lines?
  → Yes: Extract to references (Pattern 1)
  → Still growing?
      ↓
Is total code > 3000 lines with 3+ unrelated workflows?
  → Yes: Split into suite (Pattern 3)
  → No, but code is duplicated across scripts?
      → Extract utilities (Pattern 2)
  → No: Keep as large simple skill — not everything needs to be a suite

Critical rule: Do not split prematurely. Three similar scripts in one domain is better than a suite with three trivially small components. Only split when the workflows are genuinely independent — different data sources, different users, different maintenance cadences.

7.4 Refactoring Checklist

  • Identified which pattern applies (1-4)
  • Each new component is independently functional
  • Shared resources extracted to shared/ (not duplicated)
  • All SKILL.md files are <500 lines
  • All component names follow kebab-case naming
  • install.sh updated to handle new structure
  • README.md updated with new structure
  • Validation passes on all components

8. Cross-Component Communication in Suites

When a suite has multiple component skills, they need clear patterns for sharing code, data, and orchestration.

8.1 The shared/ Directory

The shared/ directory contains code that multiple components use. It is not a component skill — it has no SKILL.md and is never invoked directly.

suite-name/
├── shared/
│   ├── api_client.py       # Shared API connection + authentication
│   ├── models.py           # Shared data classes and type definitions
│   ├── utils.py            # Common utilities (date formatting, etc.)
│   └── config.json         # Shared configuration
├── skills/
│   ├── component-a/
│   │   ├── SKILL.md
│   │   └── scripts/
│   │       └── analyze.py  # imports from ../../shared/api_client.py
│   └── component-b/
│       ├── SKILL.md
│       └── scripts/
│           └── report.py   # imports from ../../shared/api_client.py

8.2 Import Patterns

Components import from shared/ using path manipulation:

import sys
from pathlib import Path

# Add shared/ to path
_SUITE_ROOT = Path(__file__).resolve().parent.parent.parent
_SHARED_DIR = _SUITE_ROOT / "shared"
if str(_SHARED_DIR) not in sys.path:
    sys.path.insert(0, str(_SHARED_DIR))

from api_client import SuiteAPIClient
from utils import format_date, parse_currency

Rules:

  • Always use Path(__file__).resolve() for reliable path resolution
  • Add shared/ to sys.path — do not copy files into each component
  • Import specific names, not from shared import *
  • Each component must still work if shared/ provides enhanced functionality but is not strictly required (graceful degradation)

8.3 Orchestration: Suite-Level SKILL.md

The suite-level SKILL.md is the router. When a user's query could match multiple components, the suite SKILL.md tells the agent how to decide:

# /ecommerce-suite — E-commerce Intelligence

You are an e-commerce analytics coordinator. Route user queries
to the right component skill based on intent:

## Routing Logic

| User Intent | Route To | Example Queries |
|-------------|----------|-----------------|
| Revenue, orders, conversion | /sales-monitor | "What were last week's sales?" |
| Segments, cohorts, churn | /customer-analytics | "Show customer retention by cohort" |
| Stock levels, reorder | /inventory-tracker | "Which products need reordering?" |
| Executive summary, dashboard | /executive-reports | "Generate the weekly executive report" |

## Cross-Component Workflows

Some requests require multiple components:

### Full Store Report
When the user asks for a "full report" or "store overview":
1. Invoke /sales-monitor for revenue summary
2. Invoke /customer-analytics for retention metrics
3. Invoke /inventory-tracker for stock alerts
4. Invoke /executive-reports to compile everything into a single report

### Churn Impact Analysis
When the user asks about churn's revenue impact:
1. Invoke /customer-analytics for churn rate and segments
2. Invoke /sales-monitor for revenue by customer segment
3. Combine: revenue at risk = churned segment revenue × churn rate

8.4 Data Flow Between Components

Components do not call each other's functions directly. Instead, they communicate through:

  1. Shared data files: Component A writes to data/sales_summary.json, Component B reads it
  2. Shared API client: Both components use the same shared/api_client.py to fetch data
  3. Agent orchestration: The agent (LLM) reads output from Component A and passes relevant parts to Component B

Anti-patterns to avoid:

  • Component A importing Component B's scripts directly (creates tight coupling)
  • Components writing to each other's directories
  • Circular dependencies between components

8.5 Component Independence Rule

Each component must be independently functional. This means:

  • A component extracted from the suite and installed alone must still work
  • shared/ utilities enhance performance (avoid duplicate API calls, consistent formatting) but are not hard requirements
  • If a component absolutely requires shared/, document this in its README.md
  • The suite-level install.sh must install shared/ alongside all components

9. Versioning Strategy

9.1 Semver for Skills

Skills follow Semantic Versioning:

Change Type Version Bump Examples
Patch (x.y.Z) Bug fixes, typo corrections, minor doc improvements Fix API timeout handling, correct calculation formula
Minor (x.Y.0) New analyses, new data sources, new output formats Add trend analysis, support CSV export, add new API endpoint
Major (X.0.0) Breaking changes to inputs, outputs, or invocation Change script arguments, rename skill, restructure output format

9.2 What Counts as Breaking

A change is breaking if existing users of the skill would get different behavior or errors:

Breaking Not Breaking
Changing script CLI arguments Adding new optional arguments
Changing output JSON structure Adding new fields to output
Removing an analysis function Adding new analysis functions
Renaming the skill Updating the description keywords
Changing required environment variables Adding optional environment variables

9.3 Suite Versioning

Suite versions are independent of component versions:

ecommerce-suite/        version: 2.0.0  (added new component)
├── sales-monitor/      version: 1.3.0  (3 minor updates since suite v1)
├── customer-analytics/  version: 1.1.0  (1 minor update)
├── inventory-tracker/   version: 2.0.0  (breaking change in its own output)
└── executive-reports/   version: 1.0.0  (unchanged)

Suite version bump rules:

Change Suite Version Bump
Bug fix in one component No suite bump (component patch only)
New capability in one component No suite bump (component minor only)
Breaking change in one component Suite minor bump (warn users)
Add new component to suite Suite minor bump
Remove component from suite Suite major bump
Restructure shared/ Suite major bump

9.4 Version in Practice

The version lives in SKILL.md frontmatter:

metadata:
  version: 1.2.0

When publishing to the registry, skill_registry.py reads this version. Publishing the same name+version is rejected unless --force is used.

When to create a new skill vs. version an existing one:

Situation Action
Same domain, improved implementation Version bump (minor or major)
Same domain, fundamentally different approach New skill (e.g., stock-analyzer-v2)
Different domain entirely New skill
Extending to cover adjacent domain If tightly coupled: version bump. If independent: new skill or convert to suite

10. Architecture Checklist

Use this checklist before proceeding to implementation (Phase 5):

Decision

  • Determined Simple Skill vs Complex Suite
  • Justified the decision based on workflow count, code size, and domain scope
  • If suite: identified shared resources and component boundaries
  • If suite: designed orchestration logic (routing, cross-component workflows)

Naming

  • Name is 1-64 characters, kebab-case
  • Name matches the parent directory
  • No -cskill suffix
  • Name is descriptive and includes the primary domain
  • If suite: all component names are unique and follow kebab-case

Structure

  • Directory layout matches the chosen sizing pattern (Small/Medium/Large)
  • SKILL.md planned at <500 lines
  • Scripts have clear separation of concerns
  • References planned for detailed content
  • install.sh included
  • README.md planned with multi-platform install instructions
  • No marketplace.json for Simple Skills
  • If Complex Suite with marketplace.json, only official fields used
  • If suite: shared/ directory planned with import patterns documented
  • If suite: each component is independently functional

Performance

  • Cache strategy defined (what to cache, TTL for each data type)
  • Rate limiting planned for external APIs
  • Error handling approach defined (retries, backoff, fallbacks)
  • SKILL.md size managed via progressive disclosure to references/

Dependencies

  • Dependency strategy decided (stdlib-only vs. third-party)
  • requirements.txt planned if third-party packages needed
  • No unnecessary heavy dependencies

Versioning

  • Initial version set (1.0.0)
  • Version bump rules understood (patch/minor/major)
  • If suite: component versions independent of suite version

Documentation

  • Architecture decisions documented
  • Script responsibilities defined (input, output, line count estimate)
  • Reference files planned (topic, estimated word count)
  • Asset files planned (config structure, metadata)