diff --git a/.dockerignore b/.dockerignore index 8092340583..3f631e2690 100644 --- a/.dockerignore +++ b/.dockerignore @@ -15,10 +15,10 @@ knowledge/** !knowledge/default/ !knowledge/default/** -# Instruments directory – keep only default/ -instruments/** -!instruments/default/ -!instruments/default/** +# Skills directory – keep only builtin/ +skills/** +!skills/builtin/ +!skills/builtin/** # Keep .gitkeep markers anywhere !**/.gitkeep diff --git a/.gitignore b/.gitignore index c33c0598cf..e9e4682737 100644 --- a/.gitignore +++ b/.gitignore @@ -33,12 +33,12 @@ knowledge/** !knowledge/default/ !knowledge/default/** -# Handle instruments directory -instruments/** -!instruments/**/ -# Explicitly allow the default folder in instruments -!instruments/default/ -!instruments/default/** +# Handle skills directory (SKILL.md standard) +skills/** +!skills/**/ +# Explicitly allow the builtin folder in skills +!skills/builtin/ +!skills/builtin/** # Global rule to include .gitkeep files anywhere !**/.gitkeep diff --git a/README.md b/README.md index d2c0d9b4bc..1e6e6a5334 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ Agent Zero now supports **Projects** – isolated workspaces with their own prom - Tool usage functionality has been developed from scratch to be the most compatible and reliable, even with very small models. - **Default Tools:** Agent Zero includes tools like knowledge, code execution, and communication. - **Creating Custom Tools:** Extend Agent Zero's functionality by creating your own custom tools. -- **Instruments:** Instruments are a new type of tool that allow you to create custom functions and procedures that can be called by Agent Zero. +- **Skills (SKILL.md Standard):** Skills are contextual expertise loaded dynamically when relevant. They use the open SKILL.md standard (developed by Anthropic), making them compatible with Claude Code, Cursor, Goose, OpenAI Codex CLI, and GitHub Copilot. 3. **Multi-agent Cooperation** diff --git a/docs/CONTRIBUTING-SKILLS.md b/docs/CONTRIBUTING-SKILLS.md new file mode 100644 index 0000000000..c8c68fcaaf --- /dev/null +++ b/docs/CONTRIBUTING-SKILLS.md @@ -0,0 +1,468 @@ +# Contributing Skills to Agent Zero + +Welcome to the Agent Zero Skills ecosystem! This guide will help you create, test, and share skills with the community. + +## Table of Contents + +- [What is a Skill?](#what-is-a-skill) +- [Quick Start](#quick-start) +- [SKILL.md Standard](#skillmd-standard) +- [Creating Your First Skill](#creating-your-first-skill) +- [Best Practices](#best-practices) +- [Testing Skills](#testing-skills) +- [Sharing Skills](#sharing-skills) +- [Community Guidelines](#community-guidelines) + +--- + +## What is a Skill? + +A **Skill** is a contextual expertise module that provides the AI agent with specialized knowledge and procedures for specific tasks. Unlike tools (which are always loaded), skills are **semantically recalled** when relevant, making them token-efficient and context-aware. + +### Skills vs Tools vs Knowledge + +| Aspect | Skills | Tools | Knowledge | +|--------|--------|-------|-----------| +| **Loading** | Semantic recall | Always in prompt | Semantic recall | +| **Purpose** | Procedures & expertise | Actions & functions | Facts & data | +| **Format** | SKILL.md (YAML + Markdown) | Python/code | Text/documents | +| **When to use** | "How to do X" | "Do X now" | "What is X" | + +### Cross-Platform Compatibility + +The SKILL.md standard is compatible with: +- **Agent Zero** (this project) +- **Claude Code** (Anthropic) +- **Cursor** (AI IDE) +- **OpenAI Codex CLI** +- **GitHub Copilot** +- **Goose** (Block) + +Skills you create here can be used in any of these platforms! + +--- + +## Quick Start + +### Using the CLI (Recommended) + +```bash +# Create a new skill interactively +python -m python.helpers.skills_cli create my-skill-name + +# List all available skills +python -m python.helpers.skills_cli list + +# Validate a skill +python -m python.helpers.skills_cli validate my-skill-name + +# Search skills +python -m python.helpers.skills_cli search "keyword" +``` + +### Manual Creation + +1. Create a folder in `skills/custom/` with your skill name +2. Add a `SKILL.md` file with YAML frontmatter +3. Optionally add supporting scripts (`.py`, `.sh`, `.js`) + +--- + +## SKILL.md Standard + +Every skill must have a `SKILL.md` file with this structure: + +```markdown +--- +name: "skill-name" +description: "A clear, concise description of what this skill does and when to use it" +version: "1.0.0" +author: "Your Name " +license: "MIT" +tags: ["category", "purpose", "technology"] +triggers: + - "keyword that activates this skill" + - "another trigger phrase" +allowed_tools: + - tool_name + - another_tool +metadata: + complexity: "beginner|intermediate|advanced" + category: "development|devops|data|productivity|creative" + estimated_time: "5 minutes" +--- + +# Skill Name + +## Overview + +Brief description of what this skill accomplishes. + +## When to Use + +- Situation 1 where this skill applies +- Situation 2 where this skill applies + +## Instructions + +### Step 1: First Step + +Detailed instructions... + +### Step 2: Second Step + +More instructions... + +## Examples + +### Example 1: Basic Usage + +\`\`\`python +# Code example +\`\`\` + +### Example 2: Advanced Usage + +\`\`\`python +# Advanced code example +\`\`\` + +## Common Pitfalls + +- Pitfall 1 and how to avoid it +- Pitfall 2 and how to avoid it + +## Related Skills + +- [related-skill-1](../related-skill-1/SKILL.md) +- [related-skill-2](../related-skill-2/SKILL.md) +``` + +### Required Fields + +| Field | Description | +|-------|-------------| +| `name` | Unique identifier (lowercase, hyphens allowed) | +| `description` | What the skill does (used for semantic matching) | + +### Optional Fields + +| Field | Description | +|-------|-------------| +| `version` | Semantic version (e.g., "1.0.0") | +| `author` | Your name and email | +| `license` | License (MIT, Apache-2.0, etc.) | +| `tags` | Categories for discovery | +| `triggers` | Phrases that activate this skill | +| `allowed_tools` | Tools this skill can use | +| `metadata` | Additional structured data | + +--- + +## Creating Your First Skill + +### Step 1: Identify the Need + +Ask yourself: +- What expertise would help the agent? +- When should this skill be activated? +- What steps should the agent follow? + +### Step 2: Create the Structure + +```bash +# Using CLI +python -m python.helpers.skills_cli create my-awesome-skill + +# Or manually +mkdir -p skills/custom/my-awesome-skill +touch skills/custom/my-awesome-skill/SKILL.md +``` + +### Step 3: Write the SKILL.md + +```markdown +--- +name: "my-awesome-skill" +description: "Helps with [specific task] when [specific situation]" +version: "1.0.0" +author: "Your Name" +tags: ["category"] +--- + +# My Awesome Skill + +## When to Use + +Use this skill when you need to [specific task]. + +## Instructions + +1. First, do this... +2. Then, do that... +3. Finally, verify by... + +## Examples + +### Example: Basic Case + +[Show a complete example] +``` + +### Step 4: Add Supporting Files (Optional) + +If your skill needs scripts: + +``` +my-awesome-skill/ +├── SKILL.md # Required +├── helper.py # Optional Python script +├── setup.sh # Optional shell script +└── templates/ # Optional templates folder + └── config.json +``` + +Reference them in your SKILL.md: + +```markdown +## Scripts + +This skill includes helper scripts: +- `helper.py` - Does X +- `setup.sh` - Sets up Y +``` + +### Step 5: Test Your Skill + +```bash +# Validate the skill +python -m python.helpers.skills_cli validate my-awesome-skill + +# Test in Agent Zero +# Start the agent and ask it to perform the task your skill handles +``` + +--- + +## Best Practices + +### Writing Effective Descriptions + +The `description` field is crucial for semantic matching. Make it: + +**Good:** +```yaml +description: "Guides systematic debugging of Python applications using print statements, debugger, and logging to identify root causes" +``` + +**Bad:** +```yaml +description: "Helps with debugging" +``` + +### Structuring Instructions + +1. **Be Specific** - Avoid vague instructions +2. **Use Steps** - Number your steps clearly +3. **Include Examples** - Show, don't just tell +4. **Anticipate Errors** - Include troubleshooting + +### Semantic Triggers + +Design your description and content so the skill is recalled when relevant: + +```yaml +# Include synonyms and related terms +description: "Helps create REST APIs, web services, HTTP endpoints, and backend routes using FastAPI, Flask, or Express" +``` + +### Keep Skills Focused + +One skill = one expertise area. If your skill is getting too long, split it: + +- `api-design` - API structure and patterns +- `api-security` - API authentication and authorization +- `api-testing` - API testing strategies + +--- + +## Testing Skills + +### Local Testing + +1. **Validate Structure:** + ```bash + python -m python.helpers.skills_cli validate my-skill + ``` + +2. **Test Semantic Recall:** + Start Agent Zero and ask questions that should trigger your skill. + +3. **Verify Instructions:** + Follow your own instructions manually to ensure they work. + +### Automated Testing + +Create a test file `test_skill.py` in your skill folder: + +```python +"""Tests for my-awesome-skill""" +import pytest +from python.helpers.skills import SkillManager + +def test_skill_loads(): + manager = SkillManager() + skill = manager.get_skill("my-awesome-skill") + assert skill is not None + assert skill.name == "my-awesome-skill" + +def test_skill_has_required_fields(): + manager = SkillManager() + skill = manager.get_skill("my-awesome-skill") + assert skill.description + assert len(skill.description) > 20 +``` + +--- + +## Sharing Skills + +### Contributing to Agent Zero + +1. **Fork the Repository:** + ```bash + git clone https://github.com/agent0ai/agent-zero.git + cd agent-zero + ``` + +2. **Create Your Skill:** + ```bash + python -m python.helpers.skills_cli create my-skill + # Edit skills/custom/my-skill/SKILL.md + ``` + +3. **Move to Builtin (for contribution):** + ```bash + mv skills/custom/my-skill skills/builtin/my-skill + ``` + +4. **Create a Pull Request:** + - Branch: `feat/skill-my-skill-name` + - Title: `feat(skills): add my-skill-name skill` + - Description: Explain what the skill does and why it's useful + +### Publishing to Skills Marketplace + +Share your skills on [skillsmp.com](https://skillsmp.com): + +1. Create a GitHub repository for your skill +2. Ensure it follows the SKILL.md standard +3. Submit to the marketplace via their contribution process + +### Creating a Skills Collection + +For multiple related skills, create a repository: + +``` +my-skills-collection/ +├── README.md +├── skills/ +│ ├── skill-1/ +│ │ └── SKILL.md +│ ├── skill-2/ +│ │ └── SKILL.md +│ └── skill-3/ +│ └── SKILL.md +└── LICENSE +``` + +--- + +## Community Guidelines + +### Quality Standards + +- **Tested** - Skills must be tested before submission +- **Documented** - Clear instructions and examples +- **Focused** - One expertise per skill +- **Original** - Don't duplicate existing skills + +### Naming Conventions + +- Use lowercase with hyphens: `my-skill-name` +- Be descriptive: `python-debugging` not `debug` +- Avoid generic names: `fastapi-crud` not `api` + +### License + +- Include a license (MIT recommended for maximum compatibility) +- Respect licenses of any code you include +- Don't include proprietary or copyrighted content + +### Code of Conduct + +- Be respectful in all interactions +- Provide constructive feedback +- Help newcomers learn +- Report issues responsibly + +--- + +## Resources + +### Official Documentation + +- [Agent Zero Documentation](./README.md) +- [Architecture Guide](./architecture.md) +- [Skills System](./architecture.md#skills-system) + +### Community + +- [GitHub Issues](https://github.com/agent0ai/agent-zero/issues) +- [Discussions](https://github.com/agent0ai/agent-zero/discussions) + +### External Resources + +- [Skills Marketplace](https://skillsmp.com) +- [Awesome Agent Skills](https://github.com/skillmatic-ai/awesome-agent-skills) +- [Anthropic Skills Repository](https://github.com/anthropics/skills) + +--- + +## FAQ + +### Q: Where should I put my skills? + +**A:** During development, use `skills/custom/`. For contribution, move to `skills/builtin/`. + +### Q: How are skills discovered? + +**A:** Skills are indexed in a vector database. When you ask the agent something, it searches for relevant skills based on semantic similarity to your query. + +### Q: Can I use skills from other platforms? + +**A:** Yes! The SKILL.md standard is cross-platform. Skills from Claude Code, Cursor, or other compatible platforms can be copied directly to `skills/shared/`. + +### Q: How do I update a skill? + +**A:** Edit the SKILL.md file and increment the version number. Changes take effect on agent restart. + +### Q: Can skills call other skills? + +**A:** Skills don't directly call each other, but the agent may combine multiple skills when appropriate for a task. + +--- + +## Example Skills to Learn From + +Check out these well-structured skills in `skills/builtin/`: + +- `brainstorming/` - Requirements exploration workflow +- `debugging/` - Systematic debugging methodology +- `tdd/` - Test-driven development process +- `code_review/` - Comprehensive review checklist +- `create_skill/` - Meta-skill for creating new skills + +--- + +Happy skill building! 🚀 diff --git a/docs/README.md b/docs/README.md index b522ed0c61..c3e1ed200a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -56,7 +56,7 @@ To begin with Agent Zero, follow the links below for detailed guides on various - [Messages History and Summarization](archicture.md#messages-history-and-summarization) - [Prompts](architecture.md#4-prompts) - [Knowledge](architecture.md#5-knowledge) - - [Instruments](architecture.md#6-instruments) + - [Skills](architecture.md#6-skills) - [Extensions](architecture.md#7-extensions) - [Contributing](contribution.md) - [Getting Started](contribution.md#getting-started) diff --git a/docs/architecture.md b/docs/architecture.md index 77ed28348d..9717d498c6 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -2,11 +2,11 @@ Agent Zero is built on a flexible and modular architecture designed for extensibility and customization. This section outlines the key components and the interactions between them. ## System Architecture -This simplified diagram illustrates the hierarchical relationship between agents and their interaction with tools, extensions, instruments, prompts, memory and knowledge base. +This simplified diagram illustrates the hierarchical relationship between agents and their interaction with tools, extensions, skills, prompts, memory and knowledge base. ![Agent Zero Architecture](res/arch-01.svg) -The user or Agent 0 is at the top of the hierarchy, delegating tasks to subordinate agents, which can further delegate to other agents. Each agent can utilize tools and access the shared assets (prompts, memory, knowledge, extensions and instruments) to perform its tasks. +The user or Agent 0 is at the top of the hierarchy, delegating tasks to subordinate agents, which can further delegate to other agents. Each agent can utilize tools and access the shared assets (prompts, memory, knowledge, extensions and skills) to perform its tasks. ## Runtime Architecture Agent Zero's runtime architecture is built around Docker containers: @@ -42,7 +42,7 @@ This architecture ensures: | --- | --- | | `/docker` | Docker-related files for runtime container | | `/docs` | Documentation files and guides | -| `/instruments` | Custom scripts and tools for runtime environment | +| `/skills` | Skills using the open SKILL.md standard (contextual expertise) | | `/knowledge` | Knowledge base storage | | `/logs` | HTML CLI-style chat logs | | `/memory` | Persistent agent memory storage | @@ -148,9 +148,9 @@ Users can create custom tools to extend Agent Zero's capabilities. Custom tools 4. Follow existing patterns for consistency > [!NOTE] -> Tools are always present in system prompt, so you should keep them to minimum. -> To save yourself some tokens, use the [Instruments module](#adding-instruments) -> to call custom scripts or functions. +> Tools are always present in system prompt, so you should keep them to minimum. +> To save yourself some tokens, use the [Skills module](#6-skills) +> to add contextual expertise that is only loaded when relevant. ### 3. Memory System The memory system is a critical component of Agent Zero, enabling the agent to learn and adapt from past interactions. It operates on a hybrid model where part of the memory is managed automatically by the framework while users can also manually input and extract information. @@ -266,20 +266,54 @@ Knowledge refers to the user-provided information and data that agents can lever - Used for answering questions and decision-making - Supports RAG-augmented tasks -### 6. Instruments -Instruments provide a way to add custom functionalities to Agent Zero without adding to the token count of the system prompt: -- Stored in long-term memory of Agent Zero -- Unlimited number of instruments available -- Recalled when needed by the agent -- Can modify agent behavior by introducing new procedures -- Function calls or scripts to integrate with other systems -- Scripts are run inside the Docker Container - -#### Adding Instruments -1. Create folder in `instruments/custom` (no spaces in name) -2. Add `.md` description file for the interface -3. Add `.sh` script (or other executable) for implementation -4. The agent will automatically detect and use the instrument +### 6. Skills +Skills provide contextual expertise using the **open SKILL.md standard** (originally developed by Anthropic). Skills are cross-platform and compatible with Claude Code, Cursor, Goose, OpenAI Codex CLI, GitHub Copilot, and more. + +#### Key Features +- **YAML Frontmatter**: Structured metadata (name, description, tags, author) +- **Cross-Platform**: Works with any AI agent that supports the SKILL.md standard +- **Semantic Recall**: Skills are indexed in vector memory and loaded when contextually relevant +- **Token Efficient**: Not in system prompt; loaded dynamically when needed +- **Scripts Support**: Can reference `.sh`, `.py`, `.js`, `.ts` scripts + +#### SKILL.md Format +```yaml +--- +name: "my-skill" +description: "What this skill does and when to use it" +version: "1.0.0" +author: "Your Name" +tags: ["category", "purpose"] +--- + +# Skill Instructions + +Your detailed instructions here... + +## Examples +- Example usage 1 +- Example usage 2 +``` + +#### Directory Structure +| Directory | Description | +|-----------|-------------| +| `/skills/builtin` | Built-in skills included with Agent Zero | +| `/skills/custom` | Your custom skills (create folders here) | +| `/skills/shared` | Skills shared across agents | + +#### Adding Skills +1. Create folder in `skills/custom` (e.g., `skills/custom/my-skill`) +2. Add `SKILL.md` file with YAML frontmatter (required) +3. Optionally add supporting scripts (`.sh`, `.py`, etc.) +4. Optionally add `docs/` subfolder for additional documentation +5. The agent will automatically discover and index the skill + +#### Using Skills +Skills are automatically recalled from memory when relevant to a task. You can also use the `skills_tool` to: +- List all available skills +- Load a specific skill by name +- Read files from within a skill directory ### 7. Extensions Extensions are a powerful feature of Agent Zero, designed to keep the main codebase clean and organized while allowing for greater flexibility and modularity. diff --git a/docs/extensibility.md b/docs/extensibility.md index db10a2a887..8f69910669 100644 --- a/docs/extensibility.md +++ b/docs/extensibility.md @@ -1,7 +1,7 @@ # Extensibility framework in Agent Zero > [!NOTE] -> Agent Zero is built with extensibility in mind. It provides a framework for creating custom extensions, agents, instruments, and tools that can be used to enhance the functionality of the framework. +> Agent Zero is built with extensibility in mind. It provides a framework for creating custom extensions, agents, skills, and tools that can be used to enhance the functionality of the framework. ## Extensible components - The Python framework controlling Agent Zero is built as simple as possible, relying on independent smaller and modular scripts for individual tools, API endpoints, system extensions and helper scripts. diff --git a/docs/installation.md b/docs/installation.md index c611b1b798..b427306809 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -87,7 +87,7 @@ The following user guide provides instructions for installing and running Agent - `/agents` - Specialized agents with their prompts and tools - `/memory` - Agent's memory and learned information - `/knowledge` - Knowledge base - - `/instruments` - Instruments and functions + - `/skills` - Skills using the open SKILL.md standard - `/prompts` - Prompt files - `.env` - Your API keys - `/tmp/settings.json` - Your Agent Zero settings @@ -372,12 +372,12 @@ For developers or users who need to run Agent Zero directly on their system,see - To update to the new Docker runtime version, you might want to backup the following files and directories: - `/memory` - Agent's memory - `/knowledge` - Custom knowledge base (if you imported any custom knowledge files) - - `/instruments` - Custom instruments and functions (if you created any custom) + - `/skills` - Custom skills using SKILL.md format (if you created any) - `/tmp/settings.json` - Your Agent Zero settings - `/tmp/chats/` - Your chat history - Once you have saved these files and directories, you can proceed with the Docker runtime [installation instructions above](#windows-macos-and-linux-setup-guide) setup guide. - Reach for the folder where you saved your data and copy it to the new Agent Zero folder set during the installation process. -- Agent Zero will automatically detect your saved data and use it across memory, knowledge, instruments, prompts and settings. +- Agent Zero will automatically detect your saved data and use it across memory, knowledge, skills, prompts and settings. > [!IMPORTANT] > If you have issues loading your settings, you can try to delete the `/tmp/settings.json` file and let Agent Zero generate a new one. diff --git a/docs/usage.md b/docs/usage.md index 045d9095a8..6e8252d9a7 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -259,7 +259,7 @@ By default, Agent Zero backs up your most important data: * **Memory System**: Agent memories and learned information * **Chat History**: All your conversations and interactions * **Configuration Files**: Settings, API keys, and system preferences -* **Custom Instruments**: Any tools you've added or modified +* **Custom Skills**: Any skills you've added or modified (SKILL.md format) * **Uploaded Files**: Documents and files you've worked with #### Customizing Backup Content diff --git a/instruments/custom/.gitkeep b/instruments/custom/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/instruments/default/.DS_Store b/instruments/default/.DS_Store deleted file mode 100644 index 5008ddfcf5..0000000000 Binary files a/instruments/default/.DS_Store and /dev/null differ diff --git a/instruments/default/.gitkeep b/instruments/default/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/instruments/default/yt_download/download_video.py b/instruments/default/yt_download/download_video.py deleted file mode 100644 index db75f32693..0000000000 --- a/instruments/default/yt_download/download_video.py +++ /dev/null @@ -1,12 +0,0 @@ -import sys -import yt_dlp # type: ignore - -if len(sys.argv) != 2: - print("Usage: python3 download_video.py ") - sys.exit(1) - -url = sys.argv[1] - -ydl_opts = {} -with yt_dlp.YoutubeDL(ydl_opts) as ydl: - ydl.download([url]) diff --git a/instruments/default/yt_download/yt_download.md b/instruments/default/yt_download/yt_download.md deleted file mode 100644 index b6fbe355ec..0000000000 --- a/instruments/default/yt_download/yt_download.md +++ /dev/null @@ -1,11 +0,0 @@ -# Problem -Download a YouTube video -# Solution -1. If folder is specified, cd to it -2. Run the shell script with your video URL: - -```bash -bash /a0/instruments/default/yt_download/yt_download.sh -``` -3. Replace `` with your video URL. -4. The script will handle the installation of yt-dlp and the download process. diff --git a/instruments/default/yt_download/yt_download.sh b/instruments/default/yt_download/yt_download.sh deleted file mode 100644 index e71f1d0e34..0000000000 --- a/instruments/default/yt_download/yt_download.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Install yt-dlp and ffmpeg -sudo apt-get update && sudo apt-get install -y yt-dlp ffmpeg - -# Install yt-dlp using pip -pip install --upgrade yt-dlp - -# Call the Python script to download the video -python3 /a0/instruments/default/yt_download/download_video.py "$1" diff --git a/knowledge/default/main/about/installation.md b/knowledge/default/main/about/installation.md index 5cbaea5e1a..d26816f101 100644 --- a/knowledge/default/main/about/installation.md +++ b/knowledge/default/main/about/installation.md @@ -80,7 +80,7 @@ The following user guide provides instructions for installing and running Agent - This directory will contain all your Agent Zero files, like the legacy root folder structure: - `/memory` - Agent's memory and learned information - `/knowledge` - Knowledge base - - `/instruments` - Instruments and functions + - `/skills` - Skills (SKILL.md standard) - `/prompts` - Prompt files - `/work_dir` - Working directory - `.env` - Your API keys @@ -301,12 +301,12 @@ For developers or users who need to run Agent Zero directly on their system,see - To update to the new Docker runtime version, you might want to backup the following files and directories: - `/memory` - Agent's memory - `/knowledge` - Custom knowledge base (if you imported any custom knowledge files) - - `/instruments` - Custom instruments and functions (if you created any custom) + - `/skills` - Custom skills (if you created any custom SKILL.md files) - `/tmp/settings.json` - Your Agent Zero settings - `/tmp/chats/` - Your chat history - Once you have saved these files and directories, you can proceed with the Docker runtime [installation instructions above](#windows-macos-and-linux-setup-guide) setup guide. - Reach for the folder where you saved your data and copy it to the new Agent Zero folder set during the installation process. -- Agent Zero will automatically detect your saved data and use it across memory, knowledge, instruments, prompts and settings. +- Agent Zero will automatically detect your saved data and use it across memory, knowledge, skills, prompts and settings. > [!IMPORTANT] > If you have issues loading your settings, you can try to delete the `/tmp/settings.json` file and let Agent Zero generate a new one. diff --git a/prompts/agent.system.instruments.md b/prompts/agent.system.instruments.md deleted file mode 100644 index ece095724b..0000000000 --- a/prompts/agent.system.instruments.md +++ /dev/null @@ -1,5 +0,0 @@ -# Instruments -- following are instruments at disposal -- do not overly rely on them they might not be relevant - -{{instruments}} diff --git a/prompts/agent.system.main.solving.md b/prompts/agent.system.main.solving.md index 4941fd7774..8c66708700 100644 --- a/prompts/agent.system.main.solving.md +++ b/prompts/agent.system.main.solving.md @@ -6,7 +6,7 @@ explain each step in thoughts 0 outline plan agentic mode active -1 check memories solutions instruments prefer instruments +1 check memories solutions skills prefer skills 2 break task into subtasks if needed diff --git a/prompts/agent.system.main.tips.md b/prompts/agent.system.main.tips.md index 1940d912f0..3827478696 100644 --- a/prompts/agent.system.main.tips.md +++ b/prompts/agent.system.main.tips.md @@ -10,10 +10,10 @@ memory refers memory tools not own knowledge when not in project save files in /root don't use spaces in file names -## Instruments +## Skills -instruments are programs to solve tasks -instrument descriptions in prompt executed with code_execution_tool +skills are contextual expertise to solve tasks (SKILL.md standard) +skill descriptions in prompt executed with code_execution_tool or skills_tool ## Best practices diff --git a/prompts/agent.system.tool.skills.md b/prompts/agent.system.tool.skills.md new file mode 100644 index 0000000000..9721ccbd10 --- /dev/null +++ b/prompts/agent.system.tool.skills.md @@ -0,0 +1,356 @@ +### skills_tool + +manage and use agent skills for specialized capabilities +skills are composable bundles of instructions context and executable code +use progressive disclosure: metadata → full content → referenced files +use "method" arg to specify operation: "list" "load" "read_file" "execute_script" "search" + +## Overview + +Skills system provides three-level progressive disclosure: +- Level 1: Metadata (name + description) loaded in system prompt at startup +- Level 2: Full SKILL.md content loaded when relevant to task +- Level 3+: Referenced files and scripts loaded on-demand + +When to use skills: +- Task matches skill description from available skills list +- Need specialized procedures or domain knowledge +- Task requires bundled scripts or automation +- Need step-by-step guidance for complex operations + +Progressive workflow: +1. Check available skills metadata already in your context +2. Use "search" if looking for specific capability +3. Use "load" to get full skill instructions and context +4. Use "read_file" to load additional reference documents +5. Use "execute_script" to run deterministic operations + +## Operations + +### 1. list available skills + +Lists all available skills with metadata +Shows name, version, description, tags, and author +Use when: exploring available capabilities or confirming skill exists + +~~~json +{ + "thoughts": [ + "Need to see what skills are available", + "User asked about available capabilities" + ], + "headline": "Listing all available skills", + "tool_name": "skills_tool", + "tool_args": { + "method": "list" + } +} +~~~ + +Response format: +- Skill name and version +- Brief description +- Tags for categorization +- Author attribution + +### 2. load full skill content + +Loads complete SKILL.md content with instructions and procedures +Returns metadata, full content, and list of referenced files +Use when: identified relevant skill and need detailed instructions + +~~~json +{ + "thoughts": [ + "User needs PDF form extraction", + "pdf_editing skill will provide procedures", + "Loading full skill content" + ], + "headline": "Loading PDF editing skill", + "tool_name": "skills_tool", + "tool_args": { + "method": "load", + "skill_name": "pdf_editing" + } +} +~~~ + +Required args: +- skill_name: exact name from metadata or list + +Response includes: +- Skill metadata (name, version, description, tags) +- Full markdown content with instructions +- List of referenced files available to load +- Code examples and procedures + +### 3. read skill reference file + +Reads additional reference files from skill directory +Files referenced in SKILL.md can be loaded progressively +Use when: need detailed documentation or examples from skill references + +~~~json +{ + "thoughts": [ + "Skill mentioned forms.md for form filling details", + "Need specific form field handling instructions", + "Loading reference file" + ], + "headline": "Reading PDF forms reference documentation", + "tool_name": "skills_tool", + "tool_args": { + "method": "read_file", + "skill_name": "pdf_editing", + "file_path": "forms.md" + } +} +~~~ + +Required args: +- skill_name: name of skill containing file +- file_path: relative path within skill directory (e.g. "reference.md" or "examples/example1.md") + +Security: +- Path validation prevents directory traversal +- Only files within skill directory accessible +- Supports markdown, text, code files + +### 4. execute skill script + +Executes bundled scripts from skill with arguments +Scripts run in sandbox with injected arguments +Use when: skill provides script for deterministic operation or automation + +~~~json +{ + "thoughts": [ + "Need to extract PDF form fields programmatically", + "Skill provides extract_fields.py script", + "Executing with target PDF path" + ], + "headline": "Executing PDF field extraction script", + "tool_name": "skills_tool", + "tool_args": { + "method": "execute_script", + "skill_name": "pdf_editing", + "script_path": "scripts/extract_fields.py", + "script_args": { + "pdf_path": "/path/to/form.pdf", + "output_format": "json" + } + } +} +~~~ + +Required args: +- skill_name: name of skill containing script +- script_path: relative path to script file +- script_args: dictionary of arguments passed to script + +Supported script types: +- .py (Python): args injected as _skill_args dictionary +- .js (Node.js): args injected as _skill_args constant +- .sh (Shell): args exported as environment variables + +Script execution: +- Runs in Docker container sandbox +- Has access to installed packages +- Returns stdout/stderr output +- Secure and isolated execution + +### 5. search skills by query + +Searches skills by text matching in name, description, and tags +Returns ranked results by relevance score +Use when: looking for skills without knowing exact name + +~~~json +{ + "thoughts": [ + "User needs web scraping capability", + "Not sure of exact skill name", + "Searching for web-related skills" + ], + "headline": "Searching for web scraping skills", + "tool_name": "skills_tool", + "tool_args": { + "method": "search", + "query": "web scraping html parsing" + } +} +~~~ + +Required args: +- query: search text (searches name, description, tags) + +Scoring: +- Name match: +3 points +- Description match: +2 points +- Tag match: +1 point per tag +- Results sorted by descending score + +## Best Practices + +### When to use skills vs other tools + +Use skills when: +- Task requires specialized domain knowledge +- Need structured procedures or step-by-step guidance +- Deterministic scripts available for automation +- Complex multi-step operations with best practices + +Use other tools when: +- Simple file operations (use code_execution_tool) +- Web search (use search_engine) +- General computation (use code_execution_tool) +- Memory operations (use memory tools) + +### Progressive disclosure workflow + +1. Start with metadata (already in context) + - Check available skills list in system prompt + - Match task to skill description + +2. Load full content when relevant + - Use "load" to get complete instructions + - Review procedures and examples + +3. Load references as needed + - Use "read_file" for detailed documentation + - Load only files relevant to current subtask + +4. Execute scripts for automation + - Use "execute_script" for deterministic operations + - Provide appropriate arguments from context + +### Common patterns + +Pattern: Using a skill for first time +1. Identify skill from metadata +2. Load full skill content +3. Follow instructions in content +4. Load reference files if mentioned +5. Execute scripts if provided + +Pattern: Quick script execution +1. Know skill name from previous use +2. Execute script directly with args +3. Process output + +Pattern: Exploring capabilities +1. Search with query terms +2. Review matches +3. Load most relevant skill + +## Error Handling + +Common errors: +- "Skill not found": Check spelling, use list or search to find correct name +- "File not found": Verify file_path matches referenced files from load output +- "Script failed": Check script_args match expected parameters, review skill docs +- "Unsupported script type": Only .py, .js, .sh supported + +When skill loading fails: +- Verify skill exists using list method +- Check for typos in skill_name +- Ensure skill system is enabled in settings + +When script execution fails: +- Review skill documentation for required arguments +- Check script_args dictionary format +- Verify required packages installed in container +- Check script output for specific error messages + +## Examples + +Example 1: PDF form field extraction +~~~json +{ + "thoughts": [ + "User has PDF form to analyze", + "pdf_editing skill has extraction capabilities", + "Will load skill and execute extraction script" + ], + "headline": "Extracting PDF form fields", + "tool_name": "skills_tool", + "tool_args": { + "method": "execute_script", + "skill_name": "pdf_editing", + "script_path": "scripts/extract_fields.py", + "script_args": { + "pdf_path": "/workspace/application.pdf" + } + } +} +~~~ + +Example 2: Web scraping with custom selector +~~~json +{ + "thoughts": [ + "Need to scrape product prices from website", + "web_scraping skill provides fetch script", + "Using CSS selector to target price elements" + ], + "headline": "Scraping product prices from webpage", + "tool_name": "skills_tool", + "tool_args": { + "method": "execute_script", + "skill_name": "web_scraping", + "script_path": "scripts/fetch_page.py", + "script_args": { + "url": "https://example.com/products", + "selector": ".price" + } + } +} +~~~ + +Example 3: Data analysis workflow +~~~json +{ + "thoughts": [ + "User needs CSV analysis", + "data_analysis skill has analysis procedures", + "Loading skill for detailed instructions" + ], + "headline": "Loading data analysis skill", + "tool_name": "skills_tool", + "tool_args": { + "method": "load", + "skill_name": "data_analysis" + } +} +~~~ + +Then follow up with script: +~~~json +{ + "thoughts": [ + "Skill loaded, now analyzing CSV with grouping", + "Using analyze_csv script with group_by parameter" + ], + "headline": "Analyzing sales data grouped by category", + "tool_name": "skills_tool", + "tool_args": { + "method": "execute_script", + "skill_name": "data_analysis", + "script_path": "scripts/analyze_csv.py", + "script_args": { + "csv_path": "/workspace/sales_data.csv", + "group_by": "category" + } + } +} +~~~ + +## Notes + +- Skills metadata already loaded in your system prompt +- Skills cache after first load for efficiency +- Referenced files listed in load response +- Scripts inject arguments as _skill_args variable +- All operations return formatted text responses +- Skills follow the open SKILL.md standard (cross-platform compatible) +- Use skills for structured procedures and contextual expertise diff --git a/python/helpers/backup.py b/python/helpers/backup.py index 4e4873371d..b0d942ffb6 100644 --- a/python/helpers/backup.py +++ b/python/helpers/backup.py @@ -64,9 +64,9 @@ def _get_default_patterns(self) -> str: {agent_root}/knowledge/** !{agent_root}/knowledge/default/** -# Agent Zero Instruments (excluding defaults) -{agent_root}/instruments/** -!{agent_root}/instruments/default/** +# Agent Zero Skills (excluding builtins) +{agent_root}/skills/** +!{agent_root}/skills/builtin/** # Memory (excluding embeddings cache) {agent_root}/memory/** diff --git a/python/helpers/mcp_server.py b/python/helpers/mcp_server.py index 3c0308ed9c..2c3a6c2210 100644 --- a/python/helpers/mcp_server.py +++ b/python/helpers/mcp_server.py @@ -318,20 +318,15 @@ def reconfigure(self, token: str): http_path = f"/t-{self.token}/http" message_path = f"/t-{self.token}/messages/" - # Update settings in the MCP server instance if provided - mcp_server.settings.message_path = message_path - mcp_server.settings.sse_path = sse_path - # Create new MCP apps with updated settings with self._lock: self.sse_app = create_sse_app( server=mcp_server, - message_path=mcp_server.settings.message_path, - sse_path=mcp_server.settings.sse_path, - auth_server_provider=mcp_server._auth_server_provider, - auth_settings=mcp_server.settings.auth, - debug=mcp_server.settings.debug, - routes=mcp_server._additional_http_routes, + message_path=message_path, + sse_path=sse_path, + auth=None, # No auth configured + debug=False, + routes=[], middleware=[Middleware(BaseHTTPMiddleware, dispatch=mcp_middleware)], ) @@ -339,13 +334,12 @@ def reconfigure(self, token: str): # doesn't work properly in our Flask/Werkzeug environment self.http_app = self._create_custom_http_app( http_path, - mcp_server._auth_server_provider, - mcp_server.settings.auth, - mcp_server.settings.debug, - mcp_server._additional_http_routes, + None, # No auth configured + False, + [], ) - def _create_custom_http_app(self, streamable_http_path, auth_server_provider, auth_settings, debug, routes): + def _create_custom_http_app(self, streamable_http_path, auth, debug, routes): """Create a custom HTTP app that manages the session manager manually.""" from fastmcp.server.http import setup_auth_middleware_and_routes, create_base_app # type: ignore from mcp.server.streamable_http_manager import StreamableHTTPSessionManager # type: ignore @@ -358,7 +352,6 @@ def _create_custom_http_app(self, streamable_http_path, auth_server_provider, au self.http_session_task_group = None - # Create session manager self.http_session_manager = StreamableHTTPSessionManager( app=mcp_server._mcp_server, @@ -367,7 +360,6 @@ def _create_custom_http_app(self, streamable_http_path, auth_server_provider, au stateless=False, ) - # Custom ASGI handler that ensures task group is initialized async def handle_streamable_http(scope, receive, send): # Lazy initialization of task group @@ -380,29 +372,13 @@ async def handle_streamable_http(scope, receive, send): if self.http_session_manager: await self.http_session_manager.handle_request(scope, receive, send) - # Get auth middleware and routes - auth_middleware, auth_routes, required_scopes = setup_auth_middleware_and_routes( - auth_server_provider, auth_settings - ) - - server_routes.extend(auth_routes) - server_middleware.extend(auth_middleware) - - # Add StreamableHTTP routes with or without auth - if auth_server_provider: - server_routes.append( - Mount( - streamable_http_path, - app=RequireAuthMiddleware(handle_streamable_http, required_scopes), - ) - ) - else: - server_routes.append( - Mount( - streamable_http_path, - app=handle_streamable_http, - ) + # Add StreamableHTTP route (no auth) + server_routes.append( + Mount( + streamable_http_path, + app=handle_streamable_http, ) + ) # Add custom routes with lowest precedence if routes: diff --git a/python/helpers/memory.py b/python/helpers/memory.py index 8c8785c5af..bb5cc593ba 100644 --- a/python/helpers/memory.py +++ b/python/helpers/memory.py @@ -57,7 +57,7 @@ class Area(Enum): MAIN = "main" FRAGMENTS = "fragments" SOLUTIONS = "solutions" - INSTRUMENTS = "instruments" + SKILLS = "skills" # Open SKILL.md standard (replaces legacy instruments) index: dict[str, "MyFaiss"] = {} @@ -323,15 +323,17 @@ def _preload_knowledge_folders( recursive=True, ) - # load instruments descriptions - index = knowledge_import.load_knowledge( - log_item, - files.get_abs_path("instruments"), - index, - {"area": Memory.Area.INSTRUMENTS.value}, - filename_pattern="**/*.md", - recursive=True, - ) + # load skills from custom, builtin, and shared directories (SKILL.md standard) + skills_dirs = ["custom", "builtin", "shared"] + for skills_subdir in skills_dirs: + skills_path = files.get_abs_path("skills", skills_subdir) + index = knowledge_import.load_knowledge( + log_item, + skills_path, + index, + {"area": Memory.Area.SKILLS.value}, + filename_pattern="**/SKILL.md", + ) return index diff --git a/python/helpers/memory_consolidation.py b/python/helpers/memory_consolidation.py index 6a100d8f48..1ba0b6b402 100644 --- a/python/helpers/memory_consolidation.py +++ b/python/helpers/memory_consolidation.py @@ -82,7 +82,7 @@ async def process_new_memory( Args: new_memory: The new memory content to process - area: Memory area (MAIN, FRAGMENTS, SOLUTIONS, INSTRUMENTS) + area: Memory area (MAIN, FRAGMENTS, SOLUTIONS, SKILLS) metadata: Initial metadata for the memory log_item: Optional log item for progress tracking diff --git a/python/helpers/skills_cli.py b/python/helpers/skills_cli.py new file mode 100644 index 0000000000..357bac6125 --- /dev/null +++ b/python/helpers/skills_cli.py @@ -0,0 +1,364 @@ +#!/usr/bin/env python3 +""" +Skills CLI - Easy skill management for Agent Zero + +Usage: + python -m python.helpers.skills_cli list List all skills + python -m python.helpers.skills_cli create Create a new skill + python -m python.helpers.skills_cli show Show skill details + python -m python.helpers.skills_cli validate Validate a skill + python -m python.helpers.skills_cli search Search skills +""" + +import argparse +import os +import sys +import yaml +import re +from pathlib import Path +from typing import Optional, List, Dict, Any +from dataclasses import dataclass +from datetime import datetime + +# Add parent directory to path for imports +sys.path.insert(0, str(Path(__file__).parent.parent.parent)) + +from python.helpers import files + + +@dataclass +class Skill: + """Represents a skill loaded from SKILL.md""" + name: str + description: str + path: Path + version: str = "1.0.0" + author: str = "" + tags: List[str] = None + trigger_patterns: List[str] = None + content: str = "" + + def __post_init__(self): + if self.tags is None: + self.tags = [] + if self.trigger_patterns is None: + self.trigger_patterns = [] + + +def get_skills_dirs() -> List[Path]: + """Get all skill directories""" + base = Path(files.get_abs_path("skills")) + return [ + base / "builtin", + base / "custom", + base / "shared", + ] + + +def parse_skill_file(skill_path: Path) -> Optional[Skill]: + """Parse a SKILL.md file and return a Skill object""" + try: + content = skill_path.read_text(encoding="utf-8") + + # Parse YAML frontmatter + if content.startswith("---"): + parts = content.split("---", 2) + if len(parts) >= 3: + frontmatter = yaml.safe_load(parts[1]) + body = parts[2].strip() + + return Skill( + name=frontmatter.get("name", skill_path.parent.name), + description=frontmatter.get("description", ""), + path=skill_path.parent, + version=frontmatter.get("version", "1.0.0"), + author=frontmatter.get("author", ""), + tags=frontmatter.get("tags", []), + trigger_patterns=frontmatter.get("trigger_patterns", []), + content=body, + ) + + return None + except Exception as e: + print(f"Error parsing {skill_path}: {e}") + return None + + +def list_skills() -> List[Skill]: + """List all available skills""" + skills = [] + for skills_dir in get_skills_dirs(): + if not skills_dir.exists(): + continue + for skill_dir in skills_dir.iterdir(): + if skill_dir.is_dir(): + skill_file = skill_dir / "SKILL.md" + if skill_file.exists(): + skill = parse_skill_file(skill_file) + if skill: + skills.append(skill) + return skills + + +def find_skill(name: str) -> Optional[Skill]: + """Find a skill by name""" + for skill in list_skills(): + if skill.name == name or skill.path.name == name: + return skill + return None + + +def search_skills(query: str) -> List[Skill]: + """Search skills by name, description, or tags""" + query = query.lower() + results = [] + for skill in list_skills(): + if ( + query in skill.name.lower() + or query in skill.description.lower() + or any(query in tag.lower() for tag in skill.tags) + or any(query in trigger.lower() for trigger in skill.trigger_patterns) + ): + results.append(skill) + return results + + +def validate_skill(skill: Skill) -> List[str]: + """Validate a skill and return list of issues""" + issues = [] + + # Required fields + if not skill.name: + issues.append("Missing required field: name") + if not skill.description: + issues.append("Missing required field: description") + + # Name format + if skill.name and not re.match(r"^[a-z0-9_-]+$", skill.name): + issues.append(f"Invalid name format: '{skill.name}' (use lowercase, hyphens, underscores)") + + # Description length + if skill.description and len(skill.description) < 20: + issues.append("Description is too short (minimum 20 characters)") + + # Content + if len(skill.content) < 100: + issues.append("Skill content is too short (minimum 100 characters)") + + # Check for associated files + skill_dir = skill.path + has_scripts = (skill_dir / "scripts").exists() + has_docs = (skill_dir / "docs").exists() + + return issues + + +def create_skill(name: str, description: str = "", author: str = "") -> Path: + """Create a new skill from template""" + # Use custom directory for user-created skills + custom_dir = Path(files.get_abs_path("skills/custom")) + custom_dir.mkdir(parents=True, exist_ok=True) + + skill_dir = custom_dir / name + if skill_dir.exists(): + raise ValueError(f"Skill '{name}' already exists at {skill_dir}") + + # Create directory structure + skill_dir.mkdir(parents=True) + (skill_dir / "scripts").mkdir() + (skill_dir / "docs").mkdir() + + # Create SKILL.md from template + skill_content = f'''--- +name: "{name}" +description: "{description or 'Description of what this skill does and when to use it'}" +version: "1.0.0" +author: "{author or 'Your Name'}" +tags: ["custom"] +trigger_patterns: + - "{name}" +--- + +# {name.replace("-", " ").replace("_", " ").title()} + +## When to Use + +Describe when this skill should be activated. + +## Instructions + +Provide detailed instructions for the agent to follow. + +### Step 1: First Step + +Description of what to do first. + +### Step 2: Second Step + +Description of what to do next. + +## Examples + +**User**: "Example prompt that triggers this skill" + +**Agent Response**: +> Example of how the agent should respond + +## Tips + +- Tip 1: Helpful guidance +- Tip 2: More helpful guidance + +## Anti-Patterns + +- Don't do this +- Avoid that +''' + + skill_file = skill_dir / "SKILL.md" + skill_file.write_text(skill_content, encoding="utf-8") + + # Create placeholder README in docs + readme = skill_dir / "docs" / "README.md" + readme.write_text(f"# {name}\n\nAdditional documentation for the {name} skill.\n") + + return skill_dir + + +def print_skill_table(skills: List[Skill]): + """Print skills in a formatted table""" + if not skills: + print("No skills found.") + return + + # Calculate column widths + name_width = max(len(s.name) for s in skills) + 2 + desc_width = 50 + + # Print header + print(f"\n{'Name':<{name_width}} {'Version':<10} {'Tags':<20} Description") + print("-" * (name_width + 80)) + + # Print skills + for skill in skills: + tags = ", ".join(skill.tags[:3]) + if len(skill.tags) > 3: + tags += "..." + desc = skill.description[:desc_width] + if len(skill.description) > desc_width: + desc += "..." + print(f"{skill.name:<{name_width}} {skill.version:<10} {tags:<20} {desc}") + + print(f"\nTotal: {len(skills)} skills") + + +def main(): + parser = argparse.ArgumentParser( + description="Agent Zero Skills CLI", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + %(prog)s list List all skills + %(prog)s create my-skill Create a new skill + %(prog)s show brainstorming Show skill details + %(prog)s validate my-skill Validate a skill + %(prog)s search python Search for skills + """ + ) + + subparsers = parser.add_subparsers(dest="command", help="Available commands") + + # List command + list_parser = subparsers.add_parser("list", help="List all skills") + list_parser.add_argument("--tags", help="Filter by tags (comma-separated)") + + # Create command + create_parser = subparsers.add_parser("create", help="Create a new skill") + create_parser.add_argument("name", help="Skill name (lowercase, use hyphens)") + create_parser.add_argument("-d", "--description", help="Skill description") + create_parser.add_argument("-a", "--author", help="Author name") + + # Show command + show_parser = subparsers.add_parser("show", help="Show skill details") + show_parser.add_argument("name", help="Skill name") + + # Validate command + validate_parser = subparsers.add_parser("validate", help="Validate a skill") + validate_parser.add_argument("name", help="Skill name") + + # Search command + search_parser = subparsers.add_parser("search", help="Search skills") + search_parser.add_argument("query", help="Search query") + + args = parser.parse_args() + + if args.command == "list": + skills = list_skills() + if args.tags: + filter_tags = [t.strip().lower() for t in args.tags.split(",")] + skills = [s for s in skills if any(t in [tag.lower() for tag in s.tags] for t in filter_tags)] + print_skill_table(skills) + + elif args.command == "create": + try: + skill_dir = create_skill(args.name, args.description, args.author) + print(f"\n✅ Created skill at: {skill_dir}") + print(f"\nNext steps:") + print(f" 1. Edit {skill_dir / 'SKILL.md'} to add your instructions") + print(f" 2. Add any helper scripts to {skill_dir / 'scripts'}/") + print(f" 3. Run: python -m python.helpers.skills_cli validate {args.name}") + except ValueError as e: + print(f"\n❌ Error: {e}") + sys.exit(1) + + elif args.command == "show": + skill = find_skill(args.name) + if skill: + print(f"\n{'=' * 60}") + print(f"Skill: {skill.name}") + print(f"{'=' * 60}") + print(f"Version: {skill.version}") + print(f"Author: {skill.author or 'Unknown'}") + print(f"Path: {skill.path}") + print(f"Tags: {', '.join(skill.tags) if skill.tags else 'None'}") + print(f"Triggers: {', '.join(skill.trigger_patterns) if skill.trigger_patterns else 'None'}") + print(f"\nDescription:") + print(f" {skill.description}") + print(f"\nContent Preview (first 500 chars):") + print("-" * 60) + print(skill.content[:500]) + if len(skill.content) > 500: + print("...") + print("-" * 60) + else: + print(f"\n❌ Skill '{args.name}' not found") + sys.exit(1) + + elif args.command == "validate": + skill = find_skill(args.name) + if skill: + issues = validate_skill(skill) + if issues: + print(f"\n⚠️ Validation issues for '{args.name}':") + for issue in issues: + print(f" - {issue}") + else: + print(f"\n✅ Skill '{args.name}' is valid!") + else: + print(f"\n❌ Skill '{args.name}' not found") + sys.exit(1) + + elif args.command == "search": + results = search_skills(args.query) + if results: + print(f"\nSearch results for '{args.query}':") + print_skill_table(results) + else: + print(f"\nNo skills found matching '{args.query}'") + + else: + parser.print_help() + + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt index a14a853393..34592991cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ browser-use==0.5.11 docker==7.1.0 duckduckgo-search==6.1.12 faiss-cpu==1.11.0 -fastmcp==2.3.4 +fastmcp==2.11.0 fasta2a==0.5.0 flask[async]==3.0.3 flask-basicauth==0.2.0 @@ -19,7 +19,7 @@ langchain-unstructured[all-docs]==0.1.6 openai-whisper==20240930 lxml_html_clean==0.3.1 markdown==3.7 -mcp==1.13.1 +mcp==1.12.4 newspaper3k==0.2.8 paramiko==3.5.0 playwright==1.52.0 @@ -47,4 +47,7 @@ html2text>=2024.2.26 beautifulsoup4>=4.12.3 boto3>=1.35.0 exchangelib>=5.4.3 -pywinpty==3.0.2; sys_platform == "win32" \ No newline at end of file +pywinpty==3.0.2; sys_platform == "win32" +seaborn==0.13.2 +pydantic>=2.0,<2.12 +pydantic-settings>=2.0,<2.12 diff --git a/skills/builtin/api_development/SKILL.md b/skills/builtin/api_development/SKILL.md new file mode 100644 index 0000000000..0893d70415 --- /dev/null +++ b/skills/builtin/api_development/SKILL.md @@ -0,0 +1,385 @@ +--- +name: "api_development" +description: "Best practices for designing and implementing RESTful and GraphQL APIs. Use when building, designing, or reviewing APIs." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["api", "rest", "graphql", "design", "backend", "web"] +trigger_patterns: + - "api" + - "endpoint" + - "rest" + - "graphql" + - "http" +--- + +# API Development Skill + +Best practices for designing, implementing, and documenting APIs. + +## RESTful API Design + +### URL Structure + +``` +https://api.example.com/v1/resources/{id}/subresources +``` + +**Guidelines:** +- Use nouns, not verbs: `/users` not `/getUsers` +- Use plural nouns: `/users` not `/user` +- Use kebab-case: `/user-profiles` not `/userProfiles` +- Nest resources logically: `/users/{id}/orders` +- Version your API: `/v1/`, `/v2/` + +### HTTP Methods + +| Method | Purpose | Example | +|--------|---------|---------| +| `GET` | Retrieve resource(s) | `GET /users/123` | +| `POST` | Create resource | `POST /users` | +| `PUT` | Replace resource | `PUT /users/123` | +| `PATCH` | Partial update | `PATCH /users/123` | +| `DELETE` | Remove resource | `DELETE /users/123` | + +### Status Codes + +| Code | Meaning | When to Use | +|------|---------|-------------| +| `200 OK` | Success | GET, PUT, PATCH success | +| `201 Created` | Resource created | POST success | +| `204 No Content` | Success, no body | DELETE success | +| `400 Bad Request` | Invalid input | Validation failed | +| `401 Unauthorized` | Not authenticated | Missing/invalid token | +| `403 Forbidden` | Not authorized | Insufficient permissions | +| `404 Not Found` | Resource not found | ID doesn't exist | +| `409 Conflict` | Resource conflict | Duplicate entry | +| `422 Unprocessable` | Semantic error | Valid syntax, invalid data | +| `429 Too Many` | Rate limited | Exceeded request limit | +| `500 Server Error` | Internal error | Unexpected failure | + +### Request/Response Format + +**Request:** +```http +POST /api/v1/users HTTP/1.1 +Content-Type: application/json +Authorization: Bearer + +{ + "email": "user@example.com", + "name": "John Doe", + "role": "user" +} +``` + +**Success Response:** +```json +{ + "data": { + "id": "123", + "email": "user@example.com", + "name": "John Doe", + "role": "user", + "created_at": "2024-01-15T10:30:00Z" + }, + "meta": { + "request_id": "abc-123" + } +} +``` + +**Error Response:** +```json +{ + "error": { + "code": "VALIDATION_ERROR", + "message": "Invalid input data", + "details": [ + { + "field": "email", + "message": "Invalid email format" + } + ] + }, + "meta": { + "request_id": "abc-123" + } +} +``` + +### Pagination + +**Request:** +```http +GET /api/v1/users?page=2&per_page=20 +``` + +**Response:** +```json +{ + "data": [...], + "meta": { + "current_page": 2, + "per_page": 20, + "total_pages": 10, + "total_count": 195 + }, + "links": { + "first": "/api/v1/users?page=1&per_page=20", + "prev": "/api/v1/users?page=1&per_page=20", + "next": "/api/v1/users?page=3&per_page=20", + "last": "/api/v1/users?page=10&per_page=20" + } +} +``` + +### Filtering & Sorting + +```http +# Filtering +GET /api/v1/users?status=active&role=admin + +# Sorting +GET /api/v1/users?sort=created_at&order=desc + +# Multiple sort fields +GET /api/v1/users?sort=-created_at,name +``` + +### Field Selection + +```http +GET /api/v1/users?fields=id,name,email +``` + +## Authentication + +### JWT (JSON Web Token) + +```javascript +// Token structure +{ + "header": { + "alg": "HS256", + "typ": "JWT" + }, + "payload": { + "sub": "user_123", + "email": "user@example.com", + "role": "admin", + "iat": 1516239022, + "exp": 1516242622 + }, + "signature": "..." +} +``` + +**Implementation:** + +```python +# Python example with PyJWT +import jwt +from datetime import datetime, timedelta + +def create_token(user_id: str, secret: str) -> str: + payload = { + "sub": user_id, + "iat": datetime.utcnow(), + "exp": datetime.utcnow() + timedelta(hours=1) + } + return jwt.encode(payload, secret, algorithm="HS256") + +def verify_token(token: str, secret: str) -> dict: + try: + return jwt.decode(token, secret, algorithms=["HS256"]) + except jwt.ExpiredSignatureError: + raise AuthError("Token expired") + except jwt.InvalidTokenError: + raise AuthError("Invalid token") +``` + +### API Keys + +```http +# Header +Authorization: Api-Key + +# Query param (less secure) +GET /api/v1/resource?api_key= +``` + +## Rate Limiting + +**Headers:** +```http +X-RateLimit-Limit: 1000 +X-RateLimit-Remaining: 999 +X-RateLimit-Reset: 1609459200 +``` + +**Implementation:** +```python +from functools import wraps +import time + +class RateLimiter: + def __init__(self, max_requests: int, window_seconds: int): + self.max_requests = max_requests + self.window = window_seconds + self.requests = {} + + def is_allowed(self, client_id: str) -> bool: + now = time.time() + window_start = now - self.window + + # Clean old requests + self.requests[client_id] = [ + t for t in self.requests.get(client_id, []) + if t > window_start + ] + + if len(self.requests[client_id]) >= self.max_requests: + return False + + self.requests[client_id].append(now) + return True +``` + +## Input Validation + +```python +from pydantic import BaseModel, EmailStr, validator + +class CreateUserRequest(BaseModel): + email: EmailStr + name: str + age: int + + @validator('name') + def name_not_empty(cls, v): + if not v.strip(): + raise ValueError('Name cannot be empty') + return v.strip() + + @validator('age') + def age_valid(cls, v): + if v < 0 or v > 150: + raise ValueError('Age must be between 0 and 150') + return v +``` + +## Error Handling + +```python +class APIError(Exception): + def __init__(self, code: str, message: str, status_code: int = 400): + self.code = code + self.message = message + self.status_code = status_code + +@app.errorhandler(APIError) +def handle_api_error(error): + return jsonify({ + "error": { + "code": error.code, + "message": error.message + } + }), error.status_code + +# Usage +raise APIError("USER_NOT_FOUND", "User with ID 123 not found", 404) +``` + +## API Documentation + +### OpenAPI/Swagger Example + +```yaml +openapi: 3.0.0 +info: + title: User API + version: 1.0.0 + +paths: + /users: + get: + summary: List all users + parameters: + - name: page + in: query + schema: + type: integer + default: 1 + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/UserList' + post: + summary: Create a user + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateUser' + responses: + '201': + description: User created + +components: + schemas: + User: + type: object + properties: + id: + type: string + email: + type: string + name: + type: string +``` + +## Security Checklist + +```markdown +- [ ] Use HTTPS only +- [ ] Validate all input +- [ ] Sanitize output +- [ ] Use parameterized queries +- [ ] Implement rate limiting +- [ ] Use secure headers (CORS, CSP) +- [ ] Don't expose internal errors +- [ ] Log security events +- [ ] Rotate secrets regularly +- [ ] Version your API +``` + +## Performance Tips + +1. **Use caching headers** + ```http + Cache-Control: max-age=3600 + ETag: "abc123" + ``` + +2. **Implement compression** + ```http + Accept-Encoding: gzip + Content-Encoding: gzip + ``` + +3. **Use pagination** for large datasets + +4. **Implement field selection** to reduce payload + +5. **Consider async processing** for long operations + ```json + { + "status": "processing", + "job_id": "job_123", + "check_url": "/api/v1/jobs/job_123" + } + ``` diff --git a/skills/builtin/brainstorming/SKILL.md b/skills/builtin/brainstorming/SKILL.md new file mode 100644 index 0000000000..71aaa8ffea --- /dev/null +++ b/skills/builtin/brainstorming/SKILL.md @@ -0,0 +1,123 @@ +--- +name: "brainstorming" +description: "Structured brainstorming and requirements exploration before implementation. Use this BEFORE any creative work like building features, creating components, or adding functionality." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["planning", "design", "requirements", "architecture", "creative"] +trigger_patterns: + - "create" + - "build" + - "implement" + - "add feature" + - "design" + - "develop" +--- + +# Brainstorming Skill + +**CRITICAL**: Use this skill BEFORE writing any implementation code. This ensures proper requirements exploration and design alignment. + +## When to Use + +Activate this skill when you encounter: +- "Create a new feature..." +- "Build a component that..." +- "Implement X functionality..." +- "Add support for..." +- "Design a system that..." + +## The Brainstorming Process + +### Phase 1: Understanding Intent (5 questions max) + +Ask clarifying questions to understand: + +1. **Goal Clarity**: What specific outcome does the user want? +2. **Context**: What existing code/systems does this interact with? +3. **Constraints**: Are there performance, security, or compatibility requirements? +4. **Edge Cases**: What happens in failure scenarios? +5. **Success Criteria**: How will we know it's working correctly? + +### Phase 2: Design Options + +Present 2-3 implementation approaches with trade-offs: + +```markdown +## Option A: [Name] +**Approach**: Brief description +**Pros**: List benefits +**Cons**: List drawbacks +**Best for**: When to choose this + +## Option B: [Name] +**Approach**: Brief description +**Pros**: List benefits +**Cons**: List drawbacks +**Best for**: When to choose this +``` + +### Phase 3: Technical Specification + +Once approach is chosen, document: + +1. **Files to Create/Modify**: List with brief description +2. **Dependencies**: External packages or internal modules needed +3. **Data Flow**: How data moves through the system +4. **API Contracts**: Input/output specifications +5. **Test Strategy**: How this will be tested + +### Phase 4: Implementation Plan + +Break down into ordered tasks: + +```markdown +## Implementation Tasks +1. [ ] Task 1 - Description +2. [ ] Task 2 - Description (depends on 1) +3. [ ] Task 3 - Description +4. [ ] Task 4 - Integration testing +``` + +## Anti-Patterns to Avoid + +- **Jumping to Code**: Never start coding without understanding requirements +- **Single Solution Bias**: Always consider at least 2 approaches +- **Ignoring Context**: Always examine existing patterns in the codebase +- **Over-Engineering**: Keep solutions proportional to the problem +- **Under-Specifying**: Be specific enough that implementation is clear + +## Example Session + +**User**: "Add dark mode to the application" + +**Agent Response**: +> Before implementing dark mode, let me understand your requirements: +> +> 1. **Scope**: Should this apply to the entire application or specific sections? +> 2. **Toggle**: How should users switch modes? (button, system preference, both?) +> 3. **Persistence**: Should the preference be saved across sessions? +> 4. **Theming Approach**: Do you have existing CSS variables, or should we create a new theme system? +> 5. **Transition**: Should there be smooth transitions when switching modes? + +## Output Format + +After brainstorming, provide a clear summary: + +```markdown +## Summary: [Feature Name] + +### Chosen Approach +[Brief description of selected approach] + +### Key Decisions +- Decision 1: Rationale +- Decision 2: Rationale + +### Implementation Tasks +1. Task 1 +2. Task 2 +3. Task 3 + +### Ready to Implement +Confirm with user before proceeding to implementation. +``` diff --git a/skills/builtin/code_review/SKILL.md b/skills/builtin/code_review/SKILL.md new file mode 100644 index 0000000000..608483d0bb --- /dev/null +++ b/skills/builtin/code_review/SKILL.md @@ -0,0 +1,272 @@ +--- +name: "code_review" +description: "Comprehensive code review skill for analyzing code quality, identifying issues, and suggesting improvements. Use when reviewing PRs or checking code quality." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["review", "quality", "security", "best-practices", "pr"] +trigger_patterns: + - "review" + - "check code" + - "code quality" + - "pull request" + - "PR" +--- + +# Code Review Skill + +**Goal**: Provide actionable, constructive feedback that improves code quality. + +## Review Categories + +### 1. Correctness +- Does the code do what it's supposed to? +- Are there logic errors? +- Are edge cases handled? + +### 2. Security +- Input validation +- Authentication/authorization +- SQL injection, XSS prevention +- Secrets exposure + +### 3. Performance +- Algorithmic complexity +- Database query efficiency +- Memory usage +- Caching opportunities + +### 4. Maintainability +- Code readability +- Naming conventions +- Documentation +- Single responsibility + +### 5. Testing +- Test coverage +- Test quality +- Edge case testing + +## Review Process + +### Phase 1: Understand Context + +Before reviewing: +1. What is the purpose of this change? +2. What problem is it solving? +3. What are the requirements? +4. Are there related changes elsewhere? + +### Phase 2: High-Level Review + +Look at: +1. **Architecture**: Does the approach make sense? +2. **Design patterns**: Are appropriate patterns used? +3. **File organization**: Is code in the right place? +4. **Dependencies**: Are new dependencies justified? + +### Phase 3: Line-by-Line Review + +For each file: +1. Read through understanding intent +2. Check for issues in each category +3. Note both problems and good practices + +### Phase 4: Provide Feedback + +Structure feedback clearly: + +```markdown +## Review Summary + +### Must Fix (Blockers) +- [ ] **Security**: SQL injection vulnerability in line 42 +- [ ] **Bug**: Off-by-one error in loop at line 78 + +### Should Fix (Important) +- [ ] **Performance**: N+1 query problem in user loader +- [ ] **Maintainability**: Function too long (150+ lines) + +### Consider (Suggestions) +- [ ] **Style**: Variable naming could be more descriptive +- [ ] **Testing**: Add test for empty input case + +### Positives +- Good use of error handling +- Clear separation of concerns +``` + +## Code Smells to Watch For + +### Complexity +- **Long methods**: > 20-30 lines +- **Deep nesting**: > 3-4 levels +- **Too many parameters**: > 4-5 params +- **God classes**: Classes doing too much + +### Duplication +- Copy-pasted code blocks +- Similar logic in multiple places +- Magic numbers repeated + +### Coupling +- Tight coupling between modules +- Circular dependencies +- Inappropriate intimacy + +### Naming +- Single-letter variables (except loops) +- Misleading names +- Inconsistent conventions + +## Security Checklist + +```markdown +- [ ] Input validation on all user input +- [ ] Parameterized queries (no string concatenation for SQL) +- [ ] Output encoding (prevent XSS) +- [ ] Authentication checked on protected routes +- [ ] Authorization checked for resource access +- [ ] Sensitive data not logged +- [ ] Secrets not hardcoded +- [ ] HTTPS enforced for sensitive data +- [ ] Rate limiting on authentication endpoints +- [ ] CORS properly configured +``` + +## Feedback Guidelines + +### Be Constructive +```markdown +# Bad +"This code is terrible" + +# Good +"This approach works, but consider using X for better +performance because [specific reason]" +``` + +### Be Specific +```markdown +# Bad +"Fix the naming" + +# Good +"Rename `d` to `document_count` for clarity. +Single-letter variables make the code harder to understand" +``` + +### Explain Why +```markdown +# Bad +"Don't use global variables" + +# Good +"Global variables can cause issues because: +1. They make testing difficult +2. They create hidden dependencies +3. They can be modified from anywhere + +Consider passing this as a parameter instead." +``` + +### Offer Solutions +```markdown +# Instead of just: +"This is inefficient" + +# Provide: +"This is O(n²) due to the nested loops. Consider using +a Set for the lookup to achieve O(n): + +```python +seen = set(processed_ids) +for item in items: + if item.id in seen: # O(1) lookup + continue +```" +``` + +## Review Checklist Template + +```markdown +## Code Review: [PR Title] + +### Context Understanding +- [ ] I understand the purpose of this change +- [ ] I've reviewed related documentation/tickets + +### Correctness +- [ ] Logic is correct +- [ ] Edge cases handled +- [ ] Error handling appropriate + +### Security +- [ ] No SQL injection vulnerabilities +- [ ] No XSS vulnerabilities +- [ ] Authentication/authorization correct +- [ ] No secrets exposed + +### Performance +- [ ] No obvious performance issues +- [ ] Database queries efficient +- [ ] No memory leaks + +### Maintainability +- [ ] Code is readable +- [ ] Functions are focused +- [ ] Good naming +- [ ] Appropriate comments + +### Testing +- [ ] Adequate test coverage +- [ ] Tests are meaningful +- [ ] Edge cases tested + +### Verdict +- [ ] Approved +- [ ] Approved with comments +- [ ] Request changes +``` + +## Example Review + +```markdown +## Review: Add user registration endpoint + +### Summary +Generally good implementation! A few security concerns to address. + +### Must Fix +1. **Security (line 45)**: Password stored in plain text + ```python + # Current + user.password = request.password + + # Fix + user.password_hash = hash_password(request.password) + ``` + +2. **Validation (line 38)**: Email not validated + Add email format validation before saving + +### Should Fix +1. **Error Handling (line 52)**: Bare except catches too much + ```python + # Current + except: + return error_response() + + # Fix + except ValidationError as e: + return error_response(str(e)) + ``` + +### Consider +1. Add rate limiting to prevent spam registrations +2. Send confirmation email async to improve response time + +### Positives +- Good use of transactions +- Clear API response structure +- Comprehensive logging +``` diff --git a/skills/builtin/create_skill/SKILL.md b/skills/builtin/create_skill/SKILL.md new file mode 100644 index 0000000000..272cea9726 --- /dev/null +++ b/skills/builtin/create_skill/SKILL.md @@ -0,0 +1,298 @@ +--- +name: "create_skill" +description: "Wizard for creating new Agent Zero skills. Guides users through creating well-structured SKILL.md files. Use when users want to create custom skills." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["meta", "wizard", "creation", "tutorial", "skills"] +trigger_patterns: + - "create skill" + - "new skill" + - "make skill" + - "add skill" + - "skill wizard" +--- + +# Create Skill Wizard + +This skill helps you create new Agent Zero skills that follow the SKILL.md standard. + +## Quick Start + +To create a new skill, I'll guide you through these steps: + +1. **Name & Purpose** - What should this skill do? +2. **Trigger Patterns** - When should this skill activate? +3. **Content Structure** - What instructions should the agent follow? +4. **Supporting Files** - Any scripts or templates needed? + +## SKILL.md Format + +Every skill needs a `SKILL.md` file with YAML frontmatter: + +```yaml +--- +name: "skill-name" +description: "Clear description of what this skill does and when to use it" +version: "1.0.0" +author: "Your Name" +tags: ["category1", "category2"] +trigger_patterns: + - "keyword1" + - "phrase that triggers this" +--- + +# Skill Title + +Your skill instructions go here... +``` + +## Required Fields + +| Field | Description | Example | +|-------|-------------|---------| +| `name` | Unique identifier (lowercase, hyphens) | `"code-review"` | +| `description` | When/why to use this skill | `"Review code for quality and security issues"` | + +## Optional Fields + +| Field | Description | Example | +|-------|-------------|---------| +| `version` | Semantic version | `"1.0.0"` | +| `author` | Creator name | `"Jane Developer"` | +| `tags` | Categorization keywords | `["review", "quality"]` | +| `trigger_patterns` | Words/phrases that activate skill | `["review", "check code"]` | +| `allowed_tools` | Tools this skill can use | `["code_execution", "web_search"]` | + +## Skill Directory Structure + +``` +skills/ +└── custom/ + └── my-skill/ + ├── SKILL.md # Required: Main skill file + ├── scripts/ # Optional: Helper scripts + │ ├── helper.py + │ └── process.sh + ├── templates/ # Optional: Templates + │ └── output.md + └── docs/ # Optional: Additional docs + └── examples.md +``` + +## Writing Good Skill Instructions + +### Be Specific and Actionable + +```markdown +# Good +When reviewing code: +1. Check for security vulnerabilities +2. Verify error handling +3. Assess test coverage + +# Bad +Review the code and make it better. +``` + +### Include Examples + +```markdown +## Example Usage + +**User**: "Review my Python function for issues" + +**Agent Response**: +> I'll review your function using the code review checklist: +> +> 1. **Security**: No user input validation detected +> 2. **Error Handling**: Missing try-catch for file operations +> 3. **Testing**: Function is testable but no tests found +``` + +### Provide Checklists + +```markdown +## Review Checklist +- [ ] Input validation present +- [ ] Error handling complete +- [ ] Tests included +- [ ] Documentation updated +``` + +## Creating Your Skill: Step by Step + +### Step 1: Define Purpose + +Answer these questions: +- What problem does this skill solve? +- When should the agent use it? +- What's the expected output? + +### Step 2: Choose a Name + +- Use lowercase letters and hyphens +- Be descriptive but concise +- Examples: `code-review`, `data-analysis`, `deploy-helper` + +### Step 3: Write Trigger Patterns + +List words/phrases that should activate this skill: + +```yaml +trigger_patterns: + - "review" + - "check code" + - "code quality" + - "pull request" +``` + +### Step 4: Structure Your Content + +Organize with clear sections: + +```markdown +# Skill Title + +## When to Use +Describe the trigger conditions + +## The Process +Step-by-step instructions + +## Examples +Show sample interactions + +## Tips +Additional guidance +``` + +### Step 5: Add Supporting Files (Optional) + +If your skill needs scripts or templates: + +```bash +# Create directory structure +mkdir -p skills/custom/my-skill/{scripts,templates,docs} +``` + +## Example: Complete Skill + +```yaml +--- +name: "python-optimizer" +description: "Optimize Python code for performance and readability. Use when asked to improve or optimize Python code." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["python", "optimization", "performance"] +trigger_patterns: + - "optimize python" + - "improve performance" + - "make faster" + - "python optimization" +--- + +# Python Optimizer + +## When to Use +Activate when user asks to optimize, improve, or speed up Python code. + +## Optimization Process + +### Step 1: Profile First +Before optimizing, understand where time is spent: +```python +import cProfile +cProfile.run('your_function()') +``` + +### Step 2: Common Optimizations + +1. **Use List Comprehensions** + ```python + # Slow + result = [] + for x in data: + result.append(x * 2) + + # Fast + result = [x * 2 for x in data] + ``` + +2. **Use Sets for Lookups** + ```python + # Slow: O(n) + if item in large_list: + + # Fast: O(1) + if item in large_set: + ``` + +3. **Use Generators for Large Data** + ```python + # Memory-heavy + data = [process(x) for x in huge_list] + + # Memory-efficient + data = (process(x) for x in huge_list) + ``` + +### Step 3: Verify Improvement +Always measure before and after: +```python +import time +start = time.perf_counter() +# code to measure +elapsed = time.perf_counter() - start +print(f"Took {elapsed:.4f} seconds") +``` + +## Anti-Patterns to Avoid +- Premature optimization +- Optimizing without profiling +- Sacrificing readability for tiny gains +``` + +## Skill Installation + +### Local Installation + +1. Create skill directory: + ```bash + mkdir -p skills/custom/my-skill + ``` + +2. Create SKILL.md: + ```bash + touch skills/custom/my-skill/SKILL.md + ``` + +3. Add content and save + +4. Skills are automatically loaded on next agent initialization + +### Sharing Skills + +To share skills with others: + +1. Create a GitHub repository +2. Include the skill directory structure +3. Add a README with installation instructions +4. Users can copy to their `skills/custom/` directory + +## Testing Your Skill + +After creating a skill: + +1. Start a new conversation +2. Use one of your trigger patterns +3. Verify the agent follows your instructions +4. Iterate and improve based on results + +## Need Help? + +Use this skill by saying: +- "Help me create a new skill for [purpose]" +- "I want to create a skill that [does something]" +- "Create a skill wizard for [task]" + +I'll guide you through each step! diff --git a/skills/builtin/database_design/SKILL.md b/skills/builtin/database_design/SKILL.md new file mode 100644 index 0000000000..dcb3a9f6c8 --- /dev/null +++ b/skills/builtin/database_design/SKILL.md @@ -0,0 +1,335 @@ +--- +name: "database_design" +description: "Database design, schema optimization, and query best practices. Use when designing schemas, optimizing queries, or working with databases." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["database", "sql", "schema", "optimization", "postgresql", "mysql"] +trigger_patterns: + - "database" + - "schema" + - "sql" + - "query" + - "table" + - "index" +--- + +# Database Design Skill + +Best practices for schema design, query optimization, and database management. + +## Schema Design Principles + +### Normalization + +**1NF (First Normal Form)** +- Each column contains atomic values +- No repeating groups + +**2NF (Second Normal Form)** +- Meet 1NF +- No partial dependencies (all non-key columns depend on the entire primary key) + +**3NF (Third Normal Form)** +- Meet 2NF +- No transitive dependencies (non-key columns don't depend on other non-key columns) + +### Example: Normalized Schema + +```sql +-- Users table +CREATE TABLE users ( + id SERIAL PRIMARY KEY, + email VARCHAR(255) UNIQUE NOT NULL, + name VARCHAR(100) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Addresses table (1:N relationship) +CREATE TABLE addresses ( + id SERIAL PRIMARY KEY, + user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, + street VARCHAR(255) NOT NULL, + city VARCHAR(100) NOT NULL, + country VARCHAR(100) NOT NULL, + postal_code VARCHAR(20), + is_primary BOOLEAN DEFAULT FALSE +); + +-- Orders table +CREATE TABLE orders ( + id SERIAL PRIMARY KEY, + user_id INTEGER REFERENCES users(id), + address_id INTEGER REFERENCES addresses(id), + status VARCHAR(50) DEFAULT 'pending', + total_amount DECIMAL(10, 2) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Order items (N:N through junction table) +CREATE TABLE order_items ( + id SERIAL PRIMARY KEY, + order_id INTEGER REFERENCES orders(id) ON DELETE CASCADE, + product_id INTEGER REFERENCES products(id), + quantity INTEGER NOT NULL CHECK (quantity > 0), + unit_price DECIMAL(10, 2) NOT NULL +); +``` + +### When to Denormalize + +Consider denormalization for: +- Read-heavy workloads +- Frequently joined tables +- Reporting/analytics queries + +```sql +-- Denormalized order summary (materialized view) +CREATE MATERIALIZED VIEW order_summaries AS +SELECT + o.id, + o.created_at, + u.name AS user_name, + u.email AS user_email, + a.city AS shipping_city, + o.total_amount, + COUNT(oi.id) AS item_count +FROM orders o +JOIN users u ON o.user_id = u.id +JOIN addresses a ON o.address_id = a.id +JOIN order_items oi ON o.id = oi.order_id +GROUP BY o.id, u.name, u.email, a.city; + +-- Refresh periodically +REFRESH MATERIALIZED VIEW order_summaries; +``` + +## Index Optimization + +### Index Types + +```sql +-- B-tree (default, good for most cases) +CREATE INDEX idx_users_email ON users(email); + +-- Composite index (order matters!) +CREATE INDEX idx_orders_user_date ON orders(user_id, created_at DESC); + +-- Partial index (for filtered queries) +CREATE INDEX idx_active_users ON users(email) WHERE status = 'active'; + +-- Expression index +CREATE INDEX idx_users_lower_email ON users(LOWER(email)); + +-- GIN index (for arrays, JSONB) +CREATE INDEX idx_products_tags ON products USING GIN(tags); + +-- BRIN index (for large tables with natural ordering) +CREATE INDEX idx_logs_timestamp ON logs USING BRIN(created_at); +``` + +### Index Guidelines + +```markdown +## When to Add Indexes +- [ ] Columns in WHERE clauses +- [ ] Columns in JOIN conditions +- [ ] Columns in ORDER BY +- [ ] Foreign keys +- [ ] Columns with high selectivity + +## When NOT to Add Indexes +- [ ] Small tables (< 1000 rows) +- [ ] Columns with low selectivity (boolean, status) +- [ ] Tables with heavy write operations +- [ ] Frequently updated columns +``` + +## Query Optimization + +### EXPLAIN ANALYZE + +```sql +EXPLAIN ANALYZE +SELECT u.name, COUNT(o.id) as order_count +FROM users u +LEFT JOIN orders o ON u.id = o.user_id +WHERE u.created_at > '2024-01-01' +GROUP BY u.id +ORDER BY order_count DESC +LIMIT 10; +``` + +### Common Optimizations + +**1. Use appropriate JOINs** +```sql +-- Bad: Subquery for each row +SELECT *, (SELECT COUNT(*) FROM orders WHERE user_id = u.id) +FROM users u; + +-- Good: Single JOIN +SELECT u.*, COUNT(o.id) as order_count +FROM users u +LEFT JOIN orders o ON u.id = o.user_id +GROUP BY u.id; +``` + +**2. Avoid SELECT *** +```sql +-- Bad +SELECT * FROM users WHERE id = 1; + +-- Good +SELECT id, name, email FROM users WHERE id = 1; +``` + +**3. Use LIMIT for pagination** +```sql +-- Offset pagination (slow for large offsets) +SELECT * FROM products ORDER BY id LIMIT 20 OFFSET 10000; + +-- Keyset pagination (faster) +SELECT * FROM products WHERE id > 10000 ORDER BY id LIMIT 20; +``` + +**4. Batch operations** +```sql +-- Bad: Individual inserts +INSERT INTO logs (message) VALUES ('log1'); +INSERT INTO logs (message) VALUES ('log2'); + +-- Good: Batch insert +INSERT INTO logs (message) VALUES ('log1'), ('log2'), ('log3'); +``` + +## Common Patterns + +### Soft Delete + +```sql +ALTER TABLE users ADD COLUMN deleted_at TIMESTAMP; + +-- "Delete" a user +UPDATE users SET deleted_at = CURRENT_TIMESTAMP WHERE id = 1; + +-- Query active users only +SELECT * FROM users WHERE deleted_at IS NULL; + +-- Create view for convenience +CREATE VIEW active_users AS +SELECT * FROM users WHERE deleted_at IS NULL; +``` + +### Audit Trail + +```sql +CREATE TABLE audit_log ( + id SERIAL PRIMARY KEY, + table_name VARCHAR(100) NOT NULL, + record_id INTEGER NOT NULL, + action VARCHAR(10) NOT NULL, -- INSERT, UPDATE, DELETE + old_data JSONB, + new_data JSONB, + changed_by INTEGER REFERENCES users(id), + changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Trigger function +CREATE OR REPLACE FUNCTION audit_trigger() +RETURNS TRIGGER AS $$ +BEGIN + IF TG_OP = 'INSERT' THEN + INSERT INTO audit_log (table_name, record_id, action, new_data) + VALUES (TG_TABLE_NAME, NEW.id, 'INSERT', to_jsonb(NEW)); + ELSIF TG_OP = 'UPDATE' THEN + INSERT INTO audit_log (table_name, record_id, action, old_data, new_data) + VALUES (TG_TABLE_NAME, NEW.id, 'UPDATE', to_jsonb(OLD), to_jsonb(NEW)); + ELSIF TG_OP = 'DELETE' THEN + INSERT INTO audit_log (table_name, record_id, action, old_data) + VALUES (TG_TABLE_NAME, OLD.id, 'DELETE', to_jsonb(OLD)); + END IF; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; +``` + +### Full-Text Search + +```sql +-- Add search column +ALTER TABLE products ADD COLUMN search_vector tsvector; + +-- Update search vector +UPDATE products SET search_vector = + setweight(to_tsvector('english', name), 'A') || + setweight(to_tsvector('english', description), 'B'); + +-- Create GIN index +CREATE INDEX idx_products_search ON products USING GIN(search_vector); + +-- Search query +SELECT * FROM products +WHERE search_vector @@ plainto_tsquery('english', 'wireless headphones') +ORDER BY ts_rank(search_vector, plainto_tsquery('english', 'wireless headphones')) DESC; +``` + +## Performance Checklist + +```markdown +## Schema Design +- [ ] Appropriate data types (don't use VARCHAR(255) for everything) +- [ ] Proper constraints (NOT NULL, UNIQUE, CHECK) +- [ ] Foreign keys with proper ON DELETE behavior +- [ ] UUID vs SERIAL for primary keys (consider use case) + +## Indexes +- [ ] Primary key indexes exist +- [ ] Foreign keys are indexed +- [ ] Frequently queried columns indexed +- [ ] No unused indexes (check pg_stat_user_indexes) + +## Queries +- [ ] No N+1 queries +- [ ] Appropriate use of JOINs vs subqueries +- [ ] LIMIT on unbounded queries +- [ ] EXPLAIN ANALYZE on slow queries + +## Maintenance +- [ ] Regular VACUUM and ANALYZE +- [ ] Connection pooling configured +- [ ] Query timeouts set +- [ ] Slow query logging enabled +``` + +## Useful Queries + +```sql +-- Find unused indexes +SELECT + schemaname || '.' || relname AS table, + indexrelname AS index, + pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size, + idx_scan AS index_scans +FROM pg_stat_user_indexes ui +JOIN pg_index i ON ui.indexrelid = i.indexrelid +WHERE idx_scan < 50 +ORDER BY pg_relation_size(i.indexrelid) DESC; + +-- Find slow queries (requires pg_stat_statements) +SELECT + query, + calls, + mean_exec_time, + total_exec_time +FROM pg_stat_statements +ORDER BY mean_exec_time DESC +LIMIT 10; + +-- Table sizes +SELECT + relname AS table, + pg_size_pretty(pg_total_relation_size(relid)) AS total_size +FROM pg_catalog.pg_statio_user_tables +ORDER BY pg_total_relation_size(relid) DESC; +``` diff --git a/skills/builtin/debugging/SKILL.md b/skills/builtin/debugging/SKILL.md new file mode 100644 index 0000000000..9f6a111a58 --- /dev/null +++ b/skills/builtin/debugging/SKILL.md @@ -0,0 +1,179 @@ +--- +name: "debugging" +description: "Systematic debugging methodology for identifying and fixing bugs. Use when encountering errors, unexpected behavior, or test failures." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["debugging", "troubleshooting", "errors", "testing", "analysis"] +trigger_patterns: + - "error" + - "bug" + - "not working" + - "fails" + - "broken" + - "fix" + - "debug" +--- + +# Systematic Debugging Skill + +**CRITICAL**: Follow this systematic process. Never guess at fixes without understanding the root cause. + +## When to Use + +Activate this skill when you encounter: +- Error messages or stack traces +- Unexpected behavior +- Test failures +- Performance issues +- "It was working before" scenarios + +## The Debugging Process + +### Phase 1: Reproduce the Issue + +**Goal**: Confirm you can consistently trigger the bug. + +1. **Document the steps** to reproduce +2. **Identify the exact error** message or unexpected behavior +3. **Note the environment**: OS, versions, configuration +4. **Establish baseline**: When did it last work correctly? + +```markdown +## Reproduction Steps +1. Step 1 +2. Step 2 +3. Step 3 +Expected: [What should happen] +Actual: [What actually happens] +``` + +### Phase 2: Gather Evidence + +**Goal**: Collect all relevant information before forming hypotheses. + +1. **Read the full error message** and stack trace +2. **Check logs** at multiple levels (app, system, network) +3. **Examine recent changes** (git diff, git log) +4. **Review related code** paths +5. **Check dependencies** and their versions + +```bash +# Useful commands +git log --oneline -20 # Recent commits +git diff HEAD~5 # Recent changes +cat /var/log/app.log # Application logs +``` + +### Phase 3: Form Hypotheses + +**Goal**: Generate multiple possible causes ranked by likelihood. + +List hypotheses in order of probability: + +```markdown +## Hypotheses +1. [Most likely] Description - Evidence supporting this +2. [Likely] Description - Evidence supporting this +3. [Possible] Description - Evidence supporting this +``` + +### Phase 4: Test Hypotheses + +**Goal**: Systematically eliminate possibilities. + +For each hypothesis: +1. **Design a test** that would confirm or refute it +2. **Execute the test** with minimal changes +3. **Document results** +4. **Move to next hypothesis** if not confirmed + +```markdown +## Testing: Hypothesis 1 +Test: [What I'll do to test this] +Result: [Confirmed/Refuted] +Evidence: [What I observed] +``` + +### Phase 5: Implement Fix + +**Goal**: Fix the root cause, not just the symptom. + +1. **Isolate the fix**: Make the smallest change that fixes the issue +2. **Verify the fix**: Confirm the original reproduction steps now pass +3. **Check for regressions**: Ensure nothing else broke +4. **Document the fix**: Explain what was wrong and why the fix works + +### Phase 6: Prevent Recurrence + +**Goal**: Stop this class of bug from happening again. + +1. **Add a test** that would have caught this bug +2. **Consider defensive coding** (validation, error handling) +3. **Update documentation** if needed +4. **Share learnings** with team if relevant + +## Anti-Patterns to Avoid + +- **Random Changes**: Never make changes hoping something works +- **Fix Symptoms**: Always find and fix the root cause +- **Skip Reproduction**: Always confirm you can reproduce before fixing +- **Single Hypothesis**: Consider multiple possibilities +- **No Testing**: Always verify the fix works + +## Debugging Tools + +### For Python +```python +# Interactive debugging +import pdb; pdb.set_trace() + +# Or using ipdb for better experience +import ipdb; ipdb.set_trace() + +# Print debugging with context +print(f"DEBUG: {variable=}, {type(variable)=}") +``` + +### For JavaScript +```javascript +// Debugger statement +debugger; + +// Console logging with labels +console.log({ variable, typeof: typeof variable }); + +// Trace to see call stack +console.trace("How did we get here?"); +``` + +### General +```bash +# Check if process is running +ps aux | grep + +# Check port usage +lsof -i : + +# Watch file changes +tail -f /path/to/log +``` + +## Example Session + +**User**: "The API endpoint returns 500 error" + +**Agent Response**: +> Let me debug this systematically: +> +> ## Phase 1: Reproduction +> - Which endpoint specifically? +> - What request parameters are you sending? +> - Does it fail consistently or intermittently? +> +> ## Phase 2: Gathering Evidence +> Let me check: +> 1. The server error logs +> 2. Recent changes to this endpoint +> 3. The full stack trace +> +> [Proceeds systematically through each phase] diff --git a/skills/builtin/docker_devops/SKILL.md b/skills/builtin/docker_devops/SKILL.md new file mode 100644 index 0000000000..e6f81f3c45 --- /dev/null +++ b/skills/builtin/docker_devops/SKILL.md @@ -0,0 +1,394 @@ +--- +name: "docker_devops" +description: "Docker and DevOps best practices for containerization, orchestration, and CI/CD pipelines. Use when working with containers, deployments, or infrastructure." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["docker", "devops", "containers", "kubernetes", "ci-cd", "infrastructure"] +trigger_patterns: + - "docker" + - "container" + - "kubernetes" + - "k8s" + - "deploy" + - "ci/cd" + - "pipeline" +--- + +# Docker & DevOps Skill + +Best practices for containerization, orchestration, and deployment pipelines. + +## Docker Fundamentals + +### Dockerfile Best Practices + +```dockerfile +# Use specific version tags +FROM python:3.11-slim + +# Set working directory +WORKDIR /app + +# Copy dependency files first (layer caching) +COPY requirements.txt . + +# Install dependencies +RUN pip install --no-cache-dir -r requirements.txt + +# Copy application code +COPY . . + +# Use non-root user +RUN useradd -m appuser && chown -R appuser:appuser /app +USER appuser + +# Expose port +EXPOSE 8000 + +# Use exec form for CMD +CMD ["python", "app.py"] +``` + +### Multi-Stage Builds + +```dockerfile +# Build stage +FROM node:18 AS builder +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npm run build + +# Production stage +FROM nginx:alpine +COPY --from=builder /app/dist /usr/share/nginx/html +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] +``` + +### Docker Compose + +```yaml +version: '3.8' + +services: + app: + build: + context: . + dockerfile: Dockerfile + ports: + - "8000:8000" + environment: + - DATABASE_URL=postgresql://user:pass@db:5432/app + depends_on: + db: + condition: service_healthy + volumes: + - ./app:/app + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + interval: 30s + timeout: 10s + retries: 3 + + db: + image: postgres:15-alpine + environment: + POSTGRES_USER: user + POSTGRES_PASSWORD: pass + POSTGRES_DB: app + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U user -d app"] + interval: 10s + timeout: 5s + retries: 5 + +volumes: + postgres_data: +``` + +## Kubernetes Basics + +### Deployment + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: myapp + labels: + app: myapp +spec: + replicas: 3 + selector: + matchLabels: + app: myapp + template: + metadata: + labels: + app: myapp + spec: + containers: + - name: myapp + image: myapp:1.0.0 + ports: + - containerPort: 8000 + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "200m" + livenessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 30 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /ready + port: 8000 + initialDelaySeconds: 5 + periodSeconds: 5 +``` + +### Service + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: myapp-service +spec: + selector: + app: myapp + ports: + - port: 80 + targetPort: 8000 + type: ClusterIP +``` + +### Ingress + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: myapp-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + rules: + - host: myapp.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: myapp-service + port: + number: 80 +``` + +## CI/CD Pipelines + +### GitHub Actions + +```yaml +name: CI/CD Pipeline + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + pip install -r requirements.txt + pip install pytest + + - name: Run tests + run: pytest + + build: + needs: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Build Docker image + run: docker build -t myapp:${{ github.sha }} . + + - name: Login to Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Push image + run: | + docker tag myapp:${{ github.sha }} ghcr.io/${{ github.repository }}:${{ github.sha }} + docker push ghcr.io/${{ github.repository }}:${{ github.sha }} + + deploy: + needs: build + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + steps: + - name: Deploy to production + run: | + echo "Deploying ${{ github.sha }}" + # kubectl set image deployment/myapp myapp=ghcr.io/${{ github.repository }}:${{ github.sha }} +``` + +### GitLab CI + +```yaml +stages: + - test + - build + - deploy + +variables: + DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA + +test: + stage: test + image: python:3.11 + script: + - pip install -r requirements.txt + - pytest + +build: + stage: build + image: docker:latest + services: + - docker:dind + script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker build -t $DOCKER_IMAGE . + - docker push $DOCKER_IMAGE + +deploy: + stage: deploy + only: + - main + script: + - kubectl set image deployment/myapp myapp=$DOCKER_IMAGE +``` + +## Useful Commands + +### Docker + +```bash +# Build image +docker build -t myapp:latest . + +# Run container +docker run -d -p 8000:8000 --name myapp myapp:latest + +# View logs +docker logs -f myapp + +# Execute in container +docker exec -it myapp /bin/sh + +# Clean up +docker system prune -a + +# List resources +docker ps -a +docker images +docker volume ls +docker network ls +``` + +### Kubernetes + +```bash +# Get resources +kubectl get pods +kubectl get services +kubectl get deployments + +# Describe resource +kubectl describe pod + +# Logs +kubectl logs -f + +# Execute in pod +kubectl exec -it -- /bin/sh + +# Apply configuration +kubectl apply -f deployment.yaml + +# Scale deployment +kubectl scale deployment myapp --replicas=5 + +# Rollback +kubectl rollout undo deployment/myapp +``` + +## Security Checklist + +```markdown +- [ ] Use specific image tags, not 'latest' +- [ ] Run as non-root user +- [ ] Scan images for vulnerabilities +- [ ] Use secrets management (not env vars for sensitive data) +- [ ] Limit container resources +- [ ] Enable network policies +- [ ] Use read-only file systems where possible +- [ ] Implement pod security policies +- [ ] Rotate credentials regularly +``` + +## Monitoring & Logging + +```yaml +# Prometheus ServiceMonitor +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: myapp +spec: + selector: + matchLabels: + app: myapp + endpoints: + - port: metrics + interval: 30s +``` + +```yaml +# Fluentd sidecar for logging +containers: +- name: myapp + image: myapp:latest +- name: fluentd + image: fluent/fluentd:latest + volumeMounts: + - name: logs + mountPath: /var/log/app +``` diff --git a/skills/builtin/git_workflow/SKILL.md b/skills/builtin/git_workflow/SKILL.md new file mode 100644 index 0000000000..9ed789d514 --- /dev/null +++ b/skills/builtin/git_workflow/SKILL.md @@ -0,0 +1,357 @@ +--- +name: "git_workflow" +description: "Git workflow best practices for branching, committing, and collaboration. Use when working with version control." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["git", "version-control", "branching", "collaboration", "workflow"] +trigger_patterns: + - "git" + - "commit" + - "branch" + - "merge" + - "pull request" +--- + +# Git Workflow Skill + +Best practices for version control and team collaboration. + +## Branching Strategy + +### Branch Naming Convention + +``` +/- +``` + +**Types:** +- `feature/` - New features +- `bugfix/` - Bug fixes +- `hotfix/` - Urgent production fixes +- `refactor/` - Code refactoring +- `docs/` - Documentation updates +- `test/` - Adding tests +- `chore/` - Maintenance tasks + +**Examples:** +```bash +feature/PROJ-123-add-user-authentication +bugfix/PROJ-456-fix-login-timeout +hotfix/PROJ-789-critical-security-patch +``` + +### Branch Workflow + +``` +main (production) + │ + ├── develop (integration) + │ │ + │ ├── feature/add-login + │ ├── feature/add-dashboard + │ └── bugfix/fix-signup + │ + └── hotfix/security-patch (urgent fixes from main) +``` + +## Commit Messages + +### Conventional Commits Format + +``` +(): + +[optional body] + +[optional footer(s)] +``` + +### Types + +| Type | Description | +|------|-------------| +| `feat` | New feature | +| `fix` | Bug fix | +| `docs` | Documentation | +| `style` | Formatting (no code change) | +| `refactor` | Code refactoring | +| `test` | Adding tests | +| `chore` | Maintenance | +| `perf` | Performance improvement | +| `ci` | CI/CD changes | + +### Examples + +```bash +# Feature +feat(auth): add JWT token refresh mechanism + +# Bug fix with ticket reference +fix(api): resolve timeout issue on large payloads + +Closes #123 + +# Breaking change +feat(api)!: change user endpoint response format + +BREAKING CHANGE: User endpoint now returns nested +address object instead of flat fields. + +# Multi-line with body +refactor(database): optimize user query performance + +- Added composite index on (email, created_at) +- Removed N+1 query in user loader +- Cached frequently accessed user data + +Performance improved from 500ms to 50ms for user list. +``` + +## Common Workflows + +### Starting New Work + +```bash +# 1. Update main branch +git checkout main +git pull origin main + +# 2. Create feature branch +git checkout -b feature/PROJ-123-new-feature + +# 3. Make changes and commit +git add . +git commit -m "feat(module): add new functionality" + +# 4. Push and create PR +git push -u origin feature/PROJ-123-new-feature +``` + +### Syncing with Main + +```bash +# Option 1: Rebase (preferred for feature branches) +git fetch origin +git rebase origin/main + +# Option 2: Merge (when history preservation needed) +git fetch origin +git merge origin/main +``` + +### Interactive Rebase (Cleaning History) + +```bash +# Squash last 3 commits +git rebase -i HEAD~3 + +# In editor, change 'pick' to 'squash' for commits to combine +pick abc1234 feat: add login form +squash def5678 fix: typo in form +squash ghi9012 style: format code +``` + +### Undoing Changes + +```bash +# Undo last commit (keep changes) +git reset --soft HEAD~1 + +# Undo last commit (discard changes) +git reset --hard HEAD~1 + +# Undo specific file changes +git checkout -- path/to/file + +# Revert a pushed commit (safe) +git revert +``` + +### Stashing Work + +```bash +# Save current changes +git stash save "WIP: feature description" + +# List stashes +git stash list + +# Apply most recent stash +git stash pop + +# Apply specific stash +git stash apply stash@{2} + +# Drop a stash +git stash drop stash@{0} +``` + +## Pull Request Guidelines + +### Before Creating PR + +1. **Rebase on latest main** + ```bash + git fetch origin + git rebase origin/main + ``` + +2. **Run tests locally** + ```bash + npm test # or your test command + ``` + +3. **Self-review your changes** + ```bash + git diff origin/main + ``` + +4. **Clean up commits** + - Squash fixup commits + - Write clear commit messages + +### PR Description Template + +```markdown +## Summary +Brief description of changes + +## Type of Change +- [ ] Feature +- [ ] Bug fix +- [ ] Refactor +- [ ] Documentation + +## Changes Made +- Change 1 +- Change 2 +- Change 3 + +## Testing Done +- [ ] Unit tests pass +- [ ] Integration tests pass +- [ ] Manual testing completed + +## Screenshots (if applicable) +[Add screenshots here] + +## Related Issues +Closes #123 +``` + +### PR Best Practices + +1. **Keep PRs Small**: < 400 lines ideally +2. **One Concern Per PR**: Don't mix features +3. **Descriptive Title**: Summarize the change +4. **Link Issues**: Reference related tickets +5. **Add Context**: Explain why, not just what +6. **Request Reviews**: Tag appropriate reviewers + +## Resolving Conflicts + +### Step-by-Step + +```bash +# 1. Update your branch +git fetch origin + +# 2. Rebase on main +git rebase origin/main + +# 3. When conflicts occur, Git will pause +# Fix conflicts in your editor + +# 4. After fixing each file +git add + +# 5. Continue rebase +git rebase --continue + +# 6. If too complex, abort and try merge instead +git rebase --abort +git merge origin/main +``` + +### Conflict Markers + +``` +<<<<<<< HEAD +Your changes +======= +Their changes +>>>>>>> branch-name +``` + +## Git Hooks + +### Pre-commit Hook Example + +```bash +#!/bin/sh +# .git/hooks/pre-commit + +# Run linter +npm run lint +if [ $? -ne 0 ]; then + echo "Lint failed. Fix errors before committing." + exit 1 +fi + +# Run tests +npm test +if [ $? -ne 0 ]; then + echo "Tests failed. Fix tests before committing." + exit 1 +fi +``` + +### Commit Message Hook + +```bash +#!/bin/sh +# .git/hooks/commit-msg + +# Enforce conventional commits +commit_regex='^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,50}' + +if ! grep -qE "$commit_regex" "$1"; then + echo "Invalid commit message format." + echo "Use: (): " + exit 1 +fi +``` + +## Useful Aliases + +Add to `~/.gitconfig`: + +```ini +[alias] + # Status + s = status -sb + + # Logging + lg = log --oneline --graph --all + last = log -1 HEAD --stat + + # Branching + co = checkout + cob = checkout -b + br = branch -v + + # Committing + cm = commit -m + amend = commit --amend --no-edit + + # Stashing + sl = stash list + sp = stash pop + + # Diffing + d = diff + dc = diff --cached + + # Cleanup + cleanup = "!git branch --merged | grep -v '\\*\\|main\\|develop' | xargs -n 1 git branch -d" +``` diff --git a/skills/builtin/prompt_engineering/SKILL.md b/skills/builtin/prompt_engineering/SKILL.md new file mode 100644 index 0000000000..cbfd765469 --- /dev/null +++ b/skills/builtin/prompt_engineering/SKILL.md @@ -0,0 +1,404 @@ +--- +name: "prompt_engineering" +description: "Best practices for crafting effective prompts for LLMs. Use when designing prompts, creating system messages, or optimizing AI interactions." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["prompts", "llm", "ai", "gpt", "claude", "optimization"] +trigger_patterns: + - "prompt" + - "system message" + - "llm" + - "ai instruction" + - "chatgpt" + - "claude" +--- + +# Prompt Engineering Skill + +Best practices for designing effective prompts for Large Language Models. + +## Core Principles + +### 1. Be Specific and Clear + +```markdown +# Bad +"Write something about dogs" + +# Good +"Write a 200-word article about the top 3 benefits of adopting +a rescue dog. Include a brief introduction and conclusion. +Use a friendly, conversational tone suitable for pet owners." +``` + +### 2. Provide Context + +```markdown +# Bad +"Fix this code" + +# Good +"I have a Python function that should validate email addresses. +Currently it accepts invalid emails like 'test@'. + +Current code: +```python +def validate_email(email): + return '@' in email +``` + +Please fix this to properly validate email format." +``` + +### 3. Specify Output Format + +```markdown +# Bad +"List some programming languages" + +# Good +"List 5 programming languages for web development. +Format as a markdown table with columns: +- Language name +- Primary use case +- Learning difficulty (Easy/Medium/Hard)" +``` + +## Prompt Patterns + +### Role Pattern + +Assign a specific persona to guide responses: + +```markdown +You are a senior Python developer with 10 years of experience. +You specialize in clean code, testing, and code reviews. +When reviewing code, you: +- Focus on readability and maintainability +- Suggest improvements with explanations +- Point out potential bugs or security issues + +Please review the following code: +[code here] +``` + +### Chain of Thought + +Guide step-by-step reasoning: + +```markdown +Solve this problem step by step: + +Problem: A store has 150 apples. They sell 30% on Monday, +then receive a shipment of 50 apples on Tuesday. +How many apples do they have now? + +Please show your work: +1. Calculate apples sold on Monday +2. Calculate remaining apples after Monday +3. Add Tuesday's shipment +4. State the final answer +``` + +### Few-Shot Learning + +Provide examples to establish patterns: + +```markdown +Convert these sentences to formal English: + +Example 1: +Casual: "gonna grab some coffee" +Formal: "I am going to get some coffee." + +Example 2: +Casual: "wanna come with?" +Formal: "Would you like to accompany me?" + +Now convert: +Casual: "lemme know if you're free" +Formal: +``` + +### Template Pattern + +Create reusable structures: + +```markdown +# Bug Report Template + +Please analyze this bug and provide: + +## Summary +[One sentence description] + +## Root Cause +[Technical explanation of why this bug occurs] + +## Impact +[Who is affected and how] + +## Solution +[Recommended fix with code example] + +## Prevention +[How to prevent similar bugs in the future] + +--- +Bug to analyze: +[user's bug description] +``` + +## System Prompts + +### Structure + +```markdown +# [Role/Identity] +You are [description of the assistant's role and expertise] + +# [Core Behaviors] +You should always: +- [Behavior 1] +- [Behavior 2] + +You should never: +- [Anti-pattern 1] +- [Anti-pattern 2] + +# [Response Format] +When responding: +- [Format guideline 1] +- [Format guideline 2] + +# [Examples] (optional) +Here's an example of how to respond: +[example interaction] +``` + +### Example System Prompt + +```markdown +# Role +You are a helpful coding assistant specializing in Python. +You have expertise in data science, web development, and automation. + +# Core Behaviors +Always: +- Write clean, well-documented code +- Explain your reasoning +- Suggest tests for code you write +- Consider edge cases + +Never: +- Write code without explanation +- Use deprecated libraries +- Ignore security best practices +- Make assumptions about requirements without clarifying + +# Response Format +When writing code: +1. Start with a brief explanation of the approach +2. Write the code with comments +3. Explain any complex parts +4. Suggest how to test it + +When debugging: +1. Identify the likely cause +2. Explain why it happens +3. Provide the fix +4. Suggest how to prevent similar issues +``` + +## Optimization Techniques + +### Iterative Refinement + +```markdown +# First attempt +"Write a story" + +# After iteration 1: Add specifics +"Write a 500-word short story about a robot" + +# After iteration 2: Add constraints +"Write a 500-word short story about a robot +learning to paint. Include dialogue." + +# After iteration 3: Add style +"Write a 500-word short story about a robot +learning to paint. Include dialogue. Write in +a warm, hopeful tone similar to Studio Ghibli films." +``` + +### Decomposition + +Break complex tasks into steps: + +```markdown +Instead of: +"Create a complete e-commerce website" + +Use: +"Let's build an e-commerce website step by step: + +Step 1: Define the data models we need for products, +users, and orders. Show me the schema. + +[Wait for response] + +Step 2: Based on those models, create the API endpoints. + +[Wait for response] + +Step 3: Now let's build the product listing page..." +``` + +### Constraint Setting + +```markdown +# Add boundaries for better results +"Write a product description for a coffee maker. + +Constraints: +- Maximum 100 words +- Include 3 key features +- End with a call to action +- Don't use superlatives like 'best' or 'amazing' +- Write at a 6th-grade reading level" +``` + +## Common Pitfalls + +### 1. Vague Instructions + +```markdown +# Bad +"Make it better" + +# Good +"Improve the readability by: +- Using shorter sentences (max 20 words) +- Adding subheadings every 100-150 words +- Replacing jargon with plain language" +``` + +### 2. Missing Context + +```markdown +# Bad +"Why isn't my code working?" + +# Good +"My Python code throws a TypeError. +Environment: Python 3.11, macOS +Error message: TypeError: 'NoneType' object is not iterable +Code: +```python +def process(items): + for item in items: + print(item) + +process(get_items()) # Error occurs here +``` +The get_items() function should return a list." +``` + +### 3. Overloading + +```markdown +# Bad (too many things at once) +"Write a blog post about AI, make it SEO optimized, +include code examples, add images, make it funny but professional, +target beginners but also appeal to experts..." + +# Good (focused request) +"Write a 500-word introduction to machine learning +for complete beginners. Use simple analogies and +avoid technical jargon. Include 3 real-world examples." +``` + +## Evaluation Checklist + +```markdown +Before submitting a prompt, verify: + +## Clarity +- [ ] Is the task clearly defined? +- [ ] Are ambiguous terms explained? +- [ ] Is the expected output format specified? + +## Context +- [ ] Is relevant background provided? +- [ ] Are constraints clearly stated? +- [ ] Are examples included if needed? + +## Structure +- [ ] Is the prompt well-organized? +- [ ] Are complex tasks broken into steps? +- [ ] Is there a clear order of operations? + +## Completeness +- [ ] Does it include all necessary information? +- [ ] Are edge cases considered? +- [ ] Is the success criteria clear? +``` + +## Examples by Use Case + +### Code Generation + +```markdown +Write a Python function that: +- Takes a list of dictionaries representing users +- Filters users older than 18 +- Sorts by last name alphabetically +- Returns their email addresses + +Input example: +[{"name": "John Doe", "age": 25, "email": "john@example.com"}] + +Requirements: +- Include type hints +- Add docstring +- Handle empty list case +- Include unit test +``` + +### Data Analysis + +```markdown +Analyze this sales data and provide: + +1. Summary statistics (mean, median, std dev) +2. Top 3 performing products +3. Month-over-month growth rate +4. Any anomalies or patterns + +Present findings in a markdown table. +Include a brief executive summary (3-4 sentences). + +Data: +[paste data here] +``` + +### Writing Assistance + +```markdown +Help me improve this email to a client: + +Context: We need to delay the project by 2 weeks +due to unexpected technical issues. + +Current draft: +"Hi, the project will be late. Sorry about that." + +Goals: +- Maintain professional relationship +- Clearly explain the delay +- Provide new timeline +- Offer mitigation options + +Tone: Professional but warm +Length: 150-200 words +``` diff --git a/skills/builtin/security_audit/SKILL.md b/skills/builtin/security_audit/SKILL.md new file mode 100644 index 0000000000..13db535346 --- /dev/null +++ b/skills/builtin/security_audit/SKILL.md @@ -0,0 +1,453 @@ +--- +name: "security_audit" +description: "Security audit and vulnerability assessment skill. Use when reviewing code for security issues, hardening systems, or implementing security best practices." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["security", "audit", "vulnerability", "owasp", "hardening"] +trigger_patterns: + - "security" + - "vulnerability" + - "secure" + - "audit" + - "owasp" + - "penetration" +--- + +# Security Audit Skill + +Comprehensive security review and vulnerability assessment guidance. + +## OWASP Top 10 Checklist + +### 1. Broken Access Control + +```markdown +## Check for: +- [ ] Direct object references (IDOR) +- [ ] Missing function-level access control +- [ ] Privilege escalation paths +- [ ] Bypassing access control via URL manipulation + +## Example vulnerability: +```python +# Bad: No authorization check +@app.get("/api/users/{user_id}") +def get_user(user_id: int): + return db.get_user(user_id) # Any user can access any other user! + +# Good: Verify authorization +@app.get("/api/users/{user_id}") +def get_user(user_id: int, current_user: User = Depends(get_current_user)): + if current_user.id != user_id and not current_user.is_admin: + raise HTTPException(403, "Not authorized") + return db.get_user(user_id) +``` +``` + +### 2. Cryptographic Failures + +```markdown +## Check for: +- [ ] Sensitive data transmitted in plaintext +- [ ] Weak encryption algorithms (MD5, SHA1 for passwords) +- [ ] Hardcoded secrets +- [ ] Insecure random number generation + +## Secure practices: +```python +# Password hashing +from argon2 import PasswordHasher +ph = PasswordHasher() +hash = ph.hash("password") +ph.verify(hash, "password") # Raises exception if invalid + +# Secure token generation +import secrets +token = secrets.token_urlsafe(32) + +# Never do this: +import hashlib +hash = hashlib.md5(password.encode()).hexdigest() # WEAK! +``` +``` + +### 3. Injection + +```markdown +## Check for: +- [ ] SQL injection +- [ ] NoSQL injection +- [ ] Command injection +- [ ] LDAP injection +- [ ] XPath injection + +## SQL Injection Prevention: +```python +# Bad: String concatenation +cursor.execute(f"SELECT * FROM users WHERE id = {user_id}") + +# Good: Parameterized queries +cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) + +# Good: ORM with proper escaping +User.query.filter_by(id=user_id).first() +``` + +## Command Injection Prevention: +```python +# Bad +os.system(f"echo {user_input}") + +# Good: Use subprocess with list arguments +subprocess.run(["echo", user_input], shell=False) + +# Better: Avoid shell commands with user input entirely +``` +``` + +### 4. Insecure Design + +```markdown +## Check for: +- [ ] Missing threat modeling +- [ ] No rate limiting on sensitive operations +- [ ] Lack of defense in depth +- [ ] Missing business logic validation + +## Example: +```python +# Bad: No rate limiting on login +@app.post("/login") +def login(credentials: Credentials): + return authenticate(credentials) + +# Good: Rate limited +from slowapi import Limiter +limiter = Limiter(key_func=get_remote_address) + +@app.post("/login") +@limiter.limit("5/minute") +def login(credentials: Credentials): + return authenticate(credentials) +``` +``` + +### 5. Security Misconfiguration + +```markdown +## Check for: +- [ ] Default credentials in use +- [ ] Unnecessary features enabled +- [ ] Missing security headers +- [ ] Verbose error messages in production +- [ ] Outdated software + +## Security Headers: +```python +# Flask example +@app.after_request +def add_security_headers(response): + response.headers['X-Content-Type-Options'] = 'nosniff' + response.headers['X-Frame-Options'] = 'DENY' + response.headers['X-XSS-Protection'] = '1; mode=block' + response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' + response.headers['Content-Security-Policy'] = "default-src 'self'" + return response +``` +``` + +### 6. Vulnerable Components + +```markdown +## Check for: +- [ ] Outdated dependencies +- [ ] Known vulnerable packages +- [ ] Unmaintained libraries + +## Tools: +```bash +# Python +pip-audit +safety check -r requirements.txt + +# JavaScript +npm audit +yarn audit + +# General +snyk test +``` +``` + +### 7. Authentication Failures + +```markdown +## Check for: +- [ ] Weak password policies +- [ ] Missing MFA option +- [ ] Session fixation +- [ ] Insecure session management + +## Secure Session Management: +```python +# Secure session configuration +app.config.update( + SESSION_COOKIE_SECURE=True, # HTTPS only + SESSION_COOKIE_HTTPONLY=True, # No JavaScript access + SESSION_COOKIE_SAMESITE='Lax', # CSRF protection + PERMANENT_SESSION_LIFETIME=3600 # 1 hour timeout +) + +# Regenerate session on login +@app.route('/login', methods=['POST']) +def login(): + if authenticate(request.form): + session.regenerate() # Prevent session fixation + session['user_id'] = user.id +``` +``` + +### 8. Data Integrity Failures + +```markdown +## Check for: +- [ ] Missing integrity checks on critical data +- [ ] Insecure deserialization +- [ ] Missing code signing + +## Secure Deserialization: +```python +# Bad: Pickle with untrusted data +import pickle +data = pickle.loads(untrusted_data) # DANGEROUS! + +# Good: Use safe serialization +import json +data = json.loads(untrusted_data) + +# If you must use pickle, sign and verify +import hmac +def safe_pickle_loads(data, key): + signature = data[:32] + pickled = data[32:] + expected = hmac.new(key, pickled, 'sha256').digest() + if not hmac.compare_digest(signature, expected): + raise ValueError("Invalid signature") + return pickle.loads(pickled) +``` +``` + +### 9. Logging & Monitoring Failures + +```markdown +## Check for: +- [ ] Sensitive data in logs +- [ ] Missing audit logs +- [ ] No alerting for security events +- [ ] Logs not protected + +## Secure Logging: +```python +import logging + +# Configure secure logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' +) + +# Sanitize sensitive data +def sanitize_log(data): + sensitive_keys = ['password', 'token', 'api_key', 'ssn'] + return {k: '***' if k in sensitive_keys else v for k, v in data.items()} + +# Log security events +def log_security_event(event_type, details): + logger.warning(f"SECURITY: {event_type} - {sanitize_log(details)}") +``` +``` + +### 10. Server-Side Request Forgery (SSRF) + +```markdown +## Check for: +- [ ] URL parameters used for server requests +- [ ] Unvalidated redirects +- [ ] Internal service exposure + +## Prevention: +```python +from urllib.parse import urlparse +import ipaddress + +ALLOWED_HOSTS = ['api.example.com', 'cdn.example.com'] +BLOCKED_NETWORKS = [ + ipaddress.ip_network('10.0.0.0/8'), + ipaddress.ip_network('172.16.0.0/12'), + ipaddress.ip_network('192.168.0.0/16'), + ipaddress.ip_network('127.0.0.0/8'), +] + +def is_safe_url(url): + try: + parsed = urlparse(url) + + # Check allowed hosts + if parsed.hostname not in ALLOWED_HOSTS: + return False + + # Check not internal IP + ip = ipaddress.ip_address(parsed.hostname) + for network in BLOCKED_NETWORKS: + if ip in network: + return False + + return True + except: + return False +``` +``` + +## Security Audit Process + +### 1. Information Gathering + +```markdown +- [ ] Identify all entry points (APIs, forms, file uploads) +- [ ] Map authentication and authorization flows +- [ ] Document data flows +- [ ] List third-party integrations +- [ ] Review infrastructure configuration +``` + +### 2. Automated Scanning + +```bash +# Web application scanning +nikto -h https://target.com +nuclei -u https://target.com -t cves/ + +# Dependency scanning +npm audit +pip-audit + +# Static analysis +bandit -r ./src # Python +semgrep --config auto ./src # Multi-language +``` + +### 3. Manual Testing + +```markdown +## Input Validation +- [ ] Test with SQL injection payloads +- [ ] Test with XSS payloads +- [ ] Test with path traversal (../) +- [ ] Test file upload restrictions + +## Authentication +- [ ] Test password reset flow +- [ ] Test session timeout +- [ ] Test concurrent session handling +- [ ] Test remember me functionality + +## Authorization +- [ ] Test horizontal privilege escalation +- [ ] Test vertical privilege escalation +- [ ] Test API endpoint permissions +``` + +### 4. Report Template + +```markdown +# Security Audit Report + +## Executive Summary +[Brief overview of findings] + +## Scope +- Systems tested: +- Testing period: +- Methodology: + +## Findings + +### Critical +| ID | Title | Impact | CVSS | +|----|-------|--------|------| +| C1 | SQL Injection in login | Data breach | 9.8 | + +### High +[Similar table] + +### Medium +[Similar table] + +### Low +[Similar table] + +## Detailed Findings + +### C1: SQL Injection in Login Form + +**Description**: The login form is vulnerable to SQL injection... + +**Impact**: An attacker could bypass authentication and access any account... + +**Proof of Concept**: +``` +Username: ' OR '1'='1 +Password: anything +``` + +**Recommendation**: Use parameterized queries... + +**References**: +- CWE-89 +- OWASP SQL Injection +``` + +## Quick Reference + +### Input Validation + +```python +import re +from html import escape + +def sanitize_input(user_input: str) -> str: + # Remove/escape HTML + sanitized = escape(user_input) + + # Limit length + sanitized = sanitized[:1000] + + # Remove null bytes + sanitized = sanitized.replace('\x00', '') + + return sanitized + +def validate_email(email: str) -> bool: + pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' + return bool(re.match(pattern, email)) +``` + +### Environment Configuration + +```python +# Never commit secrets! +import os +from dotenv import load_dotenv + +load_dotenv() + +DATABASE_URL = os.getenv('DATABASE_URL') +SECRET_KEY = os.getenv('SECRET_KEY') +API_KEY = os.getenv('API_KEY') + +# Verify all required env vars are set +required = ['DATABASE_URL', 'SECRET_KEY', 'API_KEY'] +missing = [v for v in required if not os.getenv(v)] +if missing: + raise RuntimeError(f"Missing environment variables: {missing}") +``` diff --git a/skills/builtin/tdd/SKILL.md b/skills/builtin/tdd/SKILL.md new file mode 100644 index 0000000000..6ba8d92a7c --- /dev/null +++ b/skills/builtin/tdd/SKILL.md @@ -0,0 +1,229 @@ +--- +name: "tdd" +description: "Test-Driven Development workflow. Write tests first, then implement code to make them pass. Use when implementing features or fixing bugs." +version: "1.0.0" +author: "Agent Zero Team" +tags: ["testing", "tdd", "development", "quality", "best-practices"] +trigger_patterns: + - "test first" + - "tdd" + - "write tests" + - "test-driven" + - "unit test" +--- + +# Test-Driven Development (TDD) Skill + +**CRITICAL**: Write tests BEFORE writing implementation code. This ensures code is testable and meets requirements. + +## The TDD Cycle + +``` + ┌─────────────────────────────────────┐ + │ │ + │ RED → GREEN → REFACTOR → Repeat │ + │ │ + └─────────────────────────────────────┘ +``` + +1. **RED**: Write a failing test that defines expected behavior +2. **GREEN**: Write minimum code to make the test pass +3. **REFACTOR**: Clean up while keeping tests green +4. **Repeat**: Add next test case + +## When to Use + +Activate TDD when: +- Implementing new features +- Fixing bugs (write test that reproduces bug first) +- Refactoring existing code +- Adding edge case handling + +## The TDD Process + +### Phase 1: Understand Requirements + +Before writing any code: +1. Clarify what the feature should do +2. Identify inputs, outputs, and edge cases +3. List test cases needed + +```markdown +## Feature: [Name] +### Happy Path Cases +- [ ] Test case 1: Given X, when Y, then Z +- [ ] Test case 2: Given A, when B, then C + +### Edge Cases +- [ ] Empty input +- [ ] Invalid input +- [ ] Boundary values + +### Error Cases +- [ ] What should happen when X fails? +``` + +### Phase 2: RED - Write Failing Test + +Write a test that: +1. Describes the expected behavior +2. Fails for the right reason (not implementation exists yet) +3. Is simple and focused + +```python +# Python example +def test_calculate_total_with_discount(): + """Should apply 10% discount for orders over $100""" + order = Order(items=[Item(price=150)]) + + result = order.calculate_total() + + assert result == 135.00 # 150 - 10% = 135 +``` + +```javascript +// JavaScript example +describe('calculateTotal', () => { + it('should apply 10% discount for orders over $100', () => { + const order = new Order([{ price: 150 }]); + + const result = order.calculateTotal(); + + expect(result).toBe(135); + }); +}); +``` + +### Phase 3: GREEN - Make Test Pass + +Write the simplest code that makes the test pass: +1. Don't over-engineer +2. Don't add features the test doesn't require +3. It's okay if code is ugly - we'll refactor next + +```python +def calculate_total(self): + total = sum(item.price for item in self.items) + if total > 100: + total = total * 0.9 # 10% discount + return total +``` + +### Phase 4: REFACTOR - Clean Up + +Improve code quality while keeping tests green: +1. Remove duplication +2. Improve naming +3. Extract methods if needed +4. Run tests after each change + +```python +DISCOUNT_THRESHOLD = 100 +DISCOUNT_RATE = 0.10 + +def calculate_total(self): + subtotal = self._calculate_subtotal() + discount = self._calculate_discount(subtotal) + return subtotal - discount + +def _calculate_subtotal(self): + return sum(item.price for item in self.items) + +def _calculate_discount(self, subtotal): + if subtotal > DISCOUNT_THRESHOLD: + return subtotal * DISCOUNT_RATE + return 0 +``` + +### Phase 5: Repeat + +Add the next test case and repeat the cycle. + +## Test Patterns + +### Arrange-Act-Assert (AAA) + +```python +def test_user_creation(): + # Arrange - set up test data + user_data = {"name": "Alice", "email": "alice@example.com"} + + # Act - perform the action + user = User.create(user_data) + + # Assert - verify the result + assert user.name == "Alice" + assert user.email == "alice@example.com" +``` + +### Given-When-Then (BDD style) + +```python +def test_user_login(): + # Given a registered user + user = create_user(email="test@example.com", password="secret") + + # When they attempt to login with correct credentials + result = login(email="test@example.com", password="secret") + + # Then they should be authenticated + assert result.success == True + assert result.token is not None +``` + +## Common Test Types + +### Unit Tests +- Test single functions/methods in isolation +- Mock external dependencies +- Fast execution + +### Integration Tests +- Test multiple components together +- Use real databases (test instances) +- Slower but more realistic + +### End-to-End Tests +- Test full user workflows +- Run against complete system +- Slowest but most comprehensive + +## Anti-Patterns to Avoid + +- **Test After**: Writing tests after implementation defeats the purpose +- **Testing Implementation**: Test behavior, not implementation details +- **Brittle Tests**: Tests shouldn't break when refactoring +- **Skipping Refactor**: Technical debt accumulates without refactoring +- **Too Many Mocks**: Over-mocking makes tests meaningless + +## Example TDD Session + +**User**: "Implement a password validator" + +**Agent Response**: +> Let me implement this using TDD: +> +> ## Test Cases to Cover +> 1. Password must be at least 8 characters +> 2. Password must contain uppercase letter +> 3. Password must contain number +> 4. Password must contain special character +> +> ## RED: First Test +> ```python +> def test_rejects_short_password(): +> result = validate_password("short") +> assert result.valid == False +> assert "at least 8 characters" in result.errors +> ``` +> +> ## GREEN: Minimal Implementation +> ```python +> def validate_password(password): +> errors = [] +> if len(password) < 8: +> errors.append("Password must be at least 8 characters") +> return ValidationResult(valid=len(errors) == 0, errors=errors) +> ``` +> +> [Continues with next test case...] diff --git a/webui/components/settings/memory/memory-dashboard-store.js b/webui/components/settings/memory/memory-dashboard-store.js index bf246f5e8a..90c026cf8a 100644 --- a/webui/components/settings/memory/memory-dashboard-store.js +++ b/webui/components/settings/memory/memory-dashboard-store.js @@ -511,7 +511,7 @@ ${memory.content_full} main: "#3b82f6", fragments: "#10b981", solutions: "#8b5cf6", - instruments: "#f59e0b", + skills: "#f59e0b", }; return colors[area] || "#6c757d"; }, diff --git a/webui/components/settings/memory/memory-dashboard.html b/webui/components/settings/memory/memory-dashboard.html index aaaeac15d2..08b6a449a5 100644 --- a/webui/components/settings/memory/memory-dashboard.html +++ b/webui/components/settings/memory/memory-dashboard.html @@ -35,7 +35,7 @@ - +