🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

cc-codeconductor

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cc-codeconductor - npm Package Compare versions

Comparing version
0.2.9
to
0.2.10
+354
presets/agy/AGENTS.md
<!-- CODECONDUCTOR:BEGIN managed -->
# CodeConductor — Antigravity CLI (agy) Preset
This file configures CodeConductor for **Google Antigravity CLI (agy)** and Antigravity 2.0. Place it at `.agents/AGENTS.md` relative to your project root.
---
## Workflow Contract
Do not touch a single file until you understand the task contract.
Required flow:
1. Receive or validate a **Task Card** (structured request with context, scope, constraints, and acceptance criteria)
2. Classify risk: `low` / `medium` / `high`
3. Route to the correct **Conductor Agent** based on task type and risk
4. Implement **minimal diff** — only what the task requires
5. Run tests and verify behavior
6. Produce a **Deliverable** that meets the Scorecard criteria
7. Wait for human review before merging
Skipping any step is not an optimization. It is a defect.
---
## Trigger Commands
Antigravity CLI loads custom slash commands from `.agents/workflows/*.md`. The following commands are registered:
| Slash Command | Workflow Description |
| ---------------- | ------------------------------------------------------------------ |
| `/cc-feature` | Runs the full feature design, implementation, and review workflow |
| `/cc-fix` | Runs the bug fix verification and repair workflow |
| `/cc-refactor` | Runs the code refactoring and test safety workflow |
| `/cc-review` | Runs a structured, multi-perspective code review and audit |
| `/cc-test-plan` | Generates a structured test plan for a given scope |
| `/cc-tdd-cycle` | Runs a Test-Driven Development (TDD) cycle |
| `/cc-api-contract`| Handles API contract modification and validation |
| `/cc-db-migration`| Coordinates database schema migrations safely |
| `/cc-pagespeed` | Performs a web performance and Core Web Vitals audit |
---
## Routing Policy
### Risk Classification
| Signal | Risk Level |
| ----------------------------------------- | ---------- |
| New behavior, no existing tests | medium |
| Changes to public API or contracts | high |
| Database migration | high |
| Security, auth, or payment paths | high |
| Internal refactor with full test coverage | low |
| Documentation only | low |
| Bug fix in isolated component | low–medium |
| New feature (no existing path) | high |
When multiple signals apply, take the highest risk level. Do not average.
### Agent Routing Table
| Task Type | Risk | Route |
| -------------------- | ----------- | --------------------------------------------------- |
| New feature design | any | `architect` → `implementer` |
| Bug fix | low | `implementer` |
| Bug fix | medium–high | `task-coach` → `implementer` → `tester` |
| Refactor | low | `implementer` |
| Refactor | medium–high | `architect` → `implementer` → `reviewer` |
| API change | any | `architect` → `implementer` → `reviewer` |
| Database migration | any | `architect` → `implementer` → `tester` → `reviewer` |
| Test coverage | any | `tester` |
| Documentation update | any | `docs` |
| Codebase exploration | any | `repo-explorer` |
| Code review | any | `reviewer` |
---
## Conductor Agents
---
### orchestrator
**Role:** Coordinates the workflow. Receives the Task Card, classifies risk, selects the route, delegates to agents, and monitors the deliverable.
**Use when:** Task requires multiple agents, risk is unclear, or the user needs a complete plan before implementation.
**Permissions:**
- read: `allow`
- edit: `ask`
- bash: `ask` (git status, git diff, git log only)
- network: `deny`
**Does not:** Write code. Execute tests. Push to any branch.
**Model:** `{{MODEL_GEMINI}}`
**Responsibilities:**
1. Validate the Task Card before doing anything else.
2. Classify the risk level using the table above.
3. Select and document the agent route.
4. Surface blockers rather than working around them.
5. Declare completion only when all Deliverables are produced and verified.
**Task Card validation — required fields before routing:**
- Title (short description, max 80 chars)
- Type (`feature`, `fix`, `refactor`, `review`, `docs`, `test`)
- Risk (`low`, `medium`, `high`)
- Scope (named files, modules, or components)
- Context (current behavior and problem/opportunity)
- Context scope (`isolated`, `continuation`, `full`)
- Acceptance criteria (measurable, verifiable conditions)
If any required field is missing, route to `task-coach` to clarify.
**Routing documentation format:**
```markdown
## Routing Decision
Task: [title] Type: [type] Risk: [low | medium | high] Route: [agent1] → [agent2] → ...
Justification: [one sentence explaining why this route was selected]
High-risk checkpoint: [yes | no — if yes, describe what triggers a stop]
```
---
### task-coach
**Role:** Transforms vague requests into complete, routable Task Cards by asking targeted clarifying questions.
**Use when:** Request lacks acceptance criteria, scope is ambiguous, or risk cannot be classified without more context.
**Permissions:**
- read: `allow`
- edit: `deny`
- bash: `deny`
- network: `deny`
**Model:** `{{MODEL_GEMINI}}`
**Intake process:**
1. Read the entire request before asking anything.
2. Identify missing or ambiguous fields.
3. Ask one focused question at a time.
4. Wait for the answer.
5. Produce the Task Card.
**Task Card format:**
```markdown
## Task Card
**Objective**: [one sentence]
**Acceptance Criteria**:
1. [verifiable condition]
2. [verifiable condition]
**Scope**:
- In: [what is included]
- Out: [what is explicitly excluded]
**Risk Level**: [low | medium | high] — [one-sentence justification]
**Context**:
- Files: [list relevant files or "unknown"]
- Services: [list relevant services or "none"]
- Constraints: [constraints or "none"]
```
---
### repo-explorer
**Role:** Maps the repository structure. Identifies conventions. Locates relevant files. Estimates impact radius.
**Use when:** Starting a new task without context, investigating an unfamiliar module, or identifying impact radius.
**Permissions:**
- read: `allow`
- edit: `deny`
- bash: `allow` (git log, git diff, git status)
- network: `deny`
**Model:** `{{MODEL_GEMINI}}`
**Repo Map format:**
```markdown
## Repo Map
**Task**: [objective from Task Card]
### Structure
[directory tree — relevant portions only]
### Conventions
| Concern | Convention |
| ------- | ---------- |
| Naming | ... |
| Testing | ... |
### Relevant Files
- [path/to/file] — [relevance]
```
---
### architect
**Role:** Designs the technical approach. Produces ADRs, module boundaries, and API contracts.
**Use when:** New feature, refactor with structural impact, API changes, or database changes.
**Permissions:**
- read: `allow`
- edit: `ask` (docs and ADRs only)
- bash: `deny`
- network: `deny`
**Model:** `{{MODEL_GEMINI}}`
**Technical Plan format:**
```markdown
## Technical Plan
**Task**: [objective]
**Approach**: [chosen strategy and why]
**Tradeoffs**:
- Chosen: [approach] because [reason]
- Rejected: [alternative] because [reason]
**Files Affected**:
- [path/to/file] — [what changes]
**Risks**:
- [risk] — mitigation: [how to handle]
**Open Questions**:
- [questions for human input]
```
---
### implementer
**Role:** Executes the Technical Plan. Writes code following accepted designs.
**Use when:** Task has an accepted plan, files to modify are clear, and acceptance criteria exist.
**Permissions:**
- read: `allow`
- edit: `ask`
- bash: `allow` (build, test, and lint commands only)
- network: `deny`
**Model:** `{{MODEL_GEMINI}}`
**Pre-implementation checklist:**
1. Create a Git Worktree: `git worktree add ../<branch>-session <branch>`
2. Read the Technical Plan completely.
3. Read the target files.
4. Verify tests pass before starting.
**Implementation Summary format:**
```markdown
## Implementation Summary
**Task**: [objective] **Status**: complete | blocked
**Worktree**: [path to worktree]
**Changes Made**:
- [path/to/file] — [summary of change]
**Tests**:
- Runner: [npm test | pytest | ...]
- Result: [passed | failed]
```
---
### tester
**Role:** Generates unit, integration, and contract tests. Verifies behavior against acceptance criteria.
**Use when:** New behavior is introduced, bugs are fixed, or refactoring carries behavioral risk.
**Permissions:**
- read: `allow`
- edit: `ask` (test files only)
- bash: `allow` (test commands only)
- network: `deny`
**Model:** `{{MODEL_GEMINI}}`
**Coverage Summary format:**
```markdown
## Coverage Summary
**Task**: [objective]
**Test Files Added/Modified**:
- [path/to/test] — [cases covered]
**Test Run Results**:
- Passed: [count]
- Failed: [count]
```
---
### reviewer
**Role:** Reviews diffs for correctness, architecture alignment, security, and technical debt.
**Use when:** Before committing, before opening a PR, or after agent-generated changes.
**Permissions:**
- read: `allow`
- edit: `deny`
- bash: `allow` (git diff, git status, test commands)
- network: `deny`
**Model:** `{{MODEL_GEMINI}}`
**Review Report format:**
```markdown
## Review Report
**Task**: [objective]
### Findings
- **CRITICAL**: [must be fixed before merge]
- **WARNING**: [resolve before merge]
- **SUGGESTION**: [optional enhancement]
```
---
### docs
**Role:** Updates README, OpenAPI specs, ADRs, and changelogs.
**Use when:** Public API changed, new module introduced, or behavior documented incorrectly.
**Permissions:**
- read: `allow`
- edit: `ask` (docs and markdown only)
- bash: `deny`
- network: `deny`
**Model:** `{{MODEL_GEMINI}}`
<!-- CODECONDUCTOR:END managed -->
{
"code-formatter": {
"enabled": true,
"PostToolUse": [
{
"matcher": "write_to_file|replace_file_content|multi_replace_file_content",
"hooks": [
{
"type": "command",
"command": "if [ -f \"./.agents/scripts/post-tool.sh\" ]; then bash ./.agents/scripts/post-tool.sh; else bash \"$HOME/.gemini/config/scripts/post-tool.sh\"; fi"
}
]
}
]
},
"safety-gate": {
"enabled": true,
"PreToolUse": [
{
"matcher": "run_command|write_to_file|replace_file_content|multi_replace_file_content|view_file",
"hooks": [
{
"type": "command",
"command": "if [ -f \"./.agents/scripts/pre-tool.sh\" ]; then bash ./.agents/scripts/pre-tool.sh; else bash \"$HOME/.gemini/config/scripts/pre-tool.sh\"; fi"
}
]
}
]
}
}
{
"mcpServers": {}
}
# Antigravity CLI (agy) Preset for CodeConductor
This preset configures CodeConductor for **Google Antigravity CLI (agy)** and Antigravity 2.0.
## Structure
When installed, this preset writes files into your project's workspace customizations root:
- **`.agents/AGENTS.md`**: Core agent contracts, routing policy, and workflow instructions.
- **`.agents/rules/`**: Target rules and style guidelines (e.g., commit messages, knowledge graphs).
- **`.agents/workflows/`**: Custom slash commands representing CodeConductor workflows (e.g., `/cc-feature`, `/cc-fix`).
- **`.agents/skills/`**: Domain-specific skills (e.g., Spring Boot, Django, Next.js).
---
## Orchestrator Agent Workflow
Antigravity CLI automatically parses `.agents/AGENTS.md` and registered workflows under `.agents/workflows/`.
To run any CodeConductor workflow:
1. Start the Antigravity CLI:
```bash
agy
```
2. Run one of the custom slash commands:
```text
/cc-feature "Describe the new feature to build"
/cc-fix "Describe the bug and where it is"
/cc-refactor "Describe the refactoring scope"
```
---
## Configuration Settings (`settings.json`)
To configure permissions, models, and execution modes for the Antigravity CLI, update your global settings at `~/.gemini/antigravity-cli/settings.json` or project-scoped settings.
Recommended settings:
```json
{
"model": "gemini-3.5-pro",
"toolPermission": "request-review",
"enableTerminalSandbox": true,
"allowNonWorkspaceAccess": false
}
```
---
trigger: always_on
description: Consult the graphify knowledge graph at graphify-out/ for codebase and architecture questions.
---
## graphify
This project has a graphify knowledge graph at graphify-out/.
Rules:
- For codebase or architecture questions, when `graphify-out/graph.json` exists, first run `graphify query "<question>"` (CLI) or `query_graph` (MCP). Use `graphify path "<A>" "<B>"` / `shortest_path` for relationships and `graphify explain "<concept>"` / `get_node` for focused concepts. These return a scoped subgraph, usually much smaller than `GRAPH_REPORT.md` or raw grep output.
- If graphify-out/wiki/index.md exists, navigate it instead of reading raw files
- Read graphify-out/GRAPH_REPORT.md only for broad architecture review or when query/path/explain do not surface enough context
- After modifying code files in this session, run `graphify update .` to keep the graph current (AST-only, no API cost)
#!/bin/bash
# Read stdin JSON payload
JSON_INPUT=$(cat)
TOOL_NAME=$(echo "$JSON_INPUT" | jq -r '.toolName')
if [[ "$TOOL_NAME" == "write_to_file" || "$TOOL_NAME" == "replace_file_content" || "$TOOL_NAME" == "multi_replace_file_content" ]]; then
FILE_PATH=$(echo "$JSON_INPUT" | jq -r '.arguments.TargetFile')
if [ -f "$FILE_PATH" ]; then
# Run Prettier
if echo "$FILE_PATH" | grep -qE '\.(ts|tsx|js|jsx|mjs|cjs|json|jsonc|md|mdx|css|scss|html|astro|yaml|yml)$'; then
npx --no-install prettier --write "$FILE_PATH" 2>/dev/null || true
fi
# Run ESLint
if echo "$FILE_PATH" | grep -qE '\.(ts|tsx|js|jsx|mjs|cjs)$'; then
npx --no-install eslint --fix "$FILE_PATH" 2>/dev/null || true
fi
# Run Ruff (Python)
if echo "$FILE_PATH" | grep -qE '\.py$'; then
ruff format "$FILE_PATH" 2>/dev/null && ruff check --fix "$FILE_PATH" 2>/dev/null || true
fi
fi
fi
# Return an empty JSON object to stdout
echo "{}"
#!/bin/bash
# Read stdin JSON payload
JSON_INPUT=$(cat)
TOOL_NAME=$(echo "$JSON_INPUT" | jq -r '.toolName')
# Check paths for write/edit/read operations
TARGET_PATH=""
if [[ "$TOOL_NAME" == "write_to_file" || "$TOOL_NAME" == "replace_file_content" || "$TOOL_NAME" == "multi_replace_file_content" ]]; then
TARGET_PATH=$(echo "$JSON_INPUT" | jq -r '.arguments.TargetFile')
elif [[ "$TOOL_NAME" == "view_file" ]]; then
TARGET_PATH=$(echo "$JSON_INPUT" | jq -r '.arguments.AbsolutePath')
fi
if [[ ! -z "$TARGET_PATH" ]]; then
if echo "$TARGET_PATH" | grep -qE '(\.env|secrets/|/\.ssh/|/\.aws/|/\.kube/)'; then
echo '{"action": "deny", "error": "Blocked: Attempt to access sensitive path"}'
exit 0
fi
fi
if [[ "$TOOL_NAME" == "run_command" ]]; then
COMMAND_LINE=$(echo "$JSON_INPUT" | jq -r '.arguments.CommandLine')
# 1. Deny patterns
if echo "$COMMAND_LINE" | grep -qE '(\.env|secrets/|id_rsa|\\.pem|\\.key)\\b' && echo "$COMMAND_LINE" | grep -qE '(cat|less|more|head|tail|cp |mv |scp )'; then
echo '{"action": "deny", "error": "Blocked: Attempt to read sensitive files"}'
exit 0
fi
if echo "$COMMAND_LINE" | grep -qE '^rm\s+-rf\s+\*' || \
echo "$COMMAND_LINE" | grep -qE '^sudo\s+' || \
echo "$COMMAND_LINE" | grep -qE '^git\s+push\s+.*--force' || \
echo "$COMMAND_LINE" | grep -qE '^git\s+push\s+.*-f' || \
echo "$COMMAND_LINE" | grep -qE '^git\s+rebase\s+' || \
echo "$COMMAND_LINE" | grep -qE '^git\s+reset\s+--hard\s+' || \
echo "$COMMAND_LINE" | grep -qE 'curl\s+.*\s*\|\s*(sh|bash)' || \
echo "$COMMAND_LINE" | grep -qE 'wget\s+.*\s*\|\s*(sh|bash)' || \
echo "$COMMAND_LINE" | grep -qE '^chmod\s+777\s+' || \
echo "$COMMAND_LINE" | grep -qE '^dd\s+' || \
echo "$COMMAND_LINE" | grep -qE '^mkfs\s+'; then
echo '{"action": "deny", "error": "Blocked: Command violated security policy"}'
exit 0
fi
# 2. Ask patterns
if echo "$COMMAND_LINE" | grep -qE '^git\s+commit\s*' || \
echo "$COMMAND_LINE" | grep -qE '^git\s+checkout\s*' || \
echo "$COMMAND_LINE" | grep -qE '^git\s+switch\s*' || \
echo "$COMMAND_LINE" | grep -qE '^docker\s+compose\s*'; then
echo '{"action": "ask"}'
exit 0
fi
fi
# Default: allow
echo '{"action": "allow"}'
{
"model": "gemini-3.5-pro",
"toolPermission": "request-review",
"enableTerminalSandbox": true,
"allowNonWorkspaceAccess": false,
"verbosity": "low",
"alwaysThinkingEnabled": true
}
---
name: cc-api-contract
description:
Run the API contract workflow for request/response shape changes,
compatibility constraints, contract tests, documentation, and review.
---
# API Contract Workflow
API contract request: $ARGUMENTS
## Step 1 — Task Card validation (task-coach)
Invoke `task-coach` with the request above.
The Task Card must classify the task as `feature` or `refactor` with `high`
risk unless the human provides a narrower validated risk. It must include:
- affected endpoint, command, or public interface
- request and response examples
- backward compatibility and versioning impact
- consumers that must remain compatible
- contract tests and documentation acceptance criteria
**STOP here. Show the Task Card and wait for human confirmation.**
---
## Step 2 — Technical Plan (architect)
Invoke `architect` with the approved Task Card.
architect must define the API contract, compatibility strategy, validation
rules, docs/OpenAPI impact, and migration path for consumers.
**STOP here. Show the Technical Plan and wait for explicit human approval.**
---
## Step 3 — Implementation (implementer)
Invoke `implementer` with the approved plan.
implementer must apply the minimal diff, preserve compatible behavior unless a
breaking change was explicitly approved, and update only the files named in the
plan.
---
## Step 4 — Contract tests (tester)
Invoke `tester`.
tester must add or update contract tests covering request shape, response shape,
status/error behavior, and backward compatibility constraints.
---
## Step 5 — Review (reviewer)
Invoke `reviewer`.
reviewer must block on missing contract tests, undocumented breaking changes,
or docs/OpenAPI drift.
---
## Completion
Report the final Task Card, Technical Plan, implementation summary, test report,
review report, docs updated, compatibility impact, and residual risks.
---
name: cc-db-migration
description:
Run the database migration workflow for schema/data changes, operational
sequencing, tests, and review.
---
# Database Migration Workflow
Migration request: $ARGUMENTS
## Step 1 — Task Card validation (task-coach)
Invoke `task-coach` with the request above.
The Task Card must classify the task as `high` risk and include:
- tables, collections, models, or migration files in scope
- data backfill or data cleanup requirements
- deployment ordering and compatibility window
- rollback or forward-fix strategy
- lock risk, data risk, and verification commands
**STOP here. Show the Task Card and wait for human confirmation.**
---
## Step 2 — Migration Plan (architect)
Invoke `architect` with the approved Task Card.
architect must define the schema/data plan, operational sequencing,
compatibility strategy, rollback/forward-fix notes, and test approach.
**STOP here. Show the Technical Plan and wait for explicit human approval.**
---
## Step 3 — Implementation (implementer)
Invoke `implementer` with the approved plan.
implementer must keep model and migration changes together, avoid unrelated
refactors, and preserve the deployment order specified by architect.
---
## Step 4 — Migration tests (tester)
Invoke `tester`.
tester must cover migration-sensitive behavior where the stack supports it,
including happy path, existing-data edge cases, and rollback/forward-fix notes
when automated rollback tests are not practical.
---
## Step 5 — Review (reviewer)
Invoke `reviewer`.
reviewer must block on missing migration tests, missing data-risk notes,
undocumented deployment sequencing, or model/migration drift.
---
## Completion
Report migration files changed, model files changed, tests run, lock risk, data
risk, operational sequencing, rollback/forward-fix notes, and residual risk.
---
name: cc-feature
description:
Run the full feature workflow — task validation, technical design,
implementation, testing, review, and documentation.
---
# Feature Workflow
Feature request: $ARGUMENTS
## Step 1 — Task Card validation (task-coach)
Invoke `task-coach` with the feature description above.
task-coach must produce a complete Task Card before any other agent runs. The
Task Card is ready when it contains: title, type, risk classification, scope,
context, acceptance criteria, and constraints.
If any field is missing or ambiguous, task-coach must ask one clarifying
question at a time and wait for the answer. Do not proceed with an incomplete
Task Card.
**STOP here. Show the completed Task Card and wait for human confirmation before
continuing.**
---
## Step 2 — Technical Plan (architect)
Invoke `architect` with the validated Task Card from Step 1.
architect must produce a Technical Plan that covers:
- Chosen approach and rationale
- Affected files and modules
- Data model changes (if any)
- API contract changes (if any)
- Identified risks and mitigations
- Open questions that require a human decision
**STOP here. Show the Technical Plan and wait for explicit human approval. Do
not invoke implementer until the plan is approved.**
---
## Step 3 — Implementation (implementer)
Invoke `implementer` with the approved Technical Plan and the Task Card.
Implementer creates a Git Worktree before touching any file; all edits happen inside it.
implementer must:
1. Read the Technical Plan before touching any file
2. Apply the minimal diff — only what the plan specifies
3. Run the project test suite after implementation
4. Produce an Implementation Summary: what changed, which files, how to verify
locally
---
## Step 4 — Test coverage (tester)
Invoke `tester` with the Implementation Summary and the Task Card.
tester must:
1. Write or extend tests to cover the new behavior
2. Ensure all acceptance criteria from the Task Card have at least one test
3. Run the full test suite and confirm it passes
4. Produce a Coverage Summary: test files added or modified, cases covered
---
## Step 5 — Code review (reviewer)
Invoke `reviewer` with the complete diff and the Task Card.
reviewer must produce a Review Report with findings categorized as:
- CRITICAL — must be fixed before merge
- WARNING — must be resolved before merge
- SUGGESTION — optional improvement
If any CRITICAL findings exist, **STOP and report them**. Do not proceed until
they are resolved and re-reviewed.
---
## Step 6 — Documentation (docs)
Invoke `docs` only if any of the following changed:
- A public API endpoint was added or modified
- A public interface or module was introduced
- Behavior visible to end users changed
docs must update: README (if applicable), OpenAPI spec (if applicable),
CHANGELOG (always), ADR (if an architectural decision was made).
---
## Completion
Report the following to the human:
- Task Card (final)
- Technical Plan (approved)
- Implementation Summary
- Coverage Summary
- Review Report (all findings resolved)
- List of documentation files updated (if any)
The feature is complete only when: all tests pass, no CRITICAL review findings
remain, and documentation reflects the implemented behavior.
---
name: cc-fix
description:
Run the bug fix workflow — risk-based routing through task validation,
implementation, testing, and optional review.
---
# Bug Fix Workflow
Bug description: $ARGUMENTS
Provide the following information in $ARGUMENTS:
- What is the incorrect behavior (actual)
- What is the expected behavior
- Steps to reproduce
- Environment or version where the bug occurs (if known)
- Any relevant error messages or stack traces
---
## Step 1 — Task Card validation (task-coach)
Invoke `task-coach` with the bug description above.
task-coach must produce a Task Card that includes:
- A clear statement of actual vs. expected behavior
- Reproduction steps (or a note that they are unknown)
- Risk classification: `low`, `medium`, or `high`
- Scope: which files or modules are likely affected
If reproduction steps are missing, task-coach must ask for them before
classifying risk. A bug without a reproduction path cannot be classified
reliably.
**STOP here. Show the Task Card and wait for human confirmation.**
---
## Step 2 — Route by risk
Read the risk field from the Task Card and follow the corresponding route.
### Low-risk route
Applies when: the bug is isolated to a single component, existing tests cover
the affected code, and no public API or shared state is involved.
Route: `task-coach` → `implementer` → `tester`
Proceed directly to Step 3a.
### Medium or high-risk route
Applies when: the bug touches shared state, a public API, auth or payment paths,
database writes, or the root cause is not yet understood.
Route: `task-coach` → `architect` → `implementer` → `tester` → `reviewer`
Invoke `architect` before implementation. architect must:
- Identify the root cause (or document that it is unknown)
- Define the fix approach and affected files
- Flag any regression risk to adjacent components
- Produce a Technical Plan
**STOP here if high-risk. Show the Technical Plan and wait for human approval
before continuing.**
---
## Step 3a — Implementation, low-risk (implementer)
Invoke `implementer` with the Task Card.
Implementer creates a Git Worktree before touching any file; all edits happen inside it.
implementer must:
1. Locate the defect using the reproduction steps
2. Apply the minimal fix — no unrelated changes
3. Run the test suite
4. Produce an Implementation Summary: root cause, fix applied, files changed
---
## Step 3b — Implementation, medium/high-risk (implementer)
Invoke `implementer` with the approved Technical Plan and the Task Card.
Implementer creates a Git Worktree before touching any file; all edits happen inside it.
implementer must follow the plan exactly. Any deviation requires a new Technical
Plan approval. After implementation, run the full test suite.
---
## Step 4 — Regression tests (tester)
Invoke `tester` for all risk levels.
tester must:
1. Write a regression test that reproduces the original bug (fails before the
fix, passes after)
2. Verify that existing tests still pass
3. Produce a Coverage Summary: test added, case covered
---
## Step 5 — Review (reviewer) — medium/high-risk only
Invoke `reviewer` with the diff and Task Card.
reviewer produces a Review Report with CRITICAL / WARNING / SUGGESTION findings.
If any CRITICAL findings exist, **STOP**. Do not close the fix until they are
resolved.
---
## Completion
Report: Task Card, Implementation Summary, regression test added, Review Report
(if applicable). The fix is complete only when: the regression test passes, the
full suite passes, and no CRITICAL review findings remain.
---
name: cc-pagespeed
description: >-
Run the PageSpeed performance audit — 80/20 analysis of Core Web Vitals using
the PageSpeed Insights API.
---
# PageSpeed Performance Audit
Audit URL: $ARGUMENTS
---
## Step 1 — Pre-flight (pagespeed-perf skill)
Invoke `pagespeed-perf` skill.
Read `PAGESPEED_API_KEY` from the environment. Compute the output filename:
`{YYYY-MM-DD}_pagespeed-{hostname}-claude.md`.
Log whether the API key was found. Proceed regardless — lab data is available
without a key, but CrUX field data requires it.
---
## Step 2 — Collect
Call the PageSpeed Insights API for the URL provided above.
- Strategy: `both` (mobile + desktop) unless the user specified otherwise.
- If Bun is available, use `~/.claude/skills/pagespeed-perf/scripts/run.ts`.
- If Bun is unavailable, call PSI directly via WebFetch and fetch the HTML
source for manual resource-hint analysis.
---
## Step 3 — Analyze
Extract from the PSI response:
- Core Web Vitals: LCP, INP, CLS, FCP, TBT, TTFB
- LCP element (type, selector, HTML snippet)
- Third-party scripts ordered by blocking time
- Render-blocking resources
- Unused JavaScript and CSS (savings in bytes and ms)
From the HTML source:
- Resource hints (`<link rel="preload|preconnect|prefetch">`)
- Images: lazy loading, `fetchpriority`, format, dimensions
- Fonts: `font-display`, preloaded subsets
- Blocking scripts in `<head>` (no `async`/`defer`)
---
## Step 4 — Prioritize
Score each identified optimization using the 80/20 matrix:
`Score = Impact × Ease` (each 1–5, max 25).
Order findings by descending score. Mark optimizations with Score ≥ 20 as
**Critical 20%**.
---
## Step 5 — Report
Write the full performance report to
`{YYYY-MM-DD}_pagespeed-{hostname}-claude.md` in the current directory.
Required sections:
1. Resumen Ejecutivo (2–3 paragraphs)
2. Métricas Actuales (lab vs field table)
3. Recursos con Mayor Impacto
4. Plan de Acción Priorizado (80/20 table)
5. Solución Técnica Detallada (per finding: problem, evidence, code, expected gain)
6. Quick Wins / High Impact Changes / Roadmap
End every report with:
```
---
*Informe generado el {YYYY-MM-DD} · Herramienta: Claude Code + pagespeed-perf skill*
*API Key usada: {Sí / No} · Datos CrUX: {Disponibles / No disponibles}*
```
---
## Requirements
**`PAGESPEED_API_KEY`** — Optional but strongly recommended.
- With key: real CrUX field data + 25,000 requests/day quota.
- Without key: lab data only (Lighthouse); shared rate limit applies.
Set in your shell:
```powershell
$env:PAGESPEED_API_KEY = "your-api-key" # Windows PowerShell
export PAGESPEED_API_KEY="your-api-key" # macOS / Linux
```
Get a free key: <https://developers.google.com/speed/docs/insights/v5/get-started>
---
name: cc-refactor
description:
Run the refactor workflow — mandatory architectural justification, test
verification, risk-based implementation, and scope enforcement.
---
# Refactor Workflow
Refactor description: $ARGUMENTS
Describe what you want to refactor and why. Include:
- The current structure or pattern being changed
- The target structure or pattern
- The motivation (performance, readability, architectural alignment, etc.)
- Known risk areas or dependencies
---
## Prerequisite — Test coverage check
Before any agent is invoked, verify that the code being refactored has adequate
test coverage.
A refactor without tests is not a refactor — it is a rewrite with unknown
behavioral consequences.
If coverage is insufficient:
1. **STOP**. Report the coverage gap to the human.
2. Suggest invoking `/cc:test-plan` first to establish coverage.
3. Do not proceed with the refactor until coverage is confirmed.
---
## Step 1 — Architectural justification (architect)
Always invoke `architect` first, regardless of risk level. A refactor without a
written justification is scope creep in disguise.
architect must produce a Refactor Plan that includes:
- Statement of the problem with the current structure
- Proposed target structure and rationale
- Affected files and module boundaries
- Risk level: `low`, `medium`, or `high`
- Behavioral invariants that must not change
- Open questions requiring human input
**Scope creep warning:** If during planning architect identifies unrelated
improvements, they must be listed separately as "Out of scope." They are not
part of this refactor.
**STOP here. Show the Refactor Plan and wait for explicit human approval. Do not
proceed without written approval of the plan.**
---
## Step 2 — Route by risk
Read the risk field from the Refactor Plan and follow the corresponding route.
### Low-risk route
Applies when: the refactor is purely internal, no public interfaces change, full
test coverage exists for the affected code, and behavioral impact is isolated to
the refactored module.
Route: `architect` (done) → `implementer`
Proceed to Step 3a.
### Medium or high-risk route
Applies when: module boundaries change, shared interfaces are affected,
performance characteristics may change, or the refactor touches more than two
files with behavioral impact.
Route: `architect` (done) → `implementer` → `reviewer`
Proceed to Step 3b.
---
## Step 3a — Implementation, low-risk (implementer)
Invoke `implementer` with the approved Refactor Plan.
Implementer creates a Git Worktree before touching any file; all edits happen inside it.
implementer must:
1. Read the Refactor Plan before opening any file
2. Apply only the changes specified in the plan
3. Run the full test suite before and after — both runs must pass
4. Produce an Implementation Summary: what changed, what did not change, test
results before and after
Any deviation from the plan — including "obvious improvements" encountered
during implementation — must be flagged and held for a separate task.
---
## Step 3b — Implementation, medium/high-risk (implementer)
Same rules as 3a. Additionally:
- implementer must document any unexpected complexity discovered during
implementation and pause if the complexity changes the risk assessment
- If new risks are found, **STOP** and report to the human before continuing
---
## Step 4 — Test suite verification
For all risk levels, confirm:
- All tests that existed before the refactor still pass
- No test was deleted or commented out to make the suite pass
- Behavior documented in the Task Card remains unchanged
If any test fails that was passing before, the refactor has introduced a
regression. **STOP and report.**
---
## Step 5 — Code review (reviewer) — medium/high-risk only
Invoke `reviewer` with the diff and Refactor Plan.
reviewer must verify:
- The implementation matches the approved plan
- No behavior was changed beyond the plan's scope
- No unrelated files were modified
Review Report must include CRITICAL / WARNING / SUGGESTION findings. CRITICAL
findings block completion.
---
## Completion
Report: Refactor Plan (approved), Implementation Summary, test results before
and after, Review Report (if applicable).
The refactor is complete only when: all pre-existing tests still pass, the
implementation matches the approved plan exactly, and no CRITICAL review
findings remain.
---
name: cc-review
description:
Run a structured code review — produces a Review Report with CRITICAL,
WARNING, and SUGGESTION findings; CRITICAL findings block merge.
---
# Code Review Workflow
Review target: $ARGUMENTS
Specify what to review. Accepted formats:
- A branch name: `feature/my-branch`
- A file or set of files: `src/api/UserController.kt`
- A pull request reference: `PR #42`
- Empty — defaults to the current working diff (`git diff`)
---
## Step 1 — Diff collection
Before invoking `reviewer`, collect the diff for the specified target.
If $ARGUMENTS is empty or not provided:
- Use `git diff HEAD` as the review target
If $ARGUMENTS is a branch name:
- Use `git diff main...$ARGUMENTS` (or `develop` if main is not the base)
If $ARGUMENTS is a PR reference:
- Retrieve the PR diff and the PR description for context
If $ARGUMENTS is a file path:
- Use `git diff HEAD -- $ARGUMENTS`
Show the diff summary (files changed, lines added/removed) before invoking
reviewer.
---
## Step 2 — Code review (reviewer)
Invoke `reviewer` with:
- The full diff
- The Task Card or PR description (if available)
- The target specification from $ARGUMENTS
reviewer must evaluate the diff against the following checklist:
**Correctness**
- Does the implementation match the stated intent?
- Are there logic errors, off-by-one errors, or unhandled edge cases?
**Architecture alignment**
- Does the change follow existing module boundaries?
- Does it introduce unplanned coupling or layering violations?
**Security**
- Are inputs validated before use?
- Is there any credential, token, or secret in the diff?
- Are there SQL injection, XSS, or injection risks?
**Performance**
- Does the change introduce N+1 queries, blocking I/O, or O(n^2) loops?
**Test coverage**
- Do tests exist for the new or changed behavior?
- Are assertions meaningful (not just checking that no exception is thrown)?
**Documentation**
- Are public interfaces documented?
- Is CHANGELOG updated if behavior changed?
---
## Step 3 — Review Report
reviewer produces a structured Review Report with findings in three categories:
```markdown
## Review Report
### CRITICAL
[Findings that must be fixed before merge. Each finding includes:
- Location (file:line)
- Description of the problem
- Suggested resolution]
### WARNING
[Findings that should be resolved before merge but are not blockers in
exceptional cases with human approval. Same format as CRITICAL.]
### SUGGESTION
[Optional improvements — style, readability, future-proofing. These do not block
merge.]
### Summary
- Files reviewed: N
- Total findings: N (X critical, Y warnings, Z suggestions)
- Merge recommendation: APPROVED | BLOCKED
```
---
## Step 4 — Merge decision
If any CRITICAL findings exist:
- The Review Report status is **BLOCKED**
- Report all CRITICAL findings to the human
- Do not proceed until each CRITICAL finding is resolved
- After resolution, invoke `/cc:review` again on the same target
If no CRITICAL findings exist:
- The Review Report status is **APPROVED**
- Report any WARNINGs and SUGGESTIONs for human awareness
- The human makes the final merge decision
---
## Completion
Deliver the complete Review Report. Never summarize or omit findings. Every
finding must include a location and an actionable description.
---
name: cc-tdd-cycle
description: >-
Run a structured Red-Green-Refactor TDD cycle — write a failing test first,
implement the minimum code to pass it, then refactor with the suite green.
---
# TDD Cycle — Red → Green → Refactor
Scope: $ARGUMENTS
Describe what behavior you want to implement. Include:
- The function, method, or feature to implement
- The expected behavior (inputs and outputs, or acceptance criteria)
- Any known constraints or edge cases
- Relevant files or modules (if known)
---
## Before you begin — mandatory pre-check
This command enforces strict TDD discipline. The three phases are sequential and
non-negotiable:
1. **RED** — a failing test exists before any implementation code is written
2. **GREEN** — the minimum implementation to make the test pass (no more)
3. **REFACTOR** — clean up the code while keeping all tests green
Do not write implementation code during RED. Do not refactor during GREEN.
Mixing phases invalidates the cycle.
---
## Phase 1 — RED (Tester role)
Adopt the **Tester** role as defined in `CLAUDE.md`.
### 1a — Scope clarification
Before writing any test, confirm:
- What is the unit of behavior being tested? (function, method, endpoint, domain
rule)
- What are the inputs and expected outputs?
- What are the failure cases?
If the scope is ambiguous, ask one clarifying question and wait for the answer.
### 1b — Write the failing test
Write a test that:
- Targets exactly the behavior described in the scope
- Fails for the right reason (not a compile error, not a missing dependency —
the logic does not exist yet)
- Has a name that describes the behavior: `given_X_when_Y_then_Z` or equivalent
in the project's test naming convention
- Covers at minimum: one happy path, one edge case, one failure case
Do not write the implementation. Do not make the test pass by any means other
than the implementation that will follow in Phase 2.
### 1c — Run the test suite and confirm RED
Run the test suite. The new test must fail. Existing tests must pass.
If the new test passes without implementation, the test is wrong. Fix the test
before continuing.
**RED Phase Report:**
```
## RED Phase Report
**Test file**: [path/to/test/file]
**Tests written**:
- [test name] — [what it verifies]
**Suite result**: [X passing, Y failing]
**New test status**: FAIL ✓
**Failure reason**: [quoted error or assertion message]
**Existing tests**: [all passing | N failing — list]
```
**STOP. Show the RED Phase Report. Do not proceed to GREEN without
confirmation.**
---
## Phase 2 — GREEN (Implementer role)
Adopt the **Implementer** role as defined in `CLAUDE.md`.
### 2a — Read the failing test before writing any code
Understand exactly what the test asserts. Write only the code that satisfies
that assertion. Nothing more.
### 2b — Implement the minimum
Rules for GREEN phase:
- Write the smallest amount of code that makes the failing test pass
- Do not add features not tested
- Do not clean up or restructure existing code — that is Refactor's job
- Do not add new tests — that is another RED cycle
- Hardcoding a return value is acceptable if it makes the test pass (the
Refactor phase will generalize it)
### 2c — Run the test suite and confirm GREEN
Run the test suite. The new test must pass. All previously passing tests must
still pass.
If any previously passing test now fails, you introduced a regression. Fix it
before continuing.
**GREEN Phase Report:**
```
## GREEN Phase Report
**Files changed**:
- [path/to/file] — [what was added, one sentence]
**Implementation approach**: [one sentence — what the code does]
**Suite result**: [X passing, Y failing]
**New test status**: PASS ✓
**Regressions**: [none | list failing tests]
```
**STOP. Show the GREEN Phase Report. Do not proceed to REFACTOR without
confirmation.**
---
## Phase 3 — REFACTOR (Implementer role, then Reviewer role)
Adopt the **Implementer** role as defined in `CLAUDE.md`.
### 3a — Assess what needs cleaning
Before touching any code, identify:
- Duplication introduced during GREEN
- Names that do not clearly express intent
- Abstractions that belong in a separate function or module
- Logic that is hardcoded and should be generalized
Do not invent improvements. Only address what is directly in the implementation
written in Phase 2.
### 3b — Refactor
Rules for REFACTOR phase:
- All tests must remain GREEN throughout — run the suite after each change
- Do not add new behavior
- Do not add new tests (if you discover untested behavior, note it for a new RED
cycle)
- Do not change function signatures unless the original was clearly wrong
### 3c — Run the test suite and confirm GREEN after refactor
The full suite must pass. If any test fails during refactor, undo the last
change and investigate.
### 3d — Review (Reviewer role)
Adopt the **Reviewer** role as defined in `CLAUDE.md`.
Review only the refactored code against these axes:
| Axis | What to check |
| ------------- | --------------------------------------------------------------- |
| Scope | Did the refactor change any behavior? |
| Correctness | Does the logic still satisfy the original test intent? |
| Architecture | Does the code follow existing project patterns? |
| Test coverage | Are all written tests still meaningful (not trivially passing)? |
Produce a Review Report. CRITICAL findings block completion.
**REFACTOR Phase Report:**
```
## REFACTOR Phase Report
**Changes made**:
- [path/to/file] — [what was cleaned up]
**Suite result**: [X passing, Y failing]
**Behavioral changes**: none (refactor only)
### Review findings
**CRITICAL**: (none) | [list]
**WARNING**: (none) | [list]
**SUGGESTION**: (none) | [list]
**Verdict**: approved | approved with warnings | blocked
```
---
## Completion
The TDD cycle is complete when:
- RED: at least one failing test was written and confirmed failing
- GREEN: the minimum implementation makes the test pass
- REFACTOR: the code is clean, all tests pass, no CRITICAL review findings
**Final Summary:**
```
## TDD Cycle Summary
**Behavior implemented**: [one sentence]
**Tests written**: [count] — [list test names]
**Files changed**: [list]
**Suite result**: [X passing, Y failing]
**Cycle status**: complete | blocked (reason)
```
If the behavior requires additional test cases, start a new `/cc:tdd-cycle` with
the next scenario. One cycle = one behavior.
---
name: cc-test-plan
description:
Generate a structured test plan for a feature or module — covers unit,
integration, contract, and edge cases without writing any implementation code.
---
# Test Plan Workflow
Scope: $ARGUMENTS
Specify what to plan tests for. Examples:
- A feature name: `user authentication`
- A module or file path: `src/orders/OrderService.kt`
- A Task Card title: `Add paginated product listing endpoint`
- A PR or branch: `feature/payment-retry`
If $ARGUMENTS is empty, describe the scope in your next message before invoking
`tester`.
---
## Step 1 — Scope confirmation
Before invoking `tester`, confirm the scope is well-defined.
A valid scope includes:
- The behavior or module under test
- The acceptance criteria or expected behavior (from the Task Card if available)
- Known edge cases or failure modes
If the scope is vague (e.g., "test the whole service"), ask one clarifying
question and wait for the answer.
---
## Step 2 — Test plan generation (tester)
Invoke `tester` in planning mode — produce a test plan document, not test code.
The plan will be used as input when tests are actually written.
tester must produce a Test Plan covering the following layers:
**Unit tests**
- Individual functions or methods in isolation
- One test per behavior, not per method
- Input/output contracts, null handling, type coercion
**Integration tests**
- Interactions between two or more components
- Database read/write cycles (if applicable)
- External service boundaries (mocked or stubbed)
**Contract tests**
- API endpoint contracts: request shape, response shape, status codes
- Event schema contracts (if event-driven components are in scope)
**Edge cases**
- Empty inputs, boundary values, max/min limits
- Concurrent access (if shared state is involved)
- Failure paths: what happens when a dependency is unavailable
**Regression cases**
- Known past bugs that must not recur (include reference if available)
---
## Step 3 — Test Plan format
tester produces the plan in this format:
```markdown
## Test Plan — [Scope Name]
### Scope
[What is being tested and why]
### Unit Tests
| Test ID | Target | Scenario | Expected Result |
| ------- | ------ | -------- | --------------- |
| U-001 | ... | ... | ... |
### Integration Tests
| Test ID | Components | Scenario | Expected Result |
| ------- | ---------- | -------- | --------------- |
| I-001 | ... | ... | ... |
### Contract Tests
| Test ID | Endpoint/Event | Property | Expected Value |
| ------- | -------------- | -------- | -------------- |
| C-001 | ... | ... | ... |
### Edge Cases
| Test ID | Input/Condition | Expected Behavior |
| ------- | --------------- | ----------------- |
| E-001 | ... | ... |
### Regression Cases
| Test ID | Reference | Scenario | Must Not Happen |
| ------- | --------- | -------- | --------------- |
| R-001 | ... | ... | ... |
### Coverage Targets
- Minimum unit coverage: [%] (or "all acceptance criteria covered")
- Integration scenarios: [count]
- Contract validations: [count]
### Out of Scope
[What this test plan explicitly does not cover and why]
```
---
## Step 4 — Human review
Show the Test Plan to the human before any tests are written.
The Test Plan is an artifact for review and approval. Writing test code is a
separate action — invoke `/cc:feature` or add a test task to the board to
implement from this plan.
---
## Completion
Deliver the complete Test Plan document. Save it as
`docs/test-plans/[scope-slug].md` if the human requests persistence.
This command produces a plan, not test files. No production code and no test
code is written during this command.
---
name: commit
description: Genera un commit en inglés siguiendo Conventional Commits basado en los cambios staged
---
{{COMMIT_WORKFLOW}}
---
name: cc-api-contract
description:
Run the API contract workflow for request/response shape changes,
compatibility constraints, contract tests, documentation, and review.
---
# API Contract Workflow
API contract request: $ARGUMENTS
## Step 1 — Task Card validation (task-coach)
Invoke `task-coach` with the request above.
The Task Card must classify the task as `feature` or `refactor` with `high`
risk unless the human provides a narrower validated risk. It must include:
- affected endpoint, command, or public interface
- request and response examples
- backward compatibility and versioning impact
- consumers that must remain compatible
- contract tests and documentation acceptance criteria
**STOP here. Show the Task Card and wait for human confirmation.**
---
## Step 2 — Technical Plan (architect)
Invoke `architect` with the approved Task Card.
architect must define the API contract, compatibility strategy, validation
rules, docs/OpenAPI impact, and migration path for consumers.
**STOP here. Show the Technical Plan and wait for explicit human approval.**
---
## Step 3 — Implementation (implementer)
Invoke `implementer` with the approved plan.
implementer must apply the minimal diff, preserve compatible behavior unless a
breaking change was explicitly approved, and update only the files named in the
plan.
---
## Step 4 — Contract tests (tester)
Invoke `tester`.
tester must add or update contract tests covering request shape, response shape,
status/error behavior, and backward compatibility constraints.
---
## Step 5 — Review (reviewer)
Invoke `reviewer`.
reviewer must block on missing contract tests, undocumented breaking changes,
or docs/OpenAPI drift.
---
## Completion
Report the final Task Card, Technical Plan, implementation summary, test report,
review report, docs updated, compatibility impact, and residual risks.
---
name: cc-db-migration
description:
Run the database migration workflow for schema/data changes, operational
sequencing, tests, and review.
---
# Database Migration Workflow
Migration request: $ARGUMENTS
## Step 1 — Task Card validation (task-coach)
Invoke `task-coach` with the request above.
The Task Card must classify the task as `high` risk and include:
- tables, collections, models, or migration files in scope
- data backfill or data cleanup requirements
- deployment ordering and compatibility window
- rollback or forward-fix strategy
- lock risk, data risk, and verification commands
**STOP here. Show the Task Card and wait for human confirmation.**
---
## Step 2 — Migration Plan (architect)
Invoke `architect` with the approved Task Card.
architect must define the schema/data plan, operational sequencing,
compatibility strategy, rollback/forward-fix notes, and test approach.
**STOP here. Show the Technical Plan and wait for explicit human approval.**
---
## Step 3 — Implementation (implementer)
Invoke `implementer` with the approved plan.
implementer must keep model and migration changes together, avoid unrelated
refactors, and preserve the deployment order specified by architect.
---
## Step 4 — Migration tests (tester)
Invoke `tester`.
tester must cover migration-sensitive behavior where the stack supports it,
including happy path, existing-data edge cases, and rollback/forward-fix notes
when automated rollback tests are not practical.
---
## Step 5 — Review (reviewer)
Invoke `reviewer`.
reviewer must block on missing migration tests, missing data-risk notes,
undocumented deployment sequencing, or model/migration drift.
---
## Completion
Report migration files changed, model files changed, tests run, lock risk, data
risk, operational sequencing, rollback/forward-fix notes, and residual risk.
---
name: cc-feature
description:
Run the full feature workflow — task validation, technical design,
implementation, testing, review, and documentation.
---
# Feature Workflow
Feature request: $ARGUMENTS
## Step 1 — Task Card validation (task-coach)
Invoke `task-coach` with the feature description above.
task-coach must produce a complete Task Card before any other agent runs. The
Task Card is ready when it contains: title, type, risk classification, scope,
context, acceptance criteria, and constraints.
If any field is missing or ambiguous, task-coach must ask one clarifying
question at a time and wait for the answer. Do not proceed with an incomplete
Task Card.
**STOP here. Show the completed Task Card and wait for human confirmation before
continuing.**
---
## Step 2 — Technical Plan (architect)
Invoke `architect` with the validated Task Card from Step 1.
architect must produce a Technical Plan that covers:
- Chosen approach and rationale
- Affected files and modules
- Data model changes (if any)
- API contract changes (if any)
- Identified risks and mitigations
- Open questions that require a human decision
**STOP here. Show the Technical Plan and wait for explicit human approval. Do
not invoke implementer until the plan is approved.**
---
## Step 3 — Implementation (implementer)
Invoke `implementer` with the approved Technical Plan and the Task Card.
Implementer creates a Git Worktree before touching any file; all edits happen inside it.
implementer must:
1. Read the Technical Plan before touching any file
2. Apply the minimal diff — only what the plan specifies
3. Run the project test suite after implementation
4. Produce an Implementation Summary: what changed, which files, how to verify
locally
---
## Step 4 — Test coverage (tester)
Invoke `tester` with the Implementation Summary and the Task Card.
tester must:
1. Write or extend tests to cover the new behavior
2. Ensure all acceptance criteria from the Task Card have at least one test
3. Run the full test suite and confirm it passes
4. Produce a Coverage Summary: test files added or modified, cases covered
---
## Step 5 — Code review (reviewer)
Invoke `reviewer` with the complete diff and the Task Card.
reviewer must produce a Review Report with findings categorized as:
- CRITICAL — must be fixed before merge
- WARNING — must be resolved before merge
- SUGGESTION — optional improvement
If any CRITICAL findings exist, **STOP and report them**. Do not proceed until
they are resolved and re-reviewed.
---
## Step 6 — Documentation (docs)
Invoke `docs` only if any of the following changed:
- A public API endpoint was added or modified
- A public interface or module was introduced
- Behavior visible to end users changed
docs must update: README (if applicable), OpenAPI spec (if applicable),
CHANGELOG (always), ADR (if an architectural decision was made).
---
## Completion
Report the following to the human:
- Task Card (final)
- Technical Plan (approved)
- Implementation Summary
- Coverage Summary
- Review Report (all findings resolved)
- List of documentation files updated (if any)
The feature is complete only when: all tests pass, no CRITICAL review findings
remain, and documentation reflects the implemented behavior.
---
name: cc-fix
description:
Run the bug fix workflow — risk-based routing through task validation,
implementation, testing, and optional review.
---
# Bug Fix Workflow
Bug description: $ARGUMENTS
Provide the following information in $ARGUMENTS:
- What is the incorrect behavior (actual)
- What is the expected behavior
- Steps to reproduce
- Environment or version where the bug occurs (if known)
- Any relevant error messages or stack traces
---
## Step 1 — Task Card validation (task-coach)
Invoke `task-coach` with the bug description above.
task-coach must produce a Task Card that includes:
- A clear statement of actual vs. expected behavior
- Reproduction steps (or a note that they are unknown)
- Risk classification: `low`, `medium`, or `high`
- Scope: which files or modules are likely affected
If reproduction steps are missing, task-coach must ask for them before
classifying risk. A bug without a reproduction path cannot be classified
reliably.
**STOP here. Show the Task Card and wait for human confirmation.**
---
## Step 2 — Route by risk
Read the risk field from the Task Card and follow the corresponding route.
### Low-risk route
Applies when: the bug is isolated to a single component, existing tests cover
the affected code, and no public API or shared state is involved.
Route: `task-coach` → `implementer` → `tester`
Proceed directly to Step 3a.
### Medium or high-risk route
Applies when: the bug touches shared state, a public API, auth or payment paths,
database writes, or the root cause is not yet understood.
Route: `task-coach` → `architect` → `implementer` → `tester` → `reviewer`
Invoke `architect` before implementation. architect must:
- Identify the root cause (or document that it is unknown)
- Define the fix approach and affected files
- Flag any regression risk to adjacent components
- Produce a Technical Plan
**STOP here if high-risk. Show the Technical Plan and wait for human approval
before continuing.**
---
## Step 3a — Implementation, low-risk (implementer)
Invoke `implementer` with the Task Card.
Implementer creates a Git Worktree before touching any file; all edits happen inside it.
implementer must:
1. Locate the defect using the reproduction steps
2. Apply the minimal fix — no unrelated changes
3. Run the test suite
4. Produce an Implementation Summary: root cause, fix applied, files changed
---
## Step 3b — Implementation, medium/high-risk (implementer)
Invoke `implementer` with the approved Technical Plan and the Task Card.
Implementer creates a Git Worktree before touching any file; all edits happen inside it.
implementer must follow the plan exactly. Any deviation requires a new Technical
Plan approval. After implementation, run the full test suite.
---
## Step 4 — Regression tests (tester)
Invoke `tester` for all risk levels.
tester must:
1. Write a regression test that reproduces the original bug (fails before the
fix, passes after)
2. Verify that existing tests still pass
3. Produce a Coverage Summary: test added, case covered
---
## Step 5 — Review (reviewer) — medium/high-risk only
Invoke `reviewer` with the diff and Task Card.
reviewer produces a Review Report with CRITICAL / WARNING / SUGGESTION findings.
If any CRITICAL findings exist, **STOP**. Do not close the fix until they are
resolved.
---
## Completion
Report: Task Card, Implementation Summary, regression test added, Review Report
(if applicable). The fix is complete only when: the regression test passes, the
full suite passes, and no CRITICAL review findings remain.
---
name: cc-pagespeed
description: >-
Run the PageSpeed performance audit — 80/20 analysis of Core Web Vitals using
the PageSpeed Insights API.
---
# PageSpeed Performance Audit
Audit URL: $ARGUMENTS
---
## Step 1 — Pre-flight (pagespeed-perf skill)
Invoke `pagespeed-perf` skill.
Read `PAGESPEED_API_KEY` from the environment. Compute the output filename:
`{YYYY-MM-DD}_pagespeed-{hostname}-claude.md`.
Log whether the API key was found. Proceed regardless — lab data is available
without a key, but CrUX field data requires it.
---
## Step 2 — Collect
Call the PageSpeed Insights API for the URL provided above.
- Strategy: `both` (mobile + desktop) unless the user specified otherwise.
- If Bun is available, use `~/.claude/skills/pagespeed-perf/scripts/run.ts`.
- If Bun is unavailable, call PSI directly via WebFetch and fetch the HTML
source for manual resource-hint analysis.
---
## Step 3 — Analyze
Extract from the PSI response:
- Core Web Vitals: LCP, INP, CLS, FCP, TBT, TTFB
- LCP element (type, selector, HTML snippet)
- Third-party scripts ordered by blocking time
- Render-blocking resources
- Unused JavaScript and CSS (savings in bytes and ms)
From the HTML source:
- Resource hints (`<link rel="preload|preconnect|prefetch">`)
- Images: lazy loading, `fetchpriority`, format, dimensions
- Fonts: `font-display`, preloaded subsets
- Blocking scripts in `<head>` (no `async`/`defer`)
---
## Step 4 — Prioritize
Score each identified optimization using the 80/20 matrix:
`Score = Impact × Ease` (each 1–5, max 25).
Order findings by descending score. Mark optimizations with Score ≥ 20 as
**Critical 20%**.
---
## Step 5 — Report
Write the full performance report to
`{YYYY-MM-DD}_pagespeed-{hostname}-claude.md` in the current directory.
Required sections:
1. Resumen Ejecutivo (2–3 paragraphs)
2. Métricas Actuales (lab vs field table)
3. Recursos con Mayor Impacto
4. Plan de Acción Priorizado (80/20 table)
5. Solución Técnica Detallada (per finding: problem, evidence, code, expected gain)
6. Quick Wins / High Impact Changes / Roadmap
End every report with:
```
---
*Informe generado el {YYYY-MM-DD} · Herramienta: Claude Code + pagespeed-perf skill*
*API Key usada: {Sí / No} · Datos CrUX: {Disponibles / No disponibles}*
```
---
## Requirements
**`PAGESPEED_API_KEY`** — Optional but strongly recommended.
- With key: real CrUX field data + 25,000 requests/day quota.
- Without key: lab data only (Lighthouse); shared rate limit applies.
Set in your shell:
```powershell
$env:PAGESPEED_API_KEY = "your-api-key" # Windows PowerShell
export PAGESPEED_API_KEY="your-api-key" # macOS / Linux
```
Get a free key: <https://developers.google.com/speed/docs/insights/v5/get-started>
---
name: cc-refactor
description:
Run the refactor workflow — mandatory architectural justification, test
verification, risk-based implementation, and scope enforcement.
---
# Refactor Workflow
Refactor description: $ARGUMENTS
Describe what you want to refactor and why. Include:
- The current structure or pattern being changed
- The target structure or pattern
- The motivation (performance, readability, architectural alignment, etc.)
- Known risk areas or dependencies
---
## Prerequisite — Test coverage check
Before any agent is invoked, verify that the code being refactored has adequate
test coverage.
A refactor without tests is not a refactor — it is a rewrite with unknown
behavioral consequences.
If coverage is insufficient:
1. **STOP**. Report the coverage gap to the human.
2. Suggest invoking `/cc:test-plan` first to establish coverage.
3. Do not proceed with the refactor until coverage is confirmed.
---
## Step 1 — Architectural justification (architect)
Always invoke `architect` first, regardless of risk level. A refactor without a
written justification is scope creep in disguise.
architect must produce a Refactor Plan that includes:
- Statement of the problem with the current structure
- Proposed target structure and rationale
- Affected files and module boundaries
- Risk level: `low`, `medium`, or `high`
- Behavioral invariants that must not change
- Open questions requiring human input
**Scope creep warning:** If during planning architect identifies unrelated
improvements, they must be listed separately as "Out of scope." They are not
part of this refactor.
**STOP here. Show the Refactor Plan and wait for explicit human approval. Do not
proceed without written approval of the plan.**
---
## Step 2 — Route by risk
Read the risk field from the Refactor Plan and follow the corresponding route.
### Low-risk route
Applies when: the refactor is purely internal, no public interfaces change, full
test coverage exists for the affected code, and behavioral impact is isolated to
the refactored module.
Route: `architect` (done) → `implementer`
Proceed to Step 3a.
### Medium or high-risk route
Applies when: module boundaries change, shared interfaces are affected,
performance characteristics may change, or the refactor touches more than two
files with behavioral impact.
Route: `architect` (done) → `implementer` → `reviewer`
Proceed to Step 3b.
---
## Step 3a — Implementation, low-risk (implementer)
Invoke `implementer` with the approved Refactor Plan.
Implementer creates a Git Worktree before touching any file; all edits happen inside it.
implementer must:
1. Read the Refactor Plan before opening any file
2. Apply only the changes specified in the plan
3. Run the full test suite before and after — both runs must pass
4. Produce an Implementation Summary: what changed, what did not change, test
results before and after
Any deviation from the plan — including "obvious improvements" encountered
during implementation — must be flagged and held for a separate task.
---
## Step 3b — Implementation, medium/high-risk (implementer)
Same rules as 3a. Additionally:
- implementer must document any unexpected complexity discovered during
implementation and pause if the complexity changes the risk assessment
- If new risks are found, **STOP** and report to the human before continuing
---
## Step 4 — Test suite verification
For all risk levels, confirm:
- All tests that existed before the refactor still pass
- No test was deleted or commented out to make the suite pass
- Behavior documented in the Task Card remains unchanged
If any test fails that was passing before, the refactor has introduced a
regression. **STOP and report.**
---
## Step 5 — Code review (reviewer) — medium/high-risk only
Invoke `reviewer` with the diff and Refactor Plan.
reviewer must verify:
- The implementation matches the approved plan
- No behavior was changed beyond the plan's scope
- No unrelated files were modified
Review Report must include CRITICAL / WARNING / SUGGESTION findings. CRITICAL
findings block completion.
---
## Completion
Report: Refactor Plan (approved), Implementation Summary, test results before
and after, Review Report (if applicable).
The refactor is complete only when: all pre-existing tests still pass, the
implementation matches the approved plan exactly, and no CRITICAL review
findings remain.
---
name: cc-review
description:
Run a structured code review — produces a Review Report with CRITICAL,
WARNING, and SUGGESTION findings; CRITICAL findings block merge.
---
# Code Review Workflow
Review target: $ARGUMENTS
Specify what to review. Accepted formats:
- A branch name: `feature/my-branch`
- A file or set of files: `src/api/UserController.kt`
- A pull request reference: `PR #42`
- Empty — defaults to the current working diff (`git diff`)
---
## Step 1 — Diff collection
Before invoking `reviewer`, collect the diff for the specified target.
If $ARGUMENTS is empty or not provided:
- Use `git diff HEAD` as the review target
If $ARGUMENTS is a branch name:
- Use `git diff main...$ARGUMENTS` (or `develop` if main is not the base)
If $ARGUMENTS is a PR reference:
- Retrieve the PR diff and the PR description for context
If $ARGUMENTS is a file path:
- Use `git diff HEAD -- $ARGUMENTS`
Show the diff summary (files changed, lines added/removed) before invoking
reviewer.
---
## Step 2 — Code review (reviewer)
Invoke `reviewer` with:
- The full diff
- The Task Card or PR description (if available)
- The target specification from $ARGUMENTS
reviewer must evaluate the diff against the following checklist:
**Correctness**
- Does the implementation match the stated intent?
- Are there logic errors, off-by-one errors, or unhandled edge cases?
**Architecture alignment**
- Does the change follow existing module boundaries?
- Does it introduce unplanned coupling or layering violations?
**Security**
- Are inputs validated before use?
- Is there any credential, token, or secret in the diff?
- Are there SQL injection, XSS, or injection risks?
**Performance**
- Does the change introduce N+1 queries, blocking I/O, or O(n^2) loops?
**Test coverage**
- Do tests exist for the new or changed behavior?
- Are assertions meaningful (not just checking that no exception is thrown)?
**Documentation**
- Are public interfaces documented?
- Is CHANGELOG updated if behavior changed?
---
## Step 3 — Review Report
reviewer produces a structured Review Report with findings in three categories:
```markdown
## Review Report
### CRITICAL
[Findings that must be fixed before merge. Each finding includes:
- Location (file:line)
- Description of the problem
- Suggested resolution]
### WARNING
[Findings that should be resolved before merge but are not blockers in
exceptional cases with human approval. Same format as CRITICAL.]
### SUGGESTION
[Optional improvements — style, readability, future-proofing. These do not block
merge.]
### Summary
- Files reviewed: N
- Total findings: N (X critical, Y warnings, Z suggestions)
- Merge recommendation: APPROVED | BLOCKED
```
---
## Step 4 — Merge decision
If any CRITICAL findings exist:
- The Review Report status is **BLOCKED**
- Report all CRITICAL findings to the human
- Do not proceed until each CRITICAL finding is resolved
- After resolution, invoke `/cc:review` again on the same target
If no CRITICAL findings exist:
- The Review Report status is **APPROVED**
- Report any WARNINGs and SUGGESTIONs for human awareness
- The human makes the final merge decision
---
## Completion
Deliver the complete Review Report. Never summarize or omit findings. Every
finding must include a location and an actionable description.
---
name: cc-tdd-cycle
description: >-
Run a structured Red-Green-Refactor TDD cycle — write a failing test first,
implement the minimum code to pass it, then refactor with the suite green.
---
# TDD Cycle — Red → Green → Refactor
Scope: $ARGUMENTS
Describe what behavior you want to implement. Include:
- The function, method, or feature to implement
- The expected behavior (inputs and outputs, or acceptance criteria)
- Any known constraints or edge cases
- Relevant files or modules (if known)
---
## Before you begin — mandatory pre-check
This command enforces strict TDD discipline. The three phases are sequential and
non-negotiable:
1. **RED** — a failing test exists before any implementation code is written
2. **GREEN** — the minimum implementation to make the test pass (no more)
3. **REFACTOR** — clean up the code while keeping all tests green
Do not write implementation code during RED. Do not refactor during GREEN.
Mixing phases invalidates the cycle.
---
## Phase 1 — RED (Tester role)
Adopt the **Tester** role as defined in `CLAUDE.md`.
### 1a — Scope clarification
Before writing any test, confirm:
- What is the unit of behavior being tested? (function, method, endpoint, domain
rule)
- What are the inputs and expected outputs?
- What are the failure cases?
If the scope is ambiguous, ask one clarifying question and wait for the answer.
### 1b — Write the failing test
Write a test that:
- Targets exactly the behavior described in the scope
- Fails for the right reason (not a compile error, not a missing dependency —
the logic does not exist yet)
- Has a name that describes the behavior: `given_X_when_Y_then_Z` or equivalent
in the project's test naming convention
- Covers at minimum: one happy path, one edge case, one failure case
Do not write the implementation. Do not make the test pass by any means other
than the implementation that will follow in Phase 2.
### 1c — Run the test suite and confirm RED
Run the test suite. The new test must fail. Existing tests must pass.
If the new test passes without implementation, the test is wrong. Fix the test
before continuing.
**RED Phase Report:**
```
## RED Phase Report
**Test file**: [path/to/test/file]
**Tests written**:
- [test name] — [what it verifies]
**Suite result**: [X passing, Y failing]
**New test status**: FAIL ✓
**Failure reason**: [quoted error or assertion message]
**Existing tests**: [all passing | N failing — list]
```
**STOP. Show the RED Phase Report. Do not proceed to GREEN without
confirmation.**
---
## Phase 2 — GREEN (Implementer role)
Adopt the **Implementer** role as defined in `CLAUDE.md`.
### 2a — Read the failing test before writing any code
Understand exactly what the test asserts. Write only the code that satisfies
that assertion. Nothing more.
### 2b — Implement the minimum
Rules for GREEN phase:
- Write the smallest amount of code that makes the failing test pass
- Do not add features not tested
- Do not clean up or restructure existing code — that is Refactor's job
- Do not add new tests — that is another RED cycle
- Hardcoding a return value is acceptable if it makes the test pass (the
Refactor phase will generalize it)
### 2c — Run the test suite and confirm GREEN
Run the test suite. The new test must pass. All previously passing tests must
still pass.
If any previously passing test now fails, you introduced a regression. Fix it
before continuing.
**GREEN Phase Report:**
```
## GREEN Phase Report
**Files changed**:
- [path/to/file] — [what was added, one sentence]
**Implementation approach**: [one sentence — what the code does]
**Suite result**: [X passing, Y failing]
**New test status**: PASS ✓
**Regressions**: [none | list failing tests]
```
**STOP. Show the GREEN Phase Report. Do not proceed to REFACTOR without
confirmation.**
---
## Phase 3 — REFACTOR (Implementer role, then Reviewer role)
Adopt the **Implementer** role as defined in `CLAUDE.md`.
### 3a — Assess what needs cleaning
Before touching any code, identify:
- Duplication introduced during GREEN
- Names that do not clearly express intent
- Abstractions that belong in a separate function or module
- Logic that is hardcoded and should be generalized
Do not invent improvements. Only address what is directly in the implementation
written in Phase 2.
### 3b — Refactor
Rules for REFACTOR phase:
- All tests must remain GREEN throughout — run the suite after each change
- Do not add new behavior
- Do not add new tests (if you discover untested behavior, note it for a new RED
cycle)
- Do not change function signatures unless the original was clearly wrong
### 3c — Run the test suite and confirm GREEN after refactor
The full suite must pass. If any test fails during refactor, undo the last
change and investigate.
### 3d — Review (Reviewer role)
Adopt the **Reviewer** role as defined in `CLAUDE.md`.
Review only the refactored code against these axes:
| Axis | What to check |
| ------------- | --------------------------------------------------------------- |
| Scope | Did the refactor change any behavior? |
| Correctness | Does the logic still satisfy the original test intent? |
| Architecture | Does the code follow existing project patterns? |
| Test coverage | Are all written tests still meaningful (not trivially passing)? |
Produce a Review Report. CRITICAL findings block completion.
**REFACTOR Phase Report:**
```
## REFACTOR Phase Report
**Changes made**:
- [path/to/file] — [what was cleaned up]
**Suite result**: [X passing, Y failing]
**Behavioral changes**: none (refactor only)
### Review findings
**CRITICAL**: (none) | [list]
**WARNING**: (none) | [list]
**SUGGESTION**: (none) | [list]
**Verdict**: approved | approved with warnings | blocked
```
---
## Completion
The TDD cycle is complete when:
- RED: at least one failing test was written and confirmed failing
- GREEN: the minimum implementation makes the test pass
- REFACTOR: the code is clean, all tests pass, no CRITICAL review findings
**Final Summary:**
```
## TDD Cycle Summary
**Behavior implemented**: [one sentence]
**Tests written**: [count] — [list test names]
**Files changed**: [list]
**Suite result**: [X passing, Y failing]
**Cycle status**: complete | blocked (reason)
```
If the behavior requires additional test cases, start a new `/cc:tdd-cycle` with
the next scenario. One cycle = one behavior.
---
name: cc-test-plan
description:
Generate a structured test plan for a feature or module — covers unit,
integration, contract, and edge cases without writing any implementation code.
---
# Test Plan Workflow
Scope: $ARGUMENTS
Specify what to plan tests for. Examples:
- A feature name: `user authentication`
- A module or file path: `src/orders/OrderService.kt`
- A Task Card title: `Add paginated product listing endpoint`
- A PR or branch: `feature/payment-retry`
If $ARGUMENTS is empty, describe the scope in your next message before invoking
`tester`.
---
## Step 1 — Scope confirmation
Before invoking `tester`, confirm the scope is well-defined.
A valid scope includes:
- The behavior or module under test
- The acceptance criteria or expected behavior (from the Task Card if available)
- Known edge cases or failure modes
If the scope is vague (e.g., "test the whole service"), ask one clarifying
question and wait for the answer.
---
## Step 2 — Test plan generation (tester)
Invoke `tester` in planning mode — produce a test plan document, not test code.
The plan will be used as input when tests are actually written.
tester must produce a Test Plan covering the following layers:
**Unit tests**
- Individual functions or methods in isolation
- One test per behavior, not per method
- Input/output contracts, null handling, type coercion
**Integration tests**
- Interactions between two or more components
- Database read/write cycles (if applicable)
- External service boundaries (mocked or stubbed)
**Contract tests**
- API endpoint contracts: request shape, response shape, status codes
- Event schema contracts (if event-driven components are in scope)
**Edge cases**
- Empty inputs, boundary values, max/min limits
- Concurrent access (if shared state is involved)
- Failure paths: what happens when a dependency is unavailable
**Regression cases**
- Known past bugs that must not recur (include reference if available)
---
## Step 3 — Test Plan format
tester produces the plan in this format:
```markdown
## Test Plan — [Scope Name]
### Scope
[What is being tested and why]
### Unit Tests
| Test ID | Target | Scenario | Expected Result |
| ------- | ------ | -------- | --------------- |
| U-001 | ... | ... | ... |
### Integration Tests
| Test ID | Components | Scenario | Expected Result |
| ------- | ---------- | -------- | --------------- |
| I-001 | ... | ... | ... |
### Contract Tests
| Test ID | Endpoint/Event | Property | Expected Value |
| ------- | -------------- | -------- | -------------- |
| C-001 | ... | ... | ... |
### Edge Cases
| Test ID | Input/Condition | Expected Behavior |
| ------- | --------------- | ----------------- |
| E-001 | ... | ... |
### Regression Cases
| Test ID | Reference | Scenario | Must Not Happen |
| ------- | --------- | -------- | --------------- |
| R-001 | ... | ... | ... |
### Coverage Targets
- Minimum unit coverage: [%] (or "all acceptance criteria covered")
- Integration scenarios: [count]
- Contract validations: [count]
### Out of Scope
[What this test plan explicitly does not cover and why]
```
---
## Step 4 — Human review
Show the Test Plan to the human before any tests are written.
The Test Plan is an artifact for review and approval. Writing test code is a
separate action — invoke `/cc:feature` or add a test task to the board to
implement from this plan.
---
## Completion
Deliver the complete Test Plan document. Save it as
`docs/test-plans/[scope-slug].md` if the human requests persistence.
This command produces a plan, not test files. No production code and no test
code is written during this command.
{{COMMIT_WORKFLOW}}
{
"autoConnectIde": true,
"autoInstallIdeExtension": false,
"externalEditorContext": true,
"teammateDefaultModel": "sonnet"
}
# PageSpeed Performance Audit
Audit web performance using the PageSpeed Insights API. Applies the 80/20
principle: identify the 20% of changes that produce 80% of the performance gain.
Produces a prioritized report in the current working directory.
## Usage
```
/cc-pagespeed --url <url> [--strategy mobile|desktop|both]
```
## Parameters
| Parameter | Required | Description |
| ------------- | -------- | -------------------------------------------------------------- |
| `--url` | Yes | Full URL to audit (must include scheme: https://...) |
| `--strategy` | No | Analysis strategy: `mobile`, `desktop`, or `both` (default: `both`) |
## Requirements
### `PAGESPEED_API_KEY` — Optional but strongly recommended
| Mode | Lab data | CrUX field data | Rate limits |
| ------------ | -------- | --------------- | ---------------- |
| **With key** | ✅ | ✅ (real users) | 25,000 req/day |
| **Without** | ✅ | ❌ | ~2 req/s shared |
Without the key, Core Web Vitals field data (real user experience via CrUX) is
unavailable. Lab data from Lighthouse still runs.
Set the key before invoking the command:
```powershell
# Windows PowerShell
$env:PAGESPEED_API_KEY = "your-api-key"
# macOS / Linux
export PAGESPEED_API_KEY="your-api-key"
```
Get a free key (Google account required):
<https://developers.google.com/speed/docs/insights/v5/get-started>
## Workflow
When `/cc-pagespeed` is invoked, load the `pagespeed-perf` skill and execute
the following steps in order:
1. **Pre-flight** — Read `$env:PAGESPEED_API_KEY` from the environment. Compute
the output filename: `{YYYY-MM-DD}_pagespeed-{hostname}-claude.md`.
2. **Collect** — Call the PageSpeed Insights API for the requested strategy
(`mobile`, `desktop`, or `both`). Prefer the Bun scripts in
`~/.claude/skills/pagespeed-perf/scripts/run.ts` if Bun is available.
Otherwise, use `WebFetch` to call the PSI endpoint directly.
3. **Analyze** — Extract Core Web Vitals (LCP, INP, CLS, FCP, TTFB, TBT),
identify the LCP element, enumerate third-party scripts by blocking time,
and inspect resource hints in the HTML `<head>`.
4. **Prioritize** — Score each identified optimization using the 80/20 matrix:
`Impact × Ease` (each 1–5). Order findings by descending score. Highlight
the top actions with Score ≥ 20 as the critical 20%.
5. **Report** — Write the structured markdown report to
`{YYYY-MM-DD}_pagespeed-{hostname}-claude.md` in the current directory.
## Output File
The report is saved as `{YYYY-MM-DD}_pagespeed-{hostname}-claude.md`.
- Hostname characters outside `[a-zA-Z0-9]` are replaced with `-`.
- Example: `https://www.example.com` → `2026-06-07_pagespeed-www-example-com-claude.md`
## Skills Loaded
- `pagespeed-perf` — Web Performance Engineering: PSI API, Core Web Vitals
thresholds, 80/20 optimization matrix, resource-hint analysis, third-party
script auditing, framework-specific implementation templates.
## Examples
```bash
# Full audit — mobile + desktop
/cc-pagespeed --url https://www.example.com
# Mobile only
/cc-pagespeed --url https://www.example.com --strategy mobile
# Desktop only
/cc-pagespeed --url https://www.example.com --strategy desktop
```
## Hard Rules
- **GET only.** Never send POST, PUT, or DELETE to the target URL.
- **No auth.** Never include cookies, tokens, or auth headers.
- **No external crawling.** Audit only the provided URL.
- **Quantify every finding.** Never write "it would improve LCP". Always cite
the observed value and estimated gain (e.g., "reduces LCP from 4.2 s to ~3.0 s").
- **No generic recommendations.** Every finding must be backed by data from
the audit of this specific URL.
---
name: conductor-setup
description: Configure a Rails project to work with Conductor (parallel coding agents)
allowed-tools: Bash(chmod *), Bash(bundle *), Bash(npm *), Bash(script/server)
context: fork
risk: unknown
source: community
metadata:
author: Shpigford
version: "1.0"
---
Set up this Rails project for Conductor, the Mac app for parallel coding agents.
## When to Use
- You need to configure a Rails project so it runs correctly inside Conductor workspaces.
- The project should support parallel coding agents with isolated ports, Redis settings, and shared secrets.
- You want the standard `conductor.json`, `bin/conductor-setup`, and `script/server` scaffolding for a Rails repo.
# What to Create
## 1. conductor.json (project root)
Create `conductor.json` in the project root if it doesn't already exist:
```json
{
"scripts": {
"setup": "bin/conductor-setup",
"run": "script/server"
}
}
```
## 2. bin/conductor-setup (executable)
Create `bin/conductor-setup` if it doesn't already exist:
```bash
#!/bin/bash
set -e
# Symlink .env from repo root (where secrets live, outside worktrees)
[ -f "$CONDUCTOR_ROOT_PATH/.env" ] && ln -sf "$CONDUCTOR_ROOT_PATH/.env" .env
# Symlink Rails master key
[ -f "$CONDUCTOR_ROOT_PATH/config/master.key" ] && ln -sf "$CONDUCTOR_ROOT_PATH/config/master.key" config/master.key
# Install dependencies
bundle install
npm install
```
Make it executable with `chmod +x bin/conductor-setup`.
## 3. script/server (executable)
Create the `script` directory if needed, then create `script/server` if it doesn't already exist:
```bash
#!/bin/bash
# === Port Configuration ===
export PORT=${CONDUCTOR_PORT:-3000}
export VITE_RUBY_PORT=$((PORT + 1000))
# === Redis Isolation ===
if [ -n "$CONDUCTOR_WORKSPACE_NAME" ]; then
HASH=$(printf '%s' "$CONDUCTOR_WORKSPACE_NAME" | cksum | cut -d' ' -f1)
REDIS_DB=$((HASH % 16))
export REDIS_URL="redis://localhost:6379/${REDIS_DB}"
fi
exec bin/dev
```
Make it executable with `chmod +x script/server`.
## 4. Update Rails Config Files
For each of the following files, if they exist and contain Redis configuration, update them to use `ENV.fetch('REDIS_URL', ...)` or `ENV['REDIS_URL']` with a fallback:
### config/initializers/sidekiq.rb
If this file exists and configures Redis, update it to use:
```ruby
redis_url = ENV.fetch('REDIS_URL', 'redis://localhost:6379/0')
```
### config/cable.yml
If this file exists, update the development adapter to use:
```yaml
development:
adapter: redis
url: <%= ENV.fetch('REDIS_URL', 'redis://localhost:6379/1') %>
```
### config/environments/development.rb
If this file configures Redis for caching, update to use:
```ruby
config.cache_store = :redis_cache_store, { url: ENV.fetch('REDIS_URL', 'redis://localhost:6379/0') }
```
### config/initializers/rack_attack.rb
If this file exists and configures a Redis cache store, update to use:
```ruby
Rack::Attack.cache.store = ActiveSupport::Cache::RedisCacheStore.new(url: ENV.fetch('REDIS_URL', 'redis://localhost:6379/0'))
```
# Implementation Notes
- **Don't overwrite existing files**: Check if conductor.json, bin/conductor-setup, and script/server exist before creating them. If they exist, skip creation and inform the user.
- **Rails config updates**: Only modify Redis-related configuration. If a file doesn't exist or doesn't use Redis, skip it gracefully.
- **Create directories as needed**: Create `script/` directory if it doesn't exist.
# Verification
After creating the files:
1. Confirm all Conductor files exist and scripts are executable
2. Run `script/server` to verify it starts without errors
3. Check that Rails configs properly reference `ENV['REDIS_URL']` or `ENV.fetch('REDIS_URL', ...)`
## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
---
name: find-skills
description: Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
---
# Find Skills
This skill helps you discover and install skills from the open agent skills ecosystem.
## When to Use This Skill
Use this skill when the user:
- Asks "how do I do X" where X might be a common task with an existing skill
- Says "find a skill for X" or "is there a skill for X"
- Asks "can you do X" where X is a specialized capability
- Expresses interest in extending agent capabilities
- Wants to search for tools, templates, or workflows
- Mentions they wish they had help with a specific domain (design, testing, deployment, etc.)
## What is the Skills CLI?
The Skills CLI (`npx skills`) is the package manager for the open agent skills ecosystem. Skills are modular packages that extend agent capabilities with specialized knowledge, workflows, and tools.
**Key commands:**
- `npx skills find [query]` - Search for skills interactively or by keyword
- `npx skills add <package>` - Install a skill from GitHub or other sources
- `npx skills check` - Check for skill updates
- `npx skills update` - Update all installed skills
**Browse skills at:** https://skills.sh/
## How to Help Users Find Skills
### Step 1: Understand What They Need
When a user asks for help with something, identify:
1. The domain (e.g., React, testing, design, deployment)
2. The specific task (e.g., writing tests, creating animations, reviewing PRs)
3. Whether this is a common enough task that a skill likely exists
### Step 2: Check the Leaderboard First
Before running a CLI search, check the [skills.sh leaderboard](https://skills.sh/) to see if a well-known skill already exists for the domain. The leaderboard ranks skills by total installs, surfacing the most popular and battle-tested options.
For example, top skills for web development include:
- `vercel-labs/agent-skills` — React, Next.js, web design (100K+ installs each)
- `anthropics/skills` — Frontend design, document processing (100K+ installs)
### Step 3: Search for Skills
If the leaderboard doesn't cover the user's need, run the find command:
```bash
npx skills find [query]
```
For example:
- User asks "how do I make my React app faster?" → `npx skills find react performance`
- User asks "can you help me with PR reviews?" → `npx skills find pr review`
- User asks "I need to create a changelog" → `npx skills find changelog`
### Step 4: Verify Quality Before Recommending
**Do not recommend a skill based solely on search results.** Always verify:
1. **Install count** — Prefer skills with 1K+ installs. Be cautious with anything under 100.
2. **Source reputation** — Official sources (`vercel-labs`, `anthropics`, `microsoft`) are more trustworthy than unknown authors.
3. **GitHub stars** — Check the source repository. A skill from a repo with <100 stars should be treated with skepticism.
### Step 5: Present Options to the User
When you find relevant skills, present them to the user with:
1. The skill name and what it does
2. The install count and source
3. The install command they can run
4. A link to learn more at skills.sh
Example response:
```
I found a skill that might help! The "react-best-practices" skill provides
React and Next.js performance optimization guidelines from Vercel Engineering.
(185K installs)
To install it:
npx skills add vercel-labs/agent-skills@react-best-practices
Learn more: https://skills.sh/vercel-labs/agent-skills/react-best-practices
```
### Step 6: Offer to Install
If the user wants to proceed, you can install the skill for them:
```bash
npx skills add <owner/repo@skill> -g -y
```
The `-g` flag installs globally (user-level) and `-y` skips confirmation prompts.
## Common Skill Categories
When searching, consider these common categories:
| Category | Example Queries |
| --------------- | ---------------------------------------- |
| Web Development | react, nextjs, typescript, css, tailwind |
| Testing | testing, jest, playwright, e2e |
| DevOps | deploy, docker, kubernetes, ci-cd |
| Documentation | docs, readme, changelog, api-docs |
| Code Quality | review, lint, refactor, best-practices |
| Design | ui, ux, design-system, accessibility |
| Productivity | workflow, automation, git |
## Tips for Effective Searches
1. **Use specific keywords**: "react testing" is better than just "testing"
2. **Try alternative terms**: If "deploy" doesn't work, try "deployment" or "ci-cd"
3. **Check popular sources**: Many skills come from `vercel-labs/agent-skills` or `ComposioHQ/awesome-claude-skills`
## When No Skills Are Found
If no relevant skills exist:
1. Acknowledge that no existing skill was found
2. Offer to help with the task directly using your general capabilities
3. Suggest the user could create their own skill with `npx skills init`
Example:
```
I searched for skills related to "xyz" but didn't find any matches.
I can still help you with this task directly! Would you like me to proceed?
If this is something you do often, you could create your own skill:
npx skills init my-xyz-skill
```
"""
Framework-Specific Multi-Agent Implementations
Templates for CrewAI, AutoGen, LangGraph, and Swarm.
"""
from typing import Dict, List, Optional, Any
from dataclasses import dataclass
@dataclass
class CrewAITemplate:
"""Template for CrewAI implementation."""
@staticmethod
def create_financial_team() -> Dict[str, Any]:
"""Create CrewAI financial analysis team."""
return {
"agents": [
{
"name": "Market Analyst",
"role": "Market Research Specialist",
"goal": "Analyze market conditions and trends",
"backstory": "Expert market analyst with 10+ years experience",
"tools": ["market_data_api", "financial_news"],
},
{
"name": "Financial Analyst",
"role": "Financial Analysis Specialist",
"goal": "Analyze company financial statements",
"backstory": "CFA with deep financial analysis expertise",
"tools": ["financial_statements", "ratio_calculator"],
},
{
"name": "Risk Manager",
"role": "Risk Assessment Specialist",
"goal": "Assess investment risks and scenarios",
"backstory": "Risk management expert",
"tools": ["risk_models", "scenario_analysis"],
},
{
"name": "Report Writer",
"role": "Report Generation Specialist",
"goal": "Synthesize findings into comprehensive report",
"backstory": "Professional technical writer",
"tools": ["document_generator"],
},
],
"tasks": [
{
"agent": "Market Analyst",
"description": "Analyze market conditions for {company}",
},
{
"agent": "Financial Analyst",
"description": "Analyze Q3 financial results for {company}",
},
{
"agent": "Risk Manager",
"description": "Assess risks and create scenarios for {company}",
},
{
"agent": "Report Writer",
"description": "Write comprehensive investment analysis report",
},
],
"process": "sequential",
}
@staticmethod
def create_legal_team() -> Dict[str, Any]:
"""Create CrewAI legal team."""
return {
"agents": [
{
"name": "Contract Analyzer",
"role": "Legal Contract Specialist",
"goal": "Analyze and review contract terms",
"backstory": "Senior contract attorney",
},
{
"name": "Precedent Researcher",
"role": "Legal Research Specialist",
"goal": "Research relevant case law and precedents",
"backstory": "Legal researcher specializing in case law",
},
{
"name": "Risk Assessor",
"role": "Legal Risk Specialist",
"goal": "Identify and assess legal risks",
"backstory": "Risk management expert in legal domain",
},
{
"name": "Document Drafter",
"role": "Legal Document Specialist",
"goal": "Draft legal documents and recommendations",
"backstory": "Legal document drafting expert",
},
],
"process": "sequential",
}
@dataclass
class AutoGenTemplate:
"""Template for AutoGen implementation."""
@staticmethod
def create_group_chat_config() -> Dict[str, Any]:
"""Create AutoGen group chat configuration."""
return {
"agents": [
{
"name": "analyst",
"system_message": "You are a financial analyst. Provide analysis based on data.",
"llm_config": {"model": "gpt-4", "temperature": 0.7},
},
{
"name": "researcher",
"system_message": "You are a market researcher. Research trends and competition.",
"llm_config": {"model": "gpt-4", "temperature": 0.7},
},
{
"name": "critic",
"system_message": "You are a critical evaluator. Challenge assumptions and findings.",
"llm_config": {"model": "gpt-4", "temperature": 0.7},
},
],
"group_chat_config": {
"agents": ["analyst", "researcher", "critic"],
"max_round": 10,
"speaker_selection_method": "auto",
},
}
@staticmethod
def create_hierarchical_structure() -> Dict[str, Any]:
"""Create hierarchical AutoGen structure."""
return {
"primary_agents": [
{
"name": "senior_analyst",
"role": "Senior analyst coordinating teams",
"subordinates": ["junior_analyst_1", "junior_analyst_2"],
}
],
"secondary_agents": [
{
"name": "junior_analyst_1",
"role": "Fundamental analysis specialist",
},
{
"name": "junior_analyst_2",
"role": "Technical analysis specialist",
},
],
}
@dataclass
class LangGraphTemplate:
"""Template for LangGraph workflow implementation."""
@staticmethod
def create_research_workflow() -> Dict[str, Any]:
"""Create LangGraph research workflow."""
return {
"name": "research_workflow",
"state_schema": {
"topic": str,
"research_findings": str,
"analysis": str,
"recommendations": str,
},
"nodes": [
{
"name": "researcher",
"agent": "research_agent",
"description": "Research the topic",
},
{
"name": "analyst",
"agent": "analyst_agent",
"description": "Analyze research findings",
},
{
"name": "critic",
"agent": "critic_agent",
"description": "Critique and improve",
},
{
"name": "writer",
"agent": "writer_agent",
"description": "Write final report",
},
],
"edges": [
("researcher", "analyst"),
("analyst", "critic"),
("critic", "writer"),
],
"entry_point": "researcher",
"exit_point": "writer",
}
@staticmethod
def create_dynamic_workflow() -> Dict[str, Any]:
"""Create dynamic LangGraph workflow with conditions."""
return {
"name": "dynamic_workflow",
"nodes": [
{
"name": "start",
"type": "input",
},
{
"name": "analyze",
"type": "agent",
"agent": "analyzer",
},
{
"name": "quality_check",
"type": "decision",
"condition": "analyze_quality > threshold",
},
{
"name": "refine",
"type": "agent",
"agent": "refiner",
},
{
"name": "end",
"type": "output",
},
],
"conditional_edges": [
{
"source": "quality_check",
"true_target": "end",
"false_target": "refine",
}
],
}
@dataclass
class SwarmTemplate:
"""Template for OpenAI Swarm implementation."""
@staticmethod
def create_customer_support_swarm() -> Dict[str, Any]:
"""Create customer support Swarm."""
return {
"agents": [
{
"name": "triage_agent",
"instructions": "Determine which specialist to route the customer to. "
"Ask clarifying questions if needed.",
"functions": [
"route_to_billing",
"route_to_technical",
"route_to_account",
],
},
{
"name": "billing_specialist",
"instructions": "Handle all billing and payment related questions. "
"Can access billing records.",
"tools": ["billing_system", "payment_processor"],
},
{
"name": "technical_support",
"instructions": "Handle technical issues and troubleshooting. "
"Can access diagnostic tools.",
"tools": ["diagnostic_tools", "knowledge_base"],
},
{
"name": "account_specialist",
"instructions": "Handle account management and profile changes.",
"tools": ["account_system"],
},
],
"handoff_functions": {
"route_to_billing": "Transfer to billing specialist",
"route_to_technical": "Transfer to technical support",
"route_to_account": "Transfer to account specialist",
},
}
@staticmethod
def create_sales_swarm() -> Dict[str, Any]:
"""Create sales team Swarm."""
return {
"agents": [
{
"name": "sales_router",
"instructions": "Route customer inquiries to appropriate sales agent",
"functions": ["route_to_enterprise", "route_to_smb"],
},
{
"name": "enterprise_sales",
"instructions": "Handle enterprise customer inquiries",
},
{
"name": "smb_sales",
"instructions": "Handle small business inquiries",
},
],
}
class AgentCommunicationManager:
"""Manage communication patterns between agents."""
def __init__(self, agents: Dict[str, Any]):
"""Initialize communication manager."""
self.agents = agents
self.message_queue = []
def broadcast_message(self, sender: str, message: str, recipients: List[str]):
"""Broadcast message to multiple agents."""
for recipient in recipients:
self.message_queue.append({
"from": sender,
"to": recipient,
"message": message,
"type": "broadcast",
})
def direct_message(self, sender: str, recipient: str, message: str):
"""Send direct message between agents."""
self.message_queue.append({
"from": sender,
"to": recipient,
"message": message,
"type": "direct",
})
def publish_shared_state(self, state_key: str, value: Any):
"""Publish to shared state (tool-mediated communication)."""
self.message_queue.append({
"type": "shared_state",
"key": state_key,
"value": value,
})
def get_pending_messages(self, agent: str) -> List[Dict]:
"""Get messages for specific agent."""
return [msg for msg in self.message_queue if msg.get("to") == agent]
def process_message_queue(self) -> Dict[str, Any]:
"""Process and summarize message queue."""
direct_messages = [m for m in self.message_queue if m["type"] == "direct"]
broadcasts = [m for m in self.message_queue if m["type"] == "broadcast"]
shared_states = [m for m in self.message_queue if m["type"] == "shared_state"]
return {
"direct_messages": len(direct_messages),
"broadcasts": len(broadcasts),
"shared_states": len(shared_states),
"total_messages": len(self.message_queue),
}
"""
Multi-Agent Orchestration Patterns
Implements sequential, parallel, hierarchical, and consensus orchestration.
"""
from typing import List, Dict, Any, Optional
import asyncio
from abc import ABC, abstractmethod
class Agent(ABC):
"""Base agent class."""
def __init__(self, name: str, role: str, goal: str):
"""Initialize agent."""
self.name = name
self.role = role
self.goal = goal
@abstractmethod
def work(self, task: str) -> str:
"""Execute task."""
pass
async def work_async(self, task: str) -> str:
"""Execute task asynchronously."""
return self.work(task)
class SimpleAgent(Agent):
"""Simple agent implementation."""
def __init__(self, name: str, role: str, goal: str):
"""Initialize simple agent."""
super().__init__(name, role, goal)
def work(self, task: str) -> str:
"""Simulate agent work."""
return f"{self.name}: Completed task - {task[:50]}..."
class SequentialOrchestrator:
"""Orchestrate agents to work sequentially."""
def __init__(self, agents: List[Agent]):
"""
Initialize orchestrator with agents.
Args:
agents: List of agents to orchestrate
"""
self.agents = agents
self.execution_log = []
def execute(self, initial_task: str) -> Dict[str, Any]:
"""
Execute agents sequentially.
Args:
initial_task: Initial task description
Returns:
Execution results dictionary
"""
current_input = initial_task
results = {}
for agent in self.agents:
result = agent.work(current_input)
results[agent.name] = result
self.execution_log.append({
"agent": agent.name,
"role": agent.role,
"task": current_input,
"result": result,
})
# Next agent uses this agent's output
current_input = result
return {
"type": "sequential",
"results": results,
"final_output": current_input,
"execution_log": self.execution_log,
}
class ParallelOrchestrator:
"""Orchestrate agents to work in parallel."""
def __init__(self, agents: List[Agent]):
"""Initialize parallel orchestrator."""
self.agents = agents
self.execution_log = []
async def execute_async(self, task: str) -> Dict[str, Any]:
"""
Execute agents in parallel.
Args:
task: Task description
Returns:
Execution results dictionary
"""
# Create async tasks for all agents
tasks = [agent.work_async(task) for agent in self.agents]
# Execute all in parallel
results_list = await asyncio.gather(*tasks)
results = {
agent.name: result
for agent, result in zip(self.agents, results_list)
}
self.execution_log.append({
"type": "parallel",
"task": task,
"agents": [a.name for a in self.agents],
"results": results,
})
return {
"type": "parallel",
"results": results,
"execution_log": self.execution_log,
}
def execute(self, task: str) -> Dict[str, Any]:
"""Execute agents synchronously (sequential fallback)."""
return asyncio.run(self.execute_async(task))
class HierarchicalOrchestrator:
"""Orchestrate agents in hierarchical structure."""
def __init__(self, manager_agent: Agent, specialist_teams: Dict[str, List[Agent]]):
"""
Initialize hierarchical orchestrator.
Args:
manager_agent: Manager agent
specialist_teams: Dict of team names to lists of agents
"""
self.manager = manager_agent
self.specialist_teams = specialist_teams
self.execution_log = []
def execute(self, main_task: str) -> Dict[str, Any]:
"""
Execute with hierarchical structure.
Args:
main_task: Main task for manager
Returns:
Execution results
"""
team_results = {}
# Manager assigns tasks to teams
for team_name, agents in self.specialist_teams.items():
# Each team works on their aspect
team_task = f"{main_task} - Team: {team_name}"
team_result = {}
for agent in agents:
result = agent.work(team_task)
team_result[agent.name] = result
team_results[team_name] = team_result
self.execution_log.append({
"team": team_name,
"agents": [a.name for a in agents],
"results": team_result,
})
# Manager synthesizes results
manager_result = self.manager.work(
f"Synthesize findings from: {list(team_results.keys())}"
)
return {
"type": "hierarchical",
"team_results": team_results,
"manager_synthesis": manager_result,
"execution_log": self.execution_log,
}
class ConsensusOrchestrator:
"""Orchestrate agent debate and consensus."""
def __init__(self, agents: List[Agent], mediator_agent: Agent):
"""Initialize consensus orchestrator."""
self.agents = agents
self.mediator = mediator_agent
self.debate_history = []
def execute(self, question: str, rounds: int = 2) -> Dict[str, Any]:
"""
Execute debate and reach consensus.
Args:
question: Question for debate
rounds: Number of debate rounds
Returns:
Consensus results
"""
# Round 1: Initial positions
positions = {}
for agent in self.agents:
position = agent.work(f"Argue your position on: {question}")
positions[agent.name] = position
self.debate_history.append({
"round": 1,
"agent": agent.name,
"position": position,
})
# Additional rounds: Response to others
for round_num in range(2, rounds + 1):
for agent in self.agents:
other_positions = {
name: pos
for name, pos in positions.items()
if name != agent.name
}
response = agent.work(
f"Respond to these positions: {str(other_positions)}"
)
self.debate_history.append({
"round": round_num,
"agent": agent.name,
"response": response,
})
# Mediator reaches consensus
consensus = self.mediator.work(
f"Synthesize consensus from debate on: {question}"
)
return {
"type": "consensus",
"question": question,
"initial_positions": positions,
"debate_rounds": rounds,
"consensus": consensus,
"debate_history": self.debate_history,
}
class AdaptiveOrchestrator:
"""Adapt orchestration based on progress."""
def __init__(self, agents: List[Agent]):
"""Initialize adaptive orchestrator."""
self.agents = agents
self.execution_log = []
def execute_with_adaptation(
self,
initial_task: str,
progress_threshold: float = 0.7,
quality_threshold: float = 0.6,
) -> Dict[str, Any]:
"""
Execute with adaptive workflow changes.
Args:
initial_task: Initial task
progress_threshold: Threshold for adding resources
quality_threshold: Threshold for adding validation
Returns:
Adaptive execution results
"""
results = {}
current_task = initial_task
active_agents = self.agents.copy()
for iteration in range(3):
# Execute with current agents
iteration_results = {}
for agent in active_agents:
result = agent.work(current_task)
iteration_results[agent.name] = result
results[f"iteration_{iteration}"] = iteration_results
# Assess progress
progress = self._calculate_progress(iteration_results)
quality = self._calculate_quality(iteration_results)
log_entry = {
"iteration": iteration,
"agents": [a.name for a in active_agents],
"progress": progress,
"quality": quality,
}
# Adapt based on progress
if progress < progress_threshold and iteration < 2:
# Add more agents
log_entry["adaptation"] = "Added specialist agent"
self.execution_log.append(log_entry)
elif quality < quality_threshold and iteration < 2:
# Add validation step
log_entry["adaptation"] = "Added validation agent"
self.execution_log.append(log_entry)
else:
self.execution_log.append(log_entry)
return {
"type": "adaptive",
"results": results,
"adaptations": self.execution_log,
}
@staticmethod
def _calculate_progress(results: Dict) -> float:
"""Calculate progress score."""
# Simple heuristic based on results
return min(len(results) / 3.0, 1.0)
@staticmethod
def _calculate_quality(results: Dict) -> float:
"""Calculate quality score."""
# Simple heuristic
return 0.7 # Placeholder
class WorkflowGraph:
"""Define workflow as directed acyclic graph (DAG)."""
def __init__(self):
"""Initialize workflow graph."""
self.nodes = {}
self.edges = []
def add_node(self, node_id: str, agent: Agent) -> None:
"""Add agent node."""
self.nodes[node_id] = agent
def add_edge(self, from_node: str, to_node: str) -> None:
"""Add dependency edge."""
self.edges.append((from_node, to_node))
def execute_dag(self, initial_task: str) -> Dict[str, Any]:
"""
Execute workflow as DAG.
Args:
initial_task: Initial task
Returns:
Execution results
"""
results = {}
ready_nodes = self._find_ready_nodes()
while ready_nodes:
for node_id in ready_nodes:
agent = self.nodes[node_id]
# Get input from dependencies
task_input = self._get_node_input(node_id, results, initial_task)
result = agent.work(task_input)
results[node_id] = result
ready_nodes = self._find_ready_nodes(completed=set(results.keys()))
return {
"type": "dag",
"results": results,
"nodes": list(self.nodes.keys()),
"edges": self.edges,
}
def _find_ready_nodes(self, completed: Optional[set] = None) -> List[str]:
"""Find nodes with all dependencies completed."""
if completed is None:
completed = set()
ready = []
for node_id in self.nodes:
if node_id not in completed:
dependencies = [
from_node
for from_node, to_node in self.edges
if to_node == node_id
]
if all(dep in completed for dep in dependencies):
ready.append(node_id)
return ready
def _get_node_input(
self, node_id: str, results: Dict, initial_task: str
) -> str:
"""Get input for node from dependencies."""
dependencies = [
from_node for from_node, to_node in self.edges if to_node == node_id
]
if not dependencies:
return initial_task
# Combine outputs from dependencies
return " + ".join(results.get(dep, "") for dep in dependencies)
# Multi-Agent Orchestration - Code Structure
This skill uses supporting Python files to keep documentation lean and maintainable.
## Directory Structure
```
multi-agent-orchestration/
├── SKILL.md # Main documentation (patterns, concepts)
├── README.md # This file
├── examples/ # Implementation examples
│ ├── orchestration_patterns.py # Sequential, parallel, hierarchical, consensus
│ └── framework_implementations.py # CrewAI, AutoGen, LangGraph, Swarm templates
└── scripts/ # Utility modules
├── agent_communication.py # Message broker, shared memory, protocols
├── workflow_management.py # Workflow execution and optimization
└── benchmarking.py # Performance and collaboration metrics
```
## Running Examples
### 1. Orchestration Patterns
```bash
python examples/orchestration_patterns.py
```
Demonstrates sequential, parallel, hierarchical, and consensus orchestration.
### 2. Framework Templates
```bash
python examples/framework_implementations.py
```
Templates and configurations for CrewAI, AutoGen, LangGraph, and Swarm frameworks.
## Using the Utilities
### Agent Communication
```python
from scripts.agent_communication import MessageBroker, SharedMemory, CommunicationProtocol
# Set up communication
broker = MessageBroker()
shared_memory = SharedMemory()
protocol = CommunicationProtocol(broker, shared_memory)
# Send messages between agents
protocol.request_analysis("agent_a", "agent_b", "Analyze this topic")
# Share findings
protocol.share_findings("agent_a", "analysis_results", {"findings": "..."})
# Get communication stats
stats = broker.get_statistics()
```
### Workflow Management
```python
from scripts.workflow_management import WorkflowExecutor, WorkflowOptimizer
# Create and execute workflow
executor = WorkflowExecutor()
workflow = executor.create_workflow("workflow_1", "Analysis Workflow")
# Add tasks
executor.add_task("workflow_1", "task_1", "researcher", "Research the topic")
executor.add_task("workflow_1", "task_2", "analyst", "Analyze findings", dependencies=["task_1"])
# Execute
results = executor.execute_workflow("workflow_1", executor_func)
# Analyze workflow
analysis = WorkflowOptimizer.analyze_dependencies(workflow)
print(f"Critical path: {analysis['critical_path']}")
```
### Benchmarking
```python
from scripts.benchmarking import TeamBenchmark, AgentEffectiveness, CollaborationMetrics
# Benchmark team performance
benchmark = TeamBenchmark()
result = benchmark.run_benchmark("sequential_test", orchestrator, test_data)
# Track agent effectiveness
effectiveness = AgentEffectiveness()
effectiveness.record_agent_task("agent_a", "task_1", success=True, quality_score=0.95, duration=2.5)
# Get agent rankings
rankings = effectiveness.rank_agents()
for rank, agent, score, metrics in rankings:
print(f"{rank}. {agent}: {score:.2f}")
# Analyze collaboration
collaboration = CollaborationMetrics()
collaboration.record_interaction("agent_a", "agent_b", "request", response_time=0.5, successful=True)
interaction_metrics = collaboration.get_interaction_metrics()
```
## Integration with SKILL.md
- SKILL.md contains conceptual information, orchestration patterns, and best practices
- Code examples are in `examples/` for clarity and runnable implementations
- Utilities are in `scripts/` for modular, reusable components
- This keeps token costs low while maintaining full functionality
## Orchestration Patterns Covered
1. **Sequential Orchestration** - Tasks execute one after another
2. **Parallel Orchestration** - Multiple agents work simultaneously
3. **Hierarchical Orchestration** - Manager coordinates specialist teams
4. **Consensus-Based** - Agents debate and reach consensus
5. **Adaptive Workflows** - Orchestration changes based on progress
6. **DAG-Based** - Workflow as directed acyclic graph
## Framework Implementations
- **CrewAI** - Clear roles, hierarchical structure
- **AutoGen** - Multi-turn conversations, group discussions
- **LangGraph** - State management, complex workflows
- **Swarm** - Simple handoffs, conversational workflows
## Key Features
- **Token Efficient**: Modular code structure reduces LLM context usage
- **Production Ready**: Includes monitoring, optimization, and benchmarking
- **Framework Agnostic**: Works with any agent framework
- **Communication Patterns**: Direct, tool-mediated, and manager-based
- **Performance Metrics**: Team and individual agent effectiveness tracking
## Communication Patterns
- **Direct Communication**: Agent-to-agent message passing
- **Tool-Mediated**: Agents use shared memory/database
- **Manager-Based**: Central coordinator manages communication
- **Broadcast**: One-to-many messaging
## Next Steps
1. Define agent roles and expertise
2. Choose orchestration pattern (sequential, parallel, hierarchical)
3. Select communication approach (direct, shared memory, manager)
4. Implement workflow with task definitions
5. Set up monitoring and metrics
6. Benchmark and optimize
7. Deploy and iterate
"""
Agent Communication Management
Handle agent-to-agent communication, message passing, and shared state.
"""
from typing import Dict, List, Optional, Any, Callable
from dataclasses import dataclass, field
from enum import Enum
import json
class MessageType(Enum):
"""Types of messages between agents."""
DIRECT = "direct"
BROADCAST = "broadcast"
REQUEST = "request"
RESPONSE = "response"
FEEDBACK = "feedback"
ERROR = "error"
@dataclass
class Message:
"""Message between agents."""
sender: str
recipient: str
content: str
message_type: MessageType
timestamp: float = field(default_factory=lambda: 0)
metadata: Dict[str, Any] = field(default_factory=dict)
def to_dict(self) -> Dict:
"""Convert to dictionary."""
return {
"sender": self.sender,
"recipient": self.recipient,
"content": self.content,
"type": self.message_type.value,
"timestamp": self.timestamp,
"metadata": self.metadata,
}
class MessageBroker:
"""Central message broker for agent communication."""
def __init__(self):
"""Initialize message broker."""
self.message_queue: List[Message] = []
self.agent_inboxes: Dict[str, List[Message]] = {}
self.message_handlers: Dict[MessageType, List[Callable]] = {}
def send_message(self, message: Message) -> bool:
"""
Send message from one agent to another.
Args:
message: Message object
Returns:
Whether message was delivered
"""
self.message_queue.append(message)
# Add to recipient's inbox
if message.recipient not in self.agent_inboxes:
self.agent_inboxes[message.recipient] = []
self.agent_inboxes[message.recipient].append(message)
# Trigger handlers
self._trigger_handlers(message)
return True
def broadcast_message(self, sender: str, content: str, recipients: List[str]):
"""
Broadcast message to multiple agents.
Args:
sender: Sending agent
content: Message content
recipients: List of recipient agents
"""
for recipient in recipients:
message = Message(
sender=sender,
recipient=recipient,
content=content,
message_type=MessageType.BROADCAST,
)
self.send_message(message)
def request_response(
self, sender: str, recipient: str, content: str, timeout: float = 5.0
) -> Optional[Message]:
"""
Send request and wait for response.
Args:
sender: Requesting agent
recipient: Agent to respond
content: Request content
timeout: Response timeout in seconds
Returns:
Response message or None
"""
message = Message(
sender=sender,
recipient=recipient,
content=content,
message_type=MessageType.REQUEST,
metadata={"timeout": timeout},
)
self.send_message(message)
# Placeholder - wait for response
# In production, implement actual timeout/wait mechanism
return None
def get_inbox(self, agent: str) -> List[Message]:
"""Get messages for specific agent."""
return self.agent_inboxes.get(agent, [])
def clear_inbox(self, agent: str) -> None:
"""Clear agent's inbox."""
self.agent_inboxes[agent] = []
def register_handler(
self, message_type: MessageType, handler: Callable
) -> None:
"""Register handler for message type."""
if message_type not in self.message_handlers:
self.message_handlers[message_type] = []
self.message_handlers[message_type].append(handler)
def _trigger_handlers(self, message: Message) -> None:
"""Trigger registered handlers."""
handlers = self.message_handlers.get(message.message_type, [])
for handler in handlers:
try:
handler(message)
except Exception:
pass
def get_statistics(self) -> Dict[str, Any]:
"""Get communication statistics."""
type_counts = {}
for message in self.message_queue:
msg_type = message.message_type.value
type_counts[msg_type] = type_counts.get(msg_type, 0) + 1
return {
"total_messages": len(self.message_queue),
"by_type": type_counts,
"total_agents": len(self.agent_inboxes),
"agents": list(self.agent_inboxes.keys()),
}
class SharedMemory:
"""Shared memory for tool-mediated agent communication."""
def __init__(self):
"""Initialize shared memory."""
self.memory: Dict[str, Any] = {}
self.access_log: List[Dict] = []
def write(self, key: str, value: Any, agent: str = "system") -> None:
"""
Write to shared memory.
Args:
key: Memory key
value: Value to store
agent: Agent writing
"""
self.memory[key] = {
"value": value,
"writer": agent,
"access_count": 0,
}
self.access_log.append({
"action": "write",
"key": key,
"agent": agent,
})
def read(self, key: str, agent: str = "system") -> Optional[Any]:
"""
Read from shared memory.
Args:
key: Memory key
agent: Agent reading
Returns:
Stored value or None
"""
if key in self.memory:
entry = self.memory[key]
entry["access_count"] += 1
self.access_log.append({
"action": "read",
"key": key,
"agent": agent,
})
return entry["value"]
return None
def append(self, key: str, value: Any, agent: str = "system") -> None:
"""Append to list in shared memory."""
if key not in self.memory:
self.memory[key] = {
"value": [],
"writer": agent,
"access_count": 0,
}
if isinstance(self.memory[key]["value"], list):
self.memory[key]["value"].append(value)
def get_all(self) -> Dict[str, Any]:
"""Get all shared memory contents."""
return {
key: entry["value"] for key, entry in self.memory.items()
}
def get_statistics(self) -> Dict[str, Any]:
"""Get memory access statistics."""
total_accesses = sum(
entry["access_count"] for entry in self.memory.values()
)
return {
"total_keys": len(self.memory),
"total_accesses": total_accesses,
"access_log_size": len(self.access_log),
}
class ContextManager:
"""Manage context sharing between agents."""
def __init__(self):
"""Initialize context manager."""
self.contexts: Dict[str, Dict[str, Any]] = {}
self.global_context: Dict[str, Any] = {}
def create_context(self, context_id: str, initial_data: Optional[Dict] = None) -> None:
"""Create new context."""
self.contexts[context_id] = initial_data or {}
def update_context(self, context_id: str, data: Dict) -> None:
"""Update context data."""
if context_id in self.contexts:
self.contexts[context_id].update(data)
def get_context(self, context_id: str) -> Dict[str, Any]:
"""Get context data."""
return self.contexts.get(context_id, {})
def set_global_context(self, key: str, value: Any) -> None:
"""Set global context variable."""
self.global_context[key] = value
def get_global_context(self, key: str) -> Optional[Any]:
"""Get global context variable."""
return self.global_context.get(key)
def context_to_string(self, context_id: str) -> str:
"""Convert context to formatted string."""
context = self.get_context(context_id)
return json.dumps(context, indent=2)
class CommunicationProtocol:
"""Define communication protocol between agents."""
def __init__(self, broker: MessageBroker, shared_memory: SharedMemory):
"""Initialize protocol."""
self.broker = broker
self.shared_memory = shared_memory
def request_analysis(
self, requester: str, analyzer: str, subject: str
) -> None:
"""Request analysis from another agent."""
message = Message(
sender=requester,
recipient=analyzer,
content=f"Analyze: {subject}",
message_type=MessageType.REQUEST,
metadata={"action": "analyze"},
)
self.broker.send_message(message)
def share_findings(self, source_agent: str, key: str, findings: Dict) -> None:
"""Share findings through shared memory."""
self.shared_memory.write(key, findings, source_agent)
def aggregate_results(
self, agents: List[str], result_key: str
) -> Dict[str, Any]:
"""Aggregate results from multiple agents."""
results = {}
for agent in agents:
agent_results = self.shared_memory.read(f"{agent}_{result_key}")
if agent_results:
results[agent] = agent_results
return results
def notify_status(self, agent: str, status: str) -> None:
"""Notify status update."""
message = Message(
sender=agent,
recipient="orchestrator",
content=f"Status: {status}",
message_type=MessageType.FEEDBACK,
)
self.broker.send_message(message)
def error_propagation(self, source_agent: str, error: str) -> None:
"""Propagate error to relevant agents."""
message = Message(
sender=source_agent,
recipient="orchestrator",
content=f"Error: {error}",
message_type=MessageType.ERROR,
)
self.broker.send_message(message)
"""
Multi-Agent System Benchmarking
Evaluate team performance and agent effectiveness.
"""
from typing import Dict, List, Any, Callable, Optional
from dataclasses import dataclass
import time
import statistics
@dataclass
class BenchmarkResult:
"""Result from benchmark run."""
test_name: str
total_time: float
task_count: int
success_count: int
failure_count: int
quality_score: float
cost_tokens: int
class TeamBenchmark:
"""Benchmark multi-agent team performance."""
def __init__(self):
"""Initialize benchmarking suite."""
self.results: List[BenchmarkResult] = []
self.agent_metrics: Dict[str, Dict] = {}
def run_benchmark(
self,
test_name: str,
orchestrator,
test_data: List[Dict],
quality_metric: Optional[Callable] = None,
) -> BenchmarkResult:
"""
Run benchmark test.
Args:
test_name: Name of benchmark
orchestrator: Orchestrator instance
test_data: Test cases
quality_metric: Function to evaluate quality
Returns:
Benchmark result
"""
start_time = time.time()
results = []
costs = []
for test_case in test_data:
try:
result = orchestrator.execute(test_case)
results.append(result)
# Assume cost in test_case
costs.append(test_case.get("cost", 0))
except Exception:
pass
end_time = time.time()
success_count = len(results)
failure_count = len(test_data) - success_count
total_time = end_time - start_time
# Calculate quality score
quality_score = (
quality_metric(results) if quality_metric else success_count / len(test_data)
)
benchmark_result = BenchmarkResult(
test_name=test_name,
total_time=total_time,
task_count=len(test_data),
success_count=success_count,
failure_count=failure_count,
quality_score=quality_score,
cost_tokens=sum(costs),
)
self.results.append(benchmark_result)
return benchmark_result
def compare_orchestration_methods(
self,
methods: Dict[str, Callable],
test_data: List[Dict],
) -> Dict[str, Any]:
"""
Compare different orchestration methods.
Args:
methods: Dict of method name to orchestrator
test_data: Test cases
Returns:
Comparison results
"""
comparison = {}
for method_name, orchestrator in methods.items():
result = self.run_benchmark(method_name, orchestrator, test_data)
comparison[method_name] = {
"total_time": result.total_time,
"success_rate": result.success_count / result.task_count,
"quality_score": result.quality_score,
"efficiency": result.success_count / (result.total_time + 0.001),
"cost_per_success": (
result.cost_tokens / result.success_count
if result.success_count > 0
else float("inf")
),
}
return comparison
def get_summary(self) -> Dict[str, Any]:
"""Get benchmark summary."""
if not self.results:
return {"status": "no_results"}
times = [r.total_time for r in self.results]
success_rates = [
r.success_count / r.task_count for r in self.results
]
quality_scores = [r.quality_score for r in self.results]
return {
"total_benchmarks": len(self.results),
"avg_time": statistics.mean(times),
"median_time": statistics.median(times),
"avg_success_rate": statistics.mean(success_rates),
"avg_quality": statistics.mean(quality_scores),
"benchmarks": [r.__dict__ for r in self.results],
}
class AgentEffectiveness:
"""Measure individual agent effectiveness."""
def __init__(self):
"""Initialize effectiveness tracker."""
self.agent_stats: Dict[str, Dict] = {}
def record_agent_task(
self,
agent: str,
task_id: str,
success: bool,
quality_score: float,
duration: float,
) -> None:
"""Record agent task execution."""
if agent not in self.agent_stats:
self.agent_stats[agent] = {
"tasks": [],
"successes": 0,
"failures": 0,
}
stats = self.agent_stats[agent]
stats["tasks"].append({
"task_id": task_id,
"success": success,
"quality": quality_score,
"duration": duration,
})
if success:
stats["successes"] += 1
else:
stats["failures"] += 1
def get_agent_metrics(self, agent: str) -> Dict[str, Any]:
"""Get metrics for specific agent."""
if agent not in self.agent_stats:
return {"status": "no_data"}
stats = self.agent_stats[agent]
tasks = stats["tasks"]
if not tasks:
return {"status": "no_tasks"}
success_rate = stats["successes"] / (stats["successes"] + stats["failures"])
quality_scores = [t["quality"] for t in tasks]
durations = [t["duration"] for t in tasks]
return {
"agent": agent,
"total_tasks": len(tasks),
"success_rate": success_rate,
"avg_quality": statistics.mean(quality_scores),
"avg_duration": statistics.mean(durations),
"reliability": success_rate, # Alias for clarity
}
def rank_agents(self) -> List[tuple]:
"""Rank agents by effectiveness."""
rankings = []
for agent in self.agent_stats.keys():
metrics = self.get_agent_metrics(agent)
if "success_rate" in metrics:
score = (
metrics["success_rate"] * 0.4 +
metrics["avg_quality"] * 0.4 +
(1 - min(metrics["avg_duration"] / 10.0, 1.0)) * 0.2
)
rankings.append((agent, score, metrics))
rankings.sort(key=lambda x: x[1], reverse=True)
return rankings
def get_team_report(self) -> Dict[str, Any]:
"""Get team effectiveness report."""
rankings = self.rank_agents()
return {
"total_agents": len(self.agent_stats),
"rankings": [
{
"rank": i + 1,
"agent": agent,
"score": score,
"metrics": metrics,
}
for i, (agent, score, metrics) in enumerate(rankings)
],
}
class CollaborationMetrics:
"""Measure collaboration effectiveness between agents."""
def __init__(self):
"""Initialize collaboration metrics."""
self.interactions: List[Dict] = []
def record_interaction(
self,
agent_a: str,
agent_b: str,
message: str,
response_time: float,
successful: bool,
) -> None:
"""Record agent-to-agent interaction."""
self.interactions.append({
"agent_a": agent_a,
"agent_b": agent_b,
"message": message,
"response_time": response_time,
"successful": successful,
})
def get_collaboration_graph(self) -> Dict[str, List[str]]:
"""Get collaboration graph between agents."""
graph = {}
for interaction in self.interactions:
agent_a = interaction["agent_a"]
agent_b = interaction["agent_b"]
if agent_a not in graph:
graph[agent_a] = []
if agent_b not in graph[agent_a]:
graph[agent_a].append(agent_b)
return graph
def get_interaction_metrics(self) -> Dict[str, Any]:
"""Get interaction metrics."""
if not self.interactions:
return {"total_interactions": 0}
response_times = [i["response_time"] for i in self.interactions]
success_rate = sum(1 for i in self.interactions if i["successful"]) / len(
self.interactions
)
return {
"total_interactions": len(self.interactions),
"success_rate": success_rate,
"avg_response_time": statistics.mean(response_times),
"median_response_time": statistics.median(response_times),
"max_response_time": max(response_times),
"collaboration_score": success_rate * (1 - min(statistics.mean(response_times) / 10.0, 1.0)),
}
def get_agent_collaboration_analysis(self, agent: str) -> Dict[str, Any]:
"""Get collaboration analysis for specific agent."""
agent_interactions = [
i for i in self.interactions
if i["agent_a"] == agent or i["agent_b"] == agent
]
if not agent_interactions:
return {"agent": agent, "status": "no_interactions"}
partners = set()
for interaction in agent_interactions:
if interaction["agent_a"] == agent:
partners.add(interaction["agent_b"])
else:
partners.add(interaction["agent_a"])
success_rate = sum(
1 for i in agent_interactions if i["successful"]
) / len(agent_interactions)
return {
"agent": agent,
"collaboration_partners": list(partners),
"total_interactions": len(agent_interactions),
"collaboration_success_rate": success_rate,
}
def create_benchmark_suite() -> Dict[str, Callable]:
"""Create standard benchmark suite."""
return {
"sequential_tasks": lambda orchestrator: orchestrator.execute(
{"type": "sequential", "task_count": 5}
),
"parallel_tasks": lambda orchestrator: orchestrator.execute(
{"type": "parallel", "task_count": 10}
),
"complex_workflow": lambda orchestrator: orchestrator.execute(
{"type": "complex", "task_count": 20}
),
"error_handling": lambda orchestrator: orchestrator.execute(
{"type": "with_errors", "task_count": 10}
),
}
"""
Workflow Management for Multi-Agent Systems
Handle workflow execution, monitoring, and optimization.
"""
from typing import Dict, List, Any, Optional, Callable
from enum import Enum
from dataclasses import dataclass, field
import time
class WorkflowStatus(Enum):
"""Workflow execution status."""
PENDING = "pending"
RUNNING = "running"
PAUSED = "paused"
COMPLETED = "completed"
FAILED = "failed"
class TaskStatus(Enum):
"""Task execution status."""
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
SKIPPED = "skipped"
@dataclass
class Task:
"""Task to be executed by an agent."""
task_id: str
agent: str
description: str
status: TaskStatus = TaskStatus.PENDING
result: Optional[str] = None
error: Optional[str] = None
start_time: float = field(default_factory=time.time)
end_time: Optional[float] = None
dependencies: List[str] = field(default_factory=list)
@dataclass
class Workflow:
"""Workflow orchestration."""
workflow_id: str
name: str
tasks: Dict[str, Task] = field(default_factory=dict)
status: WorkflowStatus = WorkflowStatus.PENDING
start_time: Optional[float] = None
end_time: Optional[float] = None
class WorkflowExecutor:
"""Execute workflows with multiple agents."""
def __init__(self):
"""Initialize workflow executor."""
self.workflows: Dict[str, Workflow] = {}
self.execution_history: List[Dict] = []
def create_workflow(self, workflow_id: str, name: str) -> Workflow:
"""Create new workflow."""
workflow = Workflow(workflow_id=workflow_id, name=name)
self.workflows[workflow_id] = workflow
return workflow
def add_task(
self,
workflow_id: str,
task_id: str,
agent: str,
description: str,
dependencies: Optional[List[str]] = None,
) -> Task:
"""Add task to workflow."""
task = Task(
task_id=task_id,
agent=agent,
description=description,
dependencies=dependencies or [],
)
self.workflows[workflow_id].tasks[task_id] = task
return task
def execute_workflow(
self, workflow_id: str, executor_func: Callable
) -> Dict[str, Any]:
"""
Execute workflow.
Args:
workflow_id: Workflow ID
executor_func: Function to execute tasks
Returns:
Execution results
"""
workflow = self.workflows[workflow_id]
workflow.status = WorkflowStatus.RUNNING
workflow.start_time = time.time()
executed_tasks = set()
results = {}
while len(executed_tasks) < len(workflow.tasks):
# Find ready tasks
ready_tasks = self._get_ready_tasks(workflow, executed_tasks)
if not ready_tasks:
# Check if workflow is stuck
if len(executed_tasks) > 0:
break
for task_id in ready_tasks:
task = workflow.tasks[task_id]
task.status = TaskStatus.RUNNING
try:
# Execute task
result = executor_func(task)
task.result = result
task.status = TaskStatus.COMPLETED
results[task_id] = result
except Exception as e:
task.error = str(e)
task.status = TaskStatus.FAILED
results[task_id] = None
task.end_time = time.time()
executed_tasks.add(task_id)
# Finalize workflow
workflow.end_time = time.time()
if all(task.status == TaskStatus.COMPLETED for task in workflow.tasks.values()):
workflow.status = WorkflowStatus.COMPLETED
else:
workflow.status = WorkflowStatus.FAILED
execution_record = {
"workflow_id": workflow_id,
"status": workflow.status.value,
"duration": workflow.end_time - workflow.start_time,
"results": results,
}
self.execution_history.append(execution_record)
return results
def _get_ready_tasks(
self, workflow: Workflow, executed: set
) -> List[str]:
"""Get tasks ready to execute."""
ready = []
for task_id, task in workflow.tasks.items():
if task_id not in executed and task.status == TaskStatus.PENDING:
# Check if all dependencies are complete
deps_met = all(dep in executed for dep in task.dependencies)
if deps_met:
ready.append(task_id)
return ready
def get_workflow_status(self, workflow_id: str) -> Dict[str, Any]:
"""Get workflow status."""
workflow = self.workflows[workflow_id]
return {
"id": workflow.workflow_id,
"name": workflow.name,
"status": workflow.status.value,
"tasks": {
task_id: task.status.value
for task_id, task in workflow.tasks.items()
},
}
class WorkflowOptimizer:
"""Optimize workflow execution."""
@staticmethod
def analyze_dependencies(workflow: Workflow) -> Dict[str, Any]:
"""Analyze task dependencies."""
dep_graph = {}
for task_id, task in workflow.tasks.items():
dep_graph[task_id] = task.dependencies
# Find critical path
critical_path = WorkflowOptimizer._find_critical_path(
dep_graph, workflow.tasks
)
# Find parallelizable tasks
parallel_groups = WorkflowOptimizer._find_parallel_groups(dep_graph)
return {
"dependency_graph": dep_graph,
"critical_path": critical_path,
"parallelizable_groups": parallel_groups,
}
@staticmethod
def _find_critical_path(dep_graph: Dict, tasks: Dict) -> List[str]:
"""Find tasks on critical path."""
# Simple implementation - actual critical path is more complex
return list(dep_graph.keys())
@staticmethod
def _find_parallel_groups(dep_graph: Dict) -> List[List[str]]:
"""Find groups of tasks that can execute in parallel."""
groups = []
remaining = set(dep_graph.keys())
while remaining:
# Find tasks with no dependencies in remaining set
independent = [
task
for task in remaining
if not any(dep in remaining for dep in dep_graph.get(task, []))
]
if independent:
groups.append(independent)
remaining -= set(independent)
else:
break
return groups
@staticmethod
def estimate_execution_time(
workflow: Workflow, task_times: Dict[str, float]
) -> float:
"""Estimate total execution time."""
parallel_groups = WorkflowOptimizer._find_parallel_groups({
task_id: task.dependencies
for task_id, task in workflow.tasks.items()
})
total_time = 0
for group in parallel_groups:
group_time = max(
task_times.get(task_id, 1.0) for task_id in group
)
total_time += group_time
return total_time
@staticmethod
def suggest_parallelization(workflow: Workflow) -> List[Dict[str, Any]]:
"""Suggest ways to parallelize workflow."""
suggestions = []
dep_graph = {
task_id: task.dependencies
for task_id, task in workflow.tasks.items()
}
# Find sequential chains that could be parallelized
for task_id, dependencies in dep_graph.items():
if len(dependencies) == 0:
suggestions.append({
"task": task_id,
"suggestion": "Can be parallelized with other independent tasks",
})
return suggestions
class WorkflowMonitor:
"""Monitor workflow execution."""
def __init__(self):
"""Initialize monitor."""
self.events: List[Dict] = []
def record_event(
self, workflow_id: str, task_id: str, event_type: str, data: Dict
) -> None:
"""Record workflow event."""
event = {
"workflow_id": workflow_id,
"task_id": task_id,
"event_type": event_type,
"timestamp": time.time(),
"data": data,
}
self.events.append(event)
def get_workflow_metrics(self, workflow_id: str) -> Dict[str, Any]:
"""Get workflow metrics."""
workflow_events = [e for e in self.events if e["workflow_id"] == workflow_id]
task_times = {}
for event in workflow_events:
task_id = event["task_id"]
if event["event_type"] == "start":
task_times[task_id] = {"start": event["timestamp"]}
elif event["event_type"] == "complete":
if task_id in task_times:
task_times[task_id]["end"] = event["timestamp"]
# Calculate durations
durations = {
task_id: times.get("end", time.time()) - times["start"]
for task_id, times in task_times.items()
}
return {
"total_tasks": len(task_times),
"task_durations": durations,
"avg_duration": sum(durations.values()) / len(durations)
if durations
else 0,
"max_duration": max(durations.values()) if durations else 0,
}
def get_performance_report(self) -> Dict[str, Any]:
"""Get overall performance report."""
if not self.events:
return {"status": "no_events"}
workflow_ids = set(e["workflow_id"] for e in self.events)
report = {}
for workflow_id in workflow_ids:
report[workflow_id] = self.get_workflow_metrics(workflow_id)
return report
---
name: multi-agent-orchestration
description: Design and coordinate multi-agent systems where specialized agents work together to solve complex problems. Covers agent communication, task delegation, workflow orchestration, and result aggregation. Use when building coordinated agent teams, complex workflows, or systems requiring specialized expertise across domains.
---
# Multi-Agent Orchestration
Design and orchestrate sophisticated multi-agent systems where specialized agents collaborate to solve complex problems, combining different expertise and perspectives.
## Quick Start
Get started with multi-agent implementations in the examples and utilities:
- **Examples**: See [`examples/`](examples/) directory for complete implementations:
- [`orchestration_patterns.py`](examples/orchestration_patterns.py) - Sequential, parallel, hierarchical, and consensus orchestration
- [`framework_implementations.py`](examples/framework_implementations.py) - Templates for CrewAI, AutoGen, LangGraph, and Swarm
- **Utilities**: See [`scripts/`](scripts/) directory for helper modules:
- [`agent_communication.py`](scripts/agent_communication.py) - Message broker, shared memory, and communication protocols
- [`workflow_management.py`](scripts/workflow_management.py) - Workflow execution, optimization, and monitoring
- [`benchmarking.py`](scripts/benchmarking.py) - Team performance and agent effectiveness metrics
## Overview
Multi-agent systems decompose complex problems into specialized sub-tasks, assigning each to an agent with relevant expertise, then coordinating their work toward a unified goal.
### When Multi-Agent Systems Shine
- **Complex Workflows**: Tasks requiring multiple specialized roles
- **Domain-Specific Expertise**: Finance, legal, HR, engineering need different knowledge
- **Parallel Processing**: Multiple agents work on different aspects simultaneously
- **Collaborative Reasoning**: Agents debate, refine, and improve solutions
- **Resilience**: Failures in one agent don't break the entire system
- **Scalability**: Easy to add new specialized agents
### Architecture Overview
```
User Request
Orchestrator
├→ Agent 1 (Specialist) → Task 1
├→ Agent 2 (Specialist) → Task 2
├→ Agent 3 (Specialist) → Task 3
Result Aggregator
Final Response
```
## Core Concepts
### Agent Definition
An agent is defined by:
- **Role**: What responsibility does it have? (e.g., "Financial Analyst")
- **Goal**: What should it accomplish? (e.g., "Analyze financial risks")
- **Expertise**: What knowledge/tools does it have?
- **Tools**: What capabilities can it access?
- **Context**: What information does it need to work effectively?
### Orchestration Patterns
#### 1. Sequential Orchestration
- Agents work one after another
- Each agent uses output from previous agent
- **Use Case**: Steps must follow order (research → analysis → writing)
#### 2. Parallel Orchestration
- Multiple agents work simultaneously
- Results aggregated at the end
- **Use Case**: Independent tasks (analyze competitors, market, users)
#### 3. Hierarchical Orchestration
- Senior agent delegates to junior agents
- Manager coordinates flow
- **Use Case**: Large projects with oversight
#### 4. Consensus-Based Orchestration
- Multiple agents analyze problem
- Debate and refine ideas
- Vote or reach consensus
- **Use Case**: Complex decisions needing multiple perspectives
#### 5. Tool-Mediated Orchestration
- Agents use shared tools/databases
- Minimal direct communication
- **Use Case**: Large systems, indirect coordination
## Multi-Agent Team Examples
### Finance Team
```
Coordinator Agent
├→ Market Analyst Agent
│ ├ Tools: Market data API, financial news
│ └ Task: Analyze market conditions
├→ Financial Analyst Agent
│ ├ Tools: Financial statements, ratio calculations
│ └ Task: Analyze company financials
├→ Risk Manager Agent
│ ├ Tools: Risk models, scenario analysis
│ └ Task: Assess investment risks
└→ Report Writer Agent
├ Tools: Document generation
└ Task: Synthesize findings into report
```
### Legal Team
```
Case Manager Agent (Coordinator)
├→ Contract Analyzer Agent
│ └ Task: Review contract terms
├→ Precedent Research Agent
│ └ Task: Find relevant case law
├→ Risk Assessor Agent
│ └ Task: Identify legal risks
└→ Document Drafter Agent
└ Task: Prepare legal documents
```
### Customer Support Team
```
Support Coordinator
├→ Issue Classifier Agent
│ └ Task: Categorize customer issue
├→ Knowledge Base Agent
│ └ Task: Find relevant documentation
├→ Escalation Agent
│ └ Task: Determine if human escalation needed
└→ Solution Synthesizer Agent
└ Task: Prepare comprehensive response
```
## Implementation Frameworks
### 1. CrewAI
**Best For**: Teams with clear roles and hierarchical structure
```python
from crewai import Agent, Task, Crew
# Define agents
analyst = Agent(
role="Financial Analyst",
goal="Analyze financial data and provide insights",
backstory="Expert in financial markets with 10+ years experience"
)
researcher = Agent(
role="Market Researcher",
goal="Research market trends and competition",
backstory="Data-driven researcher specializing in market analysis"
)
# Define tasks
analysis_task = Task(
description="Analyze Q3 financial results for {company}",
agent=analyst,
tools=[financial_tool, data_tool]
)
research_task = Task(
description="Research competitive landscape in {market}",
agent=researcher,
tools=[web_search_tool, industry_data_tool]
)
# Create crew and execute
crew = Crew(
agents=[analyst, researcher],
tasks=[analysis_task, research_task],
process=Process.sequential
)
result = crew.kickoff(inputs={"company": "TechCorp", "market": "AI"})
```
### 2. AutoGen (Microsoft)
**Best For**: Complex multi-turn conversations and negotiations
```python
from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager
# Define agents
analyst = AssistantAgent(
name="analyst",
system_message="You are a financial analyst..."
)
researcher = AssistantAgent(
name="researcher",
system_message="You are a market researcher..."
)
# Create group chat
groupchat = GroupChat(
agents=[analyst, researcher],
messages=[],
max_round=10,
speaker_selection_method="auto"
)
# Manage group conversation
manager = GroupChatManager(groupchat=groupchat)
# User proxy to initiate conversation
user = UserProxyAgent(name="user")
# Have conversation
user.initiate_chat(
manager,
message="Analyze if Company X should invest in Y market"
)
```
### 3. LangGraph
**Best For**: Complex workflows with state management
```python
from langgraph.graph import Graph, StateGraph
from langgraph.prebuilt import create_agent_executor
# Define state
class AgentState:
research_findings: str
analysis: str
recommendations: str
# Create graph
graph = StateGraph(AgentState)
# Add nodes for each agent
graph.add_node("researcher", research_agent)
graph.add_node("analyst", analyst_agent)
graph.add_node("writer", writer_agent)
# Define edges (workflow)
graph.add_edge("researcher", "analyst")
graph.add_edge("analyst", "writer")
# Set entry/exit points
graph.set_entry_point("researcher")
graph.set_finish_point("writer")
# Compile and run
workflow = graph.compile()
result = workflow.invoke({"topic": "AI trends"})
```
### 4. OpenAI Swarm
**Best For**: Simple agent handoffs and conversational workflows
```python
from swarm import Agent, Swarm
# Define agents
triage_agent = Agent(
name="Triage Agent",
instructions="Determine which specialist to route the customer to"
)
billing_agent = Agent(
name="Billing Specialist",
instructions="Handle billing and payment questions"
)
technical_agent = Agent(
name="Technical Support",
instructions="Handle technical issues"
)
# Define handoff functions
def route_to_billing(reason: str):
return billing_agent
def route_to_technical(reason: str):
return technical_agent
# Add tools to triage agent
triage_agent.functions = [route_to_billing, route_to_technical]
# Execute swarm
client = Swarm()
response = client.run(
agent=triage_agent,
messages=[{"role": "user", "content": "I have a billing question"}]
)
```
## Orchestration Patterns
### Pattern 1: Sequential Task Chain
Agents execute tasks in sequence, each building on previous results:
```python
# Task 1: Research
research_output = research_agent.work("Analyze AI market trends")
# Task 2: Analysis (uses research output)
analysis = analyst_agent.work(f"Analyze these findings: {research_output}")
# Task 3: Report (uses analysis)
report = writer_agent.work(f"Write report on: {analysis}")
```
**When to Use**: Steps have dependencies, each builds on previous
### Pattern 2: Parallel Execution
Multiple agents work simultaneously, results combined:
```python
import asyncio
async def parallel_teams():
# All agents work in parallel
market_task = market_agent.work_async("Analyze market")
technical_task = tech_agent.work_async("Analyze technology")
user_task = user_agent.work_async("Analyze user needs")
# Wait for all to complete
market_results, tech_results, user_results = await asyncio.gather(
market_task, technical_task, user_task
)
# Synthesize results
return synthesize(market_results, tech_results, user_results)
```
**When to Use**: Independent analyses, need quick results, want diversity
### Pattern 3: Hierarchical Structure
Manager agent coordinates specialists:
```python
manager_agent.orchestrate({
"market_analysis": {
"agents": [competitor_analyst, trend_analyst],
"task": "Comprehensive market analysis"
},
"technical_evaluation": {
"agents": [architecture_agent, security_agent],
"task": "Technical feasibility assessment"
},
"synthesis": {
"agents": [strategy_agent],
"task": "Create strategic recommendations"
}
})
```
**When to Use**: Clear hierarchy, different teams, complex coordination
### Pattern 4: Debate & Consensus
Multiple agents discuss and reach consensus:
```python
agents = [bull_agent, bear_agent, neutral_agent]
question = "Should we invest in this startup?"
# Debate round 1
arguments = {agent: agent.argue(question) for agent in agents}
# Debate round 2 (respond to others)
counter_arguments = {
agent: agent.respond(arguments) for agent in agents
}
# Reach consensus
consensus = mediator_agent.synthesize_consensus(counter_arguments)
```
**When to Use**: Complex decisions, need multiple perspectives, risk assessment
## Agent Communication Patterns
### 1. Direct Communication
Agents pass messages directly to each other:
```python
agent_a.send_message(agent_b, {
"type": "request",
"action": "analyze_document",
"document": doc_content,
"context": {"deadline": "urgent"}
})
```
### 2. Tool-Mediated Communication
Agents use shared tools/databases:
```python
# Agent A writes to shared memory
shared_memory.write("findings", {"market_size": "$5B", "growth": "20%"})
# Agent B reads from shared memory
findings = shared_memory.read("findings")
```
### 3. Manager-Based Communication
Central coordinator manages agent communication:
```python
manager.broadcast("update_all_agents", {
"new_deadline": "tomorrow",
"priority": "critical"
})
```
## Best Practices
### Agent Design
- ✓ Clear, specific role and goal
- ✓ Appropriate tools for the role
- ✓ Relevant background/expertise
- ✓ Distinct from other agents
- ✓ Reasonable scope of work
### Workflow Design
- ✓ Clear task dependencies
- ✓ Identified handoff points
- ✓ Error handling between agents
- ✓ Fallback strategies
- ✓ Performance monitoring
### Communication
- ✓ Structured message formats
- ✓ Clear context sharing
- ✓ Error propagation strategy
- ✓ Timeout handling
- ✓ Audit logging
### Orchestration
- ✓ Define process clearly (sequential, parallel, etc.)
- ✓ Set clear success criteria
- ✓ Monitor agent performance
- ✓ Implement feedback loops
- ✓ Allow human intervention points
## Common Challenges & Solutions
### Challenge: Agent Conflicts
**Solutions**:
- Clear role separation
- Explicit decision-making rules
- Consensus mechanisms
- Conflict resolution agent
- Clear authority hierarchy
### Challenge: Slow Execution
**Solutions**:
- Use parallel execution where possible
- Cache results from expensive operations
- Pre-process data
- Optimize agent logic
- Implement timeout handling
### Challenge: Poor Quality Results
**Solutions**:
- Better agent prompts/instructions
- More relevant tools
- Feedback integration
- Quality validation agents
- Result aggregation strategies
### Challenge: Complex Workflows
**Solutions**:
- Break into smaller teams
- Hierarchical structure
- Clear task definitions
- Good state management
- Documentation of workflow
## Evaluation Metrics
**Team Performance**:
- Task completion rate
- Quality of results
- Execution time
- Cost (tokens/API calls)
- Error rate
**Agent Effectiveness**:
- Task success rate
- Response quality
- Tool usage efficiency
- Communication clarity
- Collaboration score
## Advanced Techniques
### 1. Self-Organizing Teams
Agents autonomously decide roles and workflow:
```python
# Agents negotiate roles based on task
agents = [agent1, agent2, agent3]
task = "complex financial analysis"
# Agents determine best structure
negotiated_structure = self_organize(agents, task)
# Returns optimal workflow for this task
```
### 2. Adaptive Workflows
Workflow changes based on progress:
```python
# Monitor progress
if progress < expected_rate:
# Increase resources
workflow.add_agent(specialist_agent)
elif quality < threshold:
# Increase validation
workflow.insert_review_step()
```
### 3. Cross-Agent Learning
Agents learn from each other's work:
```python
# After team execution
execution_trace = crew.get_execution_trace()
# Extract learnings
learnings = extract_patterns(execution_trace)
# Update agent knowledge
for agent, learning in learnings.items():
agent.update_knowledge(learning)
```
## Resources
### Frameworks
- **CrewAI**: https://crewai.com/
- **AutoGen**: https://microsoft.github.io/autogen/
- **LangGraph**: https://langchain-ai.github.io/langgraph/
- **Swarm**: https://github.com/openai/swarm
### Papers
- "Generative Agents" (Park et al.)
- "Self-Organizing Multi-Agent Systems" (research papers)
## Implementation Checklist
- [ ] Define each agent's role, goal, and expertise
- [ ] Identify available tools/capabilities for each agent
- [ ] Plan workflow (sequential, parallel, hierarchical)
- [ ] Define communication patterns
- [ ] Implement task definitions
- [ ] Set success criteria for each task
- [ ] Add error handling and fallbacks
- [ ] Implement monitoring/logging
- [ ] Test team collaboration
- [ ] Evaluate quality and performance
- [ ] Optimize based on results
- [ ] Document workflow and decisions
## Getting Started
1. **Start Small**: Begin with 2-3 agents
2. **Clear Workflow**: Document how agents interact
3. **Test Thoroughly**: Validate agent behavior individually and together
4. **Monitor Closely**: Track performance and results
5. **Iterate**: Refine based on results
6. **Scale**: Add agents and complexity as needed
# PageSpeed Insights — Reference & Official Documentation
This file complements the pagespeed-insights skill with official documentation links for indexing.
## Official documentation (indexable)
- **PageSpeed Insights about**: https://developers.google.com/speed/docs/insights/v5/about?hl=es-419
- **PageSpeed Insights (tool)**: https://pagespeed.web.dev/
- **Lighthouse**: https://developer.chrome.com/docs/lighthouse/
- **Core Web Vitals**: https://web.dev/vitals/
- **Chrome User Experience Report (CrUX)**: https://developer.chrome.com/docs/crux/
## Core Web Vitals (metrics)
- **LCP (Largest Contentful Paint)**: https://web.dev/lcp/
- **FCP (First Contentful Paint)**: https://web.dev/fcp/
- **CLS (Cumulative Layout Shift)**: https://web.dev/cls/
- **INP (Interaction to Next Paint)**: https://web.dev/inp/
- **TTFB (Time to First Byte)**: https://web.dev/ttfb/
## Lab vs field data
- **Lab data**: Lighthouse, controlled environment, debugging
- **Field data**: CrUX, real user metrics, 28-day aggregation
- **Understanding metrics**: https://web.dev/metrics/
## Performance optimization guides
- **Optimize LCP**: https://web.dev/optimize-lcp/
- **Optimize CLS**: https://web.dev/optimize-cls/
- **Optimize INP**: https://web.dev/optimize-inp/
- **Optimize FCP**: https://web.dev/optimize-fcp/
- **Resource hints**: https://web.dev/preconnect-and-dns-prefetch/
- **Image optimization**: https://web.dev/fast/#optimize-your-images
## Tools
- **PageSpeed Insights**: https://pagespeed.web.dev/
- **Lighthouse (Chrome DevTools)**: Built-in, Audits tab
- **Web Vitals extension**: Real-time monitoring
- **Chromatic (Lighthouse CI)**: https://github.com/GoogleChrome/lighthouse-ci
## Score thresholds (reminder)
| Category | Good | Needs Improvement | Poor |
|----------|------|-------------------|------|
| Performance | 90-100 | 50-89 | 0-49 |
| Accessibility | 90-100 | 50-89 | 0-49 |
| Best Practices | 90-100 | 50-89 | 0-49 |
| SEO | 90-100 | 50-89 | 0-49 |
---
name: pagespeed-insights
description: Audit web pages for performance optimization following PageSpeed Insights guidelines. Use when analyzing page performance, optimizing web applications, reviewing performance metrics, implementing Core Web Vitals improvements, or when the user mentions page speed, performance optimization, Lighthouse scores, or Core Web Vitals.
---
# PageSpeed Insights Auditor
## Overview
You are a **PageSpeed Insights Auditor** - an expert in web performance optimization who helps developers achieve excellent PageSpeed scores by identifying performance issues, avoiding bad practices, and implementing best practices based on Google's PageSpeed Insights guidelines.
**Core Principle**: Guide developers to achieve scores of 90+ (Good) in Performance, Accessibility, Best Practices, and SEO categories, while ensuring Core Web Vitals metrics meet the "Good" thresholds.
## Understanding PageSpeed Insights
PageSpeed Insights (PSI) analyzes page performance on mobile and desktop devices, providing both **lab data** (simulated) and **field data** (real user experiences). PSI reports on user experience metrics and provides diagnostic suggestions to improve page performance.
### Two Types of Data
1. **Lab Data**: Collected in a controlled environment using Lighthouse. Useful for debugging but may not capture real-world bottlenecks.
2. **Field Data**: Real user experience data from Chrome User Experience Report (CrUX). Useful for capturing actual user experiences but has a more limited set of metrics.
## Performance Score Thresholds
### Lab Scores (Lighthouse)
| Score Range | Rating | Icon |
| ----------- | ----------------- | --------------- |
| 90-100 | Good | 🟢 Green circle |
| 50-89 | Needs Improvement | 🟡 Amber square |
| 0-49 | Poor | 🔴 Red triangle |
**Target**: Always aim for scores of **90 or higher** in all categories.
### Core Web Vitals Thresholds
Core Web Vitals are the three most important metrics for web performance:
| Metric | Good | Needs Improvement | Poor |
| ----------------------------------- | ------------ | ------------------ | --------- |
| **FCP** (First Contentful Paint) | [0, 1800 ms] | [1800 ms, 3000 ms] | > 3000 ms |
| **LCP** (Largest Contentful Paint) | [0, 2500 ms] | [2500 ms, 4000 ms] | > 4000 ms |
| **CLS** (Cumulative Layout Shift) | [0, 0.1] | [0.1, 0.25] | > 0.25 |
| **INP** (Interaction to Next Paint) | [0, 200 ms] | [200 ms, 500 ms] | > 500 ms |
| **TTFB** (Time to First Byte) | [0, 800 ms] | [800 ms, 1800 ms] | > 1800 ms |
**Target**: Ensure the 75th percentile of all Core Web Vitals metrics are in the "Good" range.
## Key Performance Metrics
### Lab Metrics (Lighthouse)
1. **First Contentful Paint (FCP)**: Time until first content is rendered
2. **Largest Contentful Paint (LCP)**: Time until largest content element is rendered
3. **Speed Index**: How quickly content is visually displayed
4. **Cumulative Layout Shift (CLS)**: Visual stability measure
5. **Total Blocking Time (TBT)**: Sum of blocking time between FCP and TTI
6. **Time to Interactive (TTI)**: Time until page is fully interactive
### Field Metrics (CrUX)
- **FCP**: First Contentful Paint from real users
- **LCP**: Largest Contentful Paint from real users
- **CLS**: Cumulative Layout Shift from real users
- **INP**: Interaction to Next Paint (replaces FID)
- **TTFB**: Time to First Byte (experimental)
## Common Performance Issues & Solutions
### ❌ Bad Practice: Unoptimized Images
**Problem**: Large images without compression, modern formats, or proper sizing.
**Impact**: Poor LCP scores, slow page loads.
**✅ Solutions**:
- Use modern image formats (WebP, AVIF)
- Implement responsive images with `srcset`
- Compress images before uploading
- Set explicit width/height to prevent CLS
- Use lazy loading for below-the-fold images
```html
<!-- Bad -->
<img src="large-image.jpg" alt="Description" />
<!-- Good -->
<img
src="image.webp"
srcset="image-small.webp 400w, image-medium.webp 800w, image-large.webp 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
width="1200"
height="800"
alt="Description"
loading="lazy"
/>
```
### ❌ Bad Practice: Render-Blocking Resources
**Problem**: CSS and JavaScript blocking initial render.
**Impact**: Poor FCP and LCP scores.
**✅ Solutions**:
- Defer non-critical CSS
- Inline critical CSS
- Use `async` or `defer` for JavaScript
- Remove unused CSS/JS
- Split code and lazy load routes
```html
<!-- Bad -->
<link rel="stylesheet" href="styles.css" />
<script src="app.js"></script>
<!-- Good -->
<link
rel="stylesheet"
href="styles.css"
media="print"
onload="this.media='all'"
/>
<link rel="preload" href="critical.css" as="style" />
<script src="app.js" defer></script>
```
### ❌ Bad Practice: Missing Resource Hints
**Problem**: Not preconnecting to important origins or prefetching critical resources.
**Impact**: Slow TTFB and LCP.
**✅ Solutions**:
- Use `rel="preconnect"` for third-party origins
- Use `rel="dns-prefetch"` for DNS resolution
- Use `rel="preload"` for critical resources
- Use `rel="prefetch"` for likely next-page resources
```html
<!-- Good -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="dns-prefetch" href="https://api.example.com" />
<link rel="preload" href="hero-image.webp" as="image" />
```
### ❌ Bad Practice: Layout Shift (CLS)
**Problem**: Content shifting during page load.
**Impact**: Poor CLS scores, bad user experience.
**✅ Solutions**:
- Set explicit dimensions for images and videos
- Reserve space for ads and embeds
- Avoid inserting content above existing content
- Use CSS aspect-ratio for responsive containers
- Prefer transform animations over layout-triggering properties
```css
/* Bad */
.image-container {
width: 100%;
/* height not set - causes CLS */
}
/* Good */
.image-container {
width: 100%;
aspect-ratio: 16 / 9;
/* or */
height: 0;
padding-bottom: 56.25%; /* 16:9 ratio */
}
```
### ❌ Bad Practice: Large JavaScript Bundles
**Problem**: Loading unnecessary JavaScript code.
**Impact**: Poor TTI, high TBT.
**✅ Solutions**:
- Code splitting and lazy loading
- Remove unused code (tree shaking)
- Minimize and compress JavaScript
- Use dynamic imports for routes
- Avoid large third-party libraries when possible
```javascript
// Bad - loading everything upfront
import { heavyLibrary } from "./heavy-library";
// Good - lazy load when needed
const loadHeavyLibrary = () => import("./heavy-library");
```
### ❌ Bad Practice: Inefficient Font Loading
**Problem**: Fonts causing FOIT (Flash of Invisible Text) or FOUT (Flash of Unstyled Text).
**Impact**: Poor FCP, layout shifts.
**✅ Solutions**:
- Use `font-display: swap` or `optional`
- Preload critical fonts
- Subset fonts to include only needed characters
- Use system fonts when possible
```css
/* Good */
@font-face {
font-family: "CustomFont";
src: url("font.woff2") format("woff2");
font-display: swap; /* or optional */
}
```
### ❌ Bad Practice: No Caching Strategy
**Problem**: Resources not cached, causing repeated downloads.
**Impact**: Slow repeat visits, poor performance.
**✅ Solutions**:
- Set appropriate Cache-Control headers
- Use service workers for offline caching
- Implement HTTP/2 server push for critical resources
- Use CDN for static assets
```
Cache-Control: public, max-age=31536000, immutable
```
### ❌ Bad Practice: Third-Party Scripts Blocking Render
**Problem**: Analytics, ads, or widgets blocking page load.
**Impact**: Poor TTI, high TBT.
**✅ Solutions**:
- Load third-party scripts asynchronously
- Defer non-critical third-party code
- Use `rel="noopener"` for external links
- Consider self-hosting analytics when possible
```html
<!-- Good -->
<script async src="https://www.google-analytics.com/analytics.js"></script>
```
## Accessibility Best Practices
### ❌ Bad Practice: Missing Alt Text
**Problem**: Images without descriptive alt attributes.
**Impact**: Poor accessibility score.
**✅ Solution**: Always provide meaningful alt text.
```html
<!-- Bad -->
<img src="chart.png" />
<!-- Good -->
<img src="chart.png" alt="Sales increased 25% from Q1 to Q2" />
```
### ❌ Bad Practice: Poor Color Contrast
**Problem**: Text not readable due to low contrast.
**Impact**: Poor accessibility score.
**✅ Solution**: Ensure contrast ratio of at least 4.5:1 for normal text, 3:1 for large text.
### ❌ Bad Practice: Missing ARIA Labels
**Problem**: Interactive elements without proper labels.
**Impact**: Poor accessibility score.
**✅ Solution**: Use ARIA labels for screen readers.
```html
<!-- Good -->
<button aria-label="Close dialog">×</button>
```
## SEO Best Practices
### ❌ Bad Practice: Missing Meta Tags
**Problem**: No title, description, or viewport meta tags.
**Impact**: Poor SEO score.
**✅ Solution**: Include essential meta tags.
```html
<!-- Good -->
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Page description" />
<title>Page Title</title>
```
### ❌ Bad Practice: Non-Descriptive Links
**Problem**: Links with generic text like "click here".
**Impact**: Poor SEO score.
**✅ Solution**: Use descriptive link text.
```html
<!-- Bad -->
<a href="/about">Click here</a>
<!-- Good -->
<a href="/about">Learn more about our company</a>
```
## Best Practices Checklist
### Performance
- [ ] Images optimized (WebP/AVIF, compressed, responsive)
- [ ] Critical CSS inlined
- [ ] Non-critical CSS deferred
- [ ] JavaScript code-split and lazy-loaded
- [ ] Render-blocking resources minimized
- [ ] Resource hints implemented (preconnect, preload, dns-prefetch)
- [ ] Fonts optimized with font-display
- [ ] Caching strategy implemented
- [ ] Third-party scripts loaded asynchronously
- [ ] Layout shifts prevented (explicit dimensions, aspect-ratio)
### Core Web Vitals
- [ ] LCP < 2.5 seconds (75th percentile)
- [ ] FCP < 1.8 seconds (75th percentile)
- [ ] CLS < 0.1 (75th percentile)
- [ ] INP < 200ms (75th percentile)
- [ ] TTFB < 800ms (75th percentile)
### Accessibility
- [ ] All images have alt text
- [ ] Color contrast meets WCAG standards
- [ ] ARIA labels on interactive elements
- [ ] Semantic HTML used
- [ ] Keyboard navigation supported
### SEO
- [ ] Meta tags present (title, description, viewport)
- [ ] Descriptive link text
- [ ] Proper heading hierarchy (h1-h6)
- [ ] Structured data implemented
- [ ] Mobile-friendly design
## Audit Workflow
When auditing a page for PageSpeed optimization:
1. **Analyze Current State**
- Check current PageSpeed scores
- Identify Core Web Vitals metrics
- Review lab and field data differences
2. **Identify Issues**
- List all performance problems
- Prioritize by impact (Core Web Vitals first)
- Categorize by type (images, JS, CSS, etc.)
3. **Provide Solutions**
- Suggest specific optimizations
- Provide code examples
- Explain expected improvements
4. **Verify Improvements**
- Re-test after changes
- Ensure scores reach 90+
- Confirm Core Web Vitals are "Good"
## Common Mistakes to Avoid
### ❌ Focusing Only on Lab Data
**Problem**: Optimizing only for Lighthouse scores without considering real user data.
**✅ Solution**: Balance both lab and field data. Field data shows real-world performance.
### ❌ Over-Optimizing
**Problem**: Implementing too many optimizations at once, making debugging difficult.
**✅ Solution**: Make incremental changes and test after each optimization.
### ❌ Ignoring Mobile Performance
**Problem**: Optimizing only for desktop.
**✅ Solution**: Mobile-first approach. Most users are on mobile devices.
### ❌ Not Testing After Changes
**Problem**: Assuming optimizations worked without verification.
**✅ Solution**: Always re-run PageSpeed Insights after implementing changes.
## Performance Optimization Priority
1. **Critical Path**: Optimize resources needed for initial render
2. **Core Web Vitals**: Focus on LCP, CLS, and INP first
3. **Render-Blocking**: Eliminate blocking CSS and JS
4. **Images**: Optimize largest contentful paint element
5. **Third-Party**: Minimize impact of external scripts
6. **Caching**: Implement proper caching strategies
## Additional Resources
- [reference.md](reference.md) — Official PageSpeed, Lighthouse, Core Web Vitals, optimization guides — indexable
- **Official**: https://developers.google.com/speed/docs/insights/v5/about?hl=es-419
- **PageSpeed Insights**: https://pagespeed.web.dev/
- **Lighthouse**: Built into Chrome DevTools
- **Web Vitals**: https://web.dev/vitals/
## Specification Reference
This skill is based on the official [PageSpeed Insights documentation](https://developers.google.com/speed/docs/insights/v5/about?hl=es-419) from Google Developers.
All thresholds, metrics, and best practices in this skill follow the official PageSpeed Insights guidelines and Core Web Vitals specifications. For complete documentation, refer to the [official PageSpeed Insights documentation](https://developers.google.com/speed/docs/insights/v5/about?hl=es-419).
---
id: pagespeed-perf
version: 1.0.0
name: PageSpeed Performance Audit
description: >
Web Performance Engineering — analyzes Core Web Vitals using the PageSpeed
Insights API (PSI v5) and applies the 80/20 principle: identify the 20% of
changes that produce 80% of the performance gain. Produces a prioritized
markdown report with quantified estimates and framework-specific code.
Trigger: When auditing page speed, analyzing Core Web Vitals, or optimizing
web performance for any URL.
user-invokable: true
license: MIT
metadata:
author: codeconductor
category: performance
compatibility:
tools: [claude, codex, gemini, agy, opencode]
stacks:
languages: []
frameworks: [astro, nextjs, react, vue, django, spring, wordpress]
risk:
level: medium
can_execute_shell: true
can_modify_files: false
requires_network: true
inputs:
- name: url
type: string
required: true
description: Full URL to audit (must include scheme: https://...)
- name: strategy
type: string
required: false
description: "mobile | desktop | both (default: both)"
outputs:
- name: report
type: markdown
description: >
Prioritized performance report saved as
{YYYY-MM-DD}_pagespeed-{hostname}-claude.md in the current directory.
quality:
reviewed_by: codeconductor-core
version: 1.0.0
---
# PageSpeed Performance Audit — Web Performance Engineering (80/20)
## Role and Purpose
Act as **Senior Web Performance Engineer, Frontend Architect, and Technical
Auditor**.
Always access the real site, measure real metrics via the PageSpeed Insights
API, analyze resources with the greatest impact, and produce a prioritized
Spanish-language report following the 80/20 principle: the **20% of critical
changes that produce 80% of the performance improvement**.
Never give generic recommendations. Every finding must be backed by data
observed from the specific URL being audited.
---
## Step 0 — Pre-flight: API Key and Output Filename
**MANDATORY. Execute before any analysis.**
### 1. Read the API key from the environment
```powershell
$env:PAGESPEED_API_KEY
```
- Value present → store as `{API_KEY}`, use in all PSI calls.
- Empty → proceed without key (CrUX field data unavailable; rate limits apply).
### 2. Define the output filename
```powershell
$date = (Get-Date -Format "yyyy-MM-dd")
$website = ([System.Uri]"{URL}").Host -replace '[^a-zA-Z0-9]', '-'
$out = "${date}_pagespeed-${website}-claude.md"
Write-Host $out
```
The final report **must** be written to this file.
---
## Data Collection
### Primary Method — Bun Scripts (always try first)
```powershell
bun --version # if available, use Primary Method; otherwise use Fallback
$skillDir = "$env:USERPROFILE\.claude\skills\pagespeed-perf\scripts"
bun run "$skillDir\run.ts" --url={URL}
```
`run.ts` calls `psi-collect.ts` and `html-audit.ts` in parallel and returns
structured JSON. Key output fields:
```
output.summary.mobileScore → Lighthouse mobile score (0-100)
output.summary.desktopScore → Lighthouse desktop score
output.summary.passesCWV → boolean — passes real CWV
output.summary.top5Actions → array ordered by 80/20 score
output.psi.mobile.lab.lcp → LCP (lab, mobile)
output.psi.mobile.lab.tbt → TBT
output.psi.mobile.lab.cls → CLS
output.psi.mobile.lab.fcp → FCP
output.psi.mobile.lab.ttfb → TTFB
output.psi.mobile.field → CrUX data (null if no key / no data)
output.psi.mobile.opportunities → array ordered by impact80_20 desc
output.psi.mobile.lcpElement → HTML snippet of the LCP element
output.psi.mobile.thirdParties → third-party scripts with blockingTime
output.psi.mobile.usedApiKey → boolean — confirms key was used
output.html.stack → detected framework / CMS
output.html.resourceHints → preloads, preconnects, prefetches
output.html.images → lazy, fetchpriority, list
output.html.scripts → blocking in <head>, third-party list
output.html.fonts → googleFonts, font-display, preloaded
output.html.issues → ordered by impact80_20
```
### Fallback Method — WebFetch (only if Bun unavailable)
```
# With API key (preferred)
https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url={URL}&strategy=mobile&category=performance&key={API_KEY}
https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url={URL}&strategy=desktop&category=performance&key={API_KEY}
# Without key (rate-limited)
https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url={URL}&strategy=mobile&category=performance
```
Key PSI response paths:
```
lighthouseResult.categories.performance.score
lighthouseResult.audits.largest-contentful-paint
lighthouseResult.audits.total-blocking-time
lighthouseResult.audits.cumulative-layout-shift
lighthouseResult.audits.first-contentful-paint
lighthouseResult.audits.server-response-time
lighthouseResult.audits.largest-contentful-paint-element.details.items[0]
lighthouseResult.audits.render-blocking-resources.details.overallSavingsMs
lighthouseResult.audits.unused-javascript.details.overallSavingsBytes
lighthouseResult.audits.third-party-summary.details.items
loadingExperience.metrics.LARGEST_CONTENTFUL_PAINT_MS.percentile (CrUX)
loadingExperience.metrics.INTERACTION_TO_NEXT_PAINT.percentile (CrUX)
loadingExperience.metrics.CUMULATIVE_LAYOUT_SHIFT_SCORE.percentile (CrUX)
loadingExperience.overall_category → "FAST" | "AVERAGE" | "SLOW"
```
Also fetch the site HTML via WebFetch and inspect the `<head>` for resource
hints, lazy loading, `fetchpriority`, `font-display`, blocking scripts, and
images without explicit dimensions.
---
## Core Web Vitals — Thresholds
| Metric | Good | Needs Improvement | Critical | Score weight |
| ------ | -------- | ----------------- | --------- | ------------ |
| LCP | ≤ 2.5 s | 2.5 s – 4.0 s | > 4.0 s | 25% |
| INP | ≤ 200 ms | 200 ms – 500 ms | > 500 ms | 10% |
| CLS | ≤ 0.1 | 0.1 – 0.25 | > 0.25 | 15% |
| FCP | ≤ 1.8 s | 1.8 s – 3.0 s | > 3.0 s | 10% |
| TBT | ≤ 200 ms | 200 ms – 600 ms | > 600 ms | 30% |
| TTFB | ≤ 800 ms | 800 ms – 1.8 s | > 1.8 s | — |
LCP + TBT represent 55% of the Lighthouse Performance Score.
---
## 80/20 Optimization Matrix
Score = `Impact (1–5) × Ease (1–5)`. Prioritize by descending score.
| Rank | Optimization | Primary metric | Impact | Ease | Score |
| ---- | --------------------------------- | -------------- | ------ | ---- | ----- |
| 1 | Preload LCP element | LCP | 5 | 5 | **25** |
| 1 | `fetchpriority="high"` on LCP img | LCP | 5 | 5 | **25** |
| 1 | Gzip / Brotli compression | FCP, LCP, TBT | 5 | 5 | **25** |
| 4 | WebP + explicit dimensions | LCP, CLS | 5 | 4 | **20** |
| 4 | Lazy loading offscreen images | LCP, TBT | 4 | 5 | **20** |
| 4 | `font-display: swap` | FCP | 4 | 5 | **20** |
| 4 | `preconnect` to critical origins | FCP, LCP, TTFB | 4 | 5 | **20** |
| 4 | Defer / facade third-party scripts| TBT, INP | 5 | 4 | **20** |
| 9 | Remove render-blocking resources | FCP, LCP | 5 | 3 | **15** |
| 9 | Long Cache-Control for assets | repeat visits | 3 | 5 | **15** |
| 11 | Remove unused JavaScript | TBT, INP | 4 | 3 | **12** |
| 12 | Remove unused CSS | FCP, TBT | 3 | 3 | **9** |
| 13 | CDN for static assets | TTFB, LCP | 4 | 2 | **8** |
| 14 | Code splitting | TBT, INP | 4 | 2 | **8** |
**Critical 20% (Score ≥ 20)** — address these first:
1. Preload LCP element + `fetchpriority="high"`
2. Brotli/Gzip compression at the server
3. WebP images with explicit `width`/`height`
4. Lazy loading of offscreen images
5. `font-display: swap` for all fonts
6. `preconnect` to all critical origins
7. Defer or facade all third-party scripts
---
## Expected Impact by Optimization
| Optimization | Metric | Expected gain |
| ---------------------- | -------- | --------------------- |
| Preload + fetchpriority| LCP | −0.5 s to −2.0 s |
| Brotli compression | FCP, LCP | −0.3 s to −1.0 s |
| WebP + dimensions | LCP, CLS | −0.3 s to −1.2 s |
| Lazy loading | LCP | −0.2 s to −0.8 s |
| font-display: swap | FCP | −0.2 s to −0.8 s |
| preconnect | FCP, LCP | −0.1 s to −0.4 s each|
| Defer third parties | TBT, INP | −50 ms to −300 ms |
---
## Report Format (mandatory structure)
Save to `{YYYY-MM-DD}_pagespeed-{hostname}-claude.md`:
```markdown
# Auditoría de Rendimiento Web — {URL}
Fecha: {YYYY-MM-DD} | Estrategia: Móvil + Escritorio | Archivo: {filename}.md
## Resumen Ejecutivo
[2-3 párrafos: estado actual, score, bottleneck principal, potencial de mejora]
## Métricas Actuales
[Tabla: Lab (Lighthouse) vs Campo (CrUX)]
## Recursos con Mayor Impacto
[Tabla: URL, Tipo, Tamaño, Tiempo, Impacto, Razón]
## Plan de Acción Priorizado (80/20)
[Tabla ordenada por Score 80/20 descendente]
## Solución Técnica Detallada
[Por hallazgo: Problema, Evidencia, Implementación, Código, Impacto Esperado]
## Quick Wins (< 1 day)
## High Impact Changes
## Roadmap
- Fase 1 — Inmediato (Semana 1)
- Fase 2 — Corto Plazo (2–4 semanas)
- Fase 3 — Mediano Plazo (1–3 meses)
---
*Informe generado el {YYYY-MM-DD} · Herramienta: Claude Code + pagespeed-perf skill*
*API Key usada: {Sí / No} · Datos CrUX: {Disponibles / No disponibles}*
```
---
## Quality Rules — Never Violate
1. **No data = no recommendation.** If PSI fails, try WebFetch directly.
2. **Always quantify.** "Reduces LCP from 4.2 s to ~3.0 s" — never "would improve LCP".
3. **Explicit evidence.** Cite the observed metric value for every finding.
4. **Site-specific code.** Adapt templates to the detected framework (Next.js,
Astro, Django, etc.). Do not paste generic snippets unchanged.
5. **80/20 order.** Always sort the action plan by descending score.
6. **Separate field vs lab data.** CrUX = real user experience. Lighthouse = controlled lab.
7. **Identify the framework.** Detect Next.js, Astro, Vue, WordPress, etc., and
provide framework-specific code samples.
# workflow-orchestration-patterns — detailed patterns and worked examples
## Critical Design Decision: Workflows vs Activities
**The Fundamental Rule** (Source: temporal.io/blog/workflow-engine-principles):
- **Workflows** = Orchestration logic and decision-making
- **Activities** = External interactions (APIs, databases, network calls)
### Workflows (Orchestration)
**Characteristics:**
- Contain business logic and coordination
- **MUST be deterministic** (same inputs → same outputs)
- **Cannot** perform direct external calls
- State automatically preserved across failures
- Can run for years despite infrastructure failures
**Example workflow tasks:**
- Decide which steps to execute
- Handle compensation logic
- Manage timeouts and retries
- Coordinate child workflows
### Activities (External Interactions)
**Characteristics:**
- Handle all external system interactions
- Can be non-deterministic (API calls, DB writes)
- Include built-in timeouts and retry logic
- **Must be idempotent** (calling N times = calling once)
- Short-lived (seconds to minutes typically)
**Example activity tasks:**
- Call payment gateway API
- Write to database
- Send emails or notifications
- Query external services
### Design Decision Framework
```
Does it touch external systems? → Activity
Is it orchestration/decision logic? → Workflow
```
## Core Workflow Patterns
### 1. Saga Pattern with Compensation
**Purpose**: Implement distributed transactions with rollback capability
**Pattern** (Source: temporal.io/blog/compensating-actions-part-of-a-complete-breakfast-with-sagas):
```
For each step:
1. Register compensation BEFORE executing
2. Execute the step (via activity)
3. On failure, run all compensations in reverse order (LIFO)
```
**Example: Payment Workflow**
1. Reserve inventory (compensation: release inventory)
2. Charge payment (compensation: refund payment)
3. Fulfill order (compensation: cancel fulfillment)
**Critical Requirements:**
- Compensations must be idempotent
- Register compensation BEFORE executing step
- Run compensations in reverse order
- Handle partial failures gracefully
### 2. Entity Workflows (Actor Model)
**Purpose**: Long-lived workflow representing single entity instance
**Pattern** (Source: docs.temporal.io/evaluate/use-cases-design-patterns):
- One workflow execution = one entity (cart, account, inventory item)
- Workflow persists for entity lifetime
- Receives signals for state changes
- Supports queries for current state
**Example Use Cases:**
- Shopping cart (add items, checkout, expiration)
- Bank account (deposits, withdrawals, balance checks)
- Product inventory (stock updates, reservations)
**Benefits:**
- Encapsulates entity behavior
- Guarantees consistency per entity
- Natural event sourcing
### 3. Fan-Out/Fan-In (Parallel Execution)
**Purpose**: Execute multiple tasks in parallel, aggregate results
**Pattern:**
- Spawn child workflows or parallel activities
- Wait for all to complete
- Aggregate results
- Handle partial failures
**Scaling Rule** (Source: temporal.io/blog/workflow-engine-principles):
- Don't scale individual workflows
- For 1M tasks: spawn 1K child workflows × 1K tasks each
- Keep each workflow bounded
### 4. Async Callback Pattern
**Purpose**: Wait for external event or human approval
**Pattern:**
- Workflow sends request and waits for signal
- External system processes asynchronously
- Sends signal to resume workflow
- Workflow continues with response
**Use Cases:**
- Human approval workflows
- Webhook callbacks
- Long-running external processes
## State Management and Determinism
### Automatic State Preservation
**How Temporal Works** (Source: docs.temporal.io/workflows):
- Complete program state preserved automatically
- Event History records every command and event
- Seamless recovery from crashes
- Applications restore pre-failure state
### Determinism Constraints
**Workflows Execute as State Machines**:
- Replay behavior must be consistent
- Same inputs → identical outputs every time
**Prohibited in Workflows** (Source: docs.temporal.io/workflows):
- ❌ Threading, locks, synchronization primitives
- ❌ Random number generation (`random()`)
- ❌ Global state or static variables
- ❌ System time (`datetime.now()`)
- ❌ Direct file I/O or network calls
- ❌ Non-deterministic libraries
**Allowed in Workflows**:
- ✅ `workflow.now()` (deterministic time)
- ✅ `workflow.random()` (deterministic random)
- ✅ Pure functions and calculations
- ✅ Calling activities (non-deterministic operations)
### Versioning Strategies
**Challenge**: Changing workflow code while old executions still running
**Solutions**:
1. **Versioning API**: Use `workflow.get_version()` for safe changes
2. **New Workflow Type**: Create new workflow, route new executions to it
3. **Backward Compatibility**: Ensure old events replay correctly
## Resilience and Error Handling
### Retry Policies
**Default Behavior**: Temporal retries activities forever
**Configure Retry**:
- Initial retry interval
- Backoff coefficient (exponential backoff)
- Maximum interval (cap retry delay)
- Maximum attempts (eventually fail)
**Non-Retryable Errors**:
- Invalid input (validation failures)
- Business rule violations
- Permanent failures (resource not found)
### Idempotency Requirements
**Why Critical** (Source: docs.temporal.io/activities):
- Activities may execute multiple times
- Network failures trigger retries
- Duplicate execution must be safe
**Implementation Strategies**:
- Idempotency keys (deduplication)
- Check-then-act with unique constraints
- Upsert operations instead of insert
- Track processed request IDs
### Activity Heartbeats
**Purpose**: Detect stalled long-running activities
**Pattern**:
- Activity sends periodic heartbeat
- Includes progress information
- Timeout if no heartbeat received
- Enables progress-based retry
---
name: workflow-orchestration-patterns
description: Design durable workflows with Temporal for distributed systems. Covers workflow vs activity separation, saga patterns, state management, and determinism constraints. Use when building long-running processes, distributed transactions, or microservice orchestration.
---
# Workflow Orchestration Patterns
Master workflow orchestration architecture with Temporal, covering fundamental design decisions, resilience patterns, and best practices for building reliable distributed systems.
## When to Use Workflow Orchestration
### Ideal Use Cases (Source: docs.temporal.io)
- **Multi-step processes** spanning machines/services/databases
- **Distributed transactions** requiring all-or-nothing semantics
- **Long-running workflows** (hours to years) with automatic state persistence
- **Failure recovery** that must resume from last successful step
- **Business processes**: bookings, orders, campaigns, approvals
- **Entity lifecycle management**: inventory tracking, account management, cart workflows
- **Infrastructure automation**: CI/CD pipelines, provisioning, deployments
- **Human-in-the-loop** systems requiring timeouts and escalations
### When NOT to Use
- Simple CRUD operations (use direct API calls)
- Pure data processing pipelines (use Airflow, batch processing)
- Stateless request/response (use standard APIs)
- Real-time streaming (use Kafka, event processors)
## Detailed patterns and worked examples
Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.
## Best Practices
### Workflow Design
1. **Keep workflows focused** - Single responsibility per workflow
2. **Small workflows** - Use child workflows for scalability
3. **Clear boundaries** - Workflow orchestrates, activities execute
4. **Test locally** - Use time-skipping test environment
### Activity Design
1. **Idempotent operations** - Safe to retry
2. **Short-lived** - Seconds to minutes, not hours
3. **Timeout configuration** - Always set timeouts
4. **Heartbeat for long tasks** - Report progress
5. **Error handling** - Distinguish retryable vs non-retryable
### Common Pitfalls
**Workflow Violations**:
- Using `datetime.now()` instead of `workflow.now()`
- Threading or async operations in workflow code
- Calling external APIs directly from workflow
- Non-deterministic logic in workflows
**Activity Mistakes**:
- Non-idempotent operations (can't handle retries)
- Missing timeouts (activities run forever)
- No error classification (retry validation errors)
- Ignoring payload limits (2MB per argument)
### Operational Considerations
**Monitoring**:
- Workflow execution duration
- Activity failure rates
- Retry attempts and backoff
- Pending workflow counts
**Scalability**:
- Horizontal scaling with workers
- Task queue partitioning
- Child workflow decomposition
- Activity batching when appropriate
## Additional Resources
**Official Documentation**:
- Temporal Core Concepts: docs.temporal.io/workflows
- Workflow Patterns: docs.temporal.io/evaluate/use-cases-design-patterns
- Best Practices: docs.temporal.io/develop/best-practices
- Saga Pattern: temporal.io/blog/saga-pattern-made-easy
**Key Principles**:
1. Workflows = orchestration, Activities = external calls
2. Determinism is non-negotiable for workflows
3. Idempotency is critical for activities
4. State preservation is automatic
5. Design for failure and recovery
---
name: conductor-setup
description: Configure a Rails project to work with Conductor (parallel coding agents)
allowed-tools: Bash(chmod *), Bash(bundle *), Bash(npm *), Bash(script/server)
context: fork
risk: unknown
source: community
metadata:
author: Shpigford
version: "1.0"
---
Set up this Rails project for Conductor, the Mac app for parallel coding agents.
## When to Use
- You need to configure a Rails project so it runs correctly inside Conductor workspaces.
- The project should support parallel coding agents with isolated ports, Redis settings, and shared secrets.
- You want the standard `conductor.json`, `bin/conductor-setup`, and `script/server` scaffolding for a Rails repo.
# What to Create
## 1. conductor.json (project root)
Create `conductor.json` in the project root if it doesn't already exist:
```json
{
"scripts": {
"setup": "bin/conductor-setup",
"run": "script/server"
}
}
```
## 2. bin/conductor-setup (executable)
Create `bin/conductor-setup` if it doesn't already exist:
```bash
#!/bin/bash
set -e
# Symlink .env from repo root (where secrets live, outside worktrees)
[ -f "$CONDUCTOR_ROOT_PATH/.env" ] && ln -sf "$CONDUCTOR_ROOT_PATH/.env" .env
# Symlink Rails master key
[ -f "$CONDUCTOR_ROOT_PATH/config/master.key" ] && ln -sf "$CONDUCTOR_ROOT_PATH/config/master.key" config/master.key
# Install dependencies
bundle install
npm install
```
Make it executable with `chmod +x bin/conductor-setup`.
## 3. script/server (executable)
Create the `script` directory if needed, then create `script/server` if it doesn't already exist:
```bash
#!/bin/bash
# === Port Configuration ===
export PORT=${CONDUCTOR_PORT:-3000}
export VITE_RUBY_PORT=$((PORT + 1000))
# === Redis Isolation ===
if [ -n "$CONDUCTOR_WORKSPACE_NAME" ]; then
HASH=$(printf '%s' "$CONDUCTOR_WORKSPACE_NAME" | cksum | cut -d' ' -f1)
REDIS_DB=$((HASH % 16))
export REDIS_URL="redis://localhost:6379/${REDIS_DB}"
fi
exec bin/dev
```
Make it executable with `chmod +x script/server`.
## 4. Update Rails Config Files
For each of the following files, if they exist and contain Redis configuration, update them to use `ENV.fetch('REDIS_URL', ...)` or `ENV['REDIS_URL']` with a fallback:
### config/initializers/sidekiq.rb
If this file exists and configures Redis, update it to use:
```ruby
redis_url = ENV.fetch('REDIS_URL', 'redis://localhost:6379/0')
```
### config/cable.yml
If this file exists, update the development adapter to use:
```yaml
development:
adapter: redis
url: <%= ENV.fetch('REDIS_URL', 'redis://localhost:6379/1') %>
```
### config/environments/development.rb
If this file configures Redis for caching, update to use:
```ruby
config.cache_store = :redis_cache_store, { url: ENV.fetch('REDIS_URL', 'redis://localhost:6379/0') }
```
### config/initializers/rack_attack.rb
If this file exists and configures a Redis cache store, update to use:
```ruby
Rack::Attack.cache.store = ActiveSupport::Cache::RedisCacheStore.new(url: ENV.fetch('REDIS_URL', 'redis://localhost:6379/0'))
```
# Implementation Notes
- **Don't overwrite existing files**: Check if conductor.json, bin/conductor-setup, and script/server exist before creating them. If they exist, skip creation and inform the user.
- **Rails config updates**: Only modify Redis-related configuration. If a file doesn't exist or doesn't use Redis, skip it gracefully.
- **Create directories as needed**: Create `script/` directory if it doesn't exist.
# Verification
After creating the files:
1. Confirm all Conductor files exist and scripts are executable
2. Run `script/server` to verify it starts without errors
3. Check that Rails configs properly reference `ENV['REDIS_URL']` or `ENV.fetch('REDIS_URL', ...)`
## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
---
name: find-skills
description: Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
---
# Find Skills
This skill helps you discover and install skills from the open agent skills ecosystem.
## When to Use This Skill
Use this skill when the user:
- Asks "how do I do X" where X might be a common task with an existing skill
- Says "find a skill for X" or "is there a skill for X"
- Asks "can you do X" where X is a specialized capability
- Expresses interest in extending agent capabilities
- Wants to search for tools, templates, or workflows
- Mentions they wish they had help with a specific domain (design, testing, deployment, etc.)
## What is the Skills CLI?
The Skills CLI (`npx skills`) is the package manager for the open agent skills ecosystem. Skills are modular packages that extend agent capabilities with specialized knowledge, workflows, and tools.
**Key commands:**
- `npx skills find [query]` - Search for skills interactively or by keyword
- `npx skills add <package>` - Install a skill from GitHub or other sources
- `npx skills check` - Check for skill updates
- `npx skills update` - Update all installed skills
**Browse skills at:** https://skills.sh/
## How to Help Users Find Skills
### Step 1: Understand What They Need
When a user asks for help with something, identify:
1. The domain (e.g., React, testing, design, deployment)
2. The specific task (e.g., writing tests, creating animations, reviewing PRs)
3. Whether this is a common enough task that a skill likely exists
### Step 2: Check the Leaderboard First
Before running a CLI search, check the [skills.sh leaderboard](https://skills.sh/) to see if a well-known skill already exists for the domain. The leaderboard ranks skills by total installs, surfacing the most popular and battle-tested options.
For example, top skills for web development include:
- `vercel-labs/agent-skills` — React, Next.js, web design (100K+ installs each)
- `anthropics/skills` — Frontend design, document processing (100K+ installs)
### Step 3: Search for Skills
If the leaderboard doesn't cover the user's need, run the find command:
```bash
npx skills find [query]
```
For example:
- User asks "how do I make my React app faster?" → `npx skills find react performance`
- User asks "can you help me with PR reviews?" → `npx skills find pr review`
- User asks "I need to create a changelog" → `npx skills find changelog`
### Step 4: Verify Quality Before Recommending
**Do not recommend a skill based solely on search results.** Always verify:
1. **Install count** — Prefer skills with 1K+ installs. Be cautious with anything under 100.
2. **Source reputation** — Official sources (`vercel-labs`, `anthropics`, `microsoft`) are more trustworthy than unknown authors.
3. **GitHub stars** — Check the source repository. A skill from a repo with <100 stars should be treated with skepticism.
### Step 5: Present Options to the User
When you find relevant skills, present them to the user with:
1. The skill name and what it does
2. The install count and source
3. The install command they can run
4. A link to learn more at skills.sh
Example response:
```
I found a skill that might help! The "react-best-practices" skill provides
React and Next.js performance optimization guidelines from Vercel Engineering.
(185K installs)
To install it:
npx skills add vercel-labs/agent-skills@react-best-practices
Learn more: https://skills.sh/vercel-labs/agent-skills/react-best-practices
```
### Step 6: Offer to Install
If the user wants to proceed, you can install the skill for them:
```bash
npx skills add <owner/repo@skill> -g -y
```
The `-g` flag installs globally (user-level) and `-y` skips confirmation prompts.
## Common Skill Categories
When searching, consider these common categories:
| Category | Example Queries |
| --------------- | ---------------------------------------- |
| Web Development | react, nextjs, typescript, css, tailwind |
| Testing | testing, jest, playwright, e2e |
| DevOps | deploy, docker, kubernetes, ci-cd |
| Documentation | docs, readme, changelog, api-docs |
| Code Quality | review, lint, refactor, best-practices |
| Design | ui, ux, design-system, accessibility |
| Productivity | workflow, automation, git |
## Tips for Effective Searches
1. **Use specific keywords**: "react testing" is better than just "testing"
2. **Try alternative terms**: If "deploy" doesn't work, try "deployment" or "ci-cd"
3. **Check popular sources**: Many skills come from `vercel-labs/agent-skills` or `ComposioHQ/awesome-claude-skills`
## When No Skills Are Found
If no relevant skills exist:
1. Acknowledge that no existing skill was found
2. Offer to help with the task directly using your general capabilities
3. Suggest the user could create their own skill with `npx skills init`
Example:
```
I searched for skills related to "xyz" but didn't find any matches.
I can still help you with this task directly! Would you like me to proceed?
If this is something you do often, you could create your own skill:
npx skills init my-xyz-skill
```
"""
Framework-Specific Multi-Agent Implementations
Templates for CrewAI, AutoGen, LangGraph, and Swarm.
"""
from typing import Dict, List, Optional, Any
from dataclasses import dataclass
@dataclass
class CrewAITemplate:
"""Template for CrewAI implementation."""
@staticmethod
def create_financial_team() -> Dict[str, Any]:
"""Create CrewAI financial analysis team."""
return {
"agents": [
{
"name": "Market Analyst",
"role": "Market Research Specialist",
"goal": "Analyze market conditions and trends",
"backstory": "Expert market analyst with 10+ years experience",
"tools": ["market_data_api", "financial_news"],
},
{
"name": "Financial Analyst",
"role": "Financial Analysis Specialist",
"goal": "Analyze company financial statements",
"backstory": "CFA with deep financial analysis expertise",
"tools": ["financial_statements", "ratio_calculator"],
},
{
"name": "Risk Manager",
"role": "Risk Assessment Specialist",
"goal": "Assess investment risks and scenarios",
"backstory": "Risk management expert",
"tools": ["risk_models", "scenario_analysis"],
},
{
"name": "Report Writer",
"role": "Report Generation Specialist",
"goal": "Synthesize findings into comprehensive report",
"backstory": "Professional technical writer",
"tools": ["document_generator"],
},
],
"tasks": [
{
"agent": "Market Analyst",
"description": "Analyze market conditions for {company}",
},
{
"agent": "Financial Analyst",
"description": "Analyze Q3 financial results for {company}",
},
{
"agent": "Risk Manager",
"description": "Assess risks and create scenarios for {company}",
},
{
"agent": "Report Writer",
"description": "Write comprehensive investment analysis report",
},
],
"process": "sequential",
}
@staticmethod
def create_legal_team() -> Dict[str, Any]:
"""Create CrewAI legal team."""
return {
"agents": [
{
"name": "Contract Analyzer",
"role": "Legal Contract Specialist",
"goal": "Analyze and review contract terms",
"backstory": "Senior contract attorney",
},
{
"name": "Precedent Researcher",
"role": "Legal Research Specialist",
"goal": "Research relevant case law and precedents",
"backstory": "Legal researcher specializing in case law",
},
{
"name": "Risk Assessor",
"role": "Legal Risk Specialist",
"goal": "Identify and assess legal risks",
"backstory": "Risk management expert in legal domain",
},
{
"name": "Document Drafter",
"role": "Legal Document Specialist",
"goal": "Draft legal documents and recommendations",
"backstory": "Legal document drafting expert",
},
],
"process": "sequential",
}
@dataclass
class AutoGenTemplate:
"""Template for AutoGen implementation."""
@staticmethod
def create_group_chat_config() -> Dict[str, Any]:
"""Create AutoGen group chat configuration."""
return {
"agents": [
{
"name": "analyst",
"system_message": "You are a financial analyst. Provide analysis based on data.",
"llm_config": {"model": "gpt-4", "temperature": 0.7},
},
{
"name": "researcher",
"system_message": "You are a market researcher. Research trends and competition.",
"llm_config": {"model": "gpt-4", "temperature": 0.7},
},
{
"name": "critic",
"system_message": "You are a critical evaluator. Challenge assumptions and findings.",
"llm_config": {"model": "gpt-4", "temperature": 0.7},
},
],
"group_chat_config": {
"agents": ["analyst", "researcher", "critic"],
"max_round": 10,
"speaker_selection_method": "auto",
},
}
@staticmethod
def create_hierarchical_structure() -> Dict[str, Any]:
"""Create hierarchical AutoGen structure."""
return {
"primary_agents": [
{
"name": "senior_analyst",
"role": "Senior analyst coordinating teams",
"subordinates": ["junior_analyst_1", "junior_analyst_2"],
}
],
"secondary_agents": [
{
"name": "junior_analyst_1",
"role": "Fundamental analysis specialist",
},
{
"name": "junior_analyst_2",
"role": "Technical analysis specialist",
},
],
}
@dataclass
class LangGraphTemplate:
"""Template for LangGraph workflow implementation."""
@staticmethod
def create_research_workflow() -> Dict[str, Any]:
"""Create LangGraph research workflow."""
return {
"name": "research_workflow",
"state_schema": {
"topic": str,
"research_findings": str,
"analysis": str,
"recommendations": str,
},
"nodes": [
{
"name": "researcher",
"agent": "research_agent",
"description": "Research the topic",
},
{
"name": "analyst",
"agent": "analyst_agent",
"description": "Analyze research findings",
},
{
"name": "critic",
"agent": "critic_agent",
"description": "Critique and improve",
},
{
"name": "writer",
"agent": "writer_agent",
"description": "Write final report",
},
],
"edges": [
("researcher", "analyst"),
("analyst", "critic"),
("critic", "writer"),
],
"entry_point": "researcher",
"exit_point": "writer",
}
@staticmethod
def create_dynamic_workflow() -> Dict[str, Any]:
"""Create dynamic LangGraph workflow with conditions."""
return {
"name": "dynamic_workflow",
"nodes": [
{
"name": "start",
"type": "input",
},
{
"name": "analyze",
"type": "agent",
"agent": "analyzer",
},
{
"name": "quality_check",
"type": "decision",
"condition": "analyze_quality > threshold",
},
{
"name": "refine",
"type": "agent",
"agent": "refiner",
},
{
"name": "end",
"type": "output",
},
],
"conditional_edges": [
{
"source": "quality_check",
"true_target": "end",
"false_target": "refine",
}
],
}
@dataclass
class SwarmTemplate:
"""Template for OpenAI Swarm implementation."""
@staticmethod
def create_customer_support_swarm() -> Dict[str, Any]:
"""Create customer support Swarm."""
return {
"agents": [
{
"name": "triage_agent",
"instructions": "Determine which specialist to route the customer to. "
"Ask clarifying questions if needed.",
"functions": [
"route_to_billing",
"route_to_technical",
"route_to_account",
],
},
{
"name": "billing_specialist",
"instructions": "Handle all billing and payment related questions. "
"Can access billing records.",
"tools": ["billing_system", "payment_processor"],
},
{
"name": "technical_support",
"instructions": "Handle technical issues and troubleshooting. "
"Can access diagnostic tools.",
"tools": ["diagnostic_tools", "knowledge_base"],
},
{
"name": "account_specialist",
"instructions": "Handle account management and profile changes.",
"tools": ["account_system"],
},
],
"handoff_functions": {
"route_to_billing": "Transfer to billing specialist",
"route_to_technical": "Transfer to technical support",
"route_to_account": "Transfer to account specialist",
},
}
@staticmethod
def create_sales_swarm() -> Dict[str, Any]:
"""Create sales team Swarm."""
return {
"agents": [
{
"name": "sales_router",
"instructions": "Route customer inquiries to appropriate sales agent",
"functions": ["route_to_enterprise", "route_to_smb"],
},
{
"name": "enterprise_sales",
"instructions": "Handle enterprise customer inquiries",
},
{
"name": "smb_sales",
"instructions": "Handle small business inquiries",
},
],
}
class AgentCommunicationManager:
"""Manage communication patterns between agents."""
def __init__(self, agents: Dict[str, Any]):
"""Initialize communication manager."""
self.agents = agents
self.message_queue = []
def broadcast_message(self, sender: str, message: str, recipients: List[str]):
"""Broadcast message to multiple agents."""
for recipient in recipients:
self.message_queue.append({
"from": sender,
"to": recipient,
"message": message,
"type": "broadcast",
})
def direct_message(self, sender: str, recipient: str, message: str):
"""Send direct message between agents."""
self.message_queue.append({
"from": sender,
"to": recipient,
"message": message,
"type": "direct",
})
def publish_shared_state(self, state_key: str, value: Any):
"""Publish to shared state (tool-mediated communication)."""
self.message_queue.append({
"type": "shared_state",
"key": state_key,
"value": value,
})
def get_pending_messages(self, agent: str) -> List[Dict]:
"""Get messages for specific agent."""
return [msg for msg in self.message_queue if msg.get("to") == agent]
def process_message_queue(self) -> Dict[str, Any]:
"""Process and summarize message queue."""
direct_messages = [m for m in self.message_queue if m["type"] == "direct"]
broadcasts = [m for m in self.message_queue if m["type"] == "broadcast"]
shared_states = [m for m in self.message_queue if m["type"] == "shared_state"]
return {
"direct_messages": len(direct_messages),
"broadcasts": len(broadcasts),
"shared_states": len(shared_states),
"total_messages": len(self.message_queue),
}
"""
Multi-Agent Orchestration Patterns
Implements sequential, parallel, hierarchical, and consensus orchestration.
"""
from typing import List, Dict, Any, Optional
import asyncio
from abc import ABC, abstractmethod
class Agent(ABC):
"""Base agent class."""
def __init__(self, name: str, role: str, goal: str):
"""Initialize agent."""
self.name = name
self.role = role
self.goal = goal
@abstractmethod
def work(self, task: str) -> str:
"""Execute task."""
pass
async def work_async(self, task: str) -> str:
"""Execute task asynchronously."""
return self.work(task)
class SimpleAgent(Agent):
"""Simple agent implementation."""
def __init__(self, name: str, role: str, goal: str):
"""Initialize simple agent."""
super().__init__(name, role, goal)
def work(self, task: str) -> str:
"""Simulate agent work."""
return f"{self.name}: Completed task - {task[:50]}..."
class SequentialOrchestrator:
"""Orchestrate agents to work sequentially."""
def __init__(self, agents: List[Agent]):
"""
Initialize orchestrator with agents.
Args:
agents: List of agents to orchestrate
"""
self.agents = agents
self.execution_log = []
def execute(self, initial_task: str) -> Dict[str, Any]:
"""
Execute agents sequentially.
Args:
initial_task: Initial task description
Returns:
Execution results dictionary
"""
current_input = initial_task
results = {}
for agent in self.agents:
result = agent.work(current_input)
results[agent.name] = result
self.execution_log.append({
"agent": agent.name,
"role": agent.role,
"task": current_input,
"result": result,
})
# Next agent uses this agent's output
current_input = result
return {
"type": "sequential",
"results": results,
"final_output": current_input,
"execution_log": self.execution_log,
}
class ParallelOrchestrator:
"""Orchestrate agents to work in parallel."""
def __init__(self, agents: List[Agent]):
"""Initialize parallel orchestrator."""
self.agents = agents
self.execution_log = []
async def execute_async(self, task: str) -> Dict[str, Any]:
"""
Execute agents in parallel.
Args:
task: Task description
Returns:
Execution results dictionary
"""
# Create async tasks for all agents
tasks = [agent.work_async(task) for agent in self.agents]
# Execute all in parallel
results_list = await asyncio.gather(*tasks)
results = {
agent.name: result
for agent, result in zip(self.agents, results_list)
}
self.execution_log.append({
"type": "parallel",
"task": task,
"agents": [a.name for a in self.agents],
"results": results,
})
return {
"type": "parallel",
"results": results,
"execution_log": self.execution_log,
}
def execute(self, task: str) -> Dict[str, Any]:
"""Execute agents synchronously (sequential fallback)."""
return asyncio.run(self.execute_async(task))
class HierarchicalOrchestrator:
"""Orchestrate agents in hierarchical structure."""
def __init__(self, manager_agent: Agent, specialist_teams: Dict[str, List[Agent]]):
"""
Initialize hierarchical orchestrator.
Args:
manager_agent: Manager agent
specialist_teams: Dict of team names to lists of agents
"""
self.manager = manager_agent
self.specialist_teams = specialist_teams
self.execution_log = []
def execute(self, main_task: str) -> Dict[str, Any]:
"""
Execute with hierarchical structure.
Args:
main_task: Main task for manager
Returns:
Execution results
"""
team_results = {}
# Manager assigns tasks to teams
for team_name, agents in self.specialist_teams.items():
# Each team works on their aspect
team_task = f"{main_task} - Team: {team_name}"
team_result = {}
for agent in agents:
result = agent.work(team_task)
team_result[agent.name] = result
team_results[team_name] = team_result
self.execution_log.append({
"team": team_name,
"agents": [a.name for a in agents],
"results": team_result,
})
# Manager synthesizes results
manager_result = self.manager.work(
f"Synthesize findings from: {list(team_results.keys())}"
)
return {
"type": "hierarchical",
"team_results": team_results,
"manager_synthesis": manager_result,
"execution_log": self.execution_log,
}
class ConsensusOrchestrator:
"""Orchestrate agent debate and consensus."""
def __init__(self, agents: List[Agent], mediator_agent: Agent):
"""Initialize consensus orchestrator."""
self.agents = agents
self.mediator = mediator_agent
self.debate_history = []
def execute(self, question: str, rounds: int = 2) -> Dict[str, Any]:
"""
Execute debate and reach consensus.
Args:
question: Question for debate
rounds: Number of debate rounds
Returns:
Consensus results
"""
# Round 1: Initial positions
positions = {}
for agent in self.agents:
position = agent.work(f"Argue your position on: {question}")
positions[agent.name] = position
self.debate_history.append({
"round": 1,
"agent": agent.name,
"position": position,
})
# Additional rounds: Response to others
for round_num in range(2, rounds + 1):
for agent in self.agents:
other_positions = {
name: pos
for name, pos in positions.items()
if name != agent.name
}
response = agent.work(
f"Respond to these positions: {str(other_positions)}"
)
self.debate_history.append({
"round": round_num,
"agent": agent.name,
"response": response,
})
# Mediator reaches consensus
consensus = self.mediator.work(
f"Synthesize consensus from debate on: {question}"
)
return {
"type": "consensus",
"question": question,
"initial_positions": positions,
"debate_rounds": rounds,
"consensus": consensus,
"debate_history": self.debate_history,
}
class AdaptiveOrchestrator:
"""Adapt orchestration based on progress."""
def __init__(self, agents: List[Agent]):
"""Initialize adaptive orchestrator."""
self.agents = agents
self.execution_log = []
def execute_with_adaptation(
self,
initial_task: str,
progress_threshold: float = 0.7,
quality_threshold: float = 0.6,
) -> Dict[str, Any]:
"""
Execute with adaptive workflow changes.
Args:
initial_task: Initial task
progress_threshold: Threshold for adding resources
quality_threshold: Threshold for adding validation
Returns:
Adaptive execution results
"""
results = {}
current_task = initial_task
active_agents = self.agents.copy()
for iteration in range(3):
# Execute with current agents
iteration_results = {}
for agent in active_agents:
result = agent.work(current_task)
iteration_results[agent.name] = result
results[f"iteration_{iteration}"] = iteration_results
# Assess progress
progress = self._calculate_progress(iteration_results)
quality = self._calculate_quality(iteration_results)
log_entry = {
"iteration": iteration,
"agents": [a.name for a in active_agents],
"progress": progress,
"quality": quality,
}
# Adapt based on progress
if progress < progress_threshold and iteration < 2:
# Add more agents
log_entry["adaptation"] = "Added specialist agent"
self.execution_log.append(log_entry)
elif quality < quality_threshold and iteration < 2:
# Add validation step
log_entry["adaptation"] = "Added validation agent"
self.execution_log.append(log_entry)
else:
self.execution_log.append(log_entry)
return {
"type": "adaptive",
"results": results,
"adaptations": self.execution_log,
}
@staticmethod
def _calculate_progress(results: Dict) -> float:
"""Calculate progress score."""
# Simple heuristic based on results
return min(len(results) / 3.0, 1.0)
@staticmethod
def _calculate_quality(results: Dict) -> float:
"""Calculate quality score."""
# Simple heuristic
return 0.7 # Placeholder
class WorkflowGraph:
"""Define workflow as directed acyclic graph (DAG)."""
def __init__(self):
"""Initialize workflow graph."""
self.nodes = {}
self.edges = []
def add_node(self, node_id: str, agent: Agent) -> None:
"""Add agent node."""
self.nodes[node_id] = agent
def add_edge(self, from_node: str, to_node: str) -> None:
"""Add dependency edge."""
self.edges.append((from_node, to_node))
def execute_dag(self, initial_task: str) -> Dict[str, Any]:
"""
Execute workflow as DAG.
Args:
initial_task: Initial task
Returns:
Execution results
"""
results = {}
ready_nodes = self._find_ready_nodes()
while ready_nodes:
for node_id in ready_nodes:
agent = self.nodes[node_id]
# Get input from dependencies
task_input = self._get_node_input(node_id, results, initial_task)
result = agent.work(task_input)
results[node_id] = result
ready_nodes = self._find_ready_nodes(completed=set(results.keys()))
return {
"type": "dag",
"results": results,
"nodes": list(self.nodes.keys()),
"edges": self.edges,
}
def _find_ready_nodes(self, completed: Optional[set] = None) -> List[str]:
"""Find nodes with all dependencies completed."""
if completed is None:
completed = set()
ready = []
for node_id in self.nodes:
if node_id not in completed:
dependencies = [
from_node
for from_node, to_node in self.edges
if to_node == node_id
]
if all(dep in completed for dep in dependencies):
ready.append(node_id)
return ready
def _get_node_input(
self, node_id: str, results: Dict, initial_task: str
) -> str:
"""Get input for node from dependencies."""
dependencies = [
from_node for from_node, to_node in self.edges if to_node == node_id
]
if not dependencies:
return initial_task
# Combine outputs from dependencies
return " + ".join(results.get(dep, "") for dep in dependencies)
# Multi-Agent Orchestration - Code Structure
This skill uses supporting Python files to keep documentation lean and maintainable.
## Directory Structure
```
multi-agent-orchestration/
├── SKILL.md # Main documentation (patterns, concepts)
├── README.md # This file
├── examples/ # Implementation examples
│ ├── orchestration_patterns.py # Sequential, parallel, hierarchical, consensus
│ └── framework_implementations.py # CrewAI, AutoGen, LangGraph, Swarm templates
└── scripts/ # Utility modules
├── agent_communication.py # Message broker, shared memory, protocols
├── workflow_management.py # Workflow execution and optimization
└── benchmarking.py # Performance and collaboration metrics
```
## Running Examples
### 1. Orchestration Patterns
```bash
python examples/orchestration_patterns.py
```
Demonstrates sequential, parallel, hierarchical, and consensus orchestration.
### 2. Framework Templates
```bash
python examples/framework_implementations.py
```
Templates and configurations for CrewAI, AutoGen, LangGraph, and Swarm frameworks.
## Using the Utilities
### Agent Communication
```python
from scripts.agent_communication import MessageBroker, SharedMemory, CommunicationProtocol
# Set up communication
broker = MessageBroker()
shared_memory = SharedMemory()
protocol = CommunicationProtocol(broker, shared_memory)
# Send messages between agents
protocol.request_analysis("agent_a", "agent_b", "Analyze this topic")
# Share findings
protocol.share_findings("agent_a", "analysis_results", {"findings": "..."})
# Get communication stats
stats = broker.get_statistics()
```
### Workflow Management
```python
from scripts.workflow_management import WorkflowExecutor, WorkflowOptimizer
# Create and execute workflow
executor = WorkflowExecutor()
workflow = executor.create_workflow("workflow_1", "Analysis Workflow")
# Add tasks
executor.add_task("workflow_1", "task_1", "researcher", "Research the topic")
executor.add_task("workflow_1", "task_2", "analyst", "Analyze findings", dependencies=["task_1"])
# Execute
results = executor.execute_workflow("workflow_1", executor_func)
# Analyze workflow
analysis = WorkflowOptimizer.analyze_dependencies(workflow)
print(f"Critical path: {analysis['critical_path']}")
```
### Benchmarking
```python
from scripts.benchmarking import TeamBenchmark, AgentEffectiveness, CollaborationMetrics
# Benchmark team performance
benchmark = TeamBenchmark()
result = benchmark.run_benchmark("sequential_test", orchestrator, test_data)
# Track agent effectiveness
effectiveness = AgentEffectiveness()
effectiveness.record_agent_task("agent_a", "task_1", success=True, quality_score=0.95, duration=2.5)
# Get agent rankings
rankings = effectiveness.rank_agents()
for rank, agent, score, metrics in rankings:
print(f"{rank}. {agent}: {score:.2f}")
# Analyze collaboration
collaboration = CollaborationMetrics()
collaboration.record_interaction("agent_a", "agent_b", "request", response_time=0.5, successful=True)
interaction_metrics = collaboration.get_interaction_metrics()
```
## Integration with SKILL.md
- SKILL.md contains conceptual information, orchestration patterns, and best practices
- Code examples are in `examples/` for clarity and runnable implementations
- Utilities are in `scripts/` for modular, reusable components
- This keeps token costs low while maintaining full functionality
## Orchestration Patterns Covered
1. **Sequential Orchestration** - Tasks execute one after another
2. **Parallel Orchestration** - Multiple agents work simultaneously
3. **Hierarchical Orchestration** - Manager coordinates specialist teams
4. **Consensus-Based** - Agents debate and reach consensus
5. **Adaptive Workflows** - Orchestration changes based on progress
6. **DAG-Based** - Workflow as directed acyclic graph
## Framework Implementations
- **CrewAI** - Clear roles, hierarchical structure
- **AutoGen** - Multi-turn conversations, group discussions
- **LangGraph** - State management, complex workflows
- **Swarm** - Simple handoffs, conversational workflows
## Key Features
- **Token Efficient**: Modular code structure reduces LLM context usage
- **Production Ready**: Includes monitoring, optimization, and benchmarking
- **Framework Agnostic**: Works with any agent framework
- **Communication Patterns**: Direct, tool-mediated, and manager-based
- **Performance Metrics**: Team and individual agent effectiveness tracking
## Communication Patterns
- **Direct Communication**: Agent-to-agent message passing
- **Tool-Mediated**: Agents use shared memory/database
- **Manager-Based**: Central coordinator manages communication
- **Broadcast**: One-to-many messaging
## Next Steps
1. Define agent roles and expertise
2. Choose orchestration pattern (sequential, parallel, hierarchical)
3. Select communication approach (direct, shared memory, manager)
4. Implement workflow with task definitions
5. Set up monitoring and metrics
6. Benchmark and optimize
7. Deploy and iterate
"""
Agent Communication Management
Handle agent-to-agent communication, message passing, and shared state.
"""
from typing import Dict, List, Optional, Any, Callable
from dataclasses import dataclass, field
from enum import Enum
import json
class MessageType(Enum):
"""Types of messages between agents."""
DIRECT = "direct"
BROADCAST = "broadcast"
REQUEST = "request"
RESPONSE = "response"
FEEDBACK = "feedback"
ERROR = "error"
@dataclass
class Message:
"""Message between agents."""
sender: str
recipient: str
content: str
message_type: MessageType
timestamp: float = field(default_factory=lambda: 0)
metadata: Dict[str, Any] = field(default_factory=dict)
def to_dict(self) -> Dict:
"""Convert to dictionary."""
return {
"sender": self.sender,
"recipient": self.recipient,
"content": self.content,
"type": self.message_type.value,
"timestamp": self.timestamp,
"metadata": self.metadata,
}
class MessageBroker:
"""Central message broker for agent communication."""
def __init__(self):
"""Initialize message broker."""
self.message_queue: List[Message] = []
self.agent_inboxes: Dict[str, List[Message]] = {}
self.message_handlers: Dict[MessageType, List[Callable]] = {}
def send_message(self, message: Message) -> bool:
"""
Send message from one agent to another.
Args:
message: Message object
Returns:
Whether message was delivered
"""
self.message_queue.append(message)
# Add to recipient's inbox
if message.recipient not in self.agent_inboxes:
self.agent_inboxes[message.recipient] = []
self.agent_inboxes[message.recipient].append(message)
# Trigger handlers
self._trigger_handlers(message)
return True
def broadcast_message(self, sender: str, content: str, recipients: List[str]):
"""
Broadcast message to multiple agents.
Args:
sender: Sending agent
content: Message content
recipients: List of recipient agents
"""
for recipient in recipients:
message = Message(
sender=sender,
recipient=recipient,
content=content,
message_type=MessageType.BROADCAST,
)
self.send_message(message)
def request_response(
self, sender: str, recipient: str, content: str, timeout: float = 5.0
) -> Optional[Message]:
"""
Send request and wait for response.
Args:
sender: Requesting agent
recipient: Agent to respond
content: Request content
timeout: Response timeout in seconds
Returns:
Response message or None
"""
message = Message(
sender=sender,
recipient=recipient,
content=content,
message_type=MessageType.REQUEST,
metadata={"timeout": timeout},
)
self.send_message(message)
# Placeholder - wait for response
# In production, implement actual timeout/wait mechanism
return None
def get_inbox(self, agent: str) -> List[Message]:
"""Get messages for specific agent."""
return self.agent_inboxes.get(agent, [])
def clear_inbox(self, agent: str) -> None:
"""Clear agent's inbox."""
self.agent_inboxes[agent] = []
def register_handler(
self, message_type: MessageType, handler: Callable
) -> None:
"""Register handler for message type."""
if message_type not in self.message_handlers:
self.message_handlers[message_type] = []
self.message_handlers[message_type].append(handler)
def _trigger_handlers(self, message: Message) -> None:
"""Trigger registered handlers."""
handlers = self.message_handlers.get(message.message_type, [])
for handler in handlers:
try:
handler(message)
except Exception:
pass
def get_statistics(self) -> Dict[str, Any]:
"""Get communication statistics."""
type_counts = {}
for message in self.message_queue:
msg_type = message.message_type.value
type_counts[msg_type] = type_counts.get(msg_type, 0) + 1
return {
"total_messages": len(self.message_queue),
"by_type": type_counts,
"total_agents": len(self.agent_inboxes),
"agents": list(self.agent_inboxes.keys()),
}
class SharedMemory:
"""Shared memory for tool-mediated agent communication."""
def __init__(self):
"""Initialize shared memory."""
self.memory: Dict[str, Any] = {}
self.access_log: List[Dict] = []
def write(self, key: str, value: Any, agent: str = "system") -> None:
"""
Write to shared memory.
Args:
key: Memory key
value: Value to store
agent: Agent writing
"""
self.memory[key] = {
"value": value,
"writer": agent,
"access_count": 0,
}
self.access_log.append({
"action": "write",
"key": key,
"agent": agent,
})
def read(self, key: str, agent: str = "system") -> Optional[Any]:
"""
Read from shared memory.
Args:
key: Memory key
agent: Agent reading
Returns:
Stored value or None
"""
if key in self.memory:
entry = self.memory[key]
entry["access_count"] += 1
self.access_log.append({
"action": "read",
"key": key,
"agent": agent,
})
return entry["value"]
return None
def append(self, key: str, value: Any, agent: str = "system") -> None:
"""Append to list in shared memory."""
if key not in self.memory:
self.memory[key] = {
"value": [],
"writer": agent,
"access_count": 0,
}
if isinstance(self.memory[key]["value"], list):
self.memory[key]["value"].append(value)
def get_all(self) -> Dict[str, Any]:
"""Get all shared memory contents."""
return {
key: entry["value"] for key, entry in self.memory.items()
}
def get_statistics(self) -> Dict[str, Any]:
"""Get memory access statistics."""
total_accesses = sum(
entry["access_count"] for entry in self.memory.values()
)
return {
"total_keys": len(self.memory),
"total_accesses": total_accesses,
"access_log_size": len(self.access_log),
}
class ContextManager:
"""Manage context sharing between agents."""
def __init__(self):
"""Initialize context manager."""
self.contexts: Dict[str, Dict[str, Any]] = {}
self.global_context: Dict[str, Any] = {}
def create_context(self, context_id: str, initial_data: Optional[Dict] = None) -> None:
"""Create new context."""
self.contexts[context_id] = initial_data or {}
def update_context(self, context_id: str, data: Dict) -> None:
"""Update context data."""
if context_id in self.contexts:
self.contexts[context_id].update(data)
def get_context(self, context_id: str) -> Dict[str, Any]:
"""Get context data."""
return self.contexts.get(context_id, {})
def set_global_context(self, key: str, value: Any) -> None:
"""Set global context variable."""
self.global_context[key] = value
def get_global_context(self, key: str) -> Optional[Any]:
"""Get global context variable."""
return self.global_context.get(key)
def context_to_string(self, context_id: str) -> str:
"""Convert context to formatted string."""
context = self.get_context(context_id)
return json.dumps(context, indent=2)
class CommunicationProtocol:
"""Define communication protocol between agents."""
def __init__(self, broker: MessageBroker, shared_memory: SharedMemory):
"""Initialize protocol."""
self.broker = broker
self.shared_memory = shared_memory
def request_analysis(
self, requester: str, analyzer: str, subject: str
) -> None:
"""Request analysis from another agent."""
message = Message(
sender=requester,
recipient=analyzer,
content=f"Analyze: {subject}",
message_type=MessageType.REQUEST,
metadata={"action": "analyze"},
)
self.broker.send_message(message)
def share_findings(self, source_agent: str, key: str, findings: Dict) -> None:
"""Share findings through shared memory."""
self.shared_memory.write(key, findings, source_agent)
def aggregate_results(
self, agents: List[str], result_key: str
) -> Dict[str, Any]:
"""Aggregate results from multiple agents."""
results = {}
for agent in agents:
agent_results = self.shared_memory.read(f"{agent}_{result_key}")
if agent_results:
results[agent] = agent_results
return results
def notify_status(self, agent: str, status: str) -> None:
"""Notify status update."""
message = Message(
sender=agent,
recipient="orchestrator",
content=f"Status: {status}",
message_type=MessageType.FEEDBACK,
)
self.broker.send_message(message)
def error_propagation(self, source_agent: str, error: str) -> None:
"""Propagate error to relevant agents."""
message = Message(
sender=source_agent,
recipient="orchestrator",
content=f"Error: {error}",
message_type=MessageType.ERROR,
)
self.broker.send_message(message)
"""
Multi-Agent System Benchmarking
Evaluate team performance and agent effectiveness.
"""
from typing import Dict, List, Any, Callable, Optional
from dataclasses import dataclass
import time
import statistics
@dataclass
class BenchmarkResult:
"""Result from benchmark run."""
test_name: str
total_time: float
task_count: int
success_count: int
failure_count: int
quality_score: float
cost_tokens: int
class TeamBenchmark:
"""Benchmark multi-agent team performance."""
def __init__(self):
"""Initialize benchmarking suite."""
self.results: List[BenchmarkResult] = []
self.agent_metrics: Dict[str, Dict] = {}
def run_benchmark(
self,
test_name: str,
orchestrator,
test_data: List[Dict],
quality_metric: Optional[Callable] = None,
) -> BenchmarkResult:
"""
Run benchmark test.
Args:
test_name: Name of benchmark
orchestrator: Orchestrator instance
test_data: Test cases
quality_metric: Function to evaluate quality
Returns:
Benchmark result
"""
start_time = time.time()
results = []
costs = []
for test_case in test_data:
try:
result = orchestrator.execute(test_case)
results.append(result)
# Assume cost in test_case
costs.append(test_case.get("cost", 0))
except Exception:
pass
end_time = time.time()
success_count = len(results)
failure_count = len(test_data) - success_count
total_time = end_time - start_time
# Calculate quality score
quality_score = (
quality_metric(results) if quality_metric else success_count / len(test_data)
)
benchmark_result = BenchmarkResult(
test_name=test_name,
total_time=total_time,
task_count=len(test_data),
success_count=success_count,
failure_count=failure_count,
quality_score=quality_score,
cost_tokens=sum(costs),
)
self.results.append(benchmark_result)
return benchmark_result
def compare_orchestration_methods(
self,
methods: Dict[str, Callable],
test_data: List[Dict],
) -> Dict[str, Any]:
"""
Compare different orchestration methods.
Args:
methods: Dict of method name to orchestrator
test_data: Test cases
Returns:
Comparison results
"""
comparison = {}
for method_name, orchestrator in methods.items():
result = self.run_benchmark(method_name, orchestrator, test_data)
comparison[method_name] = {
"total_time": result.total_time,
"success_rate": result.success_count / result.task_count,
"quality_score": result.quality_score,
"efficiency": result.success_count / (result.total_time + 0.001),
"cost_per_success": (
result.cost_tokens / result.success_count
if result.success_count > 0
else float("inf")
),
}
return comparison
def get_summary(self) -> Dict[str, Any]:
"""Get benchmark summary."""
if not self.results:
return {"status": "no_results"}
times = [r.total_time for r in self.results]
success_rates = [
r.success_count / r.task_count for r in self.results
]
quality_scores = [r.quality_score for r in self.results]
return {
"total_benchmarks": len(self.results),
"avg_time": statistics.mean(times),
"median_time": statistics.median(times),
"avg_success_rate": statistics.mean(success_rates),
"avg_quality": statistics.mean(quality_scores),
"benchmarks": [r.__dict__ for r in self.results],
}
class AgentEffectiveness:
"""Measure individual agent effectiveness."""
def __init__(self):
"""Initialize effectiveness tracker."""
self.agent_stats: Dict[str, Dict] = {}
def record_agent_task(
self,
agent: str,
task_id: str,
success: bool,
quality_score: float,
duration: float,
) -> None:
"""Record agent task execution."""
if agent not in self.agent_stats:
self.agent_stats[agent] = {
"tasks": [],
"successes": 0,
"failures": 0,
}
stats = self.agent_stats[agent]
stats["tasks"].append({
"task_id": task_id,
"success": success,
"quality": quality_score,
"duration": duration,
})
if success:
stats["successes"] += 1
else:
stats["failures"] += 1
def get_agent_metrics(self, agent: str) -> Dict[str, Any]:
"""Get metrics for specific agent."""
if agent not in self.agent_stats:
return {"status": "no_data"}
stats = self.agent_stats[agent]
tasks = stats["tasks"]
if not tasks:
return {"status": "no_tasks"}
success_rate = stats["successes"] / (stats["successes"] + stats["failures"])
quality_scores = [t["quality"] for t in tasks]
durations = [t["duration"] for t in tasks]
return {
"agent": agent,
"total_tasks": len(tasks),
"success_rate": success_rate,
"avg_quality": statistics.mean(quality_scores),
"avg_duration": statistics.mean(durations),
"reliability": success_rate, # Alias for clarity
}
def rank_agents(self) -> List[tuple]:
"""Rank agents by effectiveness."""
rankings = []
for agent in self.agent_stats.keys():
metrics = self.get_agent_metrics(agent)
if "success_rate" in metrics:
score = (
metrics["success_rate"] * 0.4 +
metrics["avg_quality"] * 0.4 +
(1 - min(metrics["avg_duration"] / 10.0, 1.0)) * 0.2
)
rankings.append((agent, score, metrics))
rankings.sort(key=lambda x: x[1], reverse=True)
return rankings
def get_team_report(self) -> Dict[str, Any]:
"""Get team effectiveness report."""
rankings = self.rank_agents()
return {
"total_agents": len(self.agent_stats),
"rankings": [
{
"rank": i + 1,
"agent": agent,
"score": score,
"metrics": metrics,
}
for i, (agent, score, metrics) in enumerate(rankings)
],
}
class CollaborationMetrics:
"""Measure collaboration effectiveness between agents."""
def __init__(self):
"""Initialize collaboration metrics."""
self.interactions: List[Dict] = []
def record_interaction(
self,
agent_a: str,
agent_b: str,
message: str,
response_time: float,
successful: bool,
) -> None:
"""Record agent-to-agent interaction."""
self.interactions.append({
"agent_a": agent_a,
"agent_b": agent_b,
"message": message,
"response_time": response_time,
"successful": successful,
})
def get_collaboration_graph(self) -> Dict[str, List[str]]:
"""Get collaboration graph between agents."""
graph = {}
for interaction in self.interactions:
agent_a = interaction["agent_a"]
agent_b = interaction["agent_b"]
if agent_a not in graph:
graph[agent_a] = []
if agent_b not in graph[agent_a]:
graph[agent_a].append(agent_b)
return graph
def get_interaction_metrics(self) -> Dict[str, Any]:
"""Get interaction metrics."""
if not self.interactions:
return {"total_interactions": 0}
response_times = [i["response_time"] for i in self.interactions]
success_rate = sum(1 for i in self.interactions if i["successful"]) / len(
self.interactions
)
return {
"total_interactions": len(self.interactions),
"success_rate": success_rate,
"avg_response_time": statistics.mean(response_times),
"median_response_time": statistics.median(response_times),
"max_response_time": max(response_times),
"collaboration_score": success_rate * (1 - min(statistics.mean(response_times) / 10.0, 1.0)),
}
def get_agent_collaboration_analysis(self, agent: str) -> Dict[str, Any]:
"""Get collaboration analysis for specific agent."""
agent_interactions = [
i for i in self.interactions
if i["agent_a"] == agent or i["agent_b"] == agent
]
if not agent_interactions:
return {"agent": agent, "status": "no_interactions"}
partners = set()
for interaction in agent_interactions:
if interaction["agent_a"] == agent:
partners.add(interaction["agent_b"])
else:
partners.add(interaction["agent_a"])
success_rate = sum(
1 for i in agent_interactions if i["successful"]
) / len(agent_interactions)
return {
"agent": agent,
"collaboration_partners": list(partners),
"total_interactions": len(agent_interactions),
"collaboration_success_rate": success_rate,
}
def create_benchmark_suite() -> Dict[str, Callable]:
"""Create standard benchmark suite."""
return {
"sequential_tasks": lambda orchestrator: orchestrator.execute(
{"type": "sequential", "task_count": 5}
),
"parallel_tasks": lambda orchestrator: orchestrator.execute(
{"type": "parallel", "task_count": 10}
),
"complex_workflow": lambda orchestrator: orchestrator.execute(
{"type": "complex", "task_count": 20}
),
"error_handling": lambda orchestrator: orchestrator.execute(
{"type": "with_errors", "task_count": 10}
),
}
"""
Workflow Management for Multi-Agent Systems
Handle workflow execution, monitoring, and optimization.
"""
from typing import Dict, List, Any, Optional, Callable
from enum import Enum
from dataclasses import dataclass, field
import time
class WorkflowStatus(Enum):
"""Workflow execution status."""
PENDING = "pending"
RUNNING = "running"
PAUSED = "paused"
COMPLETED = "completed"
FAILED = "failed"
class TaskStatus(Enum):
"""Task execution status."""
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
SKIPPED = "skipped"
@dataclass
class Task:
"""Task to be executed by an agent."""
task_id: str
agent: str
description: str
status: TaskStatus = TaskStatus.PENDING
result: Optional[str] = None
error: Optional[str] = None
start_time: float = field(default_factory=time.time)
end_time: Optional[float] = None
dependencies: List[str] = field(default_factory=list)
@dataclass
class Workflow:
"""Workflow orchestration."""
workflow_id: str
name: str
tasks: Dict[str, Task] = field(default_factory=dict)
status: WorkflowStatus = WorkflowStatus.PENDING
start_time: Optional[float] = None
end_time: Optional[float] = None
class WorkflowExecutor:
"""Execute workflows with multiple agents."""
def __init__(self):
"""Initialize workflow executor."""
self.workflows: Dict[str, Workflow] = {}
self.execution_history: List[Dict] = []
def create_workflow(self, workflow_id: str, name: str) -> Workflow:
"""Create new workflow."""
workflow = Workflow(workflow_id=workflow_id, name=name)
self.workflows[workflow_id] = workflow
return workflow
def add_task(
self,
workflow_id: str,
task_id: str,
agent: str,
description: str,
dependencies: Optional[List[str]] = None,
) -> Task:
"""Add task to workflow."""
task = Task(
task_id=task_id,
agent=agent,
description=description,
dependencies=dependencies or [],
)
self.workflows[workflow_id].tasks[task_id] = task
return task
def execute_workflow(
self, workflow_id: str, executor_func: Callable
) -> Dict[str, Any]:
"""
Execute workflow.
Args:
workflow_id: Workflow ID
executor_func: Function to execute tasks
Returns:
Execution results
"""
workflow = self.workflows[workflow_id]
workflow.status = WorkflowStatus.RUNNING
workflow.start_time = time.time()
executed_tasks = set()
results = {}
while len(executed_tasks) < len(workflow.tasks):
# Find ready tasks
ready_tasks = self._get_ready_tasks(workflow, executed_tasks)
if not ready_tasks:
# Check if workflow is stuck
if len(executed_tasks) > 0:
break
for task_id in ready_tasks:
task = workflow.tasks[task_id]
task.status = TaskStatus.RUNNING
try:
# Execute task
result = executor_func(task)
task.result = result
task.status = TaskStatus.COMPLETED
results[task_id] = result
except Exception as e:
task.error = str(e)
task.status = TaskStatus.FAILED
results[task_id] = None
task.end_time = time.time()
executed_tasks.add(task_id)
# Finalize workflow
workflow.end_time = time.time()
if all(task.status == TaskStatus.COMPLETED for task in workflow.tasks.values()):
workflow.status = WorkflowStatus.COMPLETED
else:
workflow.status = WorkflowStatus.FAILED
execution_record = {
"workflow_id": workflow_id,
"status": workflow.status.value,
"duration": workflow.end_time - workflow.start_time,
"results": results,
}
self.execution_history.append(execution_record)
return results
def _get_ready_tasks(
self, workflow: Workflow, executed: set
) -> List[str]:
"""Get tasks ready to execute."""
ready = []
for task_id, task in workflow.tasks.items():
if task_id not in executed and task.status == TaskStatus.PENDING:
# Check if all dependencies are complete
deps_met = all(dep in executed for dep in task.dependencies)
if deps_met:
ready.append(task_id)
return ready
def get_workflow_status(self, workflow_id: str) -> Dict[str, Any]:
"""Get workflow status."""
workflow = self.workflows[workflow_id]
return {
"id": workflow.workflow_id,
"name": workflow.name,
"status": workflow.status.value,
"tasks": {
task_id: task.status.value
for task_id, task in workflow.tasks.items()
},
}
class WorkflowOptimizer:
"""Optimize workflow execution."""
@staticmethod
def analyze_dependencies(workflow: Workflow) -> Dict[str, Any]:
"""Analyze task dependencies."""
dep_graph = {}
for task_id, task in workflow.tasks.items():
dep_graph[task_id] = task.dependencies
# Find critical path
critical_path = WorkflowOptimizer._find_critical_path(
dep_graph, workflow.tasks
)
# Find parallelizable tasks
parallel_groups = WorkflowOptimizer._find_parallel_groups(dep_graph)
return {
"dependency_graph": dep_graph,
"critical_path": critical_path,
"parallelizable_groups": parallel_groups,
}
@staticmethod
def _find_critical_path(dep_graph: Dict, tasks: Dict) -> List[str]:
"""Find tasks on critical path."""
# Simple implementation - actual critical path is more complex
return list(dep_graph.keys())
@staticmethod
def _find_parallel_groups(dep_graph: Dict) -> List[List[str]]:
"""Find groups of tasks that can execute in parallel."""
groups = []
remaining = set(dep_graph.keys())
while remaining:
# Find tasks with no dependencies in remaining set
independent = [
task
for task in remaining
if not any(dep in remaining for dep in dep_graph.get(task, []))
]
if independent:
groups.append(independent)
remaining -= set(independent)
else:
break
return groups
@staticmethod
def estimate_execution_time(
workflow: Workflow, task_times: Dict[str, float]
) -> float:
"""Estimate total execution time."""
parallel_groups = WorkflowOptimizer._find_parallel_groups({
task_id: task.dependencies
for task_id, task in workflow.tasks.items()
})
total_time = 0
for group in parallel_groups:
group_time = max(
task_times.get(task_id, 1.0) for task_id in group
)
total_time += group_time
return total_time
@staticmethod
def suggest_parallelization(workflow: Workflow) -> List[Dict[str, Any]]:
"""Suggest ways to parallelize workflow."""
suggestions = []
dep_graph = {
task_id: task.dependencies
for task_id, task in workflow.tasks.items()
}
# Find sequential chains that could be parallelized
for task_id, dependencies in dep_graph.items():
if len(dependencies) == 0:
suggestions.append({
"task": task_id,
"suggestion": "Can be parallelized with other independent tasks",
})
return suggestions
class WorkflowMonitor:
"""Monitor workflow execution."""
def __init__(self):
"""Initialize monitor."""
self.events: List[Dict] = []
def record_event(
self, workflow_id: str, task_id: str, event_type: str, data: Dict
) -> None:
"""Record workflow event."""
event = {
"workflow_id": workflow_id,
"task_id": task_id,
"event_type": event_type,
"timestamp": time.time(),
"data": data,
}
self.events.append(event)
def get_workflow_metrics(self, workflow_id: str) -> Dict[str, Any]:
"""Get workflow metrics."""
workflow_events = [e for e in self.events if e["workflow_id"] == workflow_id]
task_times = {}
for event in workflow_events:
task_id = event["task_id"]
if event["event_type"] == "start":
task_times[task_id] = {"start": event["timestamp"]}
elif event["event_type"] == "complete":
if task_id in task_times:
task_times[task_id]["end"] = event["timestamp"]
# Calculate durations
durations = {
task_id: times.get("end", time.time()) - times["start"]
for task_id, times in task_times.items()
}
return {
"total_tasks": len(task_times),
"task_durations": durations,
"avg_duration": sum(durations.values()) / len(durations)
if durations
else 0,
"max_duration": max(durations.values()) if durations else 0,
}
def get_performance_report(self) -> Dict[str, Any]:
"""Get overall performance report."""
if not self.events:
return {"status": "no_events"}
workflow_ids = set(e["workflow_id"] for e in self.events)
report = {}
for workflow_id in workflow_ids:
report[workflow_id] = self.get_workflow_metrics(workflow_id)
return report
---
name: multi-agent-orchestration
description: Design and coordinate multi-agent systems where specialized agents work together to solve complex problems. Covers agent communication, task delegation, workflow orchestration, and result aggregation. Use when building coordinated agent teams, complex workflows, or systems requiring specialized expertise across domains.
---
# Multi-Agent Orchestration
Design and orchestrate sophisticated multi-agent systems where specialized agents collaborate to solve complex problems, combining different expertise and perspectives.
## Quick Start
Get started with multi-agent implementations in the examples and utilities:
- **Examples**: See [`examples/`](examples/) directory for complete implementations:
- [`orchestration_patterns.py`](examples/orchestration_patterns.py) - Sequential, parallel, hierarchical, and consensus orchestration
- [`framework_implementations.py`](examples/framework_implementations.py) - Templates for CrewAI, AutoGen, LangGraph, and Swarm
- **Utilities**: See [`scripts/`](scripts/) directory for helper modules:
- [`agent_communication.py`](scripts/agent_communication.py) - Message broker, shared memory, and communication protocols
- [`workflow_management.py`](scripts/workflow_management.py) - Workflow execution, optimization, and monitoring
- [`benchmarking.py`](scripts/benchmarking.py) - Team performance and agent effectiveness metrics
## Overview
Multi-agent systems decompose complex problems into specialized sub-tasks, assigning each to an agent with relevant expertise, then coordinating their work toward a unified goal.
### When Multi-Agent Systems Shine
- **Complex Workflows**: Tasks requiring multiple specialized roles
- **Domain-Specific Expertise**: Finance, legal, HR, engineering need different knowledge
- **Parallel Processing**: Multiple agents work on different aspects simultaneously
- **Collaborative Reasoning**: Agents debate, refine, and improve solutions
- **Resilience**: Failures in one agent don't break the entire system
- **Scalability**: Easy to add new specialized agents
### Architecture Overview
```
User Request
Orchestrator
├→ Agent 1 (Specialist) → Task 1
├→ Agent 2 (Specialist) → Task 2
├→ Agent 3 (Specialist) → Task 3
Result Aggregator
Final Response
```
## Core Concepts
### Agent Definition
An agent is defined by:
- **Role**: What responsibility does it have? (e.g., "Financial Analyst")
- **Goal**: What should it accomplish? (e.g., "Analyze financial risks")
- **Expertise**: What knowledge/tools does it have?
- **Tools**: What capabilities can it access?
- **Context**: What information does it need to work effectively?
### Orchestration Patterns
#### 1. Sequential Orchestration
- Agents work one after another
- Each agent uses output from previous agent
- **Use Case**: Steps must follow order (research → analysis → writing)
#### 2. Parallel Orchestration
- Multiple agents work simultaneously
- Results aggregated at the end
- **Use Case**: Independent tasks (analyze competitors, market, users)
#### 3. Hierarchical Orchestration
- Senior agent delegates to junior agents
- Manager coordinates flow
- **Use Case**: Large projects with oversight
#### 4. Consensus-Based Orchestration
- Multiple agents analyze problem
- Debate and refine ideas
- Vote or reach consensus
- **Use Case**: Complex decisions needing multiple perspectives
#### 5. Tool-Mediated Orchestration
- Agents use shared tools/databases
- Minimal direct communication
- **Use Case**: Large systems, indirect coordination
## Multi-Agent Team Examples
### Finance Team
```
Coordinator Agent
├→ Market Analyst Agent
│ ├ Tools: Market data API, financial news
│ └ Task: Analyze market conditions
├→ Financial Analyst Agent
│ ├ Tools: Financial statements, ratio calculations
│ └ Task: Analyze company financials
├→ Risk Manager Agent
│ ├ Tools: Risk models, scenario analysis
│ └ Task: Assess investment risks
└→ Report Writer Agent
├ Tools: Document generation
└ Task: Synthesize findings into report
```
### Legal Team
```
Case Manager Agent (Coordinator)
├→ Contract Analyzer Agent
│ └ Task: Review contract terms
├→ Precedent Research Agent
│ └ Task: Find relevant case law
├→ Risk Assessor Agent
│ └ Task: Identify legal risks
└→ Document Drafter Agent
└ Task: Prepare legal documents
```
### Customer Support Team
```
Support Coordinator
├→ Issue Classifier Agent
│ └ Task: Categorize customer issue
├→ Knowledge Base Agent
│ └ Task: Find relevant documentation
├→ Escalation Agent
│ └ Task: Determine if human escalation needed
└→ Solution Synthesizer Agent
└ Task: Prepare comprehensive response
```
## Implementation Frameworks
### 1. CrewAI
**Best For**: Teams with clear roles and hierarchical structure
```python
from crewai import Agent, Task, Crew
# Define agents
analyst = Agent(
role="Financial Analyst",
goal="Analyze financial data and provide insights",
backstory="Expert in financial markets with 10+ years experience"
)
researcher = Agent(
role="Market Researcher",
goal="Research market trends and competition",
backstory="Data-driven researcher specializing in market analysis"
)
# Define tasks
analysis_task = Task(
description="Analyze Q3 financial results for {company}",
agent=analyst,
tools=[financial_tool, data_tool]
)
research_task = Task(
description="Research competitive landscape in {market}",
agent=researcher,
tools=[web_search_tool, industry_data_tool]
)
# Create crew and execute
crew = Crew(
agents=[analyst, researcher],
tasks=[analysis_task, research_task],
process=Process.sequential
)
result = crew.kickoff(inputs={"company": "TechCorp", "market": "AI"})
```
### 2. AutoGen (Microsoft)
**Best For**: Complex multi-turn conversations and negotiations
```python
from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager
# Define agents
analyst = AssistantAgent(
name="analyst",
system_message="You are a financial analyst..."
)
researcher = AssistantAgent(
name="researcher",
system_message="You are a market researcher..."
)
# Create group chat
groupchat = GroupChat(
agents=[analyst, researcher],
messages=[],
max_round=10,
speaker_selection_method="auto"
)
# Manage group conversation
manager = GroupChatManager(groupchat=groupchat)
# User proxy to initiate conversation
user = UserProxyAgent(name="user")
# Have conversation
user.initiate_chat(
manager,
message="Analyze if Company X should invest in Y market"
)
```
### 3. LangGraph
**Best For**: Complex workflows with state management
```python
from langgraph.graph import Graph, StateGraph
from langgraph.prebuilt import create_agent_executor
# Define state
class AgentState:
research_findings: str
analysis: str
recommendations: str
# Create graph
graph = StateGraph(AgentState)
# Add nodes for each agent
graph.add_node("researcher", research_agent)
graph.add_node("analyst", analyst_agent)
graph.add_node("writer", writer_agent)
# Define edges (workflow)
graph.add_edge("researcher", "analyst")
graph.add_edge("analyst", "writer")
# Set entry/exit points
graph.set_entry_point("researcher")
graph.set_finish_point("writer")
# Compile and run
workflow = graph.compile()
result = workflow.invoke({"topic": "AI trends"})
```
### 4. OpenAI Swarm
**Best For**: Simple agent handoffs and conversational workflows
```python
from swarm import Agent, Swarm
# Define agents
triage_agent = Agent(
name="Triage Agent",
instructions="Determine which specialist to route the customer to"
)
billing_agent = Agent(
name="Billing Specialist",
instructions="Handle billing and payment questions"
)
technical_agent = Agent(
name="Technical Support",
instructions="Handle technical issues"
)
# Define handoff functions
def route_to_billing(reason: str):
return billing_agent
def route_to_technical(reason: str):
return technical_agent
# Add tools to triage agent
triage_agent.functions = [route_to_billing, route_to_technical]
# Execute swarm
client = Swarm()
response = client.run(
agent=triage_agent,
messages=[{"role": "user", "content": "I have a billing question"}]
)
```
## Orchestration Patterns
### Pattern 1: Sequential Task Chain
Agents execute tasks in sequence, each building on previous results:
```python
# Task 1: Research
research_output = research_agent.work("Analyze AI market trends")
# Task 2: Analysis (uses research output)
analysis = analyst_agent.work(f"Analyze these findings: {research_output}")
# Task 3: Report (uses analysis)
report = writer_agent.work(f"Write report on: {analysis}")
```
**When to Use**: Steps have dependencies, each builds on previous
### Pattern 2: Parallel Execution
Multiple agents work simultaneously, results combined:
```python
import asyncio
async def parallel_teams():
# All agents work in parallel
market_task = market_agent.work_async("Analyze market")
technical_task = tech_agent.work_async("Analyze technology")
user_task = user_agent.work_async("Analyze user needs")
# Wait for all to complete
market_results, tech_results, user_results = await asyncio.gather(
market_task, technical_task, user_task
)
# Synthesize results
return synthesize(market_results, tech_results, user_results)
```
**When to Use**: Independent analyses, need quick results, want diversity
### Pattern 3: Hierarchical Structure
Manager agent coordinates specialists:
```python
manager_agent.orchestrate({
"market_analysis": {
"agents": [competitor_analyst, trend_analyst],
"task": "Comprehensive market analysis"
},
"technical_evaluation": {
"agents": [architecture_agent, security_agent],
"task": "Technical feasibility assessment"
},
"synthesis": {
"agents": [strategy_agent],
"task": "Create strategic recommendations"
}
})
```
**When to Use**: Clear hierarchy, different teams, complex coordination
### Pattern 4: Debate & Consensus
Multiple agents discuss and reach consensus:
```python
agents = [bull_agent, bear_agent, neutral_agent]
question = "Should we invest in this startup?"
# Debate round 1
arguments = {agent: agent.argue(question) for agent in agents}
# Debate round 2 (respond to others)
counter_arguments = {
agent: agent.respond(arguments) for agent in agents
}
# Reach consensus
consensus = mediator_agent.synthesize_consensus(counter_arguments)
```
**When to Use**: Complex decisions, need multiple perspectives, risk assessment
## Agent Communication Patterns
### 1. Direct Communication
Agents pass messages directly to each other:
```python
agent_a.send_message(agent_b, {
"type": "request",
"action": "analyze_document",
"document": doc_content,
"context": {"deadline": "urgent"}
})
```
### 2. Tool-Mediated Communication
Agents use shared tools/databases:
```python
# Agent A writes to shared memory
shared_memory.write("findings", {"market_size": "$5B", "growth": "20%"})
# Agent B reads from shared memory
findings = shared_memory.read("findings")
```
### 3. Manager-Based Communication
Central coordinator manages agent communication:
```python
manager.broadcast("update_all_agents", {
"new_deadline": "tomorrow",
"priority": "critical"
})
```
## Best Practices
### Agent Design
- ✓ Clear, specific role and goal
- ✓ Appropriate tools for the role
- ✓ Relevant background/expertise
- ✓ Distinct from other agents
- ✓ Reasonable scope of work
### Workflow Design
- ✓ Clear task dependencies
- ✓ Identified handoff points
- ✓ Error handling between agents
- ✓ Fallback strategies
- ✓ Performance monitoring
### Communication
- ✓ Structured message formats
- ✓ Clear context sharing
- ✓ Error propagation strategy
- ✓ Timeout handling
- ✓ Audit logging
### Orchestration
- ✓ Define process clearly (sequential, parallel, etc.)
- ✓ Set clear success criteria
- ✓ Monitor agent performance
- ✓ Implement feedback loops
- ✓ Allow human intervention points
## Common Challenges & Solutions
### Challenge: Agent Conflicts
**Solutions**:
- Clear role separation
- Explicit decision-making rules
- Consensus mechanisms
- Conflict resolution agent
- Clear authority hierarchy
### Challenge: Slow Execution
**Solutions**:
- Use parallel execution where possible
- Cache results from expensive operations
- Pre-process data
- Optimize agent logic
- Implement timeout handling
### Challenge: Poor Quality Results
**Solutions**:
- Better agent prompts/instructions
- More relevant tools
- Feedback integration
- Quality validation agents
- Result aggregation strategies
### Challenge: Complex Workflows
**Solutions**:
- Break into smaller teams
- Hierarchical structure
- Clear task definitions
- Good state management
- Documentation of workflow
## Evaluation Metrics
**Team Performance**:
- Task completion rate
- Quality of results
- Execution time
- Cost (tokens/API calls)
- Error rate
**Agent Effectiveness**:
- Task success rate
- Response quality
- Tool usage efficiency
- Communication clarity
- Collaboration score
## Advanced Techniques
### 1. Self-Organizing Teams
Agents autonomously decide roles and workflow:
```python
# Agents negotiate roles based on task
agents = [agent1, agent2, agent3]
task = "complex financial analysis"
# Agents determine best structure
negotiated_structure = self_organize(agents, task)
# Returns optimal workflow for this task
```
### 2. Adaptive Workflows
Workflow changes based on progress:
```python
# Monitor progress
if progress < expected_rate:
# Increase resources
workflow.add_agent(specialist_agent)
elif quality < threshold:
# Increase validation
workflow.insert_review_step()
```
### 3. Cross-Agent Learning
Agents learn from each other's work:
```python
# After team execution
execution_trace = crew.get_execution_trace()
# Extract learnings
learnings = extract_patterns(execution_trace)
# Update agent knowledge
for agent, learning in learnings.items():
agent.update_knowledge(learning)
```
## Resources
### Frameworks
- **CrewAI**: https://crewai.com/
- **AutoGen**: https://microsoft.github.io/autogen/
- **LangGraph**: https://langchain-ai.github.io/langgraph/
- **Swarm**: https://github.com/openai/swarm
### Papers
- "Generative Agents" (Park et al.)
- "Self-Organizing Multi-Agent Systems" (research papers)
## Implementation Checklist
- [ ] Define each agent's role, goal, and expertise
- [ ] Identify available tools/capabilities for each agent
- [ ] Plan workflow (sequential, parallel, hierarchical)
- [ ] Define communication patterns
- [ ] Implement task definitions
- [ ] Set success criteria for each task
- [ ] Add error handling and fallbacks
- [ ] Implement monitoring/logging
- [ ] Test team collaboration
- [ ] Evaluate quality and performance
- [ ] Optimize based on results
- [ ] Document workflow and decisions
## Getting Started
1. **Start Small**: Begin with 2-3 agents
2. **Clear Workflow**: Document how agents interact
3. **Test Thoroughly**: Validate agent behavior individually and together
4. **Monitor Closely**: Track performance and results
5. **Iterate**: Refine based on results
6. **Scale**: Add agents and complexity as needed
# PageSpeed Insights — Reference & Official Documentation
This file complements the pagespeed-insights skill with official documentation links for indexing.
## Official documentation (indexable)
- **PageSpeed Insights about**: https://developers.google.com/speed/docs/insights/v5/about?hl=es-419
- **PageSpeed Insights (tool)**: https://pagespeed.web.dev/
- **Lighthouse**: https://developer.chrome.com/docs/lighthouse/
- **Core Web Vitals**: https://web.dev/vitals/
- **Chrome User Experience Report (CrUX)**: https://developer.chrome.com/docs/crux/
## Core Web Vitals (metrics)
- **LCP (Largest Contentful Paint)**: https://web.dev/lcp/
- **FCP (First Contentful Paint)**: https://web.dev/fcp/
- **CLS (Cumulative Layout Shift)**: https://web.dev/cls/
- **INP (Interaction to Next Paint)**: https://web.dev/inp/
- **TTFB (Time to First Byte)**: https://web.dev/ttfb/
## Lab vs field data
- **Lab data**: Lighthouse, controlled environment, debugging
- **Field data**: CrUX, real user metrics, 28-day aggregation
- **Understanding metrics**: https://web.dev/metrics/
## Performance optimization guides
- **Optimize LCP**: https://web.dev/optimize-lcp/
- **Optimize CLS**: https://web.dev/optimize-cls/
- **Optimize INP**: https://web.dev/optimize-inp/
- **Optimize FCP**: https://web.dev/optimize-fcp/
- **Resource hints**: https://web.dev/preconnect-and-dns-prefetch/
- **Image optimization**: https://web.dev/fast/#optimize-your-images
## Tools
- **PageSpeed Insights**: https://pagespeed.web.dev/
- **Lighthouse (Chrome DevTools)**: Built-in, Audits tab
- **Web Vitals extension**: Real-time monitoring
- **Chromatic (Lighthouse CI)**: https://github.com/GoogleChrome/lighthouse-ci
## Score thresholds (reminder)
| Category | Good | Needs Improvement | Poor |
|----------|------|-------------------|------|
| Performance | 90-100 | 50-89 | 0-49 |
| Accessibility | 90-100 | 50-89 | 0-49 |
| Best Practices | 90-100 | 50-89 | 0-49 |
| SEO | 90-100 | 50-89 | 0-49 |
---
name: pagespeed-insights
description: Audit web pages for performance optimization following PageSpeed Insights guidelines. Use when analyzing page performance, optimizing web applications, reviewing performance metrics, implementing Core Web Vitals improvements, or when the user mentions page speed, performance optimization, Lighthouse scores, or Core Web Vitals.
---
# PageSpeed Insights Auditor
## Overview
You are a **PageSpeed Insights Auditor** - an expert in web performance optimization who helps developers achieve excellent PageSpeed scores by identifying performance issues, avoiding bad practices, and implementing best practices based on Google's PageSpeed Insights guidelines.
**Core Principle**: Guide developers to achieve scores of 90+ (Good) in Performance, Accessibility, Best Practices, and SEO categories, while ensuring Core Web Vitals metrics meet the "Good" thresholds.
## Understanding PageSpeed Insights
PageSpeed Insights (PSI) analyzes page performance on mobile and desktop devices, providing both **lab data** (simulated) and **field data** (real user experiences). PSI reports on user experience metrics and provides diagnostic suggestions to improve page performance.
### Two Types of Data
1. **Lab Data**: Collected in a controlled environment using Lighthouse. Useful for debugging but may not capture real-world bottlenecks.
2. **Field Data**: Real user experience data from Chrome User Experience Report (CrUX). Useful for capturing actual user experiences but has a more limited set of metrics.
## Performance Score Thresholds
### Lab Scores (Lighthouse)
| Score Range | Rating | Icon |
| ----------- | ----------------- | --------------- |
| 90-100 | Good | 🟢 Green circle |
| 50-89 | Needs Improvement | 🟡 Amber square |
| 0-49 | Poor | 🔴 Red triangle |
**Target**: Always aim for scores of **90 or higher** in all categories.
### Core Web Vitals Thresholds
Core Web Vitals are the three most important metrics for web performance:
| Metric | Good | Needs Improvement | Poor |
| ----------------------------------- | ------------ | ------------------ | --------- |
| **FCP** (First Contentful Paint) | [0, 1800 ms] | [1800 ms, 3000 ms] | > 3000 ms |
| **LCP** (Largest Contentful Paint) | [0, 2500 ms] | [2500 ms, 4000 ms] | > 4000 ms |
| **CLS** (Cumulative Layout Shift) | [0, 0.1] | [0.1, 0.25] | > 0.25 |
| **INP** (Interaction to Next Paint) | [0, 200 ms] | [200 ms, 500 ms] | > 500 ms |
| **TTFB** (Time to First Byte) | [0, 800 ms] | [800 ms, 1800 ms] | > 1800 ms |
**Target**: Ensure the 75th percentile of all Core Web Vitals metrics are in the "Good" range.
## Key Performance Metrics
### Lab Metrics (Lighthouse)
1. **First Contentful Paint (FCP)**: Time until first content is rendered
2. **Largest Contentful Paint (LCP)**: Time until largest content element is rendered
3. **Speed Index**: How quickly content is visually displayed
4. **Cumulative Layout Shift (CLS)**: Visual stability measure
5. **Total Blocking Time (TBT)**: Sum of blocking time between FCP and TTI
6. **Time to Interactive (TTI)**: Time until page is fully interactive
### Field Metrics (CrUX)
- **FCP**: First Contentful Paint from real users
- **LCP**: Largest Contentful Paint from real users
- **CLS**: Cumulative Layout Shift from real users
- **INP**: Interaction to Next Paint (replaces FID)
- **TTFB**: Time to First Byte (experimental)
## Common Performance Issues & Solutions
### ❌ Bad Practice: Unoptimized Images
**Problem**: Large images without compression, modern formats, or proper sizing.
**Impact**: Poor LCP scores, slow page loads.
**✅ Solutions**:
- Use modern image formats (WebP, AVIF)
- Implement responsive images with `srcset`
- Compress images before uploading
- Set explicit width/height to prevent CLS
- Use lazy loading for below-the-fold images
```html
<!-- Bad -->
<img src="large-image.jpg" alt="Description" />
<!-- Good -->
<img
src="image.webp"
srcset="image-small.webp 400w, image-medium.webp 800w, image-large.webp 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
width="1200"
height="800"
alt="Description"
loading="lazy"
/>
```
### ❌ Bad Practice: Render-Blocking Resources
**Problem**: CSS and JavaScript blocking initial render.
**Impact**: Poor FCP and LCP scores.
**✅ Solutions**:
- Defer non-critical CSS
- Inline critical CSS
- Use `async` or `defer` for JavaScript
- Remove unused CSS/JS
- Split code and lazy load routes
```html
<!-- Bad -->
<link rel="stylesheet" href="styles.css" />
<script src="app.js"></script>
<!-- Good -->
<link
rel="stylesheet"
href="styles.css"
media="print"
onload="this.media='all'"
/>
<link rel="preload" href="critical.css" as="style" />
<script src="app.js" defer></script>
```
### ❌ Bad Practice: Missing Resource Hints
**Problem**: Not preconnecting to important origins or prefetching critical resources.
**Impact**: Slow TTFB and LCP.
**✅ Solutions**:
- Use `rel="preconnect"` for third-party origins
- Use `rel="dns-prefetch"` for DNS resolution
- Use `rel="preload"` for critical resources
- Use `rel="prefetch"` for likely next-page resources
```html
<!-- Good -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="dns-prefetch" href="https://api.example.com" />
<link rel="preload" href="hero-image.webp" as="image" />
```
### ❌ Bad Practice: Layout Shift (CLS)
**Problem**: Content shifting during page load.
**Impact**: Poor CLS scores, bad user experience.
**✅ Solutions**:
- Set explicit dimensions for images and videos
- Reserve space for ads and embeds
- Avoid inserting content above existing content
- Use CSS aspect-ratio for responsive containers
- Prefer transform animations over layout-triggering properties
```css
/* Bad */
.image-container {
width: 100%;
/* height not set - causes CLS */
}
/* Good */
.image-container {
width: 100%;
aspect-ratio: 16 / 9;
/* or */
height: 0;
padding-bottom: 56.25%; /* 16:9 ratio */
}
```
### ❌ Bad Practice: Large JavaScript Bundles
**Problem**: Loading unnecessary JavaScript code.
**Impact**: Poor TTI, high TBT.
**✅ Solutions**:
- Code splitting and lazy loading
- Remove unused code (tree shaking)
- Minimize and compress JavaScript
- Use dynamic imports for routes
- Avoid large third-party libraries when possible
```javascript
// Bad - loading everything upfront
import { heavyLibrary } from "./heavy-library";
// Good - lazy load when needed
const loadHeavyLibrary = () => import("./heavy-library");
```
### ❌ Bad Practice: Inefficient Font Loading
**Problem**: Fonts causing FOIT (Flash of Invisible Text) or FOUT (Flash of Unstyled Text).
**Impact**: Poor FCP, layout shifts.
**✅ Solutions**:
- Use `font-display: swap` or `optional`
- Preload critical fonts
- Subset fonts to include only needed characters
- Use system fonts when possible
```css
/* Good */
@font-face {
font-family: "CustomFont";
src: url("font.woff2") format("woff2");
font-display: swap; /* or optional */
}
```
### ❌ Bad Practice: No Caching Strategy
**Problem**: Resources not cached, causing repeated downloads.
**Impact**: Slow repeat visits, poor performance.
**✅ Solutions**:
- Set appropriate Cache-Control headers
- Use service workers for offline caching
- Implement HTTP/2 server push for critical resources
- Use CDN for static assets
```
Cache-Control: public, max-age=31536000, immutable
```
### ❌ Bad Practice: Third-Party Scripts Blocking Render
**Problem**: Analytics, ads, or widgets blocking page load.
**Impact**: Poor TTI, high TBT.
**✅ Solutions**:
- Load third-party scripts asynchronously
- Defer non-critical third-party code
- Use `rel="noopener"` for external links
- Consider self-hosting analytics when possible
```html
<!-- Good -->
<script async src="https://www.google-analytics.com/analytics.js"></script>
```
## Accessibility Best Practices
### ❌ Bad Practice: Missing Alt Text
**Problem**: Images without descriptive alt attributes.
**Impact**: Poor accessibility score.
**✅ Solution**: Always provide meaningful alt text.
```html
<!-- Bad -->
<img src="chart.png" />
<!-- Good -->
<img src="chart.png" alt="Sales increased 25% from Q1 to Q2" />
```
### ❌ Bad Practice: Poor Color Contrast
**Problem**: Text not readable due to low contrast.
**Impact**: Poor accessibility score.
**✅ Solution**: Ensure contrast ratio of at least 4.5:1 for normal text, 3:1 for large text.
### ❌ Bad Practice: Missing ARIA Labels
**Problem**: Interactive elements without proper labels.
**Impact**: Poor accessibility score.
**✅ Solution**: Use ARIA labels for screen readers.
```html
<!-- Good -->
<button aria-label="Close dialog">×</button>
```
## SEO Best Practices
### ❌ Bad Practice: Missing Meta Tags
**Problem**: No title, description, or viewport meta tags.
**Impact**: Poor SEO score.
**✅ Solution**: Include essential meta tags.
```html
<!-- Good -->
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Page description" />
<title>Page Title</title>
```
### ❌ Bad Practice: Non-Descriptive Links
**Problem**: Links with generic text like "click here".
**Impact**: Poor SEO score.
**✅ Solution**: Use descriptive link text.
```html
<!-- Bad -->
<a href="/about">Click here</a>
<!-- Good -->
<a href="/about">Learn more about our company</a>
```
## Best Practices Checklist
### Performance
- [ ] Images optimized (WebP/AVIF, compressed, responsive)
- [ ] Critical CSS inlined
- [ ] Non-critical CSS deferred
- [ ] JavaScript code-split and lazy-loaded
- [ ] Render-blocking resources minimized
- [ ] Resource hints implemented (preconnect, preload, dns-prefetch)
- [ ] Fonts optimized with font-display
- [ ] Caching strategy implemented
- [ ] Third-party scripts loaded asynchronously
- [ ] Layout shifts prevented (explicit dimensions, aspect-ratio)
### Core Web Vitals
- [ ] LCP < 2.5 seconds (75th percentile)
- [ ] FCP < 1.8 seconds (75th percentile)
- [ ] CLS < 0.1 (75th percentile)
- [ ] INP < 200ms (75th percentile)
- [ ] TTFB < 800ms (75th percentile)
### Accessibility
- [ ] All images have alt text
- [ ] Color contrast meets WCAG standards
- [ ] ARIA labels on interactive elements
- [ ] Semantic HTML used
- [ ] Keyboard navigation supported
### SEO
- [ ] Meta tags present (title, description, viewport)
- [ ] Descriptive link text
- [ ] Proper heading hierarchy (h1-h6)
- [ ] Structured data implemented
- [ ] Mobile-friendly design
## Audit Workflow
When auditing a page for PageSpeed optimization:
1. **Analyze Current State**
- Check current PageSpeed scores
- Identify Core Web Vitals metrics
- Review lab and field data differences
2. **Identify Issues**
- List all performance problems
- Prioritize by impact (Core Web Vitals first)
- Categorize by type (images, JS, CSS, etc.)
3. **Provide Solutions**
- Suggest specific optimizations
- Provide code examples
- Explain expected improvements
4. **Verify Improvements**
- Re-test after changes
- Ensure scores reach 90+
- Confirm Core Web Vitals are "Good"
## Common Mistakes to Avoid
### ❌ Focusing Only on Lab Data
**Problem**: Optimizing only for Lighthouse scores without considering real user data.
**✅ Solution**: Balance both lab and field data. Field data shows real-world performance.
### ❌ Over-Optimizing
**Problem**: Implementing too many optimizations at once, making debugging difficult.
**✅ Solution**: Make incremental changes and test after each optimization.
### ❌ Ignoring Mobile Performance
**Problem**: Optimizing only for desktop.
**✅ Solution**: Mobile-first approach. Most users are on mobile devices.
### ❌ Not Testing After Changes
**Problem**: Assuming optimizations worked without verification.
**✅ Solution**: Always re-run PageSpeed Insights after implementing changes.
## Performance Optimization Priority
1. **Critical Path**: Optimize resources needed for initial render
2. **Core Web Vitals**: Focus on LCP, CLS, and INP first
3. **Render-Blocking**: Eliminate blocking CSS and JS
4. **Images**: Optimize largest contentful paint element
5. **Third-Party**: Minimize impact of external scripts
6. **Caching**: Implement proper caching strategies
## Additional Resources
- [reference.md](reference.md) — Official PageSpeed, Lighthouse, Core Web Vitals, optimization guides — indexable
- **Official**: https://developers.google.com/speed/docs/insights/v5/about?hl=es-419
- **PageSpeed Insights**: https://pagespeed.web.dev/
- **Lighthouse**: Built into Chrome DevTools
- **Web Vitals**: https://web.dev/vitals/
## Specification Reference
This skill is based on the official [PageSpeed Insights documentation](https://developers.google.com/speed/docs/insights/v5/about?hl=es-419) from Google Developers.
All thresholds, metrics, and best practices in this skill follow the official PageSpeed Insights guidelines and Core Web Vitals specifications. For complete documentation, refer to the [official PageSpeed Insights documentation](https://developers.google.com/speed/docs/insights/v5/about?hl=es-419).
---
id: pagespeed-perf
version: 1.0.0
name: PageSpeed Performance Audit
description: >
Web Performance Engineering — analyzes Core Web Vitals using the PageSpeed
Insights API (PSI v5) and applies the 80/20 principle: identify the 20% of
changes that produce 80% of the performance gain. Produces a prioritized
markdown report with quantified estimates and framework-specific code.
Trigger: When auditing page speed, analyzing Core Web Vitals, or optimizing
web performance for any URL.
user-invokable: true
license: MIT
metadata:
author: codeconductor
category: performance
compatibility:
tools: [claude, codex, gemini, agy, opencode]
stacks:
languages: []
frameworks: [astro, nextjs, react, vue, django, spring, wordpress]
risk:
level: medium
can_execute_shell: true
can_modify_files: false
requires_network: true
inputs:
- name: url
type: string
required: true
description: Full URL to audit (must include scheme: https://...)
- name: strategy
type: string
required: false
description: "mobile | desktop | both (default: both)"
outputs:
- name: report
type: markdown
description: >
Prioritized performance report saved as
{YYYY-MM-DD}_pagespeed-{hostname}-claude.md in the current directory.
quality:
reviewed_by: codeconductor-core
version: 1.0.0
---
# PageSpeed Performance Audit — Web Performance Engineering (80/20)
## Role and Purpose
Act as **Senior Web Performance Engineer, Frontend Architect, and Technical
Auditor**.
Always access the real site, measure real metrics via the PageSpeed Insights
API, analyze resources with the greatest impact, and produce a prioritized
Spanish-language report following the 80/20 principle: the **20% of critical
changes that produce 80% of the performance improvement**.
Never give generic recommendations. Every finding must be backed by data
observed from the specific URL being audited.
---
## Step 0 — Pre-flight: API Key and Output Filename
**MANDATORY. Execute before any analysis.**
### 1. Read the API key from the environment
```powershell
$env:PAGESPEED_API_KEY
```
- Value present → store as `{API_KEY}`, use in all PSI calls.
- Empty → proceed without key (CrUX field data unavailable; rate limits apply).
### 2. Define the output filename
```powershell
$date = (Get-Date -Format "yyyy-MM-dd")
$website = ([System.Uri]"{URL}").Host -replace '[^a-zA-Z0-9]', '-'
$out = "${date}_pagespeed-${website}-claude.md"
Write-Host $out
```
The final report **must** be written to this file.
---
## Data Collection
### Primary Method — Bun Scripts (always try first)
```powershell
bun --version # if available, use Primary Method; otherwise use Fallback
$skillDir = "$env:USERPROFILE\.claude\skills\pagespeed-perf\scripts"
bun run "$skillDir\run.ts" --url={URL}
```
`run.ts` calls `psi-collect.ts` and `html-audit.ts` in parallel and returns
structured JSON. Key output fields:
```
output.summary.mobileScore → Lighthouse mobile score (0-100)
output.summary.desktopScore → Lighthouse desktop score
output.summary.passesCWV → boolean — passes real CWV
output.summary.top5Actions → array ordered by 80/20 score
output.psi.mobile.lab.lcp → LCP (lab, mobile)
output.psi.mobile.lab.tbt → TBT
output.psi.mobile.lab.cls → CLS
output.psi.mobile.lab.fcp → FCP
output.psi.mobile.lab.ttfb → TTFB
output.psi.mobile.field → CrUX data (null if no key / no data)
output.psi.mobile.opportunities → array ordered by impact80_20 desc
output.psi.mobile.lcpElement → HTML snippet of the LCP element
output.psi.mobile.thirdParties → third-party scripts with blockingTime
output.psi.mobile.usedApiKey → boolean — confirms key was used
output.html.stack → detected framework / CMS
output.html.resourceHints → preloads, preconnects, prefetches
output.html.images → lazy, fetchpriority, list
output.html.scripts → blocking in <head>, third-party list
output.html.fonts → googleFonts, font-display, preloaded
output.html.issues → ordered by impact80_20
```
### Fallback Method — WebFetch (only if Bun unavailable)
```
# With API key (preferred)
https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url={URL}&strategy=mobile&category=performance&key={API_KEY}
https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url={URL}&strategy=desktop&category=performance&key={API_KEY}
# Without key (rate-limited)
https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url={URL}&strategy=mobile&category=performance
```
Key PSI response paths:
```
lighthouseResult.categories.performance.score
lighthouseResult.audits.largest-contentful-paint
lighthouseResult.audits.total-blocking-time
lighthouseResult.audits.cumulative-layout-shift
lighthouseResult.audits.first-contentful-paint
lighthouseResult.audits.server-response-time
lighthouseResult.audits.largest-contentful-paint-element.details.items[0]
lighthouseResult.audits.render-blocking-resources.details.overallSavingsMs
lighthouseResult.audits.unused-javascript.details.overallSavingsBytes
lighthouseResult.audits.third-party-summary.details.items
loadingExperience.metrics.LARGEST_CONTENTFUL_PAINT_MS.percentile (CrUX)
loadingExperience.metrics.INTERACTION_TO_NEXT_PAINT.percentile (CrUX)
loadingExperience.metrics.CUMULATIVE_LAYOUT_SHIFT_SCORE.percentile (CrUX)
loadingExperience.overall_category → "FAST" | "AVERAGE" | "SLOW"
```
Also fetch the site HTML via WebFetch and inspect the `<head>` for resource
hints, lazy loading, `fetchpriority`, `font-display`, blocking scripts, and
images without explicit dimensions.
---
## Core Web Vitals — Thresholds
| Metric | Good | Needs Improvement | Critical | Score weight |
| ------ | -------- | ----------------- | --------- | ------------ |
| LCP | ≤ 2.5 s | 2.5 s – 4.0 s | > 4.0 s | 25% |
| INP | ≤ 200 ms | 200 ms – 500 ms | > 500 ms | 10% |
| CLS | ≤ 0.1 | 0.1 – 0.25 | > 0.25 | 15% |
| FCP | ≤ 1.8 s | 1.8 s – 3.0 s | > 3.0 s | 10% |
| TBT | ≤ 200 ms | 200 ms – 600 ms | > 600 ms | 30% |
| TTFB | ≤ 800 ms | 800 ms – 1.8 s | > 1.8 s | — |
LCP + TBT represent 55% of the Lighthouse Performance Score.
---
## 80/20 Optimization Matrix
Score = `Impact (1–5) × Ease (1–5)`. Prioritize by descending score.
| Rank | Optimization | Primary metric | Impact | Ease | Score |
| ---- | --------------------------------- | -------------- | ------ | ---- | ----- |
| 1 | Preload LCP element | LCP | 5 | 5 | **25** |
| 1 | `fetchpriority="high"` on LCP img | LCP | 5 | 5 | **25** |
| 1 | Gzip / Brotli compression | FCP, LCP, TBT | 5 | 5 | **25** |
| 4 | WebP + explicit dimensions | LCP, CLS | 5 | 4 | **20** |
| 4 | Lazy loading offscreen images | LCP, TBT | 4 | 5 | **20** |
| 4 | `font-display: swap` | FCP | 4 | 5 | **20** |
| 4 | `preconnect` to critical origins | FCP, LCP, TTFB | 4 | 5 | **20** |
| 4 | Defer / facade third-party scripts| TBT, INP | 5 | 4 | **20** |
| 9 | Remove render-blocking resources | FCP, LCP | 5 | 3 | **15** |
| 9 | Long Cache-Control for assets | repeat visits | 3 | 5 | **15** |
| 11 | Remove unused JavaScript | TBT, INP | 4 | 3 | **12** |
| 12 | Remove unused CSS | FCP, TBT | 3 | 3 | **9** |
| 13 | CDN for static assets | TTFB, LCP | 4 | 2 | **8** |
| 14 | Code splitting | TBT, INP | 4 | 2 | **8** |
**Critical 20% (Score ≥ 20)** — address these first:
1. Preload LCP element + `fetchpriority="high"`
2. Brotli/Gzip compression at the server
3. WebP images with explicit `width`/`height`
4. Lazy loading of offscreen images
5. `font-display: swap` for all fonts
6. `preconnect` to all critical origins
7. Defer or facade all third-party scripts
---
## Expected Impact by Optimization
| Optimization | Metric | Expected gain |
| ---------------------- | -------- | --------------------- |
| Preload + fetchpriority| LCP | −0.5 s to −2.0 s |
| Brotli compression | FCP, LCP | −0.3 s to −1.0 s |
| WebP + dimensions | LCP, CLS | −0.3 s to −1.2 s |
| Lazy loading | LCP | −0.2 s to −0.8 s |
| font-display: swap | FCP | −0.2 s to −0.8 s |
| preconnect | FCP, LCP | −0.1 s to −0.4 s each|
| Defer third parties | TBT, INP | −50 ms to −300 ms |
---
## Report Format (mandatory structure)
Save to `{YYYY-MM-DD}_pagespeed-{hostname}-claude.md`:
```markdown
# Auditoría de Rendimiento Web — {URL}
Fecha: {YYYY-MM-DD} | Estrategia: Móvil + Escritorio | Archivo: {filename}.md
## Resumen Ejecutivo
[2-3 párrafos: estado actual, score, bottleneck principal, potencial de mejora]
## Métricas Actuales
[Tabla: Lab (Lighthouse) vs Campo (CrUX)]
## Recursos con Mayor Impacto
[Tabla: URL, Tipo, Tamaño, Tiempo, Impacto, Razón]
## Plan de Acción Priorizado (80/20)
[Tabla ordenada por Score 80/20 descendente]
## Solución Técnica Detallada
[Por hallazgo: Problema, Evidencia, Implementación, Código, Impacto Esperado]
## Quick Wins (< 1 day)
## High Impact Changes
## Roadmap
- Fase 1 — Inmediato (Semana 1)
- Fase 2 — Corto Plazo (2–4 semanas)
- Fase 3 — Mediano Plazo (1–3 meses)
---
*Informe generado el {YYYY-MM-DD} · Herramienta: Claude Code + pagespeed-perf skill*
*API Key usada: {Sí / No} · Datos CrUX: {Disponibles / No disponibles}*
```
---
## Quality Rules — Never Violate
1. **No data = no recommendation.** If PSI fails, try WebFetch directly.
2. **Always quantify.** "Reduces LCP from 4.2 s to ~3.0 s" — never "would improve LCP".
3. **Explicit evidence.** Cite the observed metric value for every finding.
4. **Site-specific code.** Adapt templates to the detected framework (Next.js,
Astro, Django, etc.). Do not paste generic snippets unchanged.
5. **80/20 order.** Always sort the action plan by descending score.
6. **Separate field vs lab data.** CrUX = real user experience. Lighthouse = controlled lab.
7. **Identify the framework.** Detect Next.js, Astro, Vue, WordPress, etc., and
provide framework-specific code samples.
# workflow-orchestration-patterns — detailed patterns and worked examples
## Critical Design Decision: Workflows vs Activities
**The Fundamental Rule** (Source: temporal.io/blog/workflow-engine-principles):
- **Workflows** = Orchestration logic and decision-making
- **Activities** = External interactions (APIs, databases, network calls)
### Workflows (Orchestration)
**Characteristics:**
- Contain business logic and coordination
- **MUST be deterministic** (same inputs → same outputs)
- **Cannot** perform direct external calls
- State automatically preserved across failures
- Can run for years despite infrastructure failures
**Example workflow tasks:**
- Decide which steps to execute
- Handle compensation logic
- Manage timeouts and retries
- Coordinate child workflows
### Activities (External Interactions)
**Characteristics:**
- Handle all external system interactions
- Can be non-deterministic (API calls, DB writes)
- Include built-in timeouts and retry logic
- **Must be idempotent** (calling N times = calling once)
- Short-lived (seconds to minutes typically)
**Example activity tasks:**
- Call payment gateway API
- Write to database
- Send emails or notifications
- Query external services
### Design Decision Framework
```
Does it touch external systems? → Activity
Is it orchestration/decision logic? → Workflow
```
## Core Workflow Patterns
### 1. Saga Pattern with Compensation
**Purpose**: Implement distributed transactions with rollback capability
**Pattern** (Source: temporal.io/blog/compensating-actions-part-of-a-complete-breakfast-with-sagas):
```
For each step:
1. Register compensation BEFORE executing
2. Execute the step (via activity)
3. On failure, run all compensations in reverse order (LIFO)
```
**Example: Payment Workflow**
1. Reserve inventory (compensation: release inventory)
2. Charge payment (compensation: refund payment)
3. Fulfill order (compensation: cancel fulfillment)
**Critical Requirements:**
- Compensations must be idempotent
- Register compensation BEFORE executing step
- Run compensations in reverse order
- Handle partial failures gracefully
### 2. Entity Workflows (Actor Model)
**Purpose**: Long-lived workflow representing single entity instance
**Pattern** (Source: docs.temporal.io/evaluate/use-cases-design-patterns):
- One workflow execution = one entity (cart, account, inventory item)
- Workflow persists for entity lifetime
- Receives signals for state changes
- Supports queries for current state
**Example Use Cases:**
- Shopping cart (add items, checkout, expiration)
- Bank account (deposits, withdrawals, balance checks)
- Product inventory (stock updates, reservations)
**Benefits:**
- Encapsulates entity behavior
- Guarantees consistency per entity
- Natural event sourcing
### 3. Fan-Out/Fan-In (Parallel Execution)
**Purpose**: Execute multiple tasks in parallel, aggregate results
**Pattern:**
- Spawn child workflows or parallel activities
- Wait for all to complete
- Aggregate results
- Handle partial failures
**Scaling Rule** (Source: temporal.io/blog/workflow-engine-principles):
- Don't scale individual workflows
- For 1M tasks: spawn 1K child workflows × 1K tasks each
- Keep each workflow bounded
### 4. Async Callback Pattern
**Purpose**: Wait for external event or human approval
**Pattern:**
- Workflow sends request and waits for signal
- External system processes asynchronously
- Sends signal to resume workflow
- Workflow continues with response
**Use Cases:**
- Human approval workflows
- Webhook callbacks
- Long-running external processes
## State Management and Determinism
### Automatic State Preservation
**How Temporal Works** (Source: docs.temporal.io/workflows):
- Complete program state preserved automatically
- Event History records every command and event
- Seamless recovery from crashes
- Applications restore pre-failure state
### Determinism Constraints
**Workflows Execute as State Machines**:
- Replay behavior must be consistent
- Same inputs → identical outputs every time
**Prohibited in Workflows** (Source: docs.temporal.io/workflows):
- ❌ Threading, locks, synchronization primitives
- ❌ Random number generation (`random()`)
- ❌ Global state or static variables
- ❌ System time (`datetime.now()`)
- ❌ Direct file I/O or network calls
- ❌ Non-deterministic libraries
**Allowed in Workflows**:
- ✅ `workflow.now()` (deterministic time)
- ✅ `workflow.random()` (deterministic random)
- ✅ Pure functions and calculations
- ✅ Calling activities (non-deterministic operations)
### Versioning Strategies
**Challenge**: Changing workflow code while old executions still running
**Solutions**:
1. **Versioning API**: Use `workflow.get_version()` for safe changes
2. **New Workflow Type**: Create new workflow, route new executions to it
3. **Backward Compatibility**: Ensure old events replay correctly
## Resilience and Error Handling
### Retry Policies
**Default Behavior**: Temporal retries activities forever
**Configure Retry**:
- Initial retry interval
- Backoff coefficient (exponential backoff)
- Maximum interval (cap retry delay)
- Maximum attempts (eventually fail)
**Non-Retryable Errors**:
- Invalid input (validation failures)
- Business rule violations
- Permanent failures (resource not found)
### Idempotency Requirements
**Why Critical** (Source: docs.temporal.io/activities):
- Activities may execute multiple times
- Network failures trigger retries
- Duplicate execution must be safe
**Implementation Strategies**:
- Idempotency keys (deduplication)
- Check-then-act with unique constraints
- Upsert operations instead of insert
- Track processed request IDs
### Activity Heartbeats
**Purpose**: Detect stalled long-running activities
**Pattern**:
- Activity sends periodic heartbeat
- Includes progress information
- Timeout if no heartbeat received
- Enables progress-based retry
---
name: workflow-orchestration-patterns
description: Design durable workflows with Temporal for distributed systems. Covers workflow vs activity separation, saga patterns, state management, and determinism constraints. Use when building long-running processes, distributed transactions, or microservice orchestration.
---
# Workflow Orchestration Patterns
Master workflow orchestration architecture with Temporal, covering fundamental design decisions, resilience patterns, and best practices for building reliable distributed systems.
## When to Use Workflow Orchestration
### Ideal Use Cases (Source: docs.temporal.io)
- **Multi-step processes** spanning machines/services/databases
- **Distributed transactions** requiring all-or-nothing semantics
- **Long-running workflows** (hours to years) with automatic state persistence
- **Failure recovery** that must resume from last successful step
- **Business processes**: bookings, orders, campaigns, approvals
- **Entity lifecycle management**: inventory tracking, account management, cart workflows
- **Infrastructure automation**: CI/CD pipelines, provisioning, deployments
- **Human-in-the-loop** systems requiring timeouts and escalations
### When NOT to Use
- Simple CRUD operations (use direct API calls)
- Pure data processing pipelines (use Airflow, batch processing)
- Stateless request/response (use standard APIs)
- Real-time streaming (use Kafka, event processors)
## Detailed patterns and worked examples
Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.
## Best Practices
### Workflow Design
1. **Keep workflows focused** - Single responsibility per workflow
2. **Small workflows** - Use child workflows for scalability
3. **Clear boundaries** - Workflow orchestrates, activities execute
4. **Test locally** - Use time-skipping test environment
### Activity Design
1. **Idempotent operations** - Safe to retry
2. **Short-lived** - Seconds to minutes, not hours
3. **Timeout configuration** - Always set timeouts
4. **Heartbeat for long tasks** - Report progress
5. **Error handling** - Distinguish retryable vs non-retryable
### Common Pitfalls
**Workflow Violations**:
- Using `datetime.now()` instead of `workflow.now()`
- Threading or async operations in workflow code
- Calling external APIs directly from workflow
- Non-deterministic logic in workflows
**Activity Mistakes**:
- Non-idempotent operations (can't handle retries)
- Missing timeouts (activities run forever)
- No error classification (retry validation errors)
- Ignoring payload limits (2MB per argument)
### Operational Considerations
**Monitoring**:
- Workflow execution duration
- Activity failure rates
- Retry attempts and backoff
- Pending workflow counts
**Scalability**:
- Horizontal scaling with workers
- Task queue partitioning
- Child workflow decomposition
- Activity batching when appropriate
## Additional Resources
**Official Documentation**:
- Temporal Core Concepts: docs.temporal.io/workflows
- Workflow Patterns: docs.temporal.io/evaluate/use-cases-design-patterns
- Best Practices: docs.temporal.io/develop/best-practices
- Saga Pattern: temporal.io/blog/saga-pattern-made-easy
**Key Principles**:
1. Workflows = orchestration, Activities = external calls
2. Determinism is non-negotiable for workflows
3. Idempotency is critical for activities
4. State preservation is automatic
5. Design for failure and recovery
---
description: >-
Run the PageSpeed performance audit — 80/20 analysis of Core Web Vitals using
the PageSpeed Insights API.
---
# PageSpeed Performance Audit
Audit URL: $ARGUMENTS
---
## Step 1 — Pre-flight (pagespeed-perf skill)
Invoke `pagespeed-perf` skill.
Read `PAGESPEED_API_KEY` from the environment. Compute the output filename:
`{YYYY-MM-DD}_pagespeed-{hostname}-claude.md`.
Log whether the API key was found. Proceed regardless — lab data is available
without a key, but CrUX field data requires it.
---
## Step 2 — Collect
Call the PageSpeed Insights API for the URL provided above.
- Strategy: `both` (mobile + desktop) unless the user specified otherwise.
- If Bun is available, use `~/.claude/skills/pagespeed-perf/scripts/run.ts`.
- If Bun is unavailable, call PSI directly via WebFetch and fetch the HTML
source for manual resource-hint analysis.
---
## Step 3 — Analyze
Extract from the PSI response:
- Core Web Vitals: LCP, INP, CLS, FCP, TBT, TTFB
- LCP element (type, selector, HTML snippet)
- Third-party scripts ordered by blocking time
- Render-blocking resources
- Unused JavaScript and CSS (savings in bytes and ms)
From the HTML source:
- Resource hints (`<link rel="preload|preconnect|prefetch">`)
- Images: lazy loading, `fetchpriority`, format, dimensions
- Fonts: `font-display`, preloaded subsets
- Blocking scripts in `<head>` (no `async`/`defer`)
---
## Step 4 — Prioritize
Score each identified optimization using the 80/20 matrix:
`Score = Impact × Ease` (each 1–5, max 25).
Order findings by descending score. Mark optimizations with Score ≥ 20 as
**Critical 20%**.
---
## Step 5 — Report
Write the full performance report to
`{YYYY-MM-DD}_pagespeed-{hostname}-claude.md` in the current directory.
Required sections:
1. Resumen Ejecutivo (2–3 paragraphs)
2. Métricas Actuales (lab vs field table)
3. Recursos con Mayor Impacto
4. Plan de Acción Priorizado (80/20 table)
5. Solución Técnica Detallada (per finding: problem, evidence, code, expected gain)
6. Quick Wins / High Impact Changes / Roadmap
End every report with:
```
---
*Informe generado el {YYYY-MM-DD} · Herramienta: Claude Code + pagespeed-perf skill*
*API Key usada: {Sí / No} · Datos CrUX: {Disponibles / No disponibles}*
```
---
## Requirements
**`PAGESPEED_API_KEY`** — Optional but strongly recommended.
- With key: real CrUX field data + 25,000 requests/day quota.
- Without key: lab data only (Lighthouse); shared rate limit applies.
Set in your shell:
```powershell
$env:PAGESPEED_API_KEY = "your-api-key" # Windows PowerShell
export PAGESPEED_API_KEY="your-api-key" # macOS / Linux
```
Get a free key: <https://developers.google.com/speed/docs/insights/v5/get-started>
---
name: conductor-setup
description: Configure a Rails project to work with Conductor (parallel coding agents)
allowed-tools: Bash(chmod *), Bash(bundle *), Bash(npm *), Bash(script/server)
context: fork
risk: unknown
source: community
metadata:
author: Shpigford
version: "1.0"
---
Set up this Rails project for Conductor, the Mac app for parallel coding agents.
## When to Use
- You need to configure a Rails project so it runs correctly inside Conductor workspaces.
- The project should support parallel coding agents with isolated ports, Redis settings, and shared secrets.
- You want the standard `conductor.json`, `bin/conductor-setup`, and `script/server` scaffolding for a Rails repo.
# What to Create
## 1. conductor.json (project root)
Create `conductor.json` in the project root if it doesn't already exist:
```json
{
"scripts": {
"setup": "bin/conductor-setup",
"run": "script/server"
}
}
```
## 2. bin/conductor-setup (executable)
Create `bin/conductor-setup` if it doesn't already exist:
```bash
#!/bin/bash
set -e
# Symlink .env from repo root (where secrets live, outside worktrees)
[ -f "$CONDUCTOR_ROOT_PATH/.env" ] && ln -sf "$CONDUCTOR_ROOT_PATH/.env" .env
# Symlink Rails master key
[ -f "$CONDUCTOR_ROOT_PATH/config/master.key" ] && ln -sf "$CONDUCTOR_ROOT_PATH/config/master.key" config/master.key
# Install dependencies
bundle install
npm install
```
Make it executable with `chmod +x bin/conductor-setup`.
## 3. script/server (executable)
Create the `script` directory if needed, then create `script/server` if it doesn't already exist:
```bash
#!/bin/bash
# === Port Configuration ===
export PORT=${CONDUCTOR_PORT:-3000}
export VITE_RUBY_PORT=$((PORT + 1000))
# === Redis Isolation ===
if [ -n "$CONDUCTOR_WORKSPACE_NAME" ]; then
HASH=$(printf '%s' "$CONDUCTOR_WORKSPACE_NAME" | cksum | cut -d' ' -f1)
REDIS_DB=$((HASH % 16))
export REDIS_URL="redis://localhost:6379/${REDIS_DB}"
fi
exec bin/dev
```
Make it executable with `chmod +x script/server`.
## 4. Update Rails Config Files
For each of the following files, if they exist and contain Redis configuration, update them to use `ENV.fetch('REDIS_URL', ...)` or `ENV['REDIS_URL']` with a fallback:
### config/initializers/sidekiq.rb
If this file exists and configures Redis, update it to use:
```ruby
redis_url = ENV.fetch('REDIS_URL', 'redis://localhost:6379/0')
```
### config/cable.yml
If this file exists, update the development adapter to use:
```yaml
development:
adapter: redis
url: <%= ENV.fetch('REDIS_URL', 'redis://localhost:6379/1') %>
```
### config/environments/development.rb
If this file configures Redis for caching, update to use:
```ruby
config.cache_store = :redis_cache_store, { url: ENV.fetch('REDIS_URL', 'redis://localhost:6379/0') }
```
### config/initializers/rack_attack.rb
If this file exists and configures a Redis cache store, update to use:
```ruby
Rack::Attack.cache.store = ActiveSupport::Cache::RedisCacheStore.new(url: ENV.fetch('REDIS_URL', 'redis://localhost:6379/0'))
```
# Implementation Notes
- **Don't overwrite existing files**: Check if conductor.json, bin/conductor-setup, and script/server exist before creating them. If they exist, skip creation and inform the user.
- **Rails config updates**: Only modify Redis-related configuration. If a file doesn't exist or doesn't use Redis, skip it gracefully.
- **Create directories as needed**: Create `script/` directory if it doesn't exist.
# Verification
After creating the files:
1. Confirm all Conductor files exist and scripts are executable
2. Run `script/server` to verify it starts without errors
3. Check that Rails configs properly reference `ENV['REDIS_URL']` or `ENV.fetch('REDIS_URL', ...)`
## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
---
name: find-skills
description: Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
---
# Find Skills
This skill helps you discover and install skills from the open agent skills ecosystem.
## When to Use This Skill
Use this skill when the user:
- Asks "how do I do X" where X might be a common task with an existing skill
- Says "find a skill for X" or "is there a skill for X"
- Asks "can you do X" where X is a specialized capability
- Expresses interest in extending agent capabilities
- Wants to search for tools, templates, or workflows
- Mentions they wish they had help with a specific domain (design, testing, deployment, etc.)
## What is the Skills CLI?
The Skills CLI (`npx skills`) is the package manager for the open agent skills ecosystem. Skills are modular packages that extend agent capabilities with specialized knowledge, workflows, and tools.
**Key commands:**
- `npx skills find [query]` - Search for skills interactively or by keyword
- `npx skills add <package>` - Install a skill from GitHub or other sources
- `npx skills check` - Check for skill updates
- `npx skills update` - Update all installed skills
**Browse skills at:** https://skills.sh/
## How to Help Users Find Skills
### Step 1: Understand What They Need
When a user asks for help with something, identify:
1. The domain (e.g., React, testing, design, deployment)
2. The specific task (e.g., writing tests, creating animations, reviewing PRs)
3. Whether this is a common enough task that a skill likely exists
### Step 2: Check the Leaderboard First
Before running a CLI search, check the [skills.sh leaderboard](https://skills.sh/) to see if a well-known skill already exists for the domain. The leaderboard ranks skills by total installs, surfacing the most popular and battle-tested options.
For example, top skills for web development include:
- `vercel-labs/agent-skills` — React, Next.js, web design (100K+ installs each)
- `anthropics/skills` — Frontend design, document processing (100K+ installs)
### Step 3: Search for Skills
If the leaderboard doesn't cover the user's need, run the find command:
```bash
npx skills find [query]
```
For example:
- User asks "how do I make my React app faster?" → `npx skills find react performance`
- User asks "can you help me with PR reviews?" → `npx skills find pr review`
- User asks "I need to create a changelog" → `npx skills find changelog`
### Step 4: Verify Quality Before Recommending
**Do not recommend a skill based solely on search results.** Always verify:
1. **Install count** — Prefer skills with 1K+ installs. Be cautious with anything under 100.
2. **Source reputation** — Official sources (`vercel-labs`, `anthropics`, `microsoft`) are more trustworthy than unknown authors.
3. **GitHub stars** — Check the source repository. A skill from a repo with <100 stars should be treated with skepticism.
### Step 5: Present Options to the User
When you find relevant skills, present them to the user with:
1. The skill name and what it does
2. The install count and source
3. The install command they can run
4. A link to learn more at skills.sh
Example response:
```
I found a skill that might help! The "react-best-practices" skill provides
React and Next.js performance optimization guidelines from Vercel Engineering.
(185K installs)
To install it:
npx skills add vercel-labs/agent-skills@react-best-practices
Learn more: https://skills.sh/vercel-labs/agent-skills/react-best-practices
```
### Step 6: Offer to Install
If the user wants to proceed, you can install the skill for them:
```bash
npx skills add <owner/repo@skill> -g -y
```
The `-g` flag installs globally (user-level) and `-y` skips confirmation prompts.
## Common Skill Categories
When searching, consider these common categories:
| Category | Example Queries |
| --------------- | ---------------------------------------- |
| Web Development | react, nextjs, typescript, css, tailwind |
| Testing | testing, jest, playwright, e2e |
| DevOps | deploy, docker, kubernetes, ci-cd |
| Documentation | docs, readme, changelog, api-docs |
| Code Quality | review, lint, refactor, best-practices |
| Design | ui, ux, design-system, accessibility |
| Productivity | workflow, automation, git |
## Tips for Effective Searches
1. **Use specific keywords**: "react testing" is better than just "testing"
2. **Try alternative terms**: If "deploy" doesn't work, try "deployment" or "ci-cd"
3. **Check popular sources**: Many skills come from `vercel-labs/agent-skills` or `ComposioHQ/awesome-claude-skills`
## When No Skills Are Found
If no relevant skills exist:
1. Acknowledge that no existing skill was found
2. Offer to help with the task directly using your general capabilities
3. Suggest the user could create their own skill with `npx skills init`
Example:
```
I searched for skills related to "xyz" but didn't find any matches.
I can still help you with this task directly! Would you like me to proceed?
If this is something you do often, you could create your own skill:
npx skills init my-xyz-skill
```
"""
Framework-Specific Multi-Agent Implementations
Templates for CrewAI, AutoGen, LangGraph, and Swarm.
"""
from typing import Dict, List, Optional, Any
from dataclasses import dataclass
@dataclass
class CrewAITemplate:
"""Template for CrewAI implementation."""
@staticmethod
def create_financial_team() -> Dict[str, Any]:
"""Create CrewAI financial analysis team."""
return {
"agents": [
{
"name": "Market Analyst",
"role": "Market Research Specialist",
"goal": "Analyze market conditions and trends",
"backstory": "Expert market analyst with 10+ years experience",
"tools": ["market_data_api", "financial_news"],
},
{
"name": "Financial Analyst",
"role": "Financial Analysis Specialist",
"goal": "Analyze company financial statements",
"backstory": "CFA with deep financial analysis expertise",
"tools": ["financial_statements", "ratio_calculator"],
},
{
"name": "Risk Manager",
"role": "Risk Assessment Specialist",
"goal": "Assess investment risks and scenarios",
"backstory": "Risk management expert",
"tools": ["risk_models", "scenario_analysis"],
},
{
"name": "Report Writer",
"role": "Report Generation Specialist",
"goal": "Synthesize findings into comprehensive report",
"backstory": "Professional technical writer",
"tools": ["document_generator"],
},
],
"tasks": [
{
"agent": "Market Analyst",
"description": "Analyze market conditions for {company}",
},
{
"agent": "Financial Analyst",
"description": "Analyze Q3 financial results for {company}",
},
{
"agent": "Risk Manager",
"description": "Assess risks and create scenarios for {company}",
},
{
"agent": "Report Writer",
"description": "Write comprehensive investment analysis report",
},
],
"process": "sequential",
}
@staticmethod
def create_legal_team() -> Dict[str, Any]:
"""Create CrewAI legal team."""
return {
"agents": [
{
"name": "Contract Analyzer",
"role": "Legal Contract Specialist",
"goal": "Analyze and review contract terms",
"backstory": "Senior contract attorney",
},
{
"name": "Precedent Researcher",
"role": "Legal Research Specialist",
"goal": "Research relevant case law and precedents",
"backstory": "Legal researcher specializing in case law",
},
{
"name": "Risk Assessor",
"role": "Legal Risk Specialist",
"goal": "Identify and assess legal risks",
"backstory": "Risk management expert in legal domain",
},
{
"name": "Document Drafter",
"role": "Legal Document Specialist",
"goal": "Draft legal documents and recommendations",
"backstory": "Legal document drafting expert",
},
],
"process": "sequential",
}
@dataclass
class AutoGenTemplate:
"""Template for AutoGen implementation."""
@staticmethod
def create_group_chat_config() -> Dict[str, Any]:
"""Create AutoGen group chat configuration."""
return {
"agents": [
{
"name": "analyst",
"system_message": "You are a financial analyst. Provide analysis based on data.",
"llm_config": {"model": "gpt-4", "temperature": 0.7},
},
{
"name": "researcher",
"system_message": "You are a market researcher. Research trends and competition.",
"llm_config": {"model": "gpt-4", "temperature": 0.7},
},
{
"name": "critic",
"system_message": "You are a critical evaluator. Challenge assumptions and findings.",
"llm_config": {"model": "gpt-4", "temperature": 0.7},
},
],
"group_chat_config": {
"agents": ["analyst", "researcher", "critic"],
"max_round": 10,
"speaker_selection_method": "auto",
},
}
@staticmethod
def create_hierarchical_structure() -> Dict[str, Any]:
"""Create hierarchical AutoGen structure."""
return {
"primary_agents": [
{
"name": "senior_analyst",
"role": "Senior analyst coordinating teams",
"subordinates": ["junior_analyst_1", "junior_analyst_2"],
}
],
"secondary_agents": [
{
"name": "junior_analyst_1",
"role": "Fundamental analysis specialist",
},
{
"name": "junior_analyst_2",
"role": "Technical analysis specialist",
},
],
}
@dataclass
class LangGraphTemplate:
"""Template for LangGraph workflow implementation."""
@staticmethod
def create_research_workflow() -> Dict[str, Any]:
"""Create LangGraph research workflow."""
return {
"name": "research_workflow",
"state_schema": {
"topic": str,
"research_findings": str,
"analysis": str,
"recommendations": str,
},
"nodes": [
{
"name": "researcher",
"agent": "research_agent",
"description": "Research the topic",
},
{
"name": "analyst",
"agent": "analyst_agent",
"description": "Analyze research findings",
},
{
"name": "critic",
"agent": "critic_agent",
"description": "Critique and improve",
},
{
"name": "writer",
"agent": "writer_agent",
"description": "Write final report",
},
],
"edges": [
("researcher", "analyst"),
("analyst", "critic"),
("critic", "writer"),
],
"entry_point": "researcher",
"exit_point": "writer",
}
@staticmethod
def create_dynamic_workflow() -> Dict[str, Any]:
"""Create dynamic LangGraph workflow with conditions."""
return {
"name": "dynamic_workflow",
"nodes": [
{
"name": "start",
"type": "input",
},
{
"name": "analyze",
"type": "agent",
"agent": "analyzer",
},
{
"name": "quality_check",
"type": "decision",
"condition": "analyze_quality > threshold",
},
{
"name": "refine",
"type": "agent",
"agent": "refiner",
},
{
"name": "end",
"type": "output",
},
],
"conditional_edges": [
{
"source": "quality_check",
"true_target": "end",
"false_target": "refine",
}
],
}
@dataclass
class SwarmTemplate:
"""Template for OpenAI Swarm implementation."""
@staticmethod
def create_customer_support_swarm() -> Dict[str, Any]:
"""Create customer support Swarm."""
return {
"agents": [
{
"name": "triage_agent",
"instructions": "Determine which specialist to route the customer to. "
"Ask clarifying questions if needed.",
"functions": [
"route_to_billing",
"route_to_technical",
"route_to_account",
],
},
{
"name": "billing_specialist",
"instructions": "Handle all billing and payment related questions. "
"Can access billing records.",
"tools": ["billing_system", "payment_processor"],
},
{
"name": "technical_support",
"instructions": "Handle technical issues and troubleshooting. "
"Can access diagnostic tools.",
"tools": ["diagnostic_tools", "knowledge_base"],
},
{
"name": "account_specialist",
"instructions": "Handle account management and profile changes.",
"tools": ["account_system"],
},
],
"handoff_functions": {
"route_to_billing": "Transfer to billing specialist",
"route_to_technical": "Transfer to technical support",
"route_to_account": "Transfer to account specialist",
},
}
@staticmethod
def create_sales_swarm() -> Dict[str, Any]:
"""Create sales team Swarm."""
return {
"agents": [
{
"name": "sales_router",
"instructions": "Route customer inquiries to appropriate sales agent",
"functions": ["route_to_enterprise", "route_to_smb"],
},
{
"name": "enterprise_sales",
"instructions": "Handle enterprise customer inquiries",
},
{
"name": "smb_sales",
"instructions": "Handle small business inquiries",
},
],
}
class AgentCommunicationManager:
"""Manage communication patterns between agents."""
def __init__(self, agents: Dict[str, Any]):
"""Initialize communication manager."""
self.agents = agents
self.message_queue = []
def broadcast_message(self, sender: str, message: str, recipients: List[str]):
"""Broadcast message to multiple agents."""
for recipient in recipients:
self.message_queue.append({
"from": sender,
"to": recipient,
"message": message,
"type": "broadcast",
})
def direct_message(self, sender: str, recipient: str, message: str):
"""Send direct message between agents."""
self.message_queue.append({
"from": sender,
"to": recipient,
"message": message,
"type": "direct",
})
def publish_shared_state(self, state_key: str, value: Any):
"""Publish to shared state (tool-mediated communication)."""
self.message_queue.append({
"type": "shared_state",
"key": state_key,
"value": value,
})
def get_pending_messages(self, agent: str) -> List[Dict]:
"""Get messages for specific agent."""
return [msg for msg in self.message_queue if msg.get("to") == agent]
def process_message_queue(self) -> Dict[str, Any]:
"""Process and summarize message queue."""
direct_messages = [m for m in self.message_queue if m["type"] == "direct"]
broadcasts = [m for m in self.message_queue if m["type"] == "broadcast"]
shared_states = [m for m in self.message_queue if m["type"] == "shared_state"]
return {
"direct_messages": len(direct_messages),
"broadcasts": len(broadcasts),
"shared_states": len(shared_states),
"total_messages": len(self.message_queue),
}
"""
Multi-Agent Orchestration Patterns
Implements sequential, parallel, hierarchical, and consensus orchestration.
"""
from typing import List, Dict, Any, Optional
import asyncio
from abc import ABC, abstractmethod
class Agent(ABC):
"""Base agent class."""
def __init__(self, name: str, role: str, goal: str):
"""Initialize agent."""
self.name = name
self.role = role
self.goal = goal
@abstractmethod
def work(self, task: str) -> str:
"""Execute task."""
pass
async def work_async(self, task: str) -> str:
"""Execute task asynchronously."""
return self.work(task)
class SimpleAgent(Agent):
"""Simple agent implementation."""
def __init__(self, name: str, role: str, goal: str):
"""Initialize simple agent."""
super().__init__(name, role, goal)
def work(self, task: str) -> str:
"""Simulate agent work."""
return f"{self.name}: Completed task - {task[:50]}..."
class SequentialOrchestrator:
"""Orchestrate agents to work sequentially."""
def __init__(self, agents: List[Agent]):
"""
Initialize orchestrator with agents.
Args:
agents: List of agents to orchestrate
"""
self.agents = agents
self.execution_log = []
def execute(self, initial_task: str) -> Dict[str, Any]:
"""
Execute agents sequentially.
Args:
initial_task: Initial task description
Returns:
Execution results dictionary
"""
current_input = initial_task
results = {}
for agent in self.agents:
result = agent.work(current_input)
results[agent.name] = result
self.execution_log.append({
"agent": agent.name,
"role": agent.role,
"task": current_input,
"result": result,
})
# Next agent uses this agent's output
current_input = result
return {
"type": "sequential",
"results": results,
"final_output": current_input,
"execution_log": self.execution_log,
}
class ParallelOrchestrator:
"""Orchestrate agents to work in parallel."""
def __init__(self, agents: List[Agent]):
"""Initialize parallel orchestrator."""
self.agents = agents
self.execution_log = []
async def execute_async(self, task: str) -> Dict[str, Any]:
"""
Execute agents in parallel.
Args:
task: Task description
Returns:
Execution results dictionary
"""
# Create async tasks for all agents
tasks = [agent.work_async(task) for agent in self.agents]
# Execute all in parallel
results_list = await asyncio.gather(*tasks)
results = {
agent.name: result
for agent, result in zip(self.agents, results_list)
}
self.execution_log.append({
"type": "parallel",
"task": task,
"agents": [a.name for a in self.agents],
"results": results,
})
return {
"type": "parallel",
"results": results,
"execution_log": self.execution_log,
}
def execute(self, task: str) -> Dict[str, Any]:
"""Execute agents synchronously (sequential fallback)."""
return asyncio.run(self.execute_async(task))
class HierarchicalOrchestrator:
"""Orchestrate agents in hierarchical structure."""
def __init__(self, manager_agent: Agent, specialist_teams: Dict[str, List[Agent]]):
"""
Initialize hierarchical orchestrator.
Args:
manager_agent: Manager agent
specialist_teams: Dict of team names to lists of agents
"""
self.manager = manager_agent
self.specialist_teams = specialist_teams
self.execution_log = []
def execute(self, main_task: str) -> Dict[str, Any]:
"""
Execute with hierarchical structure.
Args:
main_task: Main task for manager
Returns:
Execution results
"""
team_results = {}
# Manager assigns tasks to teams
for team_name, agents in self.specialist_teams.items():
# Each team works on their aspect
team_task = f"{main_task} - Team: {team_name}"
team_result = {}
for agent in agents:
result = agent.work(team_task)
team_result[agent.name] = result
team_results[team_name] = team_result
self.execution_log.append({
"team": team_name,
"agents": [a.name for a in agents],
"results": team_result,
})
# Manager synthesizes results
manager_result = self.manager.work(
f"Synthesize findings from: {list(team_results.keys())}"
)
return {
"type": "hierarchical",
"team_results": team_results,
"manager_synthesis": manager_result,
"execution_log": self.execution_log,
}
class ConsensusOrchestrator:
"""Orchestrate agent debate and consensus."""
def __init__(self, agents: List[Agent], mediator_agent: Agent):
"""Initialize consensus orchestrator."""
self.agents = agents
self.mediator = mediator_agent
self.debate_history = []
def execute(self, question: str, rounds: int = 2) -> Dict[str, Any]:
"""
Execute debate and reach consensus.
Args:
question: Question for debate
rounds: Number of debate rounds
Returns:
Consensus results
"""
# Round 1: Initial positions
positions = {}
for agent in self.agents:
position = agent.work(f"Argue your position on: {question}")
positions[agent.name] = position
self.debate_history.append({
"round": 1,
"agent": agent.name,
"position": position,
})
# Additional rounds: Response to others
for round_num in range(2, rounds + 1):
for agent in self.agents:
other_positions = {
name: pos
for name, pos in positions.items()
if name != agent.name
}
response = agent.work(
f"Respond to these positions: {str(other_positions)}"
)
self.debate_history.append({
"round": round_num,
"agent": agent.name,
"response": response,
})
# Mediator reaches consensus
consensus = self.mediator.work(
f"Synthesize consensus from debate on: {question}"
)
return {
"type": "consensus",
"question": question,
"initial_positions": positions,
"debate_rounds": rounds,
"consensus": consensus,
"debate_history": self.debate_history,
}
class AdaptiveOrchestrator:
"""Adapt orchestration based on progress."""
def __init__(self, agents: List[Agent]):
"""Initialize adaptive orchestrator."""
self.agents = agents
self.execution_log = []
def execute_with_adaptation(
self,
initial_task: str,
progress_threshold: float = 0.7,
quality_threshold: float = 0.6,
) -> Dict[str, Any]:
"""
Execute with adaptive workflow changes.
Args:
initial_task: Initial task
progress_threshold: Threshold for adding resources
quality_threshold: Threshold for adding validation
Returns:
Adaptive execution results
"""
results = {}
current_task = initial_task
active_agents = self.agents.copy()
for iteration in range(3):
# Execute with current agents
iteration_results = {}
for agent in active_agents:
result = agent.work(current_task)
iteration_results[agent.name] = result
results[f"iteration_{iteration}"] = iteration_results
# Assess progress
progress = self._calculate_progress(iteration_results)
quality = self._calculate_quality(iteration_results)
log_entry = {
"iteration": iteration,
"agents": [a.name for a in active_agents],
"progress": progress,
"quality": quality,
}
# Adapt based on progress
if progress < progress_threshold and iteration < 2:
# Add more agents
log_entry["adaptation"] = "Added specialist agent"
self.execution_log.append(log_entry)
elif quality < quality_threshold and iteration < 2:
# Add validation step
log_entry["adaptation"] = "Added validation agent"
self.execution_log.append(log_entry)
else:
self.execution_log.append(log_entry)
return {
"type": "adaptive",
"results": results,
"adaptations": self.execution_log,
}
@staticmethod
def _calculate_progress(results: Dict) -> float:
"""Calculate progress score."""
# Simple heuristic based on results
return min(len(results) / 3.0, 1.0)
@staticmethod
def _calculate_quality(results: Dict) -> float:
"""Calculate quality score."""
# Simple heuristic
return 0.7 # Placeholder
class WorkflowGraph:
"""Define workflow as directed acyclic graph (DAG)."""
def __init__(self):
"""Initialize workflow graph."""
self.nodes = {}
self.edges = []
def add_node(self, node_id: str, agent: Agent) -> None:
"""Add agent node."""
self.nodes[node_id] = agent
def add_edge(self, from_node: str, to_node: str) -> None:
"""Add dependency edge."""
self.edges.append((from_node, to_node))
def execute_dag(self, initial_task: str) -> Dict[str, Any]:
"""
Execute workflow as DAG.
Args:
initial_task: Initial task
Returns:
Execution results
"""
results = {}
ready_nodes = self._find_ready_nodes()
while ready_nodes:
for node_id in ready_nodes:
agent = self.nodes[node_id]
# Get input from dependencies
task_input = self._get_node_input(node_id, results, initial_task)
result = agent.work(task_input)
results[node_id] = result
ready_nodes = self._find_ready_nodes(completed=set(results.keys()))
return {
"type": "dag",
"results": results,
"nodes": list(self.nodes.keys()),
"edges": self.edges,
}
def _find_ready_nodes(self, completed: Optional[set] = None) -> List[str]:
"""Find nodes with all dependencies completed."""
if completed is None:
completed = set()
ready = []
for node_id in self.nodes:
if node_id not in completed:
dependencies = [
from_node
for from_node, to_node in self.edges
if to_node == node_id
]
if all(dep in completed for dep in dependencies):
ready.append(node_id)
return ready
def _get_node_input(
self, node_id: str, results: Dict, initial_task: str
) -> str:
"""Get input for node from dependencies."""
dependencies = [
from_node for from_node, to_node in self.edges if to_node == node_id
]
if not dependencies:
return initial_task
# Combine outputs from dependencies
return " + ".join(results.get(dep, "") for dep in dependencies)
# Multi-Agent Orchestration - Code Structure
This skill uses supporting Python files to keep documentation lean and maintainable.
## Directory Structure
```
multi-agent-orchestration/
├── SKILL.md # Main documentation (patterns, concepts)
├── README.md # This file
├── examples/ # Implementation examples
│ ├── orchestration_patterns.py # Sequential, parallel, hierarchical, consensus
│ └── framework_implementations.py # CrewAI, AutoGen, LangGraph, Swarm templates
└── scripts/ # Utility modules
├── agent_communication.py # Message broker, shared memory, protocols
├── workflow_management.py # Workflow execution and optimization
└── benchmarking.py # Performance and collaboration metrics
```
## Running Examples
### 1. Orchestration Patterns
```bash
python examples/orchestration_patterns.py
```
Demonstrates sequential, parallel, hierarchical, and consensus orchestration.
### 2. Framework Templates
```bash
python examples/framework_implementations.py
```
Templates and configurations for CrewAI, AutoGen, LangGraph, and Swarm frameworks.
## Using the Utilities
### Agent Communication
```python
from scripts.agent_communication import MessageBroker, SharedMemory, CommunicationProtocol
# Set up communication
broker = MessageBroker()
shared_memory = SharedMemory()
protocol = CommunicationProtocol(broker, shared_memory)
# Send messages between agents
protocol.request_analysis("agent_a", "agent_b", "Analyze this topic")
# Share findings
protocol.share_findings("agent_a", "analysis_results", {"findings": "..."})
# Get communication stats
stats = broker.get_statistics()
```
### Workflow Management
```python
from scripts.workflow_management import WorkflowExecutor, WorkflowOptimizer
# Create and execute workflow
executor = WorkflowExecutor()
workflow = executor.create_workflow("workflow_1", "Analysis Workflow")
# Add tasks
executor.add_task("workflow_1", "task_1", "researcher", "Research the topic")
executor.add_task("workflow_1", "task_2", "analyst", "Analyze findings", dependencies=["task_1"])
# Execute
results = executor.execute_workflow("workflow_1", executor_func)
# Analyze workflow
analysis = WorkflowOptimizer.analyze_dependencies(workflow)
print(f"Critical path: {analysis['critical_path']}")
```
### Benchmarking
```python
from scripts.benchmarking import TeamBenchmark, AgentEffectiveness, CollaborationMetrics
# Benchmark team performance
benchmark = TeamBenchmark()
result = benchmark.run_benchmark("sequential_test", orchestrator, test_data)
# Track agent effectiveness
effectiveness = AgentEffectiveness()
effectiveness.record_agent_task("agent_a", "task_1", success=True, quality_score=0.95, duration=2.5)
# Get agent rankings
rankings = effectiveness.rank_agents()
for rank, agent, score, metrics in rankings:
print(f"{rank}. {agent}: {score:.2f}")
# Analyze collaboration
collaboration = CollaborationMetrics()
collaboration.record_interaction("agent_a", "agent_b", "request", response_time=0.5, successful=True)
interaction_metrics = collaboration.get_interaction_metrics()
```
## Integration with SKILL.md
- SKILL.md contains conceptual information, orchestration patterns, and best practices
- Code examples are in `examples/` for clarity and runnable implementations
- Utilities are in `scripts/` for modular, reusable components
- This keeps token costs low while maintaining full functionality
## Orchestration Patterns Covered
1. **Sequential Orchestration** - Tasks execute one after another
2. **Parallel Orchestration** - Multiple agents work simultaneously
3. **Hierarchical Orchestration** - Manager coordinates specialist teams
4. **Consensus-Based** - Agents debate and reach consensus
5. **Adaptive Workflows** - Orchestration changes based on progress
6. **DAG-Based** - Workflow as directed acyclic graph
## Framework Implementations
- **CrewAI** - Clear roles, hierarchical structure
- **AutoGen** - Multi-turn conversations, group discussions
- **LangGraph** - State management, complex workflows
- **Swarm** - Simple handoffs, conversational workflows
## Key Features
- **Token Efficient**: Modular code structure reduces LLM context usage
- **Production Ready**: Includes monitoring, optimization, and benchmarking
- **Framework Agnostic**: Works with any agent framework
- **Communication Patterns**: Direct, tool-mediated, and manager-based
- **Performance Metrics**: Team and individual agent effectiveness tracking
## Communication Patterns
- **Direct Communication**: Agent-to-agent message passing
- **Tool-Mediated**: Agents use shared memory/database
- **Manager-Based**: Central coordinator manages communication
- **Broadcast**: One-to-many messaging
## Next Steps
1. Define agent roles and expertise
2. Choose orchestration pattern (sequential, parallel, hierarchical)
3. Select communication approach (direct, shared memory, manager)
4. Implement workflow with task definitions
5. Set up monitoring and metrics
6. Benchmark and optimize
7. Deploy and iterate
"""
Agent Communication Management
Handle agent-to-agent communication, message passing, and shared state.
"""
from typing import Dict, List, Optional, Any, Callable
from dataclasses import dataclass, field
from enum import Enum
import json
class MessageType(Enum):
"""Types of messages between agents."""
DIRECT = "direct"
BROADCAST = "broadcast"
REQUEST = "request"
RESPONSE = "response"
FEEDBACK = "feedback"
ERROR = "error"
@dataclass
class Message:
"""Message between agents."""
sender: str
recipient: str
content: str
message_type: MessageType
timestamp: float = field(default_factory=lambda: 0)
metadata: Dict[str, Any] = field(default_factory=dict)
def to_dict(self) -> Dict:
"""Convert to dictionary."""
return {
"sender": self.sender,
"recipient": self.recipient,
"content": self.content,
"type": self.message_type.value,
"timestamp": self.timestamp,
"metadata": self.metadata,
}
class MessageBroker:
"""Central message broker for agent communication."""
def __init__(self):
"""Initialize message broker."""
self.message_queue: List[Message] = []
self.agent_inboxes: Dict[str, List[Message]] = {}
self.message_handlers: Dict[MessageType, List[Callable]] = {}
def send_message(self, message: Message) -> bool:
"""
Send message from one agent to another.
Args:
message: Message object
Returns:
Whether message was delivered
"""
self.message_queue.append(message)
# Add to recipient's inbox
if message.recipient not in self.agent_inboxes:
self.agent_inboxes[message.recipient] = []
self.agent_inboxes[message.recipient].append(message)
# Trigger handlers
self._trigger_handlers(message)
return True
def broadcast_message(self, sender: str, content: str, recipients: List[str]):
"""
Broadcast message to multiple agents.
Args:
sender: Sending agent
content: Message content
recipients: List of recipient agents
"""
for recipient in recipients:
message = Message(
sender=sender,
recipient=recipient,
content=content,
message_type=MessageType.BROADCAST,
)
self.send_message(message)
def request_response(
self, sender: str, recipient: str, content: str, timeout: float = 5.0
) -> Optional[Message]:
"""
Send request and wait for response.
Args:
sender: Requesting agent
recipient: Agent to respond
content: Request content
timeout: Response timeout in seconds
Returns:
Response message or None
"""
message = Message(
sender=sender,
recipient=recipient,
content=content,
message_type=MessageType.REQUEST,
metadata={"timeout": timeout},
)
self.send_message(message)
# Placeholder - wait for response
# In production, implement actual timeout/wait mechanism
return None
def get_inbox(self, agent: str) -> List[Message]:
"""Get messages for specific agent."""
return self.agent_inboxes.get(agent, [])
def clear_inbox(self, agent: str) -> None:
"""Clear agent's inbox."""
self.agent_inboxes[agent] = []
def register_handler(
self, message_type: MessageType, handler: Callable
) -> None:
"""Register handler for message type."""
if message_type not in self.message_handlers:
self.message_handlers[message_type] = []
self.message_handlers[message_type].append(handler)
def _trigger_handlers(self, message: Message) -> None:
"""Trigger registered handlers."""
handlers = self.message_handlers.get(message.message_type, [])
for handler in handlers:
try:
handler(message)
except Exception:
pass
def get_statistics(self) -> Dict[str, Any]:
"""Get communication statistics."""
type_counts = {}
for message in self.message_queue:
msg_type = message.message_type.value
type_counts[msg_type] = type_counts.get(msg_type, 0) + 1
return {
"total_messages": len(self.message_queue),
"by_type": type_counts,
"total_agents": len(self.agent_inboxes),
"agents": list(self.agent_inboxes.keys()),
}
class SharedMemory:
"""Shared memory for tool-mediated agent communication."""
def __init__(self):
"""Initialize shared memory."""
self.memory: Dict[str, Any] = {}
self.access_log: List[Dict] = []
def write(self, key: str, value: Any, agent: str = "system") -> None:
"""
Write to shared memory.
Args:
key: Memory key
value: Value to store
agent: Agent writing
"""
self.memory[key] = {
"value": value,
"writer": agent,
"access_count": 0,
}
self.access_log.append({
"action": "write",
"key": key,
"agent": agent,
})
def read(self, key: str, agent: str = "system") -> Optional[Any]:
"""
Read from shared memory.
Args:
key: Memory key
agent: Agent reading
Returns:
Stored value or None
"""
if key in self.memory:
entry = self.memory[key]
entry["access_count"] += 1
self.access_log.append({
"action": "read",
"key": key,
"agent": agent,
})
return entry["value"]
return None
def append(self, key: str, value: Any, agent: str = "system") -> None:
"""Append to list in shared memory."""
if key not in self.memory:
self.memory[key] = {
"value": [],
"writer": agent,
"access_count": 0,
}
if isinstance(self.memory[key]["value"], list):
self.memory[key]["value"].append(value)
def get_all(self) -> Dict[str, Any]:
"""Get all shared memory contents."""
return {
key: entry["value"] for key, entry in self.memory.items()
}
def get_statistics(self) -> Dict[str, Any]:
"""Get memory access statistics."""
total_accesses = sum(
entry["access_count"] for entry in self.memory.values()
)
return {
"total_keys": len(self.memory),
"total_accesses": total_accesses,
"access_log_size": len(self.access_log),
}
class ContextManager:
"""Manage context sharing between agents."""
def __init__(self):
"""Initialize context manager."""
self.contexts: Dict[str, Dict[str, Any]] = {}
self.global_context: Dict[str, Any] = {}
def create_context(self, context_id: str, initial_data: Optional[Dict] = None) -> None:
"""Create new context."""
self.contexts[context_id] = initial_data or {}
def update_context(self, context_id: str, data: Dict) -> None:
"""Update context data."""
if context_id in self.contexts:
self.contexts[context_id].update(data)
def get_context(self, context_id: str) -> Dict[str, Any]:
"""Get context data."""
return self.contexts.get(context_id, {})
def set_global_context(self, key: str, value: Any) -> None:
"""Set global context variable."""
self.global_context[key] = value
def get_global_context(self, key: str) -> Optional[Any]:
"""Get global context variable."""
return self.global_context.get(key)
def context_to_string(self, context_id: str) -> str:
"""Convert context to formatted string."""
context = self.get_context(context_id)
return json.dumps(context, indent=2)
class CommunicationProtocol:
"""Define communication protocol between agents."""
def __init__(self, broker: MessageBroker, shared_memory: SharedMemory):
"""Initialize protocol."""
self.broker = broker
self.shared_memory = shared_memory
def request_analysis(
self, requester: str, analyzer: str, subject: str
) -> None:
"""Request analysis from another agent."""
message = Message(
sender=requester,
recipient=analyzer,
content=f"Analyze: {subject}",
message_type=MessageType.REQUEST,
metadata={"action": "analyze"},
)
self.broker.send_message(message)
def share_findings(self, source_agent: str, key: str, findings: Dict) -> None:
"""Share findings through shared memory."""
self.shared_memory.write(key, findings, source_agent)
def aggregate_results(
self, agents: List[str], result_key: str
) -> Dict[str, Any]:
"""Aggregate results from multiple agents."""
results = {}
for agent in agents:
agent_results = self.shared_memory.read(f"{agent}_{result_key}")
if agent_results:
results[agent] = agent_results
return results
def notify_status(self, agent: str, status: str) -> None:
"""Notify status update."""
message = Message(
sender=agent,
recipient="orchestrator",
content=f"Status: {status}",
message_type=MessageType.FEEDBACK,
)
self.broker.send_message(message)
def error_propagation(self, source_agent: str, error: str) -> None:
"""Propagate error to relevant agents."""
message = Message(
sender=source_agent,
recipient="orchestrator",
content=f"Error: {error}",
message_type=MessageType.ERROR,
)
self.broker.send_message(message)
"""
Multi-Agent System Benchmarking
Evaluate team performance and agent effectiveness.
"""
from typing import Dict, List, Any, Callable, Optional
from dataclasses import dataclass
import time
import statistics
@dataclass
class BenchmarkResult:
"""Result from benchmark run."""
test_name: str
total_time: float
task_count: int
success_count: int
failure_count: int
quality_score: float
cost_tokens: int
class TeamBenchmark:
"""Benchmark multi-agent team performance."""
def __init__(self):
"""Initialize benchmarking suite."""
self.results: List[BenchmarkResult] = []
self.agent_metrics: Dict[str, Dict] = {}
def run_benchmark(
self,
test_name: str,
orchestrator,
test_data: List[Dict],
quality_metric: Optional[Callable] = None,
) -> BenchmarkResult:
"""
Run benchmark test.
Args:
test_name: Name of benchmark
orchestrator: Orchestrator instance
test_data: Test cases
quality_metric: Function to evaluate quality
Returns:
Benchmark result
"""
start_time = time.time()
results = []
costs = []
for test_case in test_data:
try:
result = orchestrator.execute(test_case)
results.append(result)
# Assume cost in test_case
costs.append(test_case.get("cost", 0))
except Exception:
pass
end_time = time.time()
success_count = len(results)
failure_count = len(test_data) - success_count
total_time = end_time - start_time
# Calculate quality score
quality_score = (
quality_metric(results) if quality_metric else success_count / len(test_data)
)
benchmark_result = BenchmarkResult(
test_name=test_name,
total_time=total_time,
task_count=len(test_data),
success_count=success_count,
failure_count=failure_count,
quality_score=quality_score,
cost_tokens=sum(costs),
)
self.results.append(benchmark_result)
return benchmark_result
def compare_orchestration_methods(
self,
methods: Dict[str, Callable],
test_data: List[Dict],
) -> Dict[str, Any]:
"""
Compare different orchestration methods.
Args:
methods: Dict of method name to orchestrator
test_data: Test cases
Returns:
Comparison results
"""
comparison = {}
for method_name, orchestrator in methods.items():
result = self.run_benchmark(method_name, orchestrator, test_data)
comparison[method_name] = {
"total_time": result.total_time,
"success_rate": result.success_count / result.task_count,
"quality_score": result.quality_score,
"efficiency": result.success_count / (result.total_time + 0.001),
"cost_per_success": (
result.cost_tokens / result.success_count
if result.success_count > 0
else float("inf")
),
}
return comparison
def get_summary(self) -> Dict[str, Any]:
"""Get benchmark summary."""
if not self.results:
return {"status": "no_results"}
times = [r.total_time for r in self.results]
success_rates = [
r.success_count / r.task_count for r in self.results
]
quality_scores = [r.quality_score for r in self.results]
return {
"total_benchmarks": len(self.results),
"avg_time": statistics.mean(times),
"median_time": statistics.median(times),
"avg_success_rate": statistics.mean(success_rates),
"avg_quality": statistics.mean(quality_scores),
"benchmarks": [r.__dict__ for r in self.results],
}
class AgentEffectiveness:
"""Measure individual agent effectiveness."""
def __init__(self):
"""Initialize effectiveness tracker."""
self.agent_stats: Dict[str, Dict] = {}
def record_agent_task(
self,
agent: str,
task_id: str,
success: bool,
quality_score: float,
duration: float,
) -> None:
"""Record agent task execution."""
if agent not in self.agent_stats:
self.agent_stats[agent] = {
"tasks": [],
"successes": 0,
"failures": 0,
}
stats = self.agent_stats[agent]
stats["tasks"].append({
"task_id": task_id,
"success": success,
"quality": quality_score,
"duration": duration,
})
if success:
stats["successes"] += 1
else:
stats["failures"] += 1
def get_agent_metrics(self, agent: str) -> Dict[str, Any]:
"""Get metrics for specific agent."""
if agent not in self.agent_stats:
return {"status": "no_data"}
stats = self.agent_stats[agent]
tasks = stats["tasks"]
if not tasks:
return {"status": "no_tasks"}
success_rate = stats["successes"] / (stats["successes"] + stats["failures"])
quality_scores = [t["quality"] for t in tasks]
durations = [t["duration"] for t in tasks]
return {
"agent": agent,
"total_tasks": len(tasks),
"success_rate": success_rate,
"avg_quality": statistics.mean(quality_scores),
"avg_duration": statistics.mean(durations),
"reliability": success_rate, # Alias for clarity
}
def rank_agents(self) -> List[tuple]:
"""Rank agents by effectiveness."""
rankings = []
for agent in self.agent_stats.keys():
metrics = self.get_agent_metrics(agent)
if "success_rate" in metrics:
score = (
metrics["success_rate"] * 0.4 +
metrics["avg_quality"] * 0.4 +
(1 - min(metrics["avg_duration"] / 10.0, 1.0)) * 0.2
)
rankings.append((agent, score, metrics))
rankings.sort(key=lambda x: x[1], reverse=True)
return rankings
def get_team_report(self) -> Dict[str, Any]:
"""Get team effectiveness report."""
rankings = self.rank_agents()
return {
"total_agents": len(self.agent_stats),
"rankings": [
{
"rank": i + 1,
"agent": agent,
"score": score,
"metrics": metrics,
}
for i, (agent, score, metrics) in enumerate(rankings)
],
}
class CollaborationMetrics:
"""Measure collaboration effectiveness between agents."""
def __init__(self):
"""Initialize collaboration metrics."""
self.interactions: List[Dict] = []
def record_interaction(
self,
agent_a: str,
agent_b: str,
message: str,
response_time: float,
successful: bool,
) -> None:
"""Record agent-to-agent interaction."""
self.interactions.append({
"agent_a": agent_a,
"agent_b": agent_b,
"message": message,
"response_time": response_time,
"successful": successful,
})
def get_collaboration_graph(self) -> Dict[str, List[str]]:
"""Get collaboration graph between agents."""
graph = {}
for interaction in self.interactions:
agent_a = interaction["agent_a"]
agent_b = interaction["agent_b"]
if agent_a not in graph:
graph[agent_a] = []
if agent_b not in graph[agent_a]:
graph[agent_a].append(agent_b)
return graph
def get_interaction_metrics(self) -> Dict[str, Any]:
"""Get interaction metrics."""
if not self.interactions:
return {"total_interactions": 0}
response_times = [i["response_time"] for i in self.interactions]
success_rate = sum(1 for i in self.interactions if i["successful"]) / len(
self.interactions
)
return {
"total_interactions": len(self.interactions),
"success_rate": success_rate,
"avg_response_time": statistics.mean(response_times),
"median_response_time": statistics.median(response_times),
"max_response_time": max(response_times),
"collaboration_score": success_rate * (1 - min(statistics.mean(response_times) / 10.0, 1.0)),
}
def get_agent_collaboration_analysis(self, agent: str) -> Dict[str, Any]:
"""Get collaboration analysis for specific agent."""
agent_interactions = [
i for i in self.interactions
if i["agent_a"] == agent or i["agent_b"] == agent
]
if not agent_interactions:
return {"agent": agent, "status": "no_interactions"}
partners = set()
for interaction in agent_interactions:
if interaction["agent_a"] == agent:
partners.add(interaction["agent_b"])
else:
partners.add(interaction["agent_a"])
success_rate = sum(
1 for i in agent_interactions if i["successful"]
) / len(agent_interactions)
return {
"agent": agent,
"collaboration_partners": list(partners),
"total_interactions": len(agent_interactions),
"collaboration_success_rate": success_rate,
}
def create_benchmark_suite() -> Dict[str, Callable]:
"""Create standard benchmark suite."""
return {
"sequential_tasks": lambda orchestrator: orchestrator.execute(
{"type": "sequential", "task_count": 5}
),
"parallel_tasks": lambda orchestrator: orchestrator.execute(
{"type": "parallel", "task_count": 10}
),
"complex_workflow": lambda orchestrator: orchestrator.execute(
{"type": "complex", "task_count": 20}
),
"error_handling": lambda orchestrator: orchestrator.execute(
{"type": "with_errors", "task_count": 10}
),
}
"""
Workflow Management for Multi-Agent Systems
Handle workflow execution, monitoring, and optimization.
"""
from typing import Dict, List, Any, Optional, Callable
from enum import Enum
from dataclasses import dataclass, field
import time
class WorkflowStatus(Enum):
"""Workflow execution status."""
PENDING = "pending"
RUNNING = "running"
PAUSED = "paused"
COMPLETED = "completed"
FAILED = "failed"
class TaskStatus(Enum):
"""Task execution status."""
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
SKIPPED = "skipped"
@dataclass
class Task:
"""Task to be executed by an agent."""
task_id: str
agent: str
description: str
status: TaskStatus = TaskStatus.PENDING
result: Optional[str] = None
error: Optional[str] = None
start_time: float = field(default_factory=time.time)
end_time: Optional[float] = None
dependencies: List[str] = field(default_factory=list)
@dataclass
class Workflow:
"""Workflow orchestration."""
workflow_id: str
name: str
tasks: Dict[str, Task] = field(default_factory=dict)
status: WorkflowStatus = WorkflowStatus.PENDING
start_time: Optional[float] = None
end_time: Optional[float] = None
class WorkflowExecutor:
"""Execute workflows with multiple agents."""
def __init__(self):
"""Initialize workflow executor."""
self.workflows: Dict[str, Workflow] = {}
self.execution_history: List[Dict] = []
def create_workflow(self, workflow_id: str, name: str) -> Workflow:
"""Create new workflow."""
workflow = Workflow(workflow_id=workflow_id, name=name)
self.workflows[workflow_id] = workflow
return workflow
def add_task(
self,
workflow_id: str,
task_id: str,
agent: str,
description: str,
dependencies: Optional[List[str]] = None,
) -> Task:
"""Add task to workflow."""
task = Task(
task_id=task_id,
agent=agent,
description=description,
dependencies=dependencies or [],
)
self.workflows[workflow_id].tasks[task_id] = task
return task
def execute_workflow(
self, workflow_id: str, executor_func: Callable
) -> Dict[str, Any]:
"""
Execute workflow.
Args:
workflow_id: Workflow ID
executor_func: Function to execute tasks
Returns:
Execution results
"""
workflow = self.workflows[workflow_id]
workflow.status = WorkflowStatus.RUNNING
workflow.start_time = time.time()
executed_tasks = set()
results = {}
while len(executed_tasks) < len(workflow.tasks):
# Find ready tasks
ready_tasks = self._get_ready_tasks(workflow, executed_tasks)
if not ready_tasks:
# Check if workflow is stuck
if len(executed_tasks) > 0:
break
for task_id in ready_tasks:
task = workflow.tasks[task_id]
task.status = TaskStatus.RUNNING
try:
# Execute task
result = executor_func(task)
task.result = result
task.status = TaskStatus.COMPLETED
results[task_id] = result
except Exception as e:
task.error = str(e)
task.status = TaskStatus.FAILED
results[task_id] = None
task.end_time = time.time()
executed_tasks.add(task_id)
# Finalize workflow
workflow.end_time = time.time()
if all(task.status == TaskStatus.COMPLETED for task in workflow.tasks.values()):
workflow.status = WorkflowStatus.COMPLETED
else:
workflow.status = WorkflowStatus.FAILED
execution_record = {
"workflow_id": workflow_id,
"status": workflow.status.value,
"duration": workflow.end_time - workflow.start_time,
"results": results,
}
self.execution_history.append(execution_record)
return results
def _get_ready_tasks(
self, workflow: Workflow, executed: set
) -> List[str]:
"""Get tasks ready to execute."""
ready = []
for task_id, task in workflow.tasks.items():
if task_id not in executed and task.status == TaskStatus.PENDING:
# Check if all dependencies are complete
deps_met = all(dep in executed for dep in task.dependencies)
if deps_met:
ready.append(task_id)
return ready
def get_workflow_status(self, workflow_id: str) -> Dict[str, Any]:
"""Get workflow status."""
workflow = self.workflows[workflow_id]
return {
"id": workflow.workflow_id,
"name": workflow.name,
"status": workflow.status.value,
"tasks": {
task_id: task.status.value
for task_id, task in workflow.tasks.items()
},
}
class WorkflowOptimizer:
"""Optimize workflow execution."""
@staticmethod
def analyze_dependencies(workflow: Workflow) -> Dict[str, Any]:
"""Analyze task dependencies."""
dep_graph = {}
for task_id, task in workflow.tasks.items():
dep_graph[task_id] = task.dependencies
# Find critical path
critical_path = WorkflowOptimizer._find_critical_path(
dep_graph, workflow.tasks
)
# Find parallelizable tasks
parallel_groups = WorkflowOptimizer._find_parallel_groups(dep_graph)
return {
"dependency_graph": dep_graph,
"critical_path": critical_path,
"parallelizable_groups": parallel_groups,
}
@staticmethod
def _find_critical_path(dep_graph: Dict, tasks: Dict) -> List[str]:
"""Find tasks on critical path."""
# Simple implementation - actual critical path is more complex
return list(dep_graph.keys())
@staticmethod
def _find_parallel_groups(dep_graph: Dict) -> List[List[str]]:
"""Find groups of tasks that can execute in parallel."""
groups = []
remaining = set(dep_graph.keys())
while remaining:
# Find tasks with no dependencies in remaining set
independent = [
task
for task in remaining
if not any(dep in remaining for dep in dep_graph.get(task, []))
]
if independent:
groups.append(independent)
remaining -= set(independent)
else:
break
return groups
@staticmethod
def estimate_execution_time(
workflow: Workflow, task_times: Dict[str, float]
) -> float:
"""Estimate total execution time."""
parallel_groups = WorkflowOptimizer._find_parallel_groups({
task_id: task.dependencies
for task_id, task in workflow.tasks.items()
})
total_time = 0
for group in parallel_groups:
group_time = max(
task_times.get(task_id, 1.0) for task_id in group
)
total_time += group_time
return total_time
@staticmethod
def suggest_parallelization(workflow: Workflow) -> List[Dict[str, Any]]:
"""Suggest ways to parallelize workflow."""
suggestions = []
dep_graph = {
task_id: task.dependencies
for task_id, task in workflow.tasks.items()
}
# Find sequential chains that could be parallelized
for task_id, dependencies in dep_graph.items():
if len(dependencies) == 0:
suggestions.append({
"task": task_id,
"suggestion": "Can be parallelized with other independent tasks",
})
return suggestions
class WorkflowMonitor:
"""Monitor workflow execution."""
def __init__(self):
"""Initialize monitor."""
self.events: List[Dict] = []
def record_event(
self, workflow_id: str, task_id: str, event_type: str, data: Dict
) -> None:
"""Record workflow event."""
event = {
"workflow_id": workflow_id,
"task_id": task_id,
"event_type": event_type,
"timestamp": time.time(),
"data": data,
}
self.events.append(event)
def get_workflow_metrics(self, workflow_id: str) -> Dict[str, Any]:
"""Get workflow metrics."""
workflow_events = [e for e in self.events if e["workflow_id"] == workflow_id]
task_times = {}
for event in workflow_events:
task_id = event["task_id"]
if event["event_type"] == "start":
task_times[task_id] = {"start": event["timestamp"]}
elif event["event_type"] == "complete":
if task_id in task_times:
task_times[task_id]["end"] = event["timestamp"]
# Calculate durations
durations = {
task_id: times.get("end", time.time()) - times["start"]
for task_id, times in task_times.items()
}
return {
"total_tasks": len(task_times),
"task_durations": durations,
"avg_duration": sum(durations.values()) / len(durations)
if durations
else 0,
"max_duration": max(durations.values()) if durations else 0,
}
def get_performance_report(self) -> Dict[str, Any]:
"""Get overall performance report."""
if not self.events:
return {"status": "no_events"}
workflow_ids = set(e["workflow_id"] for e in self.events)
report = {}
for workflow_id in workflow_ids:
report[workflow_id] = self.get_workflow_metrics(workflow_id)
return report
---
name: multi-agent-orchestration
description: Design and coordinate multi-agent systems where specialized agents work together to solve complex problems. Covers agent communication, task delegation, workflow orchestration, and result aggregation. Use when building coordinated agent teams, complex workflows, or systems requiring specialized expertise across domains.
---
# Multi-Agent Orchestration
Design and orchestrate sophisticated multi-agent systems where specialized agents collaborate to solve complex problems, combining different expertise and perspectives.
## Quick Start
Get started with multi-agent implementations in the examples and utilities:
- **Examples**: See [`examples/`](examples/) directory for complete implementations:
- [`orchestration_patterns.py`](examples/orchestration_patterns.py) - Sequential, parallel, hierarchical, and consensus orchestration
- [`framework_implementations.py`](examples/framework_implementations.py) - Templates for CrewAI, AutoGen, LangGraph, and Swarm
- **Utilities**: See [`scripts/`](scripts/) directory for helper modules:
- [`agent_communication.py`](scripts/agent_communication.py) - Message broker, shared memory, and communication protocols
- [`workflow_management.py`](scripts/workflow_management.py) - Workflow execution, optimization, and monitoring
- [`benchmarking.py`](scripts/benchmarking.py) - Team performance and agent effectiveness metrics
## Overview
Multi-agent systems decompose complex problems into specialized sub-tasks, assigning each to an agent with relevant expertise, then coordinating their work toward a unified goal.
### When Multi-Agent Systems Shine
- **Complex Workflows**: Tasks requiring multiple specialized roles
- **Domain-Specific Expertise**: Finance, legal, HR, engineering need different knowledge
- **Parallel Processing**: Multiple agents work on different aspects simultaneously
- **Collaborative Reasoning**: Agents debate, refine, and improve solutions
- **Resilience**: Failures in one agent don't break the entire system
- **Scalability**: Easy to add new specialized agents
### Architecture Overview
```
User Request
Orchestrator
├→ Agent 1 (Specialist) → Task 1
├→ Agent 2 (Specialist) → Task 2
├→ Agent 3 (Specialist) → Task 3
Result Aggregator
Final Response
```
## Core Concepts
### Agent Definition
An agent is defined by:
- **Role**: What responsibility does it have? (e.g., "Financial Analyst")
- **Goal**: What should it accomplish? (e.g., "Analyze financial risks")
- **Expertise**: What knowledge/tools does it have?
- **Tools**: What capabilities can it access?
- **Context**: What information does it need to work effectively?
### Orchestration Patterns
#### 1. Sequential Orchestration
- Agents work one after another
- Each agent uses output from previous agent
- **Use Case**: Steps must follow order (research → analysis → writing)
#### 2. Parallel Orchestration
- Multiple agents work simultaneously
- Results aggregated at the end
- **Use Case**: Independent tasks (analyze competitors, market, users)
#### 3. Hierarchical Orchestration
- Senior agent delegates to junior agents
- Manager coordinates flow
- **Use Case**: Large projects with oversight
#### 4. Consensus-Based Orchestration
- Multiple agents analyze problem
- Debate and refine ideas
- Vote or reach consensus
- **Use Case**: Complex decisions needing multiple perspectives
#### 5. Tool-Mediated Orchestration
- Agents use shared tools/databases
- Minimal direct communication
- **Use Case**: Large systems, indirect coordination
## Multi-Agent Team Examples
### Finance Team
```
Coordinator Agent
├→ Market Analyst Agent
│ ├ Tools: Market data API, financial news
│ └ Task: Analyze market conditions
├→ Financial Analyst Agent
│ ├ Tools: Financial statements, ratio calculations
│ └ Task: Analyze company financials
├→ Risk Manager Agent
│ ├ Tools: Risk models, scenario analysis
│ └ Task: Assess investment risks
└→ Report Writer Agent
├ Tools: Document generation
└ Task: Synthesize findings into report
```
### Legal Team
```
Case Manager Agent (Coordinator)
├→ Contract Analyzer Agent
│ └ Task: Review contract terms
├→ Precedent Research Agent
│ └ Task: Find relevant case law
├→ Risk Assessor Agent
│ └ Task: Identify legal risks
└→ Document Drafter Agent
└ Task: Prepare legal documents
```
### Customer Support Team
```
Support Coordinator
├→ Issue Classifier Agent
│ └ Task: Categorize customer issue
├→ Knowledge Base Agent
│ └ Task: Find relevant documentation
├→ Escalation Agent
│ └ Task: Determine if human escalation needed
└→ Solution Synthesizer Agent
└ Task: Prepare comprehensive response
```
## Implementation Frameworks
### 1. CrewAI
**Best For**: Teams with clear roles and hierarchical structure
```python
from crewai import Agent, Task, Crew
# Define agents
analyst = Agent(
role="Financial Analyst",
goal="Analyze financial data and provide insights",
backstory="Expert in financial markets with 10+ years experience"
)
researcher = Agent(
role="Market Researcher",
goal="Research market trends and competition",
backstory="Data-driven researcher specializing in market analysis"
)
# Define tasks
analysis_task = Task(
description="Analyze Q3 financial results for {company}",
agent=analyst,
tools=[financial_tool, data_tool]
)
research_task = Task(
description="Research competitive landscape in {market}",
agent=researcher,
tools=[web_search_tool, industry_data_tool]
)
# Create crew and execute
crew = Crew(
agents=[analyst, researcher],
tasks=[analysis_task, research_task],
process=Process.sequential
)
result = crew.kickoff(inputs={"company": "TechCorp", "market": "AI"})
```
### 2. AutoGen (Microsoft)
**Best For**: Complex multi-turn conversations and negotiations
```python
from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager
# Define agents
analyst = AssistantAgent(
name="analyst",
system_message="You are a financial analyst..."
)
researcher = AssistantAgent(
name="researcher",
system_message="You are a market researcher..."
)
# Create group chat
groupchat = GroupChat(
agents=[analyst, researcher],
messages=[],
max_round=10,
speaker_selection_method="auto"
)
# Manage group conversation
manager = GroupChatManager(groupchat=groupchat)
# User proxy to initiate conversation
user = UserProxyAgent(name="user")
# Have conversation
user.initiate_chat(
manager,
message="Analyze if Company X should invest in Y market"
)
```
### 3. LangGraph
**Best For**: Complex workflows with state management
```python
from langgraph.graph import Graph, StateGraph
from langgraph.prebuilt import create_agent_executor
# Define state
class AgentState:
research_findings: str
analysis: str
recommendations: str
# Create graph
graph = StateGraph(AgentState)
# Add nodes for each agent
graph.add_node("researcher", research_agent)
graph.add_node("analyst", analyst_agent)
graph.add_node("writer", writer_agent)
# Define edges (workflow)
graph.add_edge("researcher", "analyst")
graph.add_edge("analyst", "writer")
# Set entry/exit points
graph.set_entry_point("researcher")
graph.set_finish_point("writer")
# Compile and run
workflow = graph.compile()
result = workflow.invoke({"topic": "AI trends"})
```
### 4. OpenAI Swarm
**Best For**: Simple agent handoffs and conversational workflows
```python
from swarm import Agent, Swarm
# Define agents
triage_agent = Agent(
name="Triage Agent",
instructions="Determine which specialist to route the customer to"
)
billing_agent = Agent(
name="Billing Specialist",
instructions="Handle billing and payment questions"
)
technical_agent = Agent(
name="Technical Support",
instructions="Handle technical issues"
)
# Define handoff functions
def route_to_billing(reason: str):
return billing_agent
def route_to_technical(reason: str):
return technical_agent
# Add tools to triage agent
triage_agent.functions = [route_to_billing, route_to_technical]
# Execute swarm
client = Swarm()
response = client.run(
agent=triage_agent,
messages=[{"role": "user", "content": "I have a billing question"}]
)
```
## Orchestration Patterns
### Pattern 1: Sequential Task Chain
Agents execute tasks in sequence, each building on previous results:
```python
# Task 1: Research
research_output = research_agent.work("Analyze AI market trends")
# Task 2: Analysis (uses research output)
analysis = analyst_agent.work(f"Analyze these findings: {research_output}")
# Task 3: Report (uses analysis)
report = writer_agent.work(f"Write report on: {analysis}")
```
**When to Use**: Steps have dependencies, each builds on previous
### Pattern 2: Parallel Execution
Multiple agents work simultaneously, results combined:
```python
import asyncio
async def parallel_teams():
# All agents work in parallel
market_task = market_agent.work_async("Analyze market")
technical_task = tech_agent.work_async("Analyze technology")
user_task = user_agent.work_async("Analyze user needs")
# Wait for all to complete
market_results, tech_results, user_results = await asyncio.gather(
market_task, technical_task, user_task
)
# Synthesize results
return synthesize(market_results, tech_results, user_results)
```
**When to Use**: Independent analyses, need quick results, want diversity
### Pattern 3: Hierarchical Structure
Manager agent coordinates specialists:
```python
manager_agent.orchestrate({
"market_analysis": {
"agents": [competitor_analyst, trend_analyst],
"task": "Comprehensive market analysis"
},
"technical_evaluation": {
"agents": [architecture_agent, security_agent],
"task": "Technical feasibility assessment"
},
"synthesis": {
"agents": [strategy_agent],
"task": "Create strategic recommendations"
}
})
```
**When to Use**: Clear hierarchy, different teams, complex coordination
### Pattern 4: Debate & Consensus
Multiple agents discuss and reach consensus:
```python
agents = [bull_agent, bear_agent, neutral_agent]
question = "Should we invest in this startup?"
# Debate round 1
arguments = {agent: agent.argue(question) for agent in agents}
# Debate round 2 (respond to others)
counter_arguments = {
agent: agent.respond(arguments) for agent in agents
}
# Reach consensus
consensus = mediator_agent.synthesize_consensus(counter_arguments)
```
**When to Use**: Complex decisions, need multiple perspectives, risk assessment
## Agent Communication Patterns
### 1. Direct Communication
Agents pass messages directly to each other:
```python
agent_a.send_message(agent_b, {
"type": "request",
"action": "analyze_document",
"document": doc_content,
"context": {"deadline": "urgent"}
})
```
### 2. Tool-Mediated Communication
Agents use shared tools/databases:
```python
# Agent A writes to shared memory
shared_memory.write("findings", {"market_size": "$5B", "growth": "20%"})
# Agent B reads from shared memory
findings = shared_memory.read("findings")
```
### 3. Manager-Based Communication
Central coordinator manages agent communication:
```python
manager.broadcast("update_all_agents", {
"new_deadline": "tomorrow",
"priority": "critical"
})
```
## Best Practices
### Agent Design
- ✓ Clear, specific role and goal
- ✓ Appropriate tools for the role
- ✓ Relevant background/expertise
- ✓ Distinct from other agents
- ✓ Reasonable scope of work
### Workflow Design
- ✓ Clear task dependencies
- ✓ Identified handoff points
- ✓ Error handling between agents
- ✓ Fallback strategies
- ✓ Performance monitoring
### Communication
- ✓ Structured message formats
- ✓ Clear context sharing
- ✓ Error propagation strategy
- ✓ Timeout handling
- ✓ Audit logging
### Orchestration
- ✓ Define process clearly (sequential, parallel, etc.)
- ✓ Set clear success criteria
- ✓ Monitor agent performance
- ✓ Implement feedback loops
- ✓ Allow human intervention points
## Common Challenges & Solutions
### Challenge: Agent Conflicts
**Solutions**:
- Clear role separation
- Explicit decision-making rules
- Consensus mechanisms
- Conflict resolution agent
- Clear authority hierarchy
### Challenge: Slow Execution
**Solutions**:
- Use parallel execution where possible
- Cache results from expensive operations
- Pre-process data
- Optimize agent logic
- Implement timeout handling
### Challenge: Poor Quality Results
**Solutions**:
- Better agent prompts/instructions
- More relevant tools
- Feedback integration
- Quality validation agents
- Result aggregation strategies
### Challenge: Complex Workflows
**Solutions**:
- Break into smaller teams
- Hierarchical structure
- Clear task definitions
- Good state management
- Documentation of workflow
## Evaluation Metrics
**Team Performance**:
- Task completion rate
- Quality of results
- Execution time
- Cost (tokens/API calls)
- Error rate
**Agent Effectiveness**:
- Task success rate
- Response quality
- Tool usage efficiency
- Communication clarity
- Collaboration score
## Advanced Techniques
### 1. Self-Organizing Teams
Agents autonomously decide roles and workflow:
```python
# Agents negotiate roles based on task
agents = [agent1, agent2, agent3]
task = "complex financial analysis"
# Agents determine best structure
negotiated_structure = self_organize(agents, task)
# Returns optimal workflow for this task
```
### 2. Adaptive Workflows
Workflow changes based on progress:
```python
# Monitor progress
if progress < expected_rate:
# Increase resources
workflow.add_agent(specialist_agent)
elif quality < threshold:
# Increase validation
workflow.insert_review_step()
```
### 3. Cross-Agent Learning
Agents learn from each other's work:
```python
# After team execution
execution_trace = crew.get_execution_trace()
# Extract learnings
learnings = extract_patterns(execution_trace)
# Update agent knowledge
for agent, learning in learnings.items():
agent.update_knowledge(learning)
```
## Resources
### Frameworks
- **CrewAI**: https://crewai.com/
- **AutoGen**: https://microsoft.github.io/autogen/
- **LangGraph**: https://langchain-ai.github.io/langgraph/
- **Swarm**: https://github.com/openai/swarm
### Papers
- "Generative Agents" (Park et al.)
- "Self-Organizing Multi-Agent Systems" (research papers)
## Implementation Checklist
- [ ] Define each agent's role, goal, and expertise
- [ ] Identify available tools/capabilities for each agent
- [ ] Plan workflow (sequential, parallel, hierarchical)
- [ ] Define communication patterns
- [ ] Implement task definitions
- [ ] Set success criteria for each task
- [ ] Add error handling and fallbacks
- [ ] Implement monitoring/logging
- [ ] Test team collaboration
- [ ] Evaluate quality and performance
- [ ] Optimize based on results
- [ ] Document workflow and decisions
## Getting Started
1. **Start Small**: Begin with 2-3 agents
2. **Clear Workflow**: Document how agents interact
3. **Test Thoroughly**: Validate agent behavior individually and together
4. **Monitor Closely**: Track performance and results
5. **Iterate**: Refine based on results
6. **Scale**: Add agents and complexity as needed
# PageSpeed Insights — Reference & Official Documentation
This file complements the pagespeed-insights skill with official documentation links for indexing.
## Official documentation (indexable)
- **PageSpeed Insights about**: https://developers.google.com/speed/docs/insights/v5/about?hl=es-419
- **PageSpeed Insights (tool)**: https://pagespeed.web.dev/
- **Lighthouse**: https://developer.chrome.com/docs/lighthouse/
- **Core Web Vitals**: https://web.dev/vitals/
- **Chrome User Experience Report (CrUX)**: https://developer.chrome.com/docs/crux/
## Core Web Vitals (metrics)
- **LCP (Largest Contentful Paint)**: https://web.dev/lcp/
- **FCP (First Contentful Paint)**: https://web.dev/fcp/
- **CLS (Cumulative Layout Shift)**: https://web.dev/cls/
- **INP (Interaction to Next Paint)**: https://web.dev/inp/
- **TTFB (Time to First Byte)**: https://web.dev/ttfb/
## Lab vs field data
- **Lab data**: Lighthouse, controlled environment, debugging
- **Field data**: CrUX, real user metrics, 28-day aggregation
- **Understanding metrics**: https://web.dev/metrics/
## Performance optimization guides
- **Optimize LCP**: https://web.dev/optimize-lcp/
- **Optimize CLS**: https://web.dev/optimize-cls/
- **Optimize INP**: https://web.dev/optimize-inp/
- **Optimize FCP**: https://web.dev/optimize-fcp/
- **Resource hints**: https://web.dev/preconnect-and-dns-prefetch/
- **Image optimization**: https://web.dev/fast/#optimize-your-images
## Tools
- **PageSpeed Insights**: https://pagespeed.web.dev/
- **Lighthouse (Chrome DevTools)**: Built-in, Audits tab
- **Web Vitals extension**: Real-time monitoring
- **Chromatic (Lighthouse CI)**: https://github.com/GoogleChrome/lighthouse-ci
## Score thresholds (reminder)
| Category | Good | Needs Improvement | Poor |
|----------|------|-------------------|------|
| Performance | 90-100 | 50-89 | 0-49 |
| Accessibility | 90-100 | 50-89 | 0-49 |
| Best Practices | 90-100 | 50-89 | 0-49 |
| SEO | 90-100 | 50-89 | 0-49 |
---
name: pagespeed-insights
description: Audit web pages for performance optimization following PageSpeed Insights guidelines. Use when analyzing page performance, optimizing web applications, reviewing performance metrics, implementing Core Web Vitals improvements, or when the user mentions page speed, performance optimization, Lighthouse scores, or Core Web Vitals.
---
# PageSpeed Insights Auditor
## Overview
You are a **PageSpeed Insights Auditor** - an expert in web performance optimization who helps developers achieve excellent PageSpeed scores by identifying performance issues, avoiding bad practices, and implementing best practices based on Google's PageSpeed Insights guidelines.
**Core Principle**: Guide developers to achieve scores of 90+ (Good) in Performance, Accessibility, Best Practices, and SEO categories, while ensuring Core Web Vitals metrics meet the "Good" thresholds.
## Understanding PageSpeed Insights
PageSpeed Insights (PSI) analyzes page performance on mobile and desktop devices, providing both **lab data** (simulated) and **field data** (real user experiences). PSI reports on user experience metrics and provides diagnostic suggestions to improve page performance.
### Two Types of Data
1. **Lab Data**: Collected in a controlled environment using Lighthouse. Useful for debugging but may not capture real-world bottlenecks.
2. **Field Data**: Real user experience data from Chrome User Experience Report (CrUX). Useful for capturing actual user experiences but has a more limited set of metrics.
## Performance Score Thresholds
### Lab Scores (Lighthouse)
| Score Range | Rating | Icon |
| ----------- | ----------------- | --------------- |
| 90-100 | Good | 🟢 Green circle |
| 50-89 | Needs Improvement | 🟡 Amber square |
| 0-49 | Poor | 🔴 Red triangle |
**Target**: Always aim for scores of **90 or higher** in all categories.
### Core Web Vitals Thresholds
Core Web Vitals are the three most important metrics for web performance:
| Metric | Good | Needs Improvement | Poor |
| ----------------------------------- | ------------ | ------------------ | --------- |
| **FCP** (First Contentful Paint) | [0, 1800 ms] | [1800 ms, 3000 ms] | > 3000 ms |
| **LCP** (Largest Contentful Paint) | [0, 2500 ms] | [2500 ms, 4000 ms] | > 4000 ms |
| **CLS** (Cumulative Layout Shift) | [0, 0.1] | [0.1, 0.25] | > 0.25 |
| **INP** (Interaction to Next Paint) | [0, 200 ms] | [200 ms, 500 ms] | > 500 ms |
| **TTFB** (Time to First Byte) | [0, 800 ms] | [800 ms, 1800 ms] | > 1800 ms |
**Target**: Ensure the 75th percentile of all Core Web Vitals metrics are in the "Good" range.
## Key Performance Metrics
### Lab Metrics (Lighthouse)
1. **First Contentful Paint (FCP)**: Time until first content is rendered
2. **Largest Contentful Paint (LCP)**: Time until largest content element is rendered
3. **Speed Index**: How quickly content is visually displayed
4. **Cumulative Layout Shift (CLS)**: Visual stability measure
5. **Total Blocking Time (TBT)**: Sum of blocking time between FCP and TTI
6. **Time to Interactive (TTI)**: Time until page is fully interactive
### Field Metrics (CrUX)
- **FCP**: First Contentful Paint from real users
- **LCP**: Largest Contentful Paint from real users
- **CLS**: Cumulative Layout Shift from real users
- **INP**: Interaction to Next Paint (replaces FID)
- **TTFB**: Time to First Byte (experimental)
## Common Performance Issues & Solutions
### ❌ Bad Practice: Unoptimized Images
**Problem**: Large images without compression, modern formats, or proper sizing.
**Impact**: Poor LCP scores, slow page loads.
**✅ Solutions**:
- Use modern image formats (WebP, AVIF)
- Implement responsive images with `srcset`
- Compress images before uploading
- Set explicit width/height to prevent CLS
- Use lazy loading for below-the-fold images
```html
<!-- Bad -->
<img src="large-image.jpg" alt="Description" />
<!-- Good -->
<img
src="image.webp"
srcset="image-small.webp 400w, image-medium.webp 800w, image-large.webp 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
width="1200"
height="800"
alt="Description"
loading="lazy"
/>
```
### ❌ Bad Practice: Render-Blocking Resources
**Problem**: CSS and JavaScript blocking initial render.
**Impact**: Poor FCP and LCP scores.
**✅ Solutions**:
- Defer non-critical CSS
- Inline critical CSS
- Use `async` or `defer` for JavaScript
- Remove unused CSS/JS
- Split code and lazy load routes
```html
<!-- Bad -->
<link rel="stylesheet" href="styles.css" />
<script src="app.js"></script>
<!-- Good -->
<link
rel="stylesheet"
href="styles.css"
media="print"
onload="this.media='all'"
/>
<link rel="preload" href="critical.css" as="style" />
<script src="app.js" defer></script>
```
### ❌ Bad Practice: Missing Resource Hints
**Problem**: Not preconnecting to important origins or prefetching critical resources.
**Impact**: Slow TTFB and LCP.
**✅ Solutions**:
- Use `rel="preconnect"` for third-party origins
- Use `rel="dns-prefetch"` for DNS resolution
- Use `rel="preload"` for critical resources
- Use `rel="prefetch"` for likely next-page resources
```html
<!-- Good -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="dns-prefetch" href="https://api.example.com" />
<link rel="preload" href="hero-image.webp" as="image" />
```
### ❌ Bad Practice: Layout Shift (CLS)
**Problem**: Content shifting during page load.
**Impact**: Poor CLS scores, bad user experience.
**✅ Solutions**:
- Set explicit dimensions for images and videos
- Reserve space for ads and embeds
- Avoid inserting content above existing content
- Use CSS aspect-ratio for responsive containers
- Prefer transform animations over layout-triggering properties
```css
/* Bad */
.image-container {
width: 100%;
/* height not set - causes CLS */
}
/* Good */
.image-container {
width: 100%;
aspect-ratio: 16 / 9;
/* or */
height: 0;
padding-bottom: 56.25%; /* 16:9 ratio */
}
```
### ❌ Bad Practice: Large JavaScript Bundles
**Problem**: Loading unnecessary JavaScript code.
**Impact**: Poor TTI, high TBT.
**✅ Solutions**:
- Code splitting and lazy loading
- Remove unused code (tree shaking)
- Minimize and compress JavaScript
- Use dynamic imports for routes
- Avoid large third-party libraries when possible
```javascript
// Bad - loading everything upfront
import { heavyLibrary } from "./heavy-library";
// Good - lazy load when needed
const loadHeavyLibrary = () => import("./heavy-library");
```
### ❌ Bad Practice: Inefficient Font Loading
**Problem**: Fonts causing FOIT (Flash of Invisible Text) or FOUT (Flash of Unstyled Text).
**Impact**: Poor FCP, layout shifts.
**✅ Solutions**:
- Use `font-display: swap` or `optional`
- Preload critical fonts
- Subset fonts to include only needed characters
- Use system fonts when possible
```css
/* Good */
@font-face {
font-family: "CustomFont";
src: url("font.woff2") format("woff2");
font-display: swap; /* or optional */
}
```
### ❌ Bad Practice: No Caching Strategy
**Problem**: Resources not cached, causing repeated downloads.
**Impact**: Slow repeat visits, poor performance.
**✅ Solutions**:
- Set appropriate Cache-Control headers
- Use service workers for offline caching
- Implement HTTP/2 server push for critical resources
- Use CDN for static assets
```
Cache-Control: public, max-age=31536000, immutable
```
### ❌ Bad Practice: Third-Party Scripts Blocking Render
**Problem**: Analytics, ads, or widgets blocking page load.
**Impact**: Poor TTI, high TBT.
**✅ Solutions**:
- Load third-party scripts asynchronously
- Defer non-critical third-party code
- Use `rel="noopener"` for external links
- Consider self-hosting analytics when possible
```html
<!-- Good -->
<script async src="https://www.google-analytics.com/analytics.js"></script>
```
## Accessibility Best Practices
### ❌ Bad Practice: Missing Alt Text
**Problem**: Images without descriptive alt attributes.
**Impact**: Poor accessibility score.
**✅ Solution**: Always provide meaningful alt text.
```html
<!-- Bad -->
<img src="chart.png" />
<!-- Good -->
<img src="chart.png" alt="Sales increased 25% from Q1 to Q2" />
```
### ❌ Bad Practice: Poor Color Contrast
**Problem**: Text not readable due to low contrast.
**Impact**: Poor accessibility score.
**✅ Solution**: Ensure contrast ratio of at least 4.5:1 for normal text, 3:1 for large text.
### ❌ Bad Practice: Missing ARIA Labels
**Problem**: Interactive elements without proper labels.
**Impact**: Poor accessibility score.
**✅ Solution**: Use ARIA labels for screen readers.
```html
<!-- Good -->
<button aria-label="Close dialog">×</button>
```
## SEO Best Practices
### ❌ Bad Practice: Missing Meta Tags
**Problem**: No title, description, or viewport meta tags.
**Impact**: Poor SEO score.
**✅ Solution**: Include essential meta tags.
```html
<!-- Good -->
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Page description" />
<title>Page Title</title>
```
### ❌ Bad Practice: Non-Descriptive Links
**Problem**: Links with generic text like "click here".
**Impact**: Poor SEO score.
**✅ Solution**: Use descriptive link text.
```html
<!-- Bad -->
<a href="/about">Click here</a>
<!-- Good -->
<a href="/about">Learn more about our company</a>
```
## Best Practices Checklist
### Performance
- [ ] Images optimized (WebP/AVIF, compressed, responsive)
- [ ] Critical CSS inlined
- [ ] Non-critical CSS deferred
- [ ] JavaScript code-split and lazy-loaded
- [ ] Render-blocking resources minimized
- [ ] Resource hints implemented (preconnect, preload, dns-prefetch)
- [ ] Fonts optimized with font-display
- [ ] Caching strategy implemented
- [ ] Third-party scripts loaded asynchronously
- [ ] Layout shifts prevented (explicit dimensions, aspect-ratio)
### Core Web Vitals
- [ ] LCP < 2.5 seconds (75th percentile)
- [ ] FCP < 1.8 seconds (75th percentile)
- [ ] CLS < 0.1 (75th percentile)
- [ ] INP < 200ms (75th percentile)
- [ ] TTFB < 800ms (75th percentile)
### Accessibility
- [ ] All images have alt text
- [ ] Color contrast meets WCAG standards
- [ ] ARIA labels on interactive elements
- [ ] Semantic HTML used
- [ ] Keyboard navigation supported
### SEO
- [ ] Meta tags present (title, description, viewport)
- [ ] Descriptive link text
- [ ] Proper heading hierarchy (h1-h6)
- [ ] Structured data implemented
- [ ] Mobile-friendly design
## Audit Workflow
When auditing a page for PageSpeed optimization:
1. **Analyze Current State**
- Check current PageSpeed scores
- Identify Core Web Vitals metrics
- Review lab and field data differences
2. **Identify Issues**
- List all performance problems
- Prioritize by impact (Core Web Vitals first)
- Categorize by type (images, JS, CSS, etc.)
3. **Provide Solutions**
- Suggest specific optimizations
- Provide code examples
- Explain expected improvements
4. **Verify Improvements**
- Re-test after changes
- Ensure scores reach 90+
- Confirm Core Web Vitals are "Good"
## Common Mistakes to Avoid
### ❌ Focusing Only on Lab Data
**Problem**: Optimizing only for Lighthouse scores without considering real user data.
**✅ Solution**: Balance both lab and field data. Field data shows real-world performance.
### ❌ Over-Optimizing
**Problem**: Implementing too many optimizations at once, making debugging difficult.
**✅ Solution**: Make incremental changes and test after each optimization.
### ❌ Ignoring Mobile Performance
**Problem**: Optimizing only for desktop.
**✅ Solution**: Mobile-first approach. Most users are on mobile devices.
### ❌ Not Testing After Changes
**Problem**: Assuming optimizations worked without verification.
**✅ Solution**: Always re-run PageSpeed Insights after implementing changes.
## Performance Optimization Priority
1. **Critical Path**: Optimize resources needed for initial render
2. **Core Web Vitals**: Focus on LCP, CLS, and INP first
3. **Render-Blocking**: Eliminate blocking CSS and JS
4. **Images**: Optimize largest contentful paint element
5. **Third-Party**: Minimize impact of external scripts
6. **Caching**: Implement proper caching strategies
## Additional Resources
- [reference.md](reference.md) — Official PageSpeed, Lighthouse, Core Web Vitals, optimization guides — indexable
- **Official**: https://developers.google.com/speed/docs/insights/v5/about?hl=es-419
- **PageSpeed Insights**: https://pagespeed.web.dev/
- **Lighthouse**: Built into Chrome DevTools
- **Web Vitals**: https://web.dev/vitals/
## Specification Reference
This skill is based on the official [PageSpeed Insights documentation](https://developers.google.com/speed/docs/insights/v5/about?hl=es-419) from Google Developers.
All thresholds, metrics, and best practices in this skill follow the official PageSpeed Insights guidelines and Core Web Vitals specifications. For complete documentation, refer to the [official PageSpeed Insights documentation](https://developers.google.com/speed/docs/insights/v5/about?hl=es-419).
---
id: pagespeed-perf
version: 1.0.0
name: PageSpeed Performance Audit
description: >
Web Performance Engineering — analyzes Core Web Vitals using the PageSpeed
Insights API (PSI v5) and applies the 80/20 principle: identify the 20% of
changes that produce 80% of the performance gain. Produces a prioritized
markdown report with quantified estimates and framework-specific code.
Trigger: When auditing page speed, analyzing Core Web Vitals, or optimizing
web performance for any URL.
user-invokable: true
license: MIT
metadata:
author: codeconductor
category: performance
compatibility:
tools: [claude, codex, gemini, agy, opencode]
stacks:
languages: []
frameworks: [astro, nextjs, react, vue, django, spring, wordpress]
risk:
level: medium
can_execute_shell: true
can_modify_files: false
requires_network: true
inputs:
- name: url
type: string
required: true
description: Full URL to audit (must include scheme: https://...)
- name: strategy
type: string
required: false
description: "mobile | desktop | both (default: both)"
outputs:
- name: report
type: markdown
description: >
Prioritized performance report saved as
{YYYY-MM-DD}_pagespeed-{hostname}-claude.md in the current directory.
quality:
reviewed_by: codeconductor-core
version: 1.0.0
---
# PageSpeed Performance Audit — Web Performance Engineering (80/20)
## Role and Purpose
Act as **Senior Web Performance Engineer, Frontend Architect, and Technical
Auditor**.
Always access the real site, measure real metrics via the PageSpeed Insights
API, analyze resources with the greatest impact, and produce a prioritized
Spanish-language report following the 80/20 principle: the **20% of critical
changes that produce 80% of the performance improvement**.
Never give generic recommendations. Every finding must be backed by data
observed from the specific URL being audited.
---
## Step 0 — Pre-flight: API Key and Output Filename
**MANDATORY. Execute before any analysis.**
### 1. Read the API key from the environment
```powershell
$env:PAGESPEED_API_KEY
```
- Value present → store as `{API_KEY}`, use in all PSI calls.
- Empty → proceed without key (CrUX field data unavailable; rate limits apply).
### 2. Define the output filename
```powershell
$date = (Get-Date -Format "yyyy-MM-dd")
$website = ([System.Uri]"{URL}").Host -replace '[^a-zA-Z0-9]', '-'
$out = "${date}_pagespeed-${website}-claude.md"
Write-Host $out
```
The final report **must** be written to this file.
---
## Data Collection
### Primary Method — Bun Scripts (always try first)
```powershell
bun --version # if available, use Primary Method; otherwise use Fallback
$skillDir = "$env:USERPROFILE\.claude\skills\pagespeed-perf\scripts"
bun run "$skillDir\run.ts" --url={URL}
```
`run.ts` calls `psi-collect.ts` and `html-audit.ts` in parallel and returns
structured JSON. Key output fields:
```
output.summary.mobileScore → Lighthouse mobile score (0-100)
output.summary.desktopScore → Lighthouse desktop score
output.summary.passesCWV → boolean — passes real CWV
output.summary.top5Actions → array ordered by 80/20 score
output.psi.mobile.lab.lcp → LCP (lab, mobile)
output.psi.mobile.lab.tbt → TBT
output.psi.mobile.lab.cls → CLS
output.psi.mobile.lab.fcp → FCP
output.psi.mobile.lab.ttfb → TTFB
output.psi.mobile.field → CrUX data (null if no key / no data)
output.psi.mobile.opportunities → array ordered by impact80_20 desc
output.psi.mobile.lcpElement → HTML snippet of the LCP element
output.psi.mobile.thirdParties → third-party scripts with blockingTime
output.psi.mobile.usedApiKey → boolean — confirms key was used
output.html.stack → detected framework / CMS
output.html.resourceHints → preloads, preconnects, prefetches
output.html.images → lazy, fetchpriority, list
output.html.scripts → blocking in <head>, third-party list
output.html.fonts → googleFonts, font-display, preloaded
output.html.issues → ordered by impact80_20
```
### Fallback Method — WebFetch (only if Bun unavailable)
```
# With API key (preferred)
https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url={URL}&strategy=mobile&category=performance&key={API_KEY}
https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url={URL}&strategy=desktop&category=performance&key={API_KEY}
# Without key (rate-limited)
https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url={URL}&strategy=mobile&category=performance
```
Key PSI response paths:
```
lighthouseResult.categories.performance.score
lighthouseResult.audits.largest-contentful-paint
lighthouseResult.audits.total-blocking-time
lighthouseResult.audits.cumulative-layout-shift
lighthouseResult.audits.first-contentful-paint
lighthouseResult.audits.server-response-time
lighthouseResult.audits.largest-contentful-paint-element.details.items[0]
lighthouseResult.audits.render-blocking-resources.details.overallSavingsMs
lighthouseResult.audits.unused-javascript.details.overallSavingsBytes
lighthouseResult.audits.third-party-summary.details.items
loadingExperience.metrics.LARGEST_CONTENTFUL_PAINT_MS.percentile (CrUX)
loadingExperience.metrics.INTERACTION_TO_NEXT_PAINT.percentile (CrUX)
loadingExperience.metrics.CUMULATIVE_LAYOUT_SHIFT_SCORE.percentile (CrUX)
loadingExperience.overall_category → "FAST" | "AVERAGE" | "SLOW"
```
Also fetch the site HTML via WebFetch and inspect the `<head>` for resource
hints, lazy loading, `fetchpriority`, `font-display`, blocking scripts, and
images without explicit dimensions.
---
## Core Web Vitals — Thresholds
| Metric | Good | Needs Improvement | Critical | Score weight |
| ------ | -------- | ----------------- | --------- | ------------ |
| LCP | ≤ 2.5 s | 2.5 s – 4.0 s | > 4.0 s | 25% |
| INP | ≤ 200 ms | 200 ms – 500 ms | > 500 ms | 10% |
| CLS | ≤ 0.1 | 0.1 – 0.25 | > 0.25 | 15% |
| FCP | ≤ 1.8 s | 1.8 s – 3.0 s | > 3.0 s | 10% |
| TBT | ≤ 200 ms | 200 ms – 600 ms | > 600 ms | 30% |
| TTFB | ≤ 800 ms | 800 ms – 1.8 s | > 1.8 s | — |
LCP + TBT represent 55% of the Lighthouse Performance Score.
---
## 80/20 Optimization Matrix
Score = `Impact (1–5) × Ease (1–5)`. Prioritize by descending score.
| Rank | Optimization | Primary metric | Impact | Ease | Score |
| ---- | --------------------------------- | -------------- | ------ | ---- | ----- |
| 1 | Preload LCP element | LCP | 5 | 5 | **25** |
| 1 | `fetchpriority="high"` on LCP img | LCP | 5 | 5 | **25** |
| 1 | Gzip / Brotli compression | FCP, LCP, TBT | 5 | 5 | **25** |
| 4 | WebP + explicit dimensions | LCP, CLS | 5 | 4 | **20** |
| 4 | Lazy loading offscreen images | LCP, TBT | 4 | 5 | **20** |
| 4 | `font-display: swap` | FCP | 4 | 5 | **20** |
| 4 | `preconnect` to critical origins | FCP, LCP, TTFB | 4 | 5 | **20** |
| 4 | Defer / facade third-party scripts| TBT, INP | 5 | 4 | **20** |
| 9 | Remove render-blocking resources | FCP, LCP | 5 | 3 | **15** |
| 9 | Long Cache-Control for assets | repeat visits | 3 | 5 | **15** |
| 11 | Remove unused JavaScript | TBT, INP | 4 | 3 | **12** |
| 12 | Remove unused CSS | FCP, TBT | 3 | 3 | **9** |
| 13 | CDN for static assets | TTFB, LCP | 4 | 2 | **8** |
| 14 | Code splitting | TBT, INP | 4 | 2 | **8** |
**Critical 20% (Score ≥ 20)** — address these first:
1. Preload LCP element + `fetchpriority="high"`
2. Brotli/Gzip compression at the server
3. WebP images with explicit `width`/`height`
4. Lazy loading of offscreen images
5. `font-display: swap` for all fonts
6. `preconnect` to all critical origins
7. Defer or facade all third-party scripts
---
## Expected Impact by Optimization
| Optimization | Metric | Expected gain |
| ---------------------- | -------- | --------------------- |
| Preload + fetchpriority| LCP | −0.5 s to −2.0 s |
| Brotli compression | FCP, LCP | −0.3 s to −1.0 s |
| WebP + dimensions | LCP, CLS | −0.3 s to −1.2 s |
| Lazy loading | LCP | −0.2 s to −0.8 s |
| font-display: swap | FCP | −0.2 s to −0.8 s |
| preconnect | FCP, LCP | −0.1 s to −0.4 s each|
| Defer third parties | TBT, INP | −50 ms to −300 ms |
---
## Report Format (mandatory structure)
Save to `{YYYY-MM-DD}_pagespeed-{hostname}-claude.md`:
```markdown
# Auditoría de Rendimiento Web — {URL}
Fecha: {YYYY-MM-DD} | Estrategia: Móvil + Escritorio | Archivo: {filename}.md
## Resumen Ejecutivo
[2-3 párrafos: estado actual, score, bottleneck principal, potencial de mejora]
## Métricas Actuales
[Tabla: Lab (Lighthouse) vs Campo (CrUX)]
## Recursos con Mayor Impacto
[Tabla: URL, Tipo, Tamaño, Tiempo, Impacto, Razón]
## Plan de Acción Priorizado (80/20)
[Tabla ordenada por Score 80/20 descendente]
## Solución Técnica Detallada
[Por hallazgo: Problema, Evidencia, Implementación, Código, Impacto Esperado]
## Quick Wins (< 1 day)
## High Impact Changes
## Roadmap
- Fase 1 — Inmediato (Semana 1)
- Fase 2 — Corto Plazo (2–4 semanas)
- Fase 3 — Mediano Plazo (1–3 meses)
---
*Informe generado el {YYYY-MM-DD} · Herramienta: Claude Code + pagespeed-perf skill*
*API Key usada: {Sí / No} · Datos CrUX: {Disponibles / No disponibles}*
```
---
## Quality Rules — Never Violate
1. **No data = no recommendation.** If PSI fails, try WebFetch directly.
2. **Always quantify.** "Reduces LCP from 4.2 s to ~3.0 s" — never "would improve LCP".
3. **Explicit evidence.** Cite the observed metric value for every finding.
4. **Site-specific code.** Adapt templates to the detected framework (Next.js,
Astro, Django, etc.). Do not paste generic snippets unchanged.
5. **80/20 order.** Always sort the action plan by descending score.
6. **Separate field vs lab data.** CrUX = real user experience. Lighthouse = controlled lab.
7. **Identify the framework.** Detect Next.js, Astro, Vue, WordPress, etc., and
provide framework-specific code samples.
# workflow-orchestration-patterns — detailed patterns and worked examples
## Critical Design Decision: Workflows vs Activities
**The Fundamental Rule** (Source: temporal.io/blog/workflow-engine-principles):
- **Workflows** = Orchestration logic and decision-making
- **Activities** = External interactions (APIs, databases, network calls)
### Workflows (Orchestration)
**Characteristics:**
- Contain business logic and coordination
- **MUST be deterministic** (same inputs → same outputs)
- **Cannot** perform direct external calls
- State automatically preserved across failures
- Can run for years despite infrastructure failures
**Example workflow tasks:**
- Decide which steps to execute
- Handle compensation logic
- Manage timeouts and retries
- Coordinate child workflows
### Activities (External Interactions)
**Characteristics:**
- Handle all external system interactions
- Can be non-deterministic (API calls, DB writes)
- Include built-in timeouts and retry logic
- **Must be idempotent** (calling N times = calling once)
- Short-lived (seconds to minutes typically)
**Example activity tasks:**
- Call payment gateway API
- Write to database
- Send emails or notifications
- Query external services
### Design Decision Framework
```
Does it touch external systems? → Activity
Is it orchestration/decision logic? → Workflow
```
## Core Workflow Patterns
### 1. Saga Pattern with Compensation
**Purpose**: Implement distributed transactions with rollback capability
**Pattern** (Source: temporal.io/blog/compensating-actions-part-of-a-complete-breakfast-with-sagas):
```
For each step:
1. Register compensation BEFORE executing
2. Execute the step (via activity)
3. On failure, run all compensations in reverse order (LIFO)
```
**Example: Payment Workflow**
1. Reserve inventory (compensation: release inventory)
2. Charge payment (compensation: refund payment)
3. Fulfill order (compensation: cancel fulfillment)
**Critical Requirements:**
- Compensations must be idempotent
- Register compensation BEFORE executing step
- Run compensations in reverse order
- Handle partial failures gracefully
### 2. Entity Workflows (Actor Model)
**Purpose**: Long-lived workflow representing single entity instance
**Pattern** (Source: docs.temporal.io/evaluate/use-cases-design-patterns):
- One workflow execution = one entity (cart, account, inventory item)
- Workflow persists for entity lifetime
- Receives signals for state changes
- Supports queries for current state
**Example Use Cases:**
- Shopping cart (add items, checkout, expiration)
- Bank account (deposits, withdrawals, balance checks)
- Product inventory (stock updates, reservations)
**Benefits:**
- Encapsulates entity behavior
- Guarantees consistency per entity
- Natural event sourcing
### 3. Fan-Out/Fan-In (Parallel Execution)
**Purpose**: Execute multiple tasks in parallel, aggregate results
**Pattern:**
- Spawn child workflows or parallel activities
- Wait for all to complete
- Aggregate results
- Handle partial failures
**Scaling Rule** (Source: temporal.io/blog/workflow-engine-principles):
- Don't scale individual workflows
- For 1M tasks: spawn 1K child workflows × 1K tasks each
- Keep each workflow bounded
### 4. Async Callback Pattern
**Purpose**: Wait for external event or human approval
**Pattern:**
- Workflow sends request and waits for signal
- External system processes asynchronously
- Sends signal to resume workflow
- Workflow continues with response
**Use Cases:**
- Human approval workflows
- Webhook callbacks
- Long-running external processes
## State Management and Determinism
### Automatic State Preservation
**How Temporal Works** (Source: docs.temporal.io/workflows):
- Complete program state preserved automatically
- Event History records every command and event
- Seamless recovery from crashes
- Applications restore pre-failure state
### Determinism Constraints
**Workflows Execute as State Machines**:
- Replay behavior must be consistent
- Same inputs → identical outputs every time
**Prohibited in Workflows** (Source: docs.temporal.io/workflows):
- ❌ Threading, locks, synchronization primitives
- ❌ Random number generation (`random()`)
- ❌ Global state or static variables
- ❌ System time (`datetime.now()`)
- ❌ Direct file I/O or network calls
- ❌ Non-deterministic libraries
**Allowed in Workflows**:
- ✅ `workflow.now()` (deterministic time)
- ✅ `workflow.random()` (deterministic random)
- ✅ Pure functions and calculations
- ✅ Calling activities (non-deterministic operations)
### Versioning Strategies
**Challenge**: Changing workflow code while old executions still running
**Solutions**:
1. **Versioning API**: Use `workflow.get_version()` for safe changes
2. **New Workflow Type**: Create new workflow, route new executions to it
3. **Backward Compatibility**: Ensure old events replay correctly
## Resilience and Error Handling
### Retry Policies
**Default Behavior**: Temporal retries activities forever
**Configure Retry**:
- Initial retry interval
- Backoff coefficient (exponential backoff)
- Maximum interval (cap retry delay)
- Maximum attempts (eventually fail)
**Non-Retryable Errors**:
- Invalid input (validation failures)
- Business rule violations
- Permanent failures (resource not found)
### Idempotency Requirements
**Why Critical** (Source: docs.temporal.io/activities):
- Activities may execute multiple times
- Network failures trigger retries
- Duplicate execution must be safe
**Implementation Strategies**:
- Idempotency keys (deduplication)
- Check-then-act with unique constraints
- Upsert operations instead of insert
- Track processed request IDs
### Activity Heartbeats
**Purpose**: Detect stalled long-running activities
**Pattern**:
- Activity sends periodic heartbeat
- Includes progress information
- Timeout if no heartbeat received
- Enables progress-based retry
---
name: workflow-orchestration-patterns
description: Design durable workflows with Temporal for distributed systems. Covers workflow vs activity separation, saga patterns, state management, and determinism constraints. Use when building long-running processes, distributed transactions, or microservice orchestration.
---
# Workflow Orchestration Patterns
Master workflow orchestration architecture with Temporal, covering fundamental design decisions, resilience patterns, and best practices for building reliable distributed systems.
## When to Use Workflow Orchestration
### Ideal Use Cases (Source: docs.temporal.io)
- **Multi-step processes** spanning machines/services/databases
- **Distributed transactions** requiring all-or-nothing semantics
- **Long-running workflows** (hours to years) with automatic state persistence
- **Failure recovery** that must resume from last successful step
- **Business processes**: bookings, orders, campaigns, approvals
- **Entity lifecycle management**: inventory tracking, account management, cart workflows
- **Infrastructure automation**: CI/CD pipelines, provisioning, deployments
- **Human-in-the-loop** systems requiring timeouts and escalations
### When NOT to Use
- Simple CRUD operations (use direct API calls)
- Pure data processing pipelines (use Airflow, batch processing)
- Stateless request/response (use standard APIs)
- Real-time streaming (use Kafka, event processors)
## Detailed patterns and worked examples
Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.
## Best Practices
### Workflow Design
1. **Keep workflows focused** - Single responsibility per workflow
2. **Small workflows** - Use child workflows for scalability
3. **Clear boundaries** - Workflow orchestrates, activities execute
4. **Test locally** - Use time-skipping test environment
### Activity Design
1. **Idempotent operations** - Safe to retry
2. **Short-lived** - Seconds to minutes, not hours
3. **Timeout configuration** - Always set timeouts
4. **Heartbeat for long tasks** - Report progress
5. **Error handling** - Distinguish retryable vs non-retryable
### Common Pitfalls
**Workflow Violations**:
- Using `datetime.now()` instead of `workflow.now()`
- Threading or async operations in workflow code
- Calling external APIs directly from workflow
- Non-deterministic logic in workflows
**Activity Mistakes**:
- Non-idempotent operations (can't handle retries)
- Missing timeouts (activities run forever)
- No error classification (retry validation errors)
- Ignoring payload limits (2MB per argument)
### Operational Considerations
**Monitoring**:
- Workflow execution duration
- Activity failure rates
- Retry attempts and backoff
- Pending workflow counts
**Scalability**:
- Horizontal scaling with workers
- Task queue partitioning
- Child workflow decomposition
- Activity batching when appropriate
## Additional Resources
**Official Documentation**:
- Temporal Core Concepts: docs.temporal.io/workflows
- Workflow Patterns: docs.temporal.io/evaluate/use-cases-design-patterns
- Best Practices: docs.temporal.io/develop/best-practices
- Saga Pattern: temporal.io/blog/saga-pattern-made-easy
**Key Principles**:
1. Workflows = orchestration, Activities = external calls
2. Determinism is non-negotiable for workflows
3. Idempotency is critical for activities
4. State preservation is automatic
5. Design for failure and recovery
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"env": {
"CLAUDE_CODE_ATTRIBUTION_HEADER": "0",
"CLAUDE_CODE_DISABLE_1M_CONTEXT": "1",
"CLAUDE_CODE_DISABLE_AUTO_MEMORY": "1",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"CLAUDE_CODE_DISABLE_TERMINAL_TITLE": "1",
"DISABLE_EXTRA_USAGE_COMMAND": "1",
"CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT": "1",
"ENABLE_TOOL_SEARCH": "auto",
"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "80",
"DISABLE_BUG_COMMAND": "1"
},
"includeCoAuthoredBy": false,
"includeGitInstructions": false,
"permissions": {
"allow": [
"Bash(git status*)",
"Bash(git diff*)",
"Bash(git log*)",
"Bash(./gradlew test*)",
"Bash(./gradlew build*)",
"Bash(./gradlew check*)",
"Bash(npm test*)",
"Bash(npm run lint*)",
"Bash(ls *)",
"Bash(cat *)",
"Bash(grep *)",
"Bash(rg *)",
"Bash(find *)",
"Bash(tree *)",
"Bash(echo *)",
"Bash(pwd)",
"Bash(which *)",
"Bash(head *)",
"Bash(tail *)",
"Bash(wc *)",
"Bash(diff *)",
"Bash(git branch*)",
"Bash(git show*)",
"Bash(git add*)",
"Bash(git commit*)",
"Bash(git stash*)",
"Bash(git checkout*)",
"Bash(git restore*)",
"Bash(git pull*)",
"Bash(git fetch*)",
"Bash(git merge*)",
"Bash(npm run *)",
"Bash(npm ci)",
"Bash(pnpm run *)",
"Bash(pnpm test*)",
"Bash(pnpm exec *)",
"Bash(pnpm dlx *)",
"Bash(yarn run *)",
"Bash(yarn test*)",
"Bash(npx *)",
"Bash(python *)",
"Bash(python3 *)",
"Bash(pip list*)",
"Bash(pip show *)",
"Bash(pytest*)",
"Bash(ruff*)",
"Bash(black --check *)",
"Bash(./gradlew *)",
"Bash(gradle *)",
"Bash(mvn test*)",
"Bash(mvn compile*)",
"Bash(java -version)",
"Bash(kotlin -version)",
"Bash(docker ps*)",
"Bash(docker logs*)",
"Bash(docker compose ps*)",
"Bash(docker compose logs*)",
"Read(**)",
"Write(./src/**)",
"Write(./app/**)",
"Write(./pages/**)",
"Write(./components/**)",
"Write(./lib/**)",
"Write(./tests/**)",
"Write(./test/**)",
"Write(./__tests__/**)",
"Write(./prisma/**)",
"Write(./drizzle/**)",
"Write(./public/**)",
"Write(./styles/**)",
"Write(./scripts/**)",
"Write(./docs/**)",
"Edit(**)",
"WebFetch(*)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(sudo *)",
"Bash(su *)",
"Bash(chmod 777 *)",
"Bash(chown *)",
"Bash(dd *)",
"Bash(mkfs *)",
"Bash(diskutil *)",
"Bash(mount *)",
"Bash(umount *)",
"Bash(systemctl *)",
"Bash(launchctl *)",
"Bash(curl * | sh)",
"Bash(curl * | bash)",
"Bash(wget * | sh)",
"Bash(wget * | bash)",
"Bash(git push --force*)",
"Bash(git push -f*)",
"Bash(git rebase *)",
"Bash(git reset --hard *)",
"Bash(rm -fr *)",
"Bash(chmod -R *)",
"Bash(eval *)",
"Bash(git push --force origin main*)",
"Bash(git push --force origin master*)",
"Bash(git push -f origin main*)",
"Bash(git push -f origin master*)",
"Read(./.env)",
"Read(./.env.*)",
"Read(./**/.env)",
"Read(./**/.env.*)",
"Read(./secrets/**)",
"Read(./**/credentials.json)",
"Read(./**/serviceAccount*.json)",
"Read(./**/*.pem)",
"Read(./**/*.key)",
"Read(./**/id_rsa*)",
"Read(~/.ssh/**)",
"Read(~/.aws/**)",
"Read(~/.gnupg/**)",
"Write(./.env)",
"Write(./.env.*)",
"Write(./**/.env)",
"Edit(./.env)",
"Edit(./.env.*)",
"Edit(./**/.env)"
],
"ask": [
"Bash(git push*)",
"Bash(git push --force*)",
"Bash(git reset --hard*)",
"Bash(npm install*)",
"Bash(npm i *)",
"Bash(pnpm install*)",
"Bash(pnpm add *)",
"Bash(yarn add *)",
"Bash(pip install*)",
"Bash(docker run*)",
"Bash(docker compose up*)",
"Bash(docker compose down*)",
"Bash(./gradlew build*)",
"Bash(./gradlew bootRun*)",
"Bash(mvn install*)",
"Bash(mvn deploy*)",
"Bash(vercel*)",
"Bash(npx vercel*)"
],
"defaultMode": "acceptEdits"
},
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_INPUT_FILE_PATH\" | grep -qE '\\.(ts|tsx|js|jsx|mjs|cjs|json|jsonc|md|mdx|css|scss|html|astro|yaml|yml)$'; then npx --no-install prettier --write \"$CLAUDE_TOOL_INPUT_FILE_PATH\" 2>/dev/null || true; fi"
},
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_INPUT_FILE_PATH\" | grep -qE '\\.(ts|tsx|js|jsx|mjs|cjs)$'; then npx --no-install eslint --fix \"$CLAUDE_TOOL_INPUT_FILE_PATH\" 2>/dev/null || true; fi"
},
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_INPUT_FILE_PATH\" | grep -qE '\\.py$'; then ruff format \"$CLAUDE_TOOL_INPUT_FILE_PATH\" 2>/dev/null && ruff check --fix \"$CLAUDE_TOOL_INPUT_FILE_PATH\" 2>/dev/null || true; fi"
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_INPUT_COMMAND\" | grep -qE '(\\.env|secrets/|id_rsa|\\.pem|\\.key)\\b' && echo \"$CLAUDE_TOOL_INPUT_COMMAND\" | grep -qE '(cat|less|more|head|tail|cp |mv |scp )'; then echo 'Bloqueado: intento de leer archivos sensibles' >&2; exit 2; fi"
}
]
}
]
},
"extraKnownMarketplaces": {
"agricidaniel-claude-seo": {
"source": {
"source": "github",
"repo": "AgriciDaniel/claude-seo"
}
}
},
"language": "spanish",
"feedbackSurveyRate": 0,
"spinnerTipsEnabled": false,
"alwaysThinkingEnabled": true,
"effortLevel": "xhigh",
"awaySummaryEnabled": false,
"showClearContextOnPlanAccept": true,
"autoUpdatesChannel": "stable",
"prefersReducedMotion": false,
"autoMemoryEnabled": false,
"showThinkingSummaries": true,
"skipDangerousModePermissionPrompt": true,
"editorMode": "vim",
"fileCheckpointingEnabled": true,
"showTurnDuration": true,
"terminalProgressBarEnabled": true,
"autoConnectIde": true,
"autoInstallIdeExtension": false,
"enabledPlugins": {
"claude-seo@agricidaniel-claude-seo": true
}
}
---
name: find-skills
description: Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
---
# Find Skills
This skill helps you discover and install skills from the open agent skills ecosystem.
## When to Use This Skill
Use this skill when the user:
- Asks "how do I do X" where X might be a common task with an existing skill
- Says "find a skill for X" or "is there a skill for X"
- Asks "can you do X" where X is a specialized capability
- Expresses interest in extending agent capabilities
- Wants to search for tools, templates, or workflows
- Mentions they wish they had help with a specific domain (design, testing, deployment, etc.)
## What is the Skills CLI?
The Skills CLI (`npx skills`) is the package manager for the open agent skills ecosystem. Skills are modular packages that extend agent capabilities with specialized knowledge, workflows, and tools.
**Key commands:**
- `npx skills find [query]` - Search for skills interactively or by keyword
- `npx skills add <package>` - Install a skill from GitHub or other sources
- `npx skills check` - Check for skill updates
- `npx skills update` - Update all installed skills
**Browse skills at:** https://skills.sh/
## How to Help Users Find Skills
### Step 1: Understand What They Need
When a user asks for help with something, identify:
1. The domain (e.g., React, testing, design, deployment)
2. The specific task (e.g., writing tests, creating animations, reviewing PRs)
3. Whether this is a common enough task that a skill likely exists
### Step 2: Check the Leaderboard First
Before running a CLI search, check the [skills.sh leaderboard](https://skills.sh/) to see if a well-known skill already exists for the domain. The leaderboard ranks skills by total installs, surfacing the most popular and battle-tested options.
For example, top skills for web development include:
- `vercel-labs/agent-skills` — React, Next.js, web design (100K+ installs each)
- `anthropics/skills` — Frontend design, document processing (100K+ installs)
### Step 3: Search for Skills
If the leaderboard doesn't cover the user's need, run the find command:
```bash
npx skills find [query]
```
For example:
- User asks "how do I make my React app faster?" → `npx skills find react performance`
- User asks "can you help me with PR reviews?" → `npx skills find pr review`
- User asks "I need to create a changelog" → `npx skills find changelog`
### Step 4: Verify Quality Before Recommending
**Do not recommend a skill based solely on search results.** Always verify:
1. **Install count** — Prefer skills with 1K+ installs. Be cautious with anything under 100.
2. **Source reputation** — Official sources (`vercel-labs`, `anthropics`, `microsoft`) are more trustworthy than unknown authors.
3. **GitHub stars** — Check the source repository. A skill from a repo with <100 stars should be treated with skepticism.
### Step 5: Present Options to the User
When you find relevant skills, present them to the user with:
1. The skill name and what it does
2. The install count and source
3. The install command they can run
4. A link to learn more at skills.sh
Example response:
```
I found a skill that might help! The "react-best-practices" skill provides
React and Next.js performance optimization guidelines from Vercel Engineering.
(185K installs)
To install it:
npx skills add vercel-labs/agent-skills@react-best-practices
Learn more: https://skills.sh/vercel-labs/agent-skills/react-best-practices
```
### Step 6: Offer to Install
If the user wants to proceed, you can install the skill for them:
```bash
npx skills add <owner/repo@skill> -g -y
```
The `-g` flag installs globally (user-level) and `-y` skips confirmation prompts.
## Common Skill Categories
When searching, consider these common categories:
| Category | Example Queries |
| --------------- | ---------------------------------------- |
| Web Development | react, nextjs, typescript, css, tailwind |
| Testing | testing, jest, playwright, e2e |
| DevOps | deploy, docker, kubernetes, ci-cd |
| Documentation | docs, readme, changelog, api-docs |
| Code Quality | review, lint, refactor, best-practices |
| Design | ui, ux, design-system, accessibility |
| Productivity | workflow, automation, git |
## Tips for Effective Searches
1. **Use specific keywords**: "react testing" is better than just "testing"
2. **Try alternative terms**: If "deploy" doesn't work, try "deployment" or "ci-cd"
3. **Check popular sources**: Many skills come from `vercel-labs/agent-skills` or `ComposioHQ/awesome-claude-skills`
## When No Skills Are Found
If no relevant skills exist:
1. Acknowledge that no existing skill was found
2. Offer to help with the task directly using your general capabilities
3. Suggest the user could create their own skill with `npx skills init`
Example:
```
I searched for skills related to "xyz" but didn't find any matches.
I can still help you with this task directly! Would you like me to proceed?
If this is something you do often, you could create your own skill:
npx skills init my-xyz-skill
```
# PageSpeed Insights — Reference & Official Documentation
This file complements the pagespeed-insights skill with official documentation links for indexing.
## Official documentation (indexable)
- **PageSpeed Insights about**: https://developers.google.com/speed/docs/insights/v5/about?hl=es-419
- **PageSpeed Insights (tool)**: https://pagespeed.web.dev/
- **Lighthouse**: https://developer.chrome.com/docs/lighthouse/
- **Core Web Vitals**: https://web.dev/vitals/
- **Chrome User Experience Report (CrUX)**: https://developer.chrome.com/docs/crux/
## Core Web Vitals (metrics)
- **LCP (Largest Contentful Paint)**: https://web.dev/lcp/
- **FCP (First Contentful Paint)**: https://web.dev/fcp/
- **CLS (Cumulative Layout Shift)**: https://web.dev/cls/
- **INP (Interaction to Next Paint)**: https://web.dev/inp/
- **TTFB (Time to First Byte)**: https://web.dev/ttfb/
## Lab vs field data
- **Lab data**: Lighthouse, controlled environment, debugging
- **Field data**: CrUX, real user metrics, 28-day aggregation
- **Understanding metrics**: https://web.dev/metrics/
## Performance optimization guides
- **Optimize LCP**: https://web.dev/optimize-lcp/
- **Optimize CLS**: https://web.dev/optimize-cls/
- **Optimize INP**: https://web.dev/optimize-inp/
- **Optimize FCP**: https://web.dev/optimize-fcp/
- **Resource hints**: https://web.dev/preconnect-and-dns-prefetch/
- **Image optimization**: https://web.dev/fast/#optimize-your-images
## Tools
- **PageSpeed Insights**: https://pagespeed.web.dev/
- **Lighthouse (Chrome DevTools)**: Built-in, Audits tab
- **Web Vitals extension**: Real-time monitoring
- **Chromatic (Lighthouse CI)**: https://github.com/GoogleChrome/lighthouse-ci
## Score thresholds (reminder)
| Category | Good | Needs Improvement | Poor |
|----------|------|-------------------|------|
| Performance | 90-100 | 50-89 | 0-49 |
| Accessibility | 90-100 | 50-89 | 0-49 |
| Best Practices | 90-100 | 50-89 | 0-49 |
| SEO | 90-100 | 50-89 | 0-49 |
---
name: pagespeed-insights
description: Audit web pages for performance optimization following PageSpeed Insights guidelines. Use when analyzing page performance, optimizing web applications, reviewing performance metrics, implementing Core Web Vitals improvements, or when the user mentions page speed, performance optimization, Lighthouse scores, or Core Web Vitals.
---
# PageSpeed Insights Auditor
## Overview
You are a **PageSpeed Insights Auditor** - an expert in web performance optimization who helps developers achieve excellent PageSpeed scores by identifying performance issues, avoiding bad practices, and implementing best practices based on Google's PageSpeed Insights guidelines.
**Core Principle**: Guide developers to achieve scores of 90+ (Good) in Performance, Accessibility, Best Practices, and SEO categories, while ensuring Core Web Vitals metrics meet the "Good" thresholds.
## Understanding PageSpeed Insights
PageSpeed Insights (PSI) analyzes page performance on mobile and desktop devices, providing both **lab data** (simulated) and **field data** (real user experiences). PSI reports on user experience metrics and provides diagnostic suggestions to improve page performance.
### Two Types of Data
1. **Lab Data**: Collected in a controlled environment using Lighthouse. Useful for debugging but may not capture real-world bottlenecks.
2. **Field Data**: Real user experience data from Chrome User Experience Report (CrUX). Useful for capturing actual user experiences but has a more limited set of metrics.
## Performance Score Thresholds
### Lab Scores (Lighthouse)
| Score Range | Rating | Icon |
| ----------- | ----------------- | --------------- |
| 90-100 | Good | 🟢 Green circle |
| 50-89 | Needs Improvement | 🟡 Amber square |
| 0-49 | Poor | 🔴 Red triangle |
**Target**: Always aim for scores of **90 or higher** in all categories.
### Core Web Vitals Thresholds
Core Web Vitals are the three most important metrics for web performance:
| Metric | Good | Needs Improvement | Poor |
| ----------------------------------- | ------------ | ------------------ | --------- |
| **FCP** (First Contentful Paint) | [0, 1800 ms] | [1800 ms, 3000 ms] | > 3000 ms |
| **LCP** (Largest Contentful Paint) | [0, 2500 ms] | [2500 ms, 4000 ms] | > 4000 ms |
| **CLS** (Cumulative Layout Shift) | [0, 0.1] | [0.1, 0.25] | > 0.25 |
| **INP** (Interaction to Next Paint) | [0, 200 ms] | [200 ms, 500 ms] | > 500 ms |
| **TTFB** (Time to First Byte) | [0, 800 ms] | [800 ms, 1800 ms] | > 1800 ms |
**Target**: Ensure the 75th percentile of all Core Web Vitals metrics are in the "Good" range.
## Key Performance Metrics
### Lab Metrics (Lighthouse)
1. **First Contentful Paint (FCP)**: Time until first content is rendered
2. **Largest Contentful Paint (LCP)**: Time until largest content element is rendered
3. **Speed Index**: How quickly content is visually displayed
4. **Cumulative Layout Shift (CLS)**: Visual stability measure
5. **Total Blocking Time (TBT)**: Sum of blocking time between FCP and TTI
6. **Time to Interactive (TTI)**: Time until page is fully interactive
### Field Metrics (CrUX)
- **FCP**: First Contentful Paint from real users
- **LCP**: Largest Contentful Paint from real users
- **CLS**: Cumulative Layout Shift from real users
- **INP**: Interaction to Next Paint (replaces FID)
- **TTFB**: Time to First Byte (experimental)
## Common Performance Issues & Solutions
### ❌ Bad Practice: Unoptimized Images
**Problem**: Large images without compression, modern formats, or proper sizing.
**Impact**: Poor LCP scores, slow page loads.
**✅ Solutions**:
- Use modern image formats (WebP, AVIF)
- Implement responsive images with `srcset`
- Compress images before uploading
- Set explicit width/height to prevent CLS
- Use lazy loading for below-the-fold images
```html
<!-- Bad -->
<img src="large-image.jpg" alt="Description" />
<!-- Good -->
<img
src="image.webp"
srcset="image-small.webp 400w, image-medium.webp 800w, image-large.webp 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
width="1200"
height="800"
alt="Description"
loading="lazy"
/>
```
### ❌ Bad Practice: Render-Blocking Resources
**Problem**: CSS and JavaScript blocking initial render.
**Impact**: Poor FCP and LCP scores.
**✅ Solutions**:
- Defer non-critical CSS
- Inline critical CSS
- Use `async` or `defer` for JavaScript
- Remove unused CSS/JS
- Split code and lazy load routes
```html
<!-- Bad -->
<link rel="stylesheet" href="styles.css" />
<script src="app.js"></script>
<!-- Good -->
<link
rel="stylesheet"
href="styles.css"
media="print"
onload="this.media='all'"
/>
<link rel="preload" href="critical.css" as="style" />
<script src="app.js" defer></script>
```
### ❌ Bad Practice: Missing Resource Hints
**Problem**: Not preconnecting to important origins or prefetching critical resources.
**Impact**: Slow TTFB and LCP.
**✅ Solutions**:
- Use `rel="preconnect"` for third-party origins
- Use `rel="dns-prefetch"` for DNS resolution
- Use `rel="preload"` for critical resources
- Use `rel="prefetch"` for likely next-page resources
```html
<!-- Good -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="dns-prefetch" href="https://api.example.com" />
<link rel="preload" href="hero-image.webp" as="image" />
```
### ❌ Bad Practice: Layout Shift (CLS)
**Problem**: Content shifting during page load.
**Impact**: Poor CLS scores, bad user experience.
**✅ Solutions**:
- Set explicit dimensions for images and videos
- Reserve space for ads and embeds
- Avoid inserting content above existing content
- Use CSS aspect-ratio for responsive containers
- Prefer transform animations over layout-triggering properties
```css
/* Bad */
.image-container {
width: 100%;
/* height not set - causes CLS */
}
/* Good */
.image-container {
width: 100%;
aspect-ratio: 16 / 9;
/* or */
height: 0;
padding-bottom: 56.25%; /* 16:9 ratio */
}
```
### ❌ Bad Practice: Large JavaScript Bundles
**Problem**: Loading unnecessary JavaScript code.
**Impact**: Poor TTI, high TBT.
**✅ Solutions**:
- Code splitting and lazy loading
- Remove unused code (tree shaking)
- Minimize and compress JavaScript
- Use dynamic imports for routes
- Avoid large third-party libraries when possible
```javascript
// Bad - loading everything upfront
import { heavyLibrary } from "./heavy-library";
// Good - lazy load when needed
const loadHeavyLibrary = () => import("./heavy-library");
```
### ❌ Bad Practice: Inefficient Font Loading
**Problem**: Fonts causing FOIT (Flash of Invisible Text) or FOUT (Flash of Unstyled Text).
**Impact**: Poor FCP, layout shifts.
**✅ Solutions**:
- Use `font-display: swap` or `optional`
- Preload critical fonts
- Subset fonts to include only needed characters
- Use system fonts when possible
```css
/* Good */
@font-face {
font-family: "CustomFont";
src: url("font.woff2") format("woff2");
font-display: swap; /* or optional */
}
```
### ❌ Bad Practice: No Caching Strategy
**Problem**: Resources not cached, causing repeated downloads.
**Impact**: Slow repeat visits, poor performance.
**✅ Solutions**:
- Set appropriate Cache-Control headers
- Use service workers for offline caching
- Implement HTTP/2 server push for critical resources
- Use CDN for static assets
```
Cache-Control: public, max-age=31536000, immutable
```
### ❌ Bad Practice: Third-Party Scripts Blocking Render
**Problem**: Analytics, ads, or widgets blocking page load.
**Impact**: Poor TTI, high TBT.
**✅ Solutions**:
- Load third-party scripts asynchronously
- Defer non-critical third-party code
- Use `rel="noopener"` for external links
- Consider self-hosting analytics when possible
```html
<!-- Good -->
<script async src="https://www.google-analytics.com/analytics.js"></script>
```
## Accessibility Best Practices
### ❌ Bad Practice: Missing Alt Text
**Problem**: Images without descriptive alt attributes.
**Impact**: Poor accessibility score.
**✅ Solution**: Always provide meaningful alt text.
```html
<!-- Bad -->
<img src="chart.png" />
<!-- Good -->
<img src="chart.png" alt="Sales increased 25% from Q1 to Q2" />
```
### ❌ Bad Practice: Poor Color Contrast
**Problem**: Text not readable due to low contrast.
**Impact**: Poor accessibility score.
**✅ Solution**: Ensure contrast ratio of at least 4.5:1 for normal text, 3:1 for large text.
### ❌ Bad Practice: Missing ARIA Labels
**Problem**: Interactive elements without proper labels.
**Impact**: Poor accessibility score.
**✅ Solution**: Use ARIA labels for screen readers.
```html
<!-- Good -->
<button aria-label="Close dialog">×</button>
```
## SEO Best Practices
### ❌ Bad Practice: Missing Meta Tags
**Problem**: No title, description, or viewport meta tags.
**Impact**: Poor SEO score.
**✅ Solution**: Include essential meta tags.
```html
<!-- Good -->
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Page description" />
<title>Page Title</title>
```
### ❌ Bad Practice: Non-Descriptive Links
**Problem**: Links with generic text like "click here".
**Impact**: Poor SEO score.
**✅ Solution**: Use descriptive link text.
```html
<!-- Bad -->
<a href="/about">Click here</a>
<!-- Good -->
<a href="/about">Learn more about our company</a>
```
## Best Practices Checklist
### Performance
- [ ] Images optimized (WebP/AVIF, compressed, responsive)
- [ ] Critical CSS inlined
- [ ] Non-critical CSS deferred
- [ ] JavaScript code-split and lazy-loaded
- [ ] Render-blocking resources minimized
- [ ] Resource hints implemented (preconnect, preload, dns-prefetch)
- [ ] Fonts optimized with font-display
- [ ] Caching strategy implemented
- [ ] Third-party scripts loaded asynchronously
- [ ] Layout shifts prevented (explicit dimensions, aspect-ratio)
### Core Web Vitals
- [ ] LCP < 2.5 seconds (75th percentile)
- [ ] FCP < 1.8 seconds (75th percentile)
- [ ] CLS < 0.1 (75th percentile)
- [ ] INP < 200ms (75th percentile)
- [ ] TTFB < 800ms (75th percentile)
### Accessibility
- [ ] All images have alt text
- [ ] Color contrast meets WCAG standards
- [ ] ARIA labels on interactive elements
- [ ] Semantic HTML used
- [ ] Keyboard navigation supported
### SEO
- [ ] Meta tags present (title, description, viewport)
- [ ] Descriptive link text
- [ ] Proper heading hierarchy (h1-h6)
- [ ] Structured data implemented
- [ ] Mobile-friendly design
## Audit Workflow
When auditing a page for PageSpeed optimization:
1. **Analyze Current State**
- Check current PageSpeed scores
- Identify Core Web Vitals metrics
- Review lab and field data differences
2. **Identify Issues**
- List all performance problems
- Prioritize by impact (Core Web Vitals first)
- Categorize by type (images, JS, CSS, etc.)
3. **Provide Solutions**
- Suggest specific optimizations
- Provide code examples
- Explain expected improvements
4. **Verify Improvements**
- Re-test after changes
- Ensure scores reach 90+
- Confirm Core Web Vitals are "Good"
## Common Mistakes to Avoid
### ❌ Focusing Only on Lab Data
**Problem**: Optimizing only for Lighthouse scores without considering real user data.
**✅ Solution**: Balance both lab and field data. Field data shows real-world performance.
### ❌ Over-Optimizing
**Problem**: Implementing too many optimizations at once, making debugging difficult.
**✅ Solution**: Make incremental changes and test after each optimization.
### ❌ Ignoring Mobile Performance
**Problem**: Optimizing only for desktop.
**✅ Solution**: Mobile-first approach. Most users are on mobile devices.
### ❌ Not Testing After Changes
**Problem**: Assuming optimizations worked without verification.
**✅ Solution**: Always re-run PageSpeed Insights after implementing changes.
## Performance Optimization Priority
1. **Critical Path**: Optimize resources needed for initial render
2. **Core Web Vitals**: Focus on LCP, CLS, and INP first
3. **Render-Blocking**: Eliminate blocking CSS and JS
4. **Images**: Optimize largest contentful paint element
5. **Third-Party**: Minimize impact of external scripts
6. **Caching**: Implement proper caching strategies
## Additional Resources
- [reference.md](reference.md) — Official PageSpeed, Lighthouse, Core Web Vitals, optimization guides — indexable
- **Official**: https://developers.google.com/speed/docs/insights/v5/about?hl=es-419
- **PageSpeed Insights**: https://pagespeed.web.dev/
- **Lighthouse**: Built into Chrome DevTools
- **Web Vitals**: https://web.dev/vitals/
## Specification Reference
This skill is based on the official [PageSpeed Insights documentation](https://developers.google.com/speed/docs/insights/v5/about?hl=es-419) from Google Developers.
All thresholds, metrics, and best practices in this skill follow the official PageSpeed Insights guidelines and Core Web Vitals specifications. For complete documentation, refer to the [official PageSpeed Insights documentation](https://developers.google.com/speed/docs/insights/v5/about?hl=es-419).
+1
-1
{
"name": "cc-codeconductor",
"version": "0.2.9",
"version": "0.2.10",
"description": "A multi-agent orchestration framework for AI-assisted software engineering workflows.",

@@ -5,0 +5,0 @@ "keywords": [

@@ -286,4 +286,4 @@ # CodeConductor — Multi-Agent Orchestration Framework

0. Create a Git Worktree for this session before opening any file for editing:
`git worktree add ../<branch>-session <branch>`
All changes happen inside this worktree. Never modify the main working tree directly.
`git worktree add ../<branch>-session <branch>` All changes happen inside
this worktree. Never modify the main working tree directly.
1. Read the Technical Plan completely.

@@ -298,3 +298,4 @@ 2. Read each file listed under "Files Affected."

- **Work in a worktree.** Create a session worktree before touching any file.
All edits happen inside it. Include the worktree path in the Implementation Summary.
All edits happen inside it. Include the worktree path in the Implementation
Summary.
- **Minimal diff.** Change only what the plan specifies.

@@ -571,2 +572,10 @@ - **Follow existing patterns.** Match naming conventions, error handling, and

When the active task requires web performance analysis, Core Web Vitals
auditing, PageSpeed Insights data, or optimization of LCP, TBT, CLS, FCP, or
TTFB, apply `.claude/skills/pagespeed-perf/SKILL.md` and
`.claude/skills/pagespeed-insights/SKILL.md`.
When the user asks about discovering, searching, or installing agent skills or
extending capabilities, apply `.claude/skills/find-skills/SKILL.md`.
---

@@ -596,2 +605,3 @@

- When using tools, be precise and minimal with context.
{{LANGUAGE_INSTRUCTIONS}}

@@ -598,0 +608,0 @@ ## Context Budget

{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"env": {
"CLAUDE_CODE_ATTRIBUTION_HEADER": "0",
"CLAUDE_CODE_DISABLE_1M_CONTEXT": "1",
"CLAUDE_CODE_DISABLE_AUTO_MEMORY": "1",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"CLAUDE_CODE_DISABLE_TERMINAL_TITLE": "1",
"DISABLE_EXTRA_USAGE_COMMAND": "1",
"DISABLE_TELEMETRY": "1",
"DISABLE_ERROR_REPORTING": "1",
"DISABLE_FEEDBACK_COMMAND": "1",
"CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT": "1",
"ENABLE_TOOL_SEARCH": "auto",
"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "80",
"CLAUDE_CODE_SUBPROCESS_ENV_SCRUB": "1",
"CLAUDE_CODE_SUBAGENT_MODEL": "haiku",
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
"MAX_THINKING_TOKENS": "24000",
"DISABLE_BUG_COMMAND": "1"
},
"attribution": {
"commit": "",
"pr": ""
},
"includeCoAuthoredBy": false,
"includeGitInstructions": false,
"permissions": {

@@ -12,5 +37,72 @@ "allow": [

"Bash(npm test*)",
"Bash(npm run lint*)"
"Bash(npm run lint*)",
"Bash(ls *)",
"Bash(cat *)",
"Bash(grep *)",
"Bash(rg *)",
"Bash(find *)",
"Bash(tree *)",
"Bash(echo *)",
"Bash(pwd)",
"Bash(which *)",
"Bash(head *)",
"Bash(tail *)",
"Bash(wc *)",
"Bash(diff *)",
"Bash(git branch*)",
"Bash(git show*)",
"Bash(git add*)",
"Bash(git commit*)",
"Bash(git stash*)",
"Bash(git checkout*)",
"Bash(git restore*)",
"Bash(git pull*)",
"Bash(git fetch*)",
"Bash(git merge*)",
"Bash(npm run *)",
"Bash(npm ci)",
"Bash(pnpm run *)",
"Bash(pnpm test*)",
"Bash(pnpm exec *)",
"Bash(pnpm dlx *)",
"Bash(yarn run *)",
"Bash(yarn test*)",
"Bash(npx *)",
"Bash(python *)",
"Bash(python3 *)",
"Bash(pip list*)",
"Bash(pip show *)",
"Bash(pytest*)",
"Bash(ruff*)",
"Bash(black --check *)",
"Bash(./gradlew *)",
"Bash(gradle *)",
"Bash(mvn test*)",
"Bash(mvn compile*)",
"Bash(java -version)",
"Bash(kotlin -version)",
"Bash(docker ps*)",
"Bash(docker logs*)",
"Bash(docker compose ps*)",
"Bash(docker compose logs*)",
"Read(**)",
"Write(./src/**)",
"Write(./app/**)",
"Write(./pages/**)",
"Write(./components/**)",
"Write(./lib/**)",
"Write(./tests/**)",
"Write(./test/**)",
"Write(./__tests__/**)",
"Write(./prisma/**)",
"Write(./drizzle/**)",
"Write(./public/**)",
"Write(./styles/**)",
"Write(./scripts/**)",
"Write(./docs/**)",
"Edit(**)",
"WebFetch(*)"
],
"deny": [
"Agent(bypass-runner)",
"Bash(rm -rf *)",

@@ -35,5 +127,160 @@ "Bash(sudo *)",

"Bash(git rebase *)",
"Bash(git reset --hard *)"
"Bash(git reset --hard *)",
"Bash(rm -fr *)",
"Bash(chmod -R *)",
"Bash(eval *)",
"Bash(git push --force origin main*)",
"Bash(git push --force origin master*)",
"Bash(git push -f origin main*)",
"Bash(git push -f origin master*)",
"Read(./.env)",
"Read(./.env.*)",
"Read(./**/.env)",
"Read(./**/.env.*)",
"Read(./secrets/**)",
"Read(./**/credentials.json)",
"Read(./**/serviceAccount*.json)",
"Read(./**/*.pem)",
"Read(./**/*.key)",
"Read(./**/id_rsa*)",
"Read(~/.ssh/**)",
"Read(~/.aws/**)",
"Read(~/.gnupg/**)",
"Write(./.env)",
"Write(./.env.*)",
"Write(./**/.env)",
"Edit(./.env)",
"Edit(./.env.*)",
"Edit(./**/.env)"
],
"ask": [
"Bash(git push*)",
"Bash(git push --force*)",
"Bash(git reset --hard*)",
"Bash(npm install*)",
"Bash(npm i *)",
"Bash(pnpm install*)",
"Bash(pnpm add *)",
"Bash(yarn add *)",
"Bash(pip install*)",
"Bash(docker run*)",
"Bash(docker compose up*)",
"Bash(docker compose down*)",
"Bash(./gradlew build*)",
"Bash(./gradlew bootRun*)",
"Bash(mvn install*)",
"Bash(mvn deploy*)",
"Bash(vercel*)",
"Bash(npx vercel*)"
],
"defaultMode": "acceptEdits",
"disableBypassPermissionsMode": "disable"
},
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_INPUT_FILE_PATH\" | grep -qE '\\.(ts|tsx|js|jsx|mjs|cjs|json|jsonc|md|mdx|css|scss|html|astro|yaml|yml)$'; then npx --no-install prettier --write \"$CLAUDE_TOOL_INPUT_FILE_PATH\" 2>/dev/null || true; fi"
},
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_INPUT_FILE_PATH\" | grep -qE '\\.(ts|tsx|js|jsx|mjs|cjs)$'; then npx --no-install eslint --fix \"$CLAUDE_TOOL_INPUT_FILE_PATH\" 2>/dev/null || true; fi"
},
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_INPUT_FILE_PATH\" | grep -qE '\\.py$'; then ruff format \"$CLAUDE_TOOL_INPUT_FILE_PATH\" 2>/dev/null && ruff check --fix \"$CLAUDE_TOOL_INPUT_FILE_PATH\" 2>/dev/null || true; fi"
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_INPUT_COMMAND\" | grep -qE '(\\.env|secrets/|id_rsa|\\.pem|\\.key)\\b' && echo \"$CLAUDE_TOOL_INPUT_COMMAND\" | grep -qE '(cat|less|more|head|tail|cp |mv |scp )'; then echo 'Bloqueado: intento de leer archivos sensibles' >&2; exit 2; fi"
}
]
}
],
"SubagentStop": [
{
"hooks": [
{
"type": "command",
"command": "echo \"[subagent fin] $(date -Iseconds)\" >> ~/.claude/subagent.log"
}
]
}
]
},
"sandbox": {
"enabled": false,
"failIfUnavailable": false,
"autoAllowBashIfSandboxed": true,
"network": {
"allowedDomains": [
"github.com",
"*.githubusercontent.com",
"registry.npmjs.org",
"*.npmjs.org",
"registry.yarnpkg.com",
"pypi.org",
"*.pythonhosted.org",
"repo.maven.apache.org",
"repo1.maven.org",
"services.gradle.org",
"plugins.gradle.org",
"*.gradle.org",
"*.googleapis.com",
"api.anthropic.com"
],
"allowLocalBinding": true
},
"filesystem": {
"denyRead": [
"~/.ssh",
"~/.aws",
"~/.gnupg",
"./.env",
"./.env.*"
]
},
"excludedCommands": [
"docker *"
]
},
"extraKnownMarketplaces": {
"agricidaniel-claude-seo": {
"source": {
"source": "github",
"repo": "AgriciDaniel/claude-seo"
}
}
},
"language": "spanish",
"feedbackSurveyRate": 0,
"spinnerTipsEnabled": false,
"alwaysThinkingEnabled": true,
"effortLevel": "xhigh",
"awaySummaryEnabled": false,
"showClearContextOnPlanAccept": true,
"autoUpdatesChannel": "stable",
"prefersReducedMotion": false,
"autoMemoryEnabled": false,
"showThinkingSummaries": true,
"skipDangerousModePermissionPrompt": true,
"editorMode": "vim",
"fileCheckpointingEnabled": true,
"showTurnDuration": true,
"terminalProgressBarEnabled": true,
"autoConnectIde": true,
"autoInstallIdeExtension": false,
"enabledPlugins": {
"claude-seo@agricidaniel-claude-seo": true
}
}

@@ -37,12 +37,13 @@ <!-- CODECONDUCTOR:BEGIN managed -->

| Workflow | Trigger phrase |
| ------------ | ------------------------------------------------- |
| Full feature | "Run the feature workflow for: [description]" |
| Bug fix | "Run the fix workflow for: [description]" |
| Refactor | "Run the refactor workflow for: [scope]" |
| API contract | "Run the API contract workflow for: [change]" |
| Workflow | Trigger phrase |
| ------------ | -------------------------------------------------- |
| Full feature | "Run the feature workflow for: [description]" |
| Bug fix | "Run the fix workflow for: [description]" |
| Refactor | "Run the refactor workflow for: [scope]" |
| API contract | "Run the API contract workflow for: [change]" |
| DB migration | "Run the database migration workflow for: [scope]" |
| Code review | "Run a structured review of: [target]" |
| Test plan | "Create a test plan for: [scope]" |
| Task intake | "Help me define a Task Card for: [vague request]" |
| Code review | "Run a structured review of: [target]" |
| Test plan | "Create a test plan for: [scope]" |
| Task intake | "Help me define a Task Card for: [vague request]" |
| PageSpeed | "Run a PageSpeed audit for: [url]" |

@@ -377,3 +378,4 @@ ---

**Does not:** Design architecture. Force push. Declare done before running tests.
**Does not:** Design architecture. Force push. Declare done before running
tests.

@@ -385,4 +387,4 @@ **Model:** `{{MODEL_CODEX}}`

0. Create a Git Worktree for this session before opening any file for editing:
`git worktree add ../<branch>-session <branch>`
All changes happen inside this worktree. Never modify the main working tree directly.
`git worktree add ../<branch>-session <branch>` All changes happen inside
this worktree. Never modify the main working tree directly.
1. Read the Technical Plan completely.

@@ -397,3 +399,4 @@ 2. Read each file listed under "Files Affected."

- **Work in a worktree.** Create a session worktree before touching any file.
All edits happen inside it. Include the worktree path in the Implementation Summary.
All edits happen inside it. Include the worktree path in the Implementation
Summary.
- **Minimal diff.** Change only what the plan specifies.

@@ -597,3 +600,4 @@ - **Follow existing patterns.** Match naming conventions, error handling, and

**Does not:** Write implementation code. Document behavior that was not implemented. Omit CHANGELOG entries.
**Does not:** Write implementation code. Document behavior that was not
implemented. Omit CHANGELOG entries.

@@ -887,2 +891,3 @@ **Model:** `{{MODEL_CODEX}}`

- When using tools, be precise and minimal with context.
{{LANGUAGE_INSTRUCTIONS}}

@@ -889,0 +894,0 @@ ## Context Budget

@@ -49,12 +49,12 @@ # OpenCode Preset for CodeConductor

| Agent | Mode | Description |
| ----------------- | --------- | ---------------------------------------------------- |
| **Orchestrator** | primary | Main coordinator — Tab to switch to it |
| **Architect** | subagent | Invoked by Orchestrator for design work |
| **Implementer** | subagent | Invoked by Orchestrator for code implementation |
| **Tester** | subagent | Invoked by Orchestrator for test generation |
| **Reviewer** | subagent | Invoked by Orchestrator for code review |
| **Task Coach** | subagent | Invoked by Orchestrator for intake clarification |
| **Docs** | subagent | Invoked by Orchestrator for documentation updates |
| **Repo Explorer** | subagent | Invoked by Orchestrator for codebase exploration |
| Agent | Mode | Description |
| ----------------- | -------- | ------------------------------------------------- |
| **Orchestrator** | primary | Main coordinator — Tab to switch to it |
| **Architect** | subagent | Invoked by Orchestrator for design work |
| **Implementer** | subagent | Invoked by Orchestrator for code implementation |
| **Tester** | subagent | Invoked by Orchestrator for test generation |
| **Reviewer** | subagent | Invoked by Orchestrator for code review |
| **Task Coach** | subagent | Invoked by Orchestrator for intake clarification |
| **Docs** | subagent | Invoked by Orchestrator for documentation updates |
| **Repo Explorer** | subagent | Invoked by Orchestrator for codebase exploration |

@@ -187,2 +187,3 @@ ---

- When using tools, be precise and minimal with context.
{{LANGUAGE_INSTRUCTIONS}}

@@ -189,0 +190,0 @@ ## Context Budget

@@ -5,2 +5,6 @@ # SEO Audit

> Spanish prose/docs/reports/Markdown: preserve natural Spanish orthography,
> including accents, `ñ`, `¿`, `¡`, and normal Unicode. The ASCII-only editing
> preference does not apply to these artifacts.
## Usage

@@ -16,11 +20,11 @@

| Parameter | Required | Description |
|-----------|----------|-------------|
| `--url` | One of `--url` or `--sitemap` | Single URL to audit |
| Parameter | Required | Description |
| ----------- | ----------------------------- | -------------------------------------------------------------- |
| `--url` | One of `--url` or `--sitemap` | Single URL to audit |
| `--sitemap` | One of `--url` or `--sitemap` | Remote sitemap XML URL. Only URLs listed here will be audited. |
| `--format` | No | Output format: `cli` (default) or `json` |
| `--fail-on` | No | Exit code trigger: `error` (default) or `warning` |
| `--astro` | No | Run Astro-specific SEO validation on source code |
| `--path` | With `--astro` | Path to Astro source directory |
| `--delay` | No | Delay between requests in ms (default: 500) |
| `--format` | No | Output format: `cli` (default) or `json` |
| `--fail-on` | No | Exit code trigger: `error` (default) or `warning` |
| `--astro` | No | Run Astro-specific SEO validation on source code |
| `--path` | With `--astro` | Path to Astro source directory |
| `--delay` | No | Delay between requests in ms (default: 500) |

@@ -60,3 +64,4 @@ ## Workflow

- **Sitemap-scoped only.** When `--sitemap` is provided, only audit URLs from the sitemap.
- **Sitemap-scoped only.** When `--sitemap` is provided, only audit URLs from
the sitemap.
- **No external crawling.** Never follow hyperlinks found on pages.

@@ -91,1 +96,4 @@ - **GET only.** No POST, PUT, DELETE requests.

- `off-page` — Off-page SEO strategy guidance
- `pagespeed-insights` — Audit web pages for performance optimization following
PageSpeed Insights guidelines
- `find-skills` — Discover and install agent skills
+105
-25

@@ -39,2 +39,11 @@ # CodeConductor

> for AI-search readiness from sitemap content
> - `/cc-pagespeed --url <url>` — audits web performance using the PageSpeed
> Insights API; applies the 80/20 principle to produce a prioritized report of
> Core Web Vitals (LCP, TBT, CLS, FCP, TTFB) with framework-specific fixes;
> requires `PAGESPEED_API_KEY` env var for full CrUX field data (optional but
> recommended)
> - `npx cc-codeconductor install preset --target <opencode|claude|codex|all>` —
> installs the full preset (agents, prompts, skills, commands, settings) for the
> chosen runner; use `--locale=es` to inject Spanish-aware instructions into
> agent files, or rely on the locale saved during `init`
> - Manual presets for OpenCode, Claude Code, and Codex

@@ -115,3 +124,3 @@ > - Versioned Agent Contracts

- OpenCode preset
- Claude Code-compatible preset
- Claude Code-compatible preset (see [Claude Environment Options & Best Practices](file:///c:/Users/R2D2/Documents/GitHub/codeconductor/docs/claude-env-options.md))
- Codex preset

@@ -149,2 +158,4 @@ - Spring Boot / Kotlin workflow

npx cc-codeconductor init --dry-run # preview without writing
npx cc-codeconductor init --locale=es # set Spanish as the instruction language
npx cc-codeconductor init --locale=en # set English (default)
```

@@ -156,2 +167,9 @@

> [!IMPORTANT]
>
> **`--locale` is remembered.** Once you run `init --locale=es`, the value is
> saved to `.codeconductor/config.yml`. Every subsequent `install preset` will
> automatically use that locale — no need to repeat the flag. To change it,
> run `init --locale=en --force` or edit `defaults.locale` in your config.
#### `detect` — detect project stack

@@ -173,5 +191,37 @@

#### `install` — install council preset
#### `install preset` — install full agent preset
```bash
npx cc-codeconductor install preset --target opencode # project-level
npx cc-codeconductor install preset --target claude
npx cc-codeconductor install preset --target codex
npx cc-codeconductor install preset --target all # all targets
npx cc-codeconductor install preset --target claude --global # write to ~/.claude/
npx cc-codeconductor install preset --target all --global
npx cc-codeconductor install preset --target claude --locale=es # override locale once
npx cc-codeconductor install preset --target all --dry-run # preview
npx cc-codeconductor install preset --target claude --force # overwrite
```
Locale resolution order (first match wins):
1. `--locale` flag on the command line
2. `defaults.locale` in `.codeconductor/config.yml` (set by `init --locale`)
3. `en` (built-in default)
Files installed per target:
| Target | Notable files |
| ---------- | ---------------------------------------------------------------- |
| `claude` | `.claude/CLAUDE.md`, `.claude/settings.json`, `.claude/agents/` |
| `opencode` | `.opencode/agents/`, `.opencode/commands/`, `.opencode/skills/` |
| `codex` | `.codex/AGENTS.md`, `.codex/skills/`, `.codex/prompts/` |
With `--global`, files are written under `~/` instead of `./`.
#### `install council` — install council spec
```bash
npx cc-codeconductor install council --target opencode # project-level

@@ -190,12 +240,2 @@ npx cc-codeconductor install council --target claude

Files generated per target:
| Target | Files written |
| ---------- | ---------------------------------------------------------------- |
| `opencode` | `.opencode/commands/cc-council.md`, `.opencode/agents/council-*.md` |
| `claude` | `.claude/skills/council/SKILL.md`, `.claude/agents/council-*.md` |
| `codex` | `.codex/config.toml`, `.codex/agents/council_*.toml` |
With `--global`, the same files are written under `~/` instead of `./`.
#### `install lsp` — install and configure LSP servers

@@ -235,8 +275,9 @@

| Flag | Description |
| --------------- | ---------------------------------------- |
| `--force` | Overwrite existing files |
| `--dry-run` | Preview actions without writing |
| `--global` | Target home directory instead of project |
| `--output json` | Machine-readable JSON output |
| Flag | Description |
| ---------------- | -------------------------------------------------------- |
| `--force` | Overwrite existing files |
| `--dry-run` | Preview actions without writing |
| `--global` | Target home directory instead of project |
| `--output json` | Machine-readable JSON output |
| `--locale=en` | Agent instruction language: `en` (default) or `es` |

@@ -249,3 +290,3 @@ ### Config directory

.codeconductor/
├── config.yml # project settings, target, preset versions
├── config.yml # project settings, target, locale, preset versions
└── presets/

@@ -256,2 +297,10 @@ ├── council.yml # customizable copy of the council preset

Key fields in `config.yml`:
```yaml
defaults:
target: opencode # default runner for install/update
locale: es # instruction language injected into agent files
```
Edit `.codeconductor/presets/council.yml` to add, remove, or reconfigure agents

@@ -272,9 +321,10 @@ before running `install`.

Agent template files contain placeholders that are replaced during `install`:
Agent template files contain placeholders replaced during `install`:
| Placeholder | Description |
| -------------------- | ------------------------------- |
| `{{MODEL_CLAUDE}}` | Model for the Claude provider |
| `{{MODEL_OPENCODE}}` | Model for the OpenCode provider |
| `{{MODEL_CODEX}}` | Model for the Codex provider |
| Placeholder | Description |
| ------------------------------ | --------------------------------------------- |
| `{{MODEL_CLAUDE}}` | Model for the Claude provider |
| `{{MODEL_OPENCODE}}` | Model for the OpenCode provider |
| `{{MODEL_CODEX}}` | Model for the Codex provider |
| `{{LANGUAGE_INSTRUCTIONS}}` | Locale-aware instruction injected by `locale` |

@@ -284,2 +334,32 @@ To customize models, edit the YAML file for your target before running

#### Instruction Language (`--locale`)
Agent markdown files (`CLAUDE.md`, `AGENTS.md`, `README.md`) include a
`{{LANGUAGE_INSTRUCTIONS}}` placeholder that is replaced at install time based
on the active locale:
| Locale | Injected instruction |
| ------ | -------------------- |
| `en` | *Prose/docs/code comments: be terse and direct. Prefer concrete nouns over abstract ones. Omit filler phrases. One idea per sentence.* |
| `es` | *Spanish prose/docs/reports/Markdown: preserve natural Spanish orthography, including accents, `ñ`, `¿`, `¡`, and normal Unicode. The ASCII-only editing preference does not apply to these artifacts.* |
The locale is **sticky**: set it once with `init --locale=es` and every
subsequent `install preset` will use it automatically. Override per-run with
`install preset --locale=en`.
```bash
# One-time setup
npx cc-codeconductor init --locale=es
# All future installs use Spanish automatically
npx cc-codeconductor install preset --target=claude
npx cc-codeconductor install preset --target=all --global
# Override just this run
npx cc-codeconductor install preset --target=claude --locale=en
# Change the saved locale
npx cc-codeconductor init --locale=en --force
```
---

@@ -286,0 +366,0 @@

target: agy
entries:
- src: agy/AGENTS.md
dest: .agents/AGENTS.md
strategy: merge-managed
template: true
- src: agy/rules
dest: .agents/rules
strategy: overwrite
template: true
- src: agy/workflows
dest: .agents/workflows
strategy: overwrite
template: true
- src: agy/settings.json
dest: .agents/../antigravity-cli/settings.json
strategy: skip
globalStrategy: merge-json
- src: agy/hooks.json
dest: .agents/hooks.json
strategy: overwrite
- src: agy/mcp_config.json
dest: .agents/mcp_config.json
strategy: overwrite
- src: agy/scripts
dest: .agents/scripts
strategy: overwrite
- src: opencode/skills
dest: .agents/skills
strategy: overwrite
- src: agy/skills
dest: .agents/skills
strategy: overwrite
template: true
- src: opencode/agents
dest: .agy/agents
dest: .agents/agents
strategy: overwrite
template: true
- src: opencode/prompts/v0.2.0
dest: .agy/prompts/v0.2.0
dest: .agents/prompts/v0.2.0
strategy: overwrite

@@ -7,2 +7,3 @@ target: claude

globalStrategy: append
template: true
- src: claude/settings.json

@@ -12,2 +13,6 @@ dest: .claude/settings.json

globalStrategy: merge-json
- src: claude/claude.json
dest: .claude.json
strategy: merge-json
globalStrategy: merge-json
- src: claude/commands

@@ -14,0 +19,0 @@ dest: .claude/commands

@@ -7,2 +7,6 @@ target: opencode

globalStrategy: merge-json
- src: opencode/README.md
dest: .opencode/README.md
strategy: overwrite
template: true
- src: opencode/agents

@@ -9,0 +13,0 @@ dest: .opencode/agents

@@ -60,1 +60,17 @@ # Model configuration for Agy preset (experimental)

agy: gemini-2.5-flash
tools:
Read:
agy: view_file
Write:
agy: write_to_file
Edit:
agy: replace_file_content / multi_replace_file_content
Bash:
agy: run_command
Glob:
agy: list_dir
Grep:
agy: grep_search
WebFetch:
agy: read_url_content / read_browser_page

Sorry, the diff of this file is too big to display