How DeerFlow Skills System Extends AI Agent Capabilities
Purpose
I’ve been frustrated with how most AI agent frameworks handle capabilities. Every time I need a new feature, I have to:
- Modify the agent code
- Understand the codebase architecture
- Risk breaking existing functionality
- Deploy a new version
When I explored DeerFlow, I found a different approach: the skills system. Instead of hardcoding capabilities, DeerFlow uses declarative Markdown files that inject workflows at runtime.
This post explains how the skills system works, why it matters, and how to create custom skills.
The Problem: Hardcoded Agent Capabilities
Traditional AI agents have capabilities baked into their code. Here’s what happens when you want to add a new feature:
Developer Request: "Add web research capability" | v1. Fork the agent codebase2. Find where tools are defined3. Write new tool function4. Register the tool5. Update documentation6. Submit PR or redeploy | vUser gets the feature (maybe)This works for developers but fails for end users. If you’re using an agent platform and need a custom workflow, you’re stuck unless you can modify the source.
What DeerFlow Skills Are
DeerFlow skills are Markdown files (SKILL.md) that define:
- Metadata: Name, description, license, allowed tools
- Workflow: Step-by-step instructions for the agent
- Examples: How to use the skill in practice
The key insight: skills are loaded progressively, not all at once. The agent sees skill descriptions in its system prompt, then loads full skill content only when needed.
Exploring the Built-in Skills
I started by examining the skills directory structure:
cd deer-flowls -la skills/public/drwxr-xr-x deep-research/drwxr-xr-x ppt-generation/drwxr-xr-x image-generation/drwxr-xr-x video-generation/drwxr-xr-x podcast-generation/drwxr-xr-x data-analysis/drwxr-xr-x frontend-design/drwxr-xr-x github-deep-research/drwxr-xr-x skill-creator/drwxr-xr-x claude-to-deerflow/... (17 total)Each skill has a SKILL.md file. I examined the deep-research skill:
cat skills/public/deep-research/SKILL.md | head -50---name: deep-researchdescription: Use this skill for ANY question requiring web research...license: MITallowed-tools: - web_search - web_fetch - bash---
# Deep Research Skill
## OverviewThis skill provides a systematic methodology for conducting thorough web research.
## Workflow
### Phase 1: Broad ExplorationStart with general queries to understand the landscape...
### Phase 2: Deep DiveFocus on specific aspects based on Phase 1 findings...
### Phase 3: SynthesisCombine findings into a coherent response...The YAML frontmatter defines what the skill is and what tools it can use. The body contains the workflow instructions.
How Skills Get Loaded
I wanted to understand the loading mechanism. Here’s what I found:
Step 1: Skill Discovery
DeerFlow recursively scans the skills directory:
skills/├── public/ # Built-in skills│ ├── deep-research/SKILL.md│ ├── ppt-generation/SKILL.md│ └── ...└── custom/ # User-defined skills └── my-skill/SKILL.mdThe system parses each SKILL.md file and extracts metadata.
Step 2: System Prompt Injection
Enabled skills are listed in the agent’s system prompt:
## Available Skills
1. **deep-research**: Use for systematic web research... Path: /mnt/skills/public/deep-research/SKILL.md
2. **ppt-generation**: Create professional presentations... Path: /mnt/skills/public/ppt-generation/SKILL.md
3. **image-generation**: AI image creation... Path: /mnt/skills/public/image-generation/SKILL.mdOnly the descriptions are loaded initially. The full skill content loads when the agent decides to use it.
Step 3: Progressive Loading
When the agent encounters a task matching a skill:
User: "Research the latest React 19 features" | vAgent sees: deep-research skill description matches | vAgent loads: Full SKILL.md content | vAgent follows: Workflow defined in skillThis approach keeps the context window lean. With 17 skills, loading everything would waste tokens. Progressive loading means only relevant skills consume context.
Testing a Skill in Practice
I tested the deep-research skill with a real request:
from deerflow.client import DeerFlowClient
client = DeerFlowClient()
response = client.chat( "Research the current state of server-sent events (SSE) " "in web frameworks. What are the alternatives?", thread_id="research-test")
print(response)The agent recognized this as a research task and loaded the deep-research skill. I watched the logs:
[lead-agent] Analyzing request...[lead-agent] Matched skill: deep-research[lead-agent] Loading skill from: /mnt/skills/public/deep-research/SKILL.md[lead-agent] Executing workflow: - Phase 1: Broad exploration (3 queries) - Phase 2: Deep dive (2 focused queries) - Phase 3: Synthesis[lead-agent] Skill execution completeThe result was a structured research report with sources.
Creating a Custom Skill
I wanted to test custom skill creation. Here’s what I did:
Step 1: Create the Directory Structure
mkdir -p skills/custom/code-reviewerStep 2: Write the Skill Definition
---name: code-reviewerdescription: "Use this skill when reviewing code for security, performance, and best practices"license: MITallowed-tools: - bash - read_file - write_file---
# Code Reviewer Skill
## OverviewThis skill provides a systematic methodology for conducting thorough code reviews.
## Workflow
### Phase 1: Security Analysis1. Check for hardcoded secrets (API keys, passwords, tokens)2. Identify SQL injection risks3. Look for XSS vulnerabilities4. Verify CSRF protection5. Check authentication/authorization
### Phase 2: Performance Review1. Identify N+1 queries2. Check for memory leaks3. Look for unnecessary loops4. Verify caching is used appropriately
### Phase 3: Code Quality1. Check function length (<50 lines recommended)2. Verify proper error handling3. Look for code duplication4. Check naming conventions
## Output Format
```markdown## Code Review Report
### Security Issues- [CRITICAL] Description...- [HIGH] Description...
### Performance Issues- [MEDIUM] Description...
### Quality Issues- [LOW] Description...
### Recommendations1. ...Examples
User: “Review the code in /mnt/data/auth.py” Agent: [Loads skill, follows workflow, outputs report]
### Step 3: Enable the Skill
I updated the extensions config:
```json title="extensions_config.json"{ "skills": { "deep-research": {"enabled": true}, "ppt-generation": {"enabled": true}, "code-reviewer": {"enabled": true} }}Step 4: Test the Custom Skill
from deerflow.client import DeerFlowClient
client = DeerFlowClient()
# Write some code to reviewclient.chat( "Create a file called test_auth.py with a simple login function", thread_id="review-test")
# Request a code reviewresponse = client.chat( "Review the code in test_auth.py for security issues", thread_id="review-test")
print(response)The agent loaded my custom skill and followed the workflow I defined:
## Code Review Report
### Security Issues- [CRITICAL] Password stored in plain text- [HIGH] No input validation on username
### Performance Issues- [LOW] Database connection not pooled
### Recommendations1. Use bcrypt for password hashing2. Add input sanitization3. Implement connection poolingProgrammatic Skill Management
DeerFlow provides APIs for managing skills programmatically.
Using the Python Client
from deerflow.client import DeerFlowClient
client = DeerFlowClient()
# List all skillsskills = client.list_skills()print(skills)# {"skills": [# {"name": "deep-research", "enabled": true, ...},# {"name": "ppt-generation", "enabled": false, ...},# ...# ]}
# Enable a skillclient.update_skill("ppt-generation", enabled=True)
# Disable a skillclient.update_skill("deep-research", enabled=False)
# Install a skill from archiveclient.install_skill("/path/to/skill.archive.skill")Using the Gateway API
# List skillscurl http://localhost:2026/api/skills
# Enable/disable a skillcurl -X PUT http://localhost:2026/api/skills/deep-research \ -H "Content-Type: application/json" \ -d '{"enabled": true}'
# Install from archivecurl -X POST http://localhost:2026/api/skills/install \ -F "archive=@./my-skill.skill"Why This Approach Matters
After testing, I identified several advantages of the skills approach:
1. User Customization Without Code Changes
End users can add capabilities by creating a SKILL.md file. No Python knowledge required, no codebase modifications.
2. Domain-Specific Workflows
Teams can inject domain expertise:
legal-team/ └── contract-reviewer/SKILL.md # Legal review workflow
medical-team/ └── patient-summary/SKILL.md # Medical note summarization
finance-team/ └── expense-analyzer/SKILL.md # Expense report workflow3. Efficiency Through Progressive Loading
With 17+ skills, loading all content would consume ~10,000+ tokens. Progressive loading means the agent only loads what it needs.
4. Sharing and Distribution
Skills can be packaged as .skill archives:
# Export a skilldeerflow skill export code-reviewer --output code-reviewer.skill
# Share with team# Import on another machinedeerflow skill install code-reviewer.skillIssues I Encountered
Not everything was smooth:
-
Skill debugging: When a skill fails, the error messages are cryptic. I had to check container logs to understand what went wrong.
-
Tool restrictions: The
allowed-toolsfield doesn’t enforce restrictions. It’s more of a documentation hint. The agent can still use any available tool. -
Skill conflicts: When multiple skills match a task, the agent sometimes picks the wrong one. There’s no priority system.
-
Documentation: The skill format documentation was sparse. I learned mostly by reading the built-in skills.
Comparison: Skills vs Other Approaches
I’ve used other extensibility patterns. Here’s how skills compare:
| Approach | User Customizable | Code Required | Context Efficient |
|---|---|---|---|
| Hardcoded tools | No | Yes | Yes |
| Plugin system | Yes | Yes (usually) | Depends |
| MCP servers | Yes | Yes | Yes |
| DeerFlow Skills | Yes | No (Markdown) | Yes |
The Markdown-based approach is unique. It trades some flexibility (no arbitrary code execution) for accessibility (anyone can write Markdown).
When to Create Custom Skills
Based on my testing, custom skills make sense when:
- You have a repeatable workflow: A multi-step process you use regularly
- Domain expertise matters: You want to inject specialized knowledge
- Consistency is important: You want the agent to follow the same steps each time
- You’re not a developer: You can express your workflow in natural language
Skip custom skills if:
- Simple tool access: You just need the agent to call an API
- One-off tasks: The workflow doesn’t repeat
- Code is easier: Your workflow is complex enough to need actual code
My Recommendation
The skills system is one of DeerFlow’s most thoughtful features. It solves the real problem of agent extensibility without requiring users to modify code.
Use custom skills when:
- You have domain-specific workflows
- You want to share capabilities across a team
- You prefer Markdown over code
Stick with tools/MCP when:
- You need to call external APIs
- Your workflow requires arbitrary computation
- You’re building something for developers
For teams using DeerFlow, I recommend starting with the built-in skills, then creating custom skills for your most common workflows. The investment pays off quickly when the agent consistently follows your team’s best practices.
Summary
DeerFlow’s skills system provides a Markdown-based way to extend AI agent capabilities. Skills are loaded progressively (only when needed), keeping context windows efficient. The system includes 17 built-in skills and supports custom skill creation.
I tested custom skill creation and found it straightforward: create a directory, write a SKILL.md file, enable in config. The main limitation is that skills are workflow definitions, not executable code—they guide the agent rather than run independently.
For developers building on DeerFlow, the skills system offers a practical path to domain-specific customization that doesn’t require modifying the codebase.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments