
Create Tooluniverse Skill
- 361 installs
- 1.6k repo stars
- Updated August 4, 2026
- mims-harvard/tooluniverse
create-tooluniverse-skill is a Claude Code skill that scaffolds production-ready ToolUniverse skills using a test-driven, 7-phase workflow so agents can discover and invoke new tools reliably.
About
create-tooluniverse-skill is a Harvard MIMS ToolUniverse authoring skill that walks developers through a 7-phase, roughly 1.5–2 hour workflow to create agent-invokable research skills. It enforces 10 quality pillars from devtu-optimize-skills—test first, verify tool contracts, handle SOAP operation parameters, keep SKILL.md implementation-agnostic, and grade evidence T1–T4. Phase 2 searches 186 tool JSON files under /src/tooluniverse/data/, runs test_tools_template.py against each tool, then produces python_implementation.py, agnostic SKILL.md, QUICK_START.md, and a validation checklist before packaging. disable-model-invocation is true, so developers explicitly invoke it when authoring new domain skills. Use create-tooluniverse-skill when adding ToolUniverse domain coverage—not for one-off scripts, undocumented tools, or skills that embed Python directly in SKILL.md.
- Scaffolds ToolUniverse skill layout
- Encodes discovery metadata
- Aligns with Harvard MIMS conventions
- Speeds repeatable skill creation
- Improves agent skill consistency
Create Tooluniverse Skill by the numbers
- 361 all-time installs (skills.sh)
- +6 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #122 of 782 Skill Development skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mims-harvard/tooluniverse --skill create-tooluniverse-skillAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 361 |
|---|---|
| repo stars | ★ 1.6k |
| Last updated | August 4, 2026 |
| Repository | mims-harvard/tooluniverse ↗ |
How do you author ToolUniverse agent skills correctly?
Scaffold and author new ToolUniverse-compatible Claude Code skills with correct structure, metadata, and conventions so agents can discover and invoke them reliably.
Who is it for?
Developers extending Harvard ToolUniverse who need a test-driven recipe for skills agents can discover and invoke without broken tool contracts.
Skip if: Skip create-tooluniverse-skill for quick one-off scripts, skills with Python embedded in SKILL.md, or using tools without running the mandatory test script first.
When should I use this skill?
User wants to create, scaffold, or validate a new ToolUniverse-compatible skill or domain workflow with tested tools and agnostic documentation.
What you get
Tested python_implementation.py, agnostic SKILL.md, QUICK_START.md, test_skill.py, validation checklist sign-off, and packaging summary for a new tooluniverse-[domain] skill folder.
- SKILL.md
- QUICK_START.md
- python_implementation.py
By the numbers
- Defines a 7-phase workflow (~1.5–2 hours without tool creation)
- Enforces 10 quality pillars from devtu-optimize-skills
- Searches 186 tool JSON files under /src/tooluniverse/data/
Files
[Domain Name] Analysis
[One paragraph overview describing what this skill does, what problems it solves, and what outputs it provides.]
When to Use This Skill
Triggers:
- "[Trigger phrase 1]"
- "[Trigger phrase 2]"
- "[Trigger phrase 3]"
Use Cases: 1. [Use Case 1]: [Description] 2. [Use Case 2]: [Description] 3. [Use Case 3]: [Description]
Core Databases Integrated
| Database | Coverage | Strengths |
|---|---|---|
| Database 1 | [What it covers] | [What it's best for] |
| Database 2 | [What it covers] | [What it's best for] |
| Database 3 | [What it covers] | [What it's best for] |
Workflow Overview
Input → Phase 1: [Name] → Phase 2: [Name] → Phase 3: [Name] → Report---
Phase 1: [Phase Name]
When: [When this phase runs - e.g., "When input_param_1 provided"]
Objective: [What this phase achieves]
Tools Used
TOOL_NAME_1:
- Input:
parameter1(type, required/optional): Descriptionparameter2(type, required/optional): Description- Output: Description of what the tool returns
- Use: What this tool provides for the analysis
TOOL_NAME_2 (Fallback):
- Input: [Parameters]
- Output: [Description]
- Use: [Purpose]
Workflow
1. Query TOOL_NAME_1 with [input description] 2. Extract [specific data fields] from response 3. If no results → try TOOL_NAME_2 (fallback) 4. Process data and add to report 5. Continue with available data
Decision Logic
- Successful query: Process and display top 10-15 results
- Empty results: Note "[Database] returned no results"
- API error: Fall back to TOOL_NAME_2
- Both fail: Document unavailability and continue
---
Phase 2: [Phase Name]
When: [Conditions]
Objective: [Goal]
Tools Used
[Similar structure to Phase 1]
Workflow
[Step-by-step process]
Decision Logic
[How to handle different scenarios]
---
Phase 3: [Phase Name]
[Similar structure]
---
Phase 4: [Summary/Context Phase]
When: Always included
Objective: Provide context even when specific phases empty
[Structure similar to above phases]
---
Output Structure
Report Format
Progressive Markdown Report:
- Create report file first
- Add sections progressively
- Each section self-contained
- Handles empty data gracefully
Required Sections: 1. Header: Analysis parameters and metadata 2. Phase 1 Results: [Description] 3. Phase 2 Results: [Description] 4. Phase 3 Results: [Description] 5. Phase 4 Results: [Description]
Per-Database Subsections:
- Database name and result count
- Table of results with key metadata
- Note if database returns no results
- Links or IDs for follow-up
Data Tables
Phase 1 Results: | Column 1 | Column 2 | Column 3 | | ... | ... | ... |
Phase 2 Results: | Column 1 | Column 2 | Column 3 | | ... | ... | ... |
---
Tool Parameter Reference
Critical Parameter Notes (from testing):
| Tool | Parameter | CORRECT Name | Common Mistake |
|---|---|---|---|
| TOOL_NAME_1 | param | ✅ actual_param_name | ❌ assumed_param_name |
| TOOL_NAME_2 | param | ✅ correct_name | ❌ function_name_param |
Response Format Notes:
- TOOL_NAME_1: Returns standard
{status: "success", data: [...]}format - TOOL_NAME_2: Returns list directly (not wrapped in status/data)
- TOOL_NAME_3: Returns dict with custom structure
{field1: ..., field2: ...}
SOAP Tools (if applicable):
- TOOL_NAME_4: Requires
operationparameter (e.g.,operation="method_name") - See QUICK_START.md for side-by-side Python/MCP examples
---
Fallback Strategies
Phase 1: [Phase Name]
- Primary: TOOL_NAME_1 ([reason it's primary])
- Fallback: TOOL_NAME_2 ([what it provides instead])
- Default: Continue with noting data unavailable
Phase 2: [Phase Name]
- Primary: TOOL_NAME_3
- Fallback: [Alternative approach]
- Default: [How to proceed]
---
Common Use Patterns
Pattern 1: [Use Case Name]
Input: [Description of typical input]
Workflow: Phase 1 → Phase 3 → Report
Output: [What user gets]Pattern 2: [Use Case Name]
Input: [Description]
Workflow: [Which phases run]
Output: [Result type]Pattern 3: [Comprehensive Analysis]
Input: [Multiple inputs]
Workflow: All phases
Output: [Complete analysis]---
Quality Checks
Data Completeness
- [ ] At least one phase completed successfully
- [ ] Each database result includes source attribution
- [ ] Empty results explicitly noted (not silently omitted)
- [ ] All required fields documented in tables
- [ ] IDs provided for follow-up analysis
Biological/Scientific Validity
- [ ] Results consistent with known [domain] knowledge
- [ ] Cross-database results show expected overlaps
- [ ] Anomalies flagged for review
- [ ] Data quality indicators included
Report Quality
- [ ] All sections present even if "no data"
- [ ] Tables formatted consistently
- [ ] Source databases clearly attributed
- [ ] Follow-up recommendations if data sparse
---
Limitations & Known Issues
Database-Specific
- Database 1: [Known limitations, coverage gaps, update frequency]
- Database 2: [Limitations]
- Database 3: [Limitations]
Technical
- Response formats: Different tools use different structures (handled in implementation)
- Rate limits: [Any rate limiting concerns]
- Version differences: [Database version considerations]
Analysis
- [Domain]-specific limitation 1: [Description]
- [Domain]-specific limitation 2: [Description]
---
Summary
[Domain] Analysis Skill provides: 1. ✅ [Capability 1 with database] 2. ✅ [Capability 2 with databases] 3. ✅ [Capability 3 with databases] 4. ✅ [Capability 4]
Outputs: Markdown report with [description of content]
Best for: [Primary use cases and target users]
#!/usr/bin/env python3
"""
[DOMAIN NAME] - Python SDK Implementation
Tested implementation following TDD principles
INSTRUCTIONS:
1. Replace [DOMAIN NAME] with your domain (e.g., "Metabolomics Research")
2. Replace [domain] with lowercase domain name (e.g., "metabolomics")
3. Update function parameters based on your needs
4. Implement each phase using TESTED tools
5. Add error handling for each database/tool
6. Create progressive report with clear sections
7. Test with test_skill.py before documenting
"""
from datetime import datetime
from tooluniverse import ToolUniverse
def domain_analysis_pipeline(
input_param_1=None,
input_param_2=None,
input_param_3=None,
organism="Homo sapiens",
output_file=None
):
"""
[DOMAIN] analysis pipeline.
Args:
input_param_1: [Description of input 1]
input_param_2: [Description of input 2]
input_param_3: [Description of input 3]
organism: Organism name (default: "Homo sapiens")
output_file: Output markdown file path (default: auto-generated)
Returns:
Path to generated report file
"""
tu = ToolUniverse()
tu.load_tools()
# Generate output filename
if output_file is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
if input_param_1:
output_file = f"domain_analysis_{input_param_1}_{timestamp}.md"
else:
output_file = f"domain_analysis_{timestamp}.md"
# Initialize report
report = []
report.append("# [DOMAIN] Analysis Report\n")
report.append(f"**Generated**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
if input_param_1:
report.append(f"**Input 1**: {input_param_1}\n")
if input_param_2:
report.append(f"**Input 2**: {input_param_2}\n")
if input_param_3:
report.append(f"**Input 3**: {input_param_3}\n")
report.append(f"**Organism**: {organism}\n")
report.append("\n---\n")
# Phase 1: [PHASE NAME]
if input_param_1:
report.append("\n## 1. [Phase 1 Name]\n")
# Database 1
try:
result = tu.tools.DATABASE1_TOOL(param=input_param_1)
# Handle different response formats
if isinstance(result, dict) and result.get('status') == 'success':
data = result.get('data', [])
if data:
report.append(f"\n### Database 1 Results ({len(data)} entries)\n")
report.append("\n| Column 1 | Column 2 | Column 3 |\n")
report.append("|----------|----------|----------|\n")
for item in data[:10]: # Limit to top 10
col1 = item.get('field1', 'N/A')
col2 = item.get('field2', 'N/A')
col3 = item.get('field3', 'N/A')
report.append(f"| {col1} | {col2} | {col3} |\n")
else:
report.append("\n*No results found from Database 1.*\n")
elif isinstance(result, list):
# Handle direct list response
if result:
report.append(f"\n### Database 1 Results ({len(result)} entries)\n")
# Process list
else:
report.append("\n*No results found from Database 1.*\n")
else:
report.append("\n*Database 1 data unavailable.*\n")
except Exception as e:
report.append(f"\n*Error querying Database 1: {str(e)}*\n")
# Database 2 (Fallback)
try:
result = tu.tools.DATABASE2_TOOL(param=input_param_1)
# Similar processing
except Exception as e:
report.append(f"\n*Error querying Database 2: {str(e)}*\n")
# Phase 2: [PHASE NAME]
if input_param_2:
report.append("\n## 2. [Phase 2 Name]\n")
try:
result = tu.tools.DATABASE3_TOOL(param=input_param_2)
# Process results
except Exception as e:
report.append(f"\n*Error in Phase 2: {str(e)}*\n")
# Phase 3: [PHASE NAME]
if input_param_3:
report.append("\n## 3. [Phase 3 Name]\n")
# Multiple databases in parallel
try:
_result1 = tu.tools.DATABASE4_TOOL(param=input_param_3)
_result2 = tu.tools.DATABASE5_TOOL(param=input_param_3)
# Process and combine results
except Exception as e:
report.append(f"\n*Error in Phase 3: {str(e)}*\n")
# Phase 4: Summary/Context (always included)
report.append("\n## 4. [Summary/Context]\n")
try:
result = tu.tools.SUMMARY_TOOL(organism=organism)
# Process summary data
except Exception as e:
report.append(f"\n*Error generating summary: {str(e)}*\n")
# Write report to file
report_content = ''.join(report)
with open(output_file, 'w') as f:
f.write(report_content)
print(f"\n✅ Report generated: {output_file}")
return output_file
if __name__ == "__main__":
# Example usage
print("[DOMAIN] Analysis - Python SDK Implementation")
print("="*80)
# Example 1: Basic usage
print("\n[Example 1] Basic analysis...")
domain_analysis_pipeline(
input_param_1="example_value",
output_file="example1_basic.md"
)
# Example 2: Multiple inputs
print("\n[Example 2] Complex analysis...")
domain_analysis_pipeline(
input_param_1="value1",
input_param_2="value2",
input_param_3="value3",
organism="Homo sapiens",
output_file="example2_complex.md"
)
print("\n✅ All examples completed!")
Quick Start: [Domain] Analysis
[One paragraph overview of what this skill does and what outputs it provides.]
---
Choose Your Implementation
Python SDK
####Option 1: Complete Pipeline (Recommended)
Use the ready-made pipeline function for comprehensive analysis:
from skills.tooluniverse_[domain].python_implementation import domain_analysis_pipeline
# Example 1: Basic usage
domain_analysis_pipeline(
input_param_1="example_value",
output_file="analysis.md"
)
# Example 2: Multiple inputs
domain_analysis_pipeline(
input_param_1="value1",
input_param_2="value2",
input_param_3="value3",
organism="Homo sapiens",
output_file="comprehensive_analysis.md"
)Option 2: Individual Tools
Use specific tools for targeted queries:
from tooluniverse import ToolUniverse
tu = ToolUniverse()
tu.load_tools()
# 1. Tool from Database 1
result = tu.tools.TOOL_NAME_1(
parameter1="value1",
parameter2="value2"
)
# 2. Tool from Database 2
result = tu.tools.TOOL_NAME_2(
parameter="value"
)
# 3. SOAP tool (if applicable) - note operation parameter
result = tu.tools.SOAP_TOOL_NAME(
operation="method_name", # CRITICAL for SOAP tools
parameter="value"
)---
MCP (Model Context Protocol)
Option 1: Conversational (Natural Language)
Ask Claude to perform analysis directly:
"Analyze [domain] for [input_description]"
"Find [data_type] related to [query]"
"[Domain-specific request phrase]"
"Perform comprehensive [domain] analysis for [input] in [organism]"Option 2: Direct Tool Calls
Use specific tools via JSON (for programmatic MCP usage):
1. Tool from Database 1:
{
"tool": "TOOL_NAME_1",
"parameters": {
"parameter1": "value1",
"parameter2": "value2"
}
}2. Tool from Database 2:
{
"tool": "TOOL_NAME_2",
"parameters": {
"parameter": "value"
}
}3. SOAP Tool (if applicable):
{
"tool": "SOAP_TOOL_NAME",
"parameters": {
"operation": "method_name",
"parameter": "value"
}
}---
Tool Parameters (All Implementations)
Note: Whether using Python SDK or MCP, the parameter names are the same.
TOOL_NAME_1
| Parameter | Type | Required | Description |
|---|---|---|---|
parameter1 | string | Yes | [Description] |
parameter2 | integer | No | [Description] |
parameter3 | boolean | No | [Description] (default: false) |
TOOL_NAME_2
| Parameter | Type | Required | Description |
|---|---|---|---|
parameter | string | Yes | [Description] |
limit | integer | No | Max results (default: 10) |
SOAP_TOOL_NAME (if applicable)
| Parameter | Type | Required | Description |
|---|---|---|---|
operation | string | Yes | ⚠️ CRITICAL: SOAP method name (e.g., "search") |
parameter | string | Yes | [Description] |
CRITICAL: SOAP tools MUST include operation parameter or they will fail.
---
Common Recipes
Recipe 1: [Use Case Name]
Scenario: [Description of when to use this]
Python SDK:
domain_analysis_pipeline(
input_param_1="specific_value",
output_file="recipe1_output.md"
)MCP:
"[Conversational request matching this use case]"Recipe 2: [Use Case Name]
Scenario: [Description]
Python SDK:
# More complex example with multiple parameters
domain_analysis_pipeline(
input_param_1="value1",
input_param_2="value2",
organism="Mus musculus", # Mouse
output_file="recipe2_output.md"
)MCP:
"[Conversational request for this scenario]"Recipe 3: [Multi-Database Comparison]
Scenario: Compare results across multiple databases
Python SDK:
from tooluniverse import ToolUniverse
tu = ToolUniverse()
tu.load_tools()
query = "example_query"
# Query all databases
result1 = tu.tools.DATABASE1_TOOL(param=query)
result2 = tu.tools.DATABASE2_TOOL(param=query)
result3 = tu.tools.DATABASE3_TOOL(param=query)
# Compare coverage
print(f"Database 1: {len(result1.get('data', []))} results")
print(f"Database 2: {len(result2.get('data', []))} results")
print(f"Database 3: {len(result3.get('data', []))} results")MCP:
"Search for [query] across [Database 1], [Database 2], and [Database 3].
Compare the coverage across databases."---
CRITICAL: SOAP Tool Parameters (if applicable)
Only for skills using SOAP tools like IMGT, SAbDab, TheraSAbDab
Python SDK Example
# CORRECT - includes operation parameter
result = tu.tools.SOAP_TOOL_NAME(
operation="method_name", # Required!
parameter="value"
)
# WRONG - missing operation
result = tu.tools.SOAP_TOOL_NAME(
parameter="value" # Will fail!
)MCP Example
{
"operation": "method_name",
"parameter": "value"
}Error if missing: "Parameter validation failed: 'operation' is a required property"
---
Expected Output
Report Structure
The skill generates a markdown report with these sections:
1. Header: Analysis parameters and metadata 2. Phase 1: [Name] (if input_param_1 provided)
- Table of results from Database 1
- Fallback results from Database 2 if needed
3. Phase 2: [Name] (if input_param_2 provided)
- Results from Database 3
4. Phase 3: [Name] (if input_param_3 provided)
- Results from Databases 4 and 5
5. Phase 4: [Summary/Context] (always included)
- Contextual information
Example Output Snippet
# [Domain] Analysis Report
**Generated**: 2026-02-09 14:30:00
**Input 1**: example_value
**Organism**: Homo sapiens
---
## 1. [Phase 1 Name]
### Database 1 Results (15 entries)
| Column 1 | Column 2 | Column 3 |
|----------|----------|----------|
| Value 1 | Value 2 | Value 3 |
| ... | ... | ... |
## 2. [Phase 2 Name]
### Database 3 Results (8 entries)
...---
Troubleshooting
Issue: Empty results from all databases
Solution: Check that input values are valid. Try alternative input formats or synonyms.
Issue: Tool returns "operation is a required property" error
Solution: You're using a SOAP tool. Add operation="method_name" parameter.
Issue: Different result counts across databases
Expected: Different databases have different coverage. Cross-reference to validate findings.
Issue: Timeout or API errors
Solution: Check internet connection. If persistent, database may be down - check fallback options.
Issue: "Tool not found" error
Solution: Ensure ToolUniverse is properly loaded: tu = ToolUniverse(); tu.load_tools()
---
Next Steps
After running this skill:
1. Follow-up Analysis: Use IDs from report to get detailed information 2. Visualization: [Suggestions for visualizing results] 3. Validation: Cross-reference key findings across databases 4. Export: Convert tables to CSV/Excel for further analysis 5. Literature Search: Use [domain] names/IDs for literature searches
---
Additional Resources
- Database 1: [URL]
- Database 2: [URL]
- Database 3: [URL]
- [Domain] Documentation: [URL]
- ToolUniverse Docs: https://github.com/mims-harvard/ToolUniverse
---
Performance Notes
- Typical runtime: 30-60 seconds for basic queries
- Complex queries: 2-5 minutes with multiple inputs
- Large datasets: May take longer, progress shown during execution
Optimization tips:
- Start with single input to test
- Use specific rather than broad queries
- Consider organism-specific searches
#!/usr/bin/env python3
"""
Test script for [DOMAIN] skill
Verifies the complete pipeline works correctly
INSTRUCTIONS:
1. Replace [DOMAIN] with your domain name
2. Replace [domain] with lowercase domain name
3. Update test cases based on your skill's inputs
4. Add assertions to verify report sections
5. Test error handling scenarios
6. Ensure 100% pass rate before documenting
"""
import sys
import os
# Add parent directory to path to import python_implementation
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from python_implementation import domain_analysis_pipeline
def test_basic_analysis():
"""Test basic analysis with single input"""
print("\n" + "="*80)
print("TEST 1: Basic Analysis")
print("="*80)
output = domain_analysis_pipeline(
input_param_1="test_value",
output_file="test1_basic.md"
)
# Verify output file created
assert os.path.exists(output), f"Output file {output} not created"
# Verify report has expected sections
with open(output, 'r') as f:
content = f.read()
assert "[DOMAIN] Analysis Report" in content, "Missing report header"
assert "Phase 1" in content or "no data" in content.lower(), "Missing Phase 1 section"
print(f"✅ Test 1 PASSED: {output}")
def test_multiple_inputs():
"""Test with multiple input parameters"""
print("\n" + "="*80)
print("TEST 2: Multiple Inputs")
print("="*80)
output = domain_analysis_pipeline(
input_param_1="value1",
input_param_2="value2",
output_file="test2_multiple.md"
)
assert os.path.exists(output), f"Output file {output} not created"
# Verify multiple sections present
with open(output, 'r') as f:
content = f.read()
# Check that multiple phases are present
phase_count = sum([
"## 1." in content,
"## 2." in content,
"## 3." in content
])
assert phase_count >= 2, f"Expected multiple phases, found {phase_count}"
print(f"✅ Test 2 PASSED: {output}")
def test_comprehensive_analysis():
"""Test comprehensive analysis with all inputs"""
print("\n" + "="*80)
print("TEST 3: Comprehensive Analysis")
print("="*80)
output = domain_analysis_pipeline(
input_param_1="value1",
input_param_2="value2",
input_param_3="value3",
organism="Homo sapiens",
output_file="test3_comprehensive.md"
)
assert os.path.exists(output), f"Output file {output} not created"
# Check report contains all expected sections
with open(output, 'r') as f:
content = f.read()
# Required sections
assert "# [DOMAIN] Analysis Report" in content, "Missing report title"
assert "Generated:" in content, "Missing timestamp"
assert "Organism:" in content, "Missing organism"
# Phase sections (at least attempt to include)
phases = ["## 1.", "## 2.", "## 3.", "## 4."]
present_phases = sum([phase in content for phase in phases])
assert present_phases >= 3, f"Expected at least 3 phases, found {present_phases}"
# Data quality checks
assert len(content) > 500, "Report seems too short"
assert content.count("##") >= 3, "Not enough sections"
print(f"✅ Test 3 PASSED: {output}")
def test_error_handling():
"""Test error handling with invalid inputs"""
print("\n" + "="*80)
print("TEST 4: Error Handling")
print("="*80)
# Test with invalid/nonsense input (should not crash)
try:
output = domain_analysis_pipeline(
input_param_1="INVALID_TEST_VALUE_XYZ123",
output_file="test4_errors.md"
)
assert os.path.exists(output), "Output file not created even with invalid input"
# Should complete but may have empty/error sections
with open(output, 'r') as f:
content = f.read()
assert "# [DOMAIN] Analysis Report" in content, "Missing report header"
# May have error messages - that's OK
# Should not crash or fail to generate report
print(f"✅ Test 4 PASSED: Error handling works, report generated: {output}")
except Exception as e:
print(f"❌ Test 4 FAILED: Skill crashed with invalid input: {e}")
raise
def test_empty_input_handling():
"""Test behavior when no specific inputs provided"""
print("\n" + "="*80)
print("TEST 5: Empty Input Handling")
print("="*80)
# Some skills may require at least one input
# Adjust this test based on your skill's requirements
try:
output = domain_analysis_pipeline(
output_file="test5_empty.md"
)
assert os.path.exists(output), "Output file not created"
with open(output, 'r') as f:
content = f.read()
# Should at least have header and summary sections
assert "# [DOMAIN] Analysis Report" in content
assert len(content) > 100, "Report should have some content"
print(f"✅ Test 5 PASSED: {output}")
except Exception:
# If skill requires inputs, this is expected
print(f"⚠️ Test 5 SKIPPED: Skill requires at least one input (expected)")
def main():
"""Run all tests"""
print("\n" + "="*80)
print("[DOMAIN] SKILL TEST SUITE")
print("="*80)
tests = [
("Basic Analysis", test_basic_analysis),
("Multiple Inputs", test_multiple_inputs),
("Comprehensive Analysis", test_comprehensive_analysis),
("Error Handling", test_error_handling),
("Empty Input Handling", test_empty_input_handling),
]
results = {}
for name, test_func in tests:
try:
test_func()
results[name] = "✅ PASS"
except Exception as e:
print(f"\n❌ EXCEPTION in {name}: {e}")
results[name] = f"❌ FAIL: {str(e)[:100]}"
# Summary
print("\n" + "="*80)
print("TEST SUMMARY")
print("="*80)
for name, result in results.items():
print(f"{name:30} {result}")
# Overall status
passed = sum(1 for r in results.values() if "PASS" in r)
total = len(results)
pass_rate = (passed / total) * 100
print(f"\n{'='*80}")
print(f"PASS RATE: {passed}/{total} ({pass_rate:.0f}%)")
print(f"{'='*80}")
if pass_rate == 100:
print("\n✅ ALL TESTS PASSED - Skill is ready to use!")
return 0
elif pass_rate >= 80:
print("\n⚠️ MOST TESTS PASSED - Review failures before release")
return 1
else:
print("\n❌ MULTIPLE TESTS FAILED - Fix issues before continuing")
return 1
if __name__ == "__main__":
sys.exit(main())
Code Templates
Python implementation and test templates for ToolUniverse skills.
python_implementation.py Template
#!/usr/bin/env python3
"""
[DOMAIN NAME] - Python SDK Implementation
Replace [DOMAIN NAME], [domain], tool names, and parameters.
"""
from datetime import datetime
from tooluniverse import ToolUniverse
def domain_analysis_pipeline(
input_param_1=None,
input_param_2=None,
organism="Homo sapiens",
output_file=None,
):
"""[DOMAIN] analysis pipeline."""
tu = ToolUniverse()
tu.load_tools()
if output_file is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_file = f"domain_analysis_{timestamp}.md"
report = []
report.append("# [DOMAIN] Analysis Report\n")
report.append(f"**Generated**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
if input_param_1:
report.append(f"**Input 1**: {input_param_1}\n")
report.append(f"**Organism**: {organism}\n\n---\n")
# Phase 1
if input_param_1:
report.append("\n## 1. [Phase 1 Name]\n")
try:
result = tu.tools.DATABASE1_TOOL(param=input_param_1)
if isinstance(result, dict) and result.get("status") == "success":
data = result.get("data", [])
if data:
report.append(f"\n### Results ({len(data)} entries)\n")
report.append("\n| Col1 | Col2 |\n|------|------|\n")
for item in data[:10]:
report.append(f"| {item.get('f1','N/A')} | {item.get('f2','N/A')} |\n")
else:
report.append("\n*No results found.*\n")
elif isinstance(result, list) and result:
report.append(f"\n### Results ({len(result)} entries)\n")
else:
report.append("\n*Data unavailable.*\n")
except Exception as e:
report.append(f"\n*Error: {e}*\n")
# Phase 2, 3... (similar pattern)
# Summary phase (always included)
report.append("\n## Summary\n")
with open(output_file, "w") as f:
f.write("".join(report))
print(f"Report generated: {output_file}")
return output_file
if __name__ == "__main__":
domain_analysis_pipeline(input_param_1="example", output_file="example.md")test_skill.py Template
#!/usr/bin/env python3
"""Test script for [DOMAIN] skill."""
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from python_implementation import domain_analysis_pipeline
def test_basic():
"""Test basic analysis with single input."""
output = domain_analysis_pipeline(input_param_1="test", output_file="test1.md")
assert os.path.exists(output)
with open(output) as f:
content = f.read()
assert "Analysis Report" in content
print("PASS: basic analysis")
def test_multiple_inputs():
"""Test with multiple inputs."""
output = domain_analysis_pipeline(
input_param_1="v1", input_param_2="v2", output_file="test2.md"
)
assert os.path.exists(output)
print("PASS: multiple inputs")
def test_error_handling():
"""Test graceful handling of invalid input."""
try:
output = domain_analysis_pipeline(
input_param_1="INVALID_XYZ", output_file="test3.md"
)
assert os.path.exists(output)
print("PASS: error handling")
except Exception as e:
print(f"FAIL: crashed with {e}")
raise
def main():
tests = [test_basic, test_multiple_inputs, test_error_handling]
passed = failed = 0
for t in tests:
try:
t()
passed += 1
except Exception as e:
print(f"FAIL: {t.__name__}: {e}")
failed += 1
print(f"\nResults: {passed}/{len(tests)} passed")
return 0 if failed == 0 else 1
if __name__ == "__main__":
sys.exit(main())test_tools_template.py Template
See test_tools_template.py in this directory for the tool-testing script template. Key steps: 1. Load ToolUniverse once 2. Test each tool with known-good params 3. Check response format (standard dict, direct list, direct dict) 4. Detect SOAP tools (retry with operation param) 5. Print parameter corrections table and response format notes
Response Format Handling
Three formats tools may return:
- Standard:
{status: "success", data: [...]} - Direct list:
[...]without wrapper - Direct dict:
{field1: ..., field2: ...}without status
Handle all three with isinstance() checks in implementation.
Integration with devtu-optimize-skills
How to apply the 10 pillars when creating new ToolUniverse skills.
When to Reference devtu-optimize-skills
Invoke or review when: creating research report skills, need evidence grading, report optimization, completeness checking, or synthesis sections.
Not needed for: simple data retrieval, pure tool integration without reports.
The 10 Pillars Applied
1. TEST FIRST (Always)
Create test script BEFORE documentation. Verify all tool parameters through actual API calls. Document discoveries. Only proceed to implementation after 100% tool verification.
Lesson: All 4 broken skills (DDI, Clinical Trial, Antibody, CRISPR) had 0-20% functionality because tools were never tested.
2. Verify Tool Contracts (Always)
Check params via get_tool_info(). Maintain corrections table. Don't trust function names. Example: drugbank_get_drug_basic_info_by_drug_name_or_id(query=...) not name=...
3. Handle SOAP Tools (Always, if present)
Indicators: error about operation required, tool name includes IMGT/SAbDab/TheraSAbDab. Fix: add operation parameter as first argument with method name.
4. Implementation-Agnostic Docs (Always)
SKILL.md has ZERO Python/MCP code. Separate python_implementation.py. QUICK_START.md equal treatment of both interfaces. Tool parameter table notes "applies to all implementations."
5. Foundation First (If aggregator exists)
Query comprehensive aggregators before specialized tools. Structure: Phase 0 (aggregator) then Phases 1-N (specialized). Example: Open Targets (foundation) then specialized databases (details).
6. Disambiguate Carefully (If ambiguous inputs)
Include disambiguation phase early. Support multiple ID types. Handle versioned IDs (e.g., GTEx requires versioned Ensembl). Document ID resolution strategy.
7. Implement Fallbacks (If external APIs)
Primary -> Fallback -> Default chains. Design fallback for each critical tool. Document in SKILL.md. Example: DepMap_search_genes (primary) -> Pharos_get_target (fallback) -> continue with unvalidated genes (default).
8. Grade Evidence (If literature)
T1 (3 stars): Mechanistic study. T2 (2 stars): Functional study. T3 (1 star): Association. T4 (0 stars): Mention. Apply when skills search literature, aggregate multi-source evidence, or make scientific claims.
9. Quantified Completeness (If multi-section)
Define numeric minimums per section. Example: ">=20 pathways OR explanation why fewer." Implement checks in code.
10. Synthesize (If research-oriented)
Include biological models and testable hypotheses, not just paper lists. Sections: Biological Model (3-5 paragraphs), Testable Hypotheses table, Suggested Experiments.
Quick Reference: Which Pillars Apply
| Skill Type | Applicable Pillars |
|---|---|
| Research/Analysis | All 10 |
| Data Retrieval | 1-4, 6-7 |
| Multi-Database | 1-5, 7 |
| Specialized Analysis | 1-4, 7-9 |
| Simple Tool Wrapper | 1-4 |
Integration Checklist
- [ ] Reviewed 10 pillars
- [ ] Identified which apply
- [ ] TEST FIRST (always)
- [ ] Verified tool contracts (always)
- [ ] Implementation-agnostic docs (always)
- [ ] Fallback strategies (if external APIs)
- [ ] Evidence grading (if literature)
- [ ] Quantified completeness (if multi-section)
- [ ] Synthesis (if research-oriented)
Packaging Template
Use this template to create the summary document when a skill is complete.
Summary Document Template
File: NEW_SKILL_[DOMAIN].md
# New Skill Created: [Domain] Analysis
**Date**: [Date]
**Status**: COMPLETE AND TESTED
## Overview
[Brief description]
### Key Features
- [Feature 1]
- [Feature 2]
## Skill Details
**Location**: `skills/tooluniverse-[domain]/`
**Files Created**:
1. `python_implementation.py` ([lines]) - Working pipeline
2. `SKILL.md` ([lines]) - Implementation-agnostic docs
3. `QUICK_START.md` ([lines]) - Multi-implementation guide
4. `test_skill.py` ([lines]) - Test suite
**Total**: [total lines]
## Tools Integrated
- **Database 1**: [X tools]
- **Database 2**: [Y tools]
**Total**: [N tools]
## Test Results
Test 1 - PASS Test 2 - PASS Test 3 - PASS
100% test pass rate
## Capabilities
[List key capabilities]
## Impact & Value
[Describe impact]
## Next Steps
[Suggest enhancements]Session Tracking
If creating multiple skills in a session, update tracking with:
- Skills created count
- Total tools utilized
- Test coverage metrics
- Time per skill
Tool Parameter Verification Guide
From devtu-optimize-skills -- CRITICAL for avoiding common mistakes.
Common Parameter Mistakes to Avoid
| Pattern | Don't Assume | Always Verify |
|---|---|---|
| Function name includes param name | drugbank_get_drug_basic_info_by_drug_name_or_id(name=...) | Test reveals uses query |
| Descriptive function name | map_uniprot_to_pathways(uniprot_id=...) | Test reveals uses id |
| Consistent naming | All similar functions use same param | Each tool may differ |
SOAP Tools Detection
Indicators:
- Error: "Parameter validation failed: 'operation' is a required property"
- Tool name includes: IMGT, SAbDab, TheraSAbDab
- Tool config shows
operationin schema
Fix: Add operation parameter as first argument with method name.
Response Format Variations
Standard: {status: "success", data: [...]} Direct list: Returns [...] without wrapper Direct dict: Returns {field1: ..., field2: ...} without status
Solution: Handle all three in implementation with isinstance() checks.
QUICK_START.md Template
Use this template when writing the QUICK_START.md for a new ToolUniverse skill.
Key Rule: Equal treatment of Python SDK and MCP. Concrete examples for both.
---
## Quick Start: [Domain] Analysis
[One paragraph overview]
---
## Choose Your Implementation
### Python SDK
#### Option 1: Complete Pipeline (Recommended)
from skills.tooluniverse_[domain].python_implementation import domain_pipeline
Example 1
domain_pipeline( input_param="value", output_file="analysis.md" )
#### Option 2: Individual Tools
from tooluniverse import ToolUniverse
tu = ToolUniverse() tu.load_tools()
Tool 1
result = tu.tools.TOOL_NAME(param="value")
Tool 2
result = tu.tools.TOOL_NAME2(param="value")
---
### MCP (Model Context Protocol)
#### Option 1: Conversational (Natural Language)
"Analyze [domain] for [input]"
"Find [data] related to [query]"
#### Option 2: Direct Tool Calls
{ "tool": "TOOL_NAME", "parameters": { "param": "value" } }
---
## Tool Parameters (All Implementations)
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `param1` | string | Yes | [Description] |
| `param2` | integer | No | [Description] |
---
## Common Recipes
### Recipe 1: [Use Case Name]
**Python SDK**:[Code example]
**MCP**:[Conversational example]
### Recipe 2, 3... (similar)
---
## Expected Output
[Show example report structure]
---
## Troubleshooting
### Issue: [Problem]
**Solution**: [Fix]
---
## Next Steps
After running this skill:
1. [Follow-up action 1]
2. [Follow-up action 2]Integration with devtu-optimize-skills
This skill builds on principles from devtu-optimize-skills. This reference explains how to apply those principles when creating new skills.
When to Reference devtu-optimize-skills
Invoke or review devtu-optimize-skills when:
- Creating skills that generate research reports
- Need evidence grading patterns
- Want report optimization strategies
- Implementing completeness checking
- Designing synthesis sections
Don't need devtu-optimize-skills when:
- Creating simple data retrieval skills
- Building workflows without reports
- Pure tool integration (no analysis)
The 10 Pillars Applied to Skill Creation
1. TEST FIRST
devtu-optimize principle: Never write skill documentation without testing all tool calls
Application in skill creation:
- Phase 2: Tool Discovery & Testing - Create test script BEFORE implementation
- Verify all tool parameters through actual API calls
- Document discoveries (response formats, parameter mismatches)
- Only proceed to Phase 4 (Implementation) after 100% tool verification
Why critical: All 4 broken skills (DDI, Clinical Trial, Antibody, CRISPR) had 0-20% functionality because tools were never tested.
2. Verify Tool Contracts
devtu-optimize principle: Check params via get_tool_info(); maintain corrections table; don't trust function names
Application in skill creation:
- Test script checks actual parameter names
- Create parameter corrections table in SKILL.md
- Document: "Tool function names DO NOT predict parameter names"
- Example:
drugbank_get_drug_basic_info_by_drug_name_or_id(query=...)notname=...
3. Handle SOAP Tools
devtu-optimize principle: Add operation parameter to IMGT, SAbDab, TheraSAbDab tools
Application in skill creation:
- Test script identifies SOAP tools (error: "operation is required")
- Add
operationparameter to all SOAP tool calls - Document prominently in SKILL.md and QUICK_START
- Show side-by-side Python/MCP examples
4. Implementation-Agnostic Docs
devtu-optimize principle: SKILL.md general; separate python_implementation.py; QUICK_START for both SDK and MCP
Application in skill creation:
- Phase 5: Documentation - SKILL.md has ZERO Python/MCP code
- python_implementation.py contains working pipeline
- QUICK_START.md equal treatment of both interfaces
- Tool parameter table notes "applies to all implementations"
5. Foundation First
devtu-optimize principle: Query comprehensive aggregators before specialized tools
Application in skill creation:
- Identify if domain has comprehensive aggregator (e.g., Open Targets for targets)
- Structure workflow: Phase 0 (aggregator) → Phases 1-N (specialized)
- Document in SKILL.md which tool provides foundation data
- Use aggregator to provide baseline when specialized tools fail
Example:
- Target research: Open Targets (foundation) → specialized databases (details)
- Pathway analysis: Reactome top-level (foundation) → keyword search (specific)
6. Disambiguate Carefully
devtu-optimize principle: Resolve IDs (versioned + unversioned), detect collisions, get baseline from annotation DBs
Application in skill creation:
- Include disambiguation phase early in workflow
- Support multiple ID types (e.g., gene symbols, Ensembl, UniProt)
- Handle versioned IDs where needed (GTEx requires versioned Ensembl)
- Document ID resolution strategy in SKILL.md
When critical:
- Skills with ambiguous inputs (gene names, compound names)
- Skills querying multiple databases with different ID systems
- Skills where ID collisions are common
7. Implement Fallbacks
devtu-optimize principle: Primary → Fallback → Default chains for critical functionality
Application in skill creation:
- Identify critical tools that may fail
- Design fallback strategy for each
- Implement try/except with fallback calls
- Document strategy in SKILL.md
Example from CRISPR skill:
## Fallback Strategy
**Primary**: DepMap_search_genes (comprehensive data)
**Fallback**: Pharos_get_target (TDL classification)
**Default**: Continue with unvalidated genes
Impact: 20% → 60% functional when primary down8. Grade Evidence
devtu-optimize principle: T1-T4 tiers on all claims; summarize quality per section
Application in skill creation:
- Include evidence tier in report if skill analyzes literature
- T1 (★★★): Mechanistic study
- T2 (★★☆): Functional study
- T3 (★☆☆): Association
- T4 (☆☆☆): Mention
- Document in SKILL.md how to assign tiers
When to apply:
- Skills that search literature
- Skills that aggregate evidence from multiple sources
- Skills making scientific claims
When not needed:
- Pure data retrieval skills
- Skills without analysis component
9. Require Quantified Completeness
devtu-optimize principle: Numeric minimums, not just "include X"
Application in skill creation:
- Define numeric minimums for each section in SKILL.md
- Example: "≥20 pathways OR explanation why fewer"
- Document what constitutes "complete" for each data type
- Implement checks in python_implementation.py
Example:
## Quantified Minimums
| Section | Minimum Data | If Not Met |
|---------|--------------|------------|
| Pathways | ≥10 pathways | Note "limited pathways available" |
| Interactions | ≥20 interactors | Explain why fewer + which tools failed |
| Expression | Top 10 tissues | Note specific gaps |10. Synthesize
devtu-optimize principle: Biological models and testable hypotheses, not just paper lists
Application in skill creation:
- Include synthesis section if skill does analysis
- Document what synthesis looks like for the domain
- Provide template for biological model
- Show example testable hypotheses
When to apply:
- Research-oriented skills
- Skills that integrate multiple data sources
- Skills where users need actionable insights
Example sections:
- Biological Model (3-5 paragraphs integrating all evidence)
- Testable Hypotheses (table with predictions)
- Suggested Experiments (how to test hypotheses)
---
Skill-Specific Additions
Beyond the 10 pillars, skills may need:
Multi-Database Integration
- Document which databases provide what
- Note overlaps and complementary coverage
- Cross-reference results across sources
Progressive Report Writing
- Create report file first
- Add sections progressively
- Each section self-contained
- Handles empty data gracefully
Domain-Specific Quality Checks
- Metabolomics: Chemical structure validation
- Genomics: Variant format checking
- Proteomics: Sequence validation
---
When devtu-optimize-skills Doesn't Apply
Not applicable for:
- Simple data retrieval skills (no analysis)
- Tool integration without reporting
- Workflows without literature component
- Pure visualization skills
Partially applicable for:
- Data transformation skills (use TEST FIRST, fallbacks)
- Multi-tool orchestration (use fallbacks, error handling)
- Specialized analysis (use relevant pillars only)
---
Quick Reference: Which Principles for Which Skills
| Skill Type | Applicable Principles |
|---|---|
| Research/Analysis | All 10 pillars |
| Data Retrieval | 1-4, 6-7 (test, verify, agnostic, disambiguate, fallbacks) |
| Multi-Database | 1-5, 7 (test, verify, agnostic, foundation, fallbacks) |
| Specialized Analysis | 1-4, 7-9 (test, verify, agnostic, fallbacks, evidence, completeness) |
| Simple Tool Wrapper | 1-4 (test, verify, agnostic) |
---
Integration Checklist
When creating a new skill, check devtu-optimize-skills integration:
- [ ] Reviewed 10 pillars
- [ ] Identified which principles apply
- [ ] Implemented TEST FIRST (always)
- [ ] Verified tool contracts (always)
- [ ] Implementation-agnostic docs (always)
- [ ] Fallback strategies (if external APIs)
- [ ] Evidence grading (if literature)
- [ ] Quantified completeness (if multi-section)
- [ ] Synthesis (if research-oriented)
- [ ] Documented application in SKILL.md
---
Summary
devtu-optimize-skills provides foundational principles for all ToolUniverse skills:
Always apply: 1. TEST FIRST 2. Verify tool contracts 3. Handle SOAP tools (if present) 4. Implementation-agnostic docs
Apply when relevant: 5. Foundation first (if aggregator exists) 6. Disambiguate carefully (if ambiguous inputs) 7. Implement fallbacks (if external APIs) 8. Grade evidence (if literature) 9. Quantified completeness (if multi-section) 10. Synthesize (if research-oriented)
Result: High-quality, production-ready skills following established best practices.
Implementation-Agnostic Documentation Format
Principle: Separate general workflow (SKILL.md) from implementation code
Why Implementation-Agnostic?
Users access ToolUniverse via:
- Python SDK: Direct Python code
- MCP (Model Context Protocol): Conversational or JSON tool calls
- Future interfaces: Other APIs or frameworks
Skills with implementation-specific code limit users to one interface.
File Structure
skills/tooluniverse-[domain]/
├── SKILL.md # General workflow (NO Python/MCP code)
├── python_implementation.py # Python SDK implementation
├── QUICK_START.md # Multi-implementation examples
└── test_skill.py # Test scriptSKILL.md: General Workflow
What to include: ✅ WHAT to do (conceptual workflow) ✅ WHICH tools to use (tool names) ✅ WHAT parameters are needed (descriptions) ✅ WHAT results to expect ✅ Decision logic and conditions ✅ Fallback strategies ✅ Tool parameter reference table
What NOT to include: ❌ from tooluniverse import ToolUniverse ❌ tu.tools.TOOL_NAME(...) ❌ Python-specific code or imports ❌ MCP-specific JSON or prompts ❌ Any language/framework syntax
SKILL.md Structure
---
name: tooluniverse-[domain]
description: [Complete description with triggers]
---
# [Domain] Analysis
[Overview paragraph]
## When to Use This Skill
[Trigger phrases and use cases]
## Workflow Overview
Input → Phase 1 → Phase 2 → Phase 3 → Report
---
## Phase 1: [Phase Name]
**Objective**: [What this phase achieves]
### Tools Used
**TOOL_NAME**:
- **Input**:
- `parameter1` (type, required/optional): Description
- `parameter2` (type, required/optional): Description
- **Output**: Description of returned data
- **Use**: What this tool provides
### Workflow
1. Query TOOL_NAME with [inputs]
2. Extract [specific data] from results
3. If no results → try FALLBACK_TOOL
4. Continue with available data
### Decision Logic
- **Condition 1**: Take action A
- **Empty results**: How to handle
- **Errors**: Fallback to alternative tool
---
## Tool Parameter Reference
**Critical Parameter Notes** (from testing):
| Tool | Parameter | CORRECT Name | Common Mistake |
|------|-----------|--------------|----------------|
| TOOL_1 | `param` | ✅ `actual_name` | ❌ `assumed_name` |
**Response Format Notes**:
- **TOOL_1**: Returns standard `{status, data}` format
- **TOOL_2**: Returns list directly (no wrapper)python_implementation.py: Python SDK
What to include:
- Complete working pipeline function
- Error handling
- Progress messages
- Example usage in
if __name__ == "__main__"
#!/usr/bin/env python3
"""
[Domain] - Python SDK Implementation
Tested implementation following TDD principles
"""
from tooluniverse import ToolUniverse
from datetime import datetime
def domain_pipeline(
param1=None,
param2=None,
output_file=None
):
"""
[Domain] analysis pipeline.
Args:
param1: Description
param2: Description
output_file: Output markdown file path
Returns:
Path to generated report file
"""
tu = ToolUniverse()
tu.load_tools()
# Implementation with tested tools
# Error handling for each phase
# Progressive report writing
return output_file
if __name__ == "__main__":
# Example usage
domain_pipeline(
param1="example",
output_file="example.md"
)QUICK_START.md: Multi-Implementation
What to include:
- Equal treatment of Python SDK and MCP
- Concrete examples for both
- Tool parameter table noting "applies to both"
- Common recipes in both formats
## Quick Start: [Domain] Analysis
[Overview]
---
## Choose Your Implementation
### Python SDK
#### Option 1: Complete Pipeline (Recommended)
from skills.tooluniverse_[domain].python_implementation import pipeline
pipeline(param="value", output_file="output.md")
#### Option 2: Individual Tools
from tooluniverse import ToolUniverse
tu = ToolUniverse() tu.load_tools()
result = tu.tools.TOOL_NAME(param="value")
---
### MCP (Model Context Protocol)
#### Option 1: Conversational (Natural Language)
"Analyze [domain] for [input]"
"Find [data] related to [query]"
#### Option 2: Direct Tool Calls
{ "tool": "TOOL_NAME", "parameters": { "param": "value" } }
---
## Tool Parameters (All Implementations)
**Note**: Whether using Python SDK or MCP, parameter names are the same.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `param1` | string | Yes | Description |
| `param2` | integer | No | Description |
---
## Common Recipes
### Recipe 1: [Use Case]
**Python SDK**:[Code example]
**MCP**:[Conversational example or JSON]
Best Practices
DO:
✅ Keep SKILL.md completely general ✅ Describe workflow conceptually ✅ List tool names and parameters ✅ Document decision logic ✅ Include fallback strategies ✅ Create separate implementation files ✅ Provide equal examples for both interfaces
DON'T:
❌ Put Python code in SKILL.md ❌ Put MCP prompts in SKILL.md ❌ Favor one implementation over another ❌ Assume users know which interface to use ❌ Skip parameter documentation ❌ Forget to test both interfaces
Examples
Good: Implementation-Agnostic
### Phase 1: Metabolite Identification
**Tools Used**:
**HMDB_search**:
- **Input**:
- `operation` (string, required): "search"
- `query` (string, required): Metabolite name
- **Output**: Array of matching metabolites with HMDB IDs
- **Use**: Find metabolite database IDs from names
**Workflow**:
1. Query HMDB_search with metabolite name
2. Extract HMDB ID from first result
3. If no results → try alternative name
4. Continue with available ID or note as unidentifiedBad: Python-Specific
### Phase 1: Metabolite Identification
tu = ToolUniverse() tu.load_tools()
result = tu.tools.HMDB_search( operation="search", query="glucose" ) hmdb_id = result['data'][0]['hmdb_id']
Validation
Check SKILL.md for implementation-specific content:
# Should return nothing
grep -E "(from|import|def |tu\.tools)" SKILL.md
grep -E "(json|mcp|conversational)" SKILL.mdIf anything matches, revise SKILL.md to be general.
Skill Standards Checklist
Complete checklist for validating ToolUniverse skills before release.
Implementation & Testing
Tool Verification
- [ ] All tools tested with real ToolUniverse instance (CRITICAL)
- [ ] Test script created BEFORE documentation
- [ ] Tool parameters verified (not assumed from function names)
- [ ] Response formats documented (standard, direct list, direct dict)
- [ ] SOAP tools have
operationparameter (if applicable) - [ ] Parameter corrections table included
Testing
- [ ] Test script passes (
test_[skill].py) - [ ] 100% test success rate
- [ ] Working pipeline runs without errors
- [ ] 2-3 complete examples tested end-to-end
- [ ] Error cases handled gracefully
- [ ] Empty data scenarios tested
- [ ] API failures tested
Error Handling
- [ ] Fallback strategies implemented
- [ ] Primary → Fallback → Default pattern used
- [ ] Try/except blocks for each database
- [ ] Clear error messages in reports
- [ ] Continues if one phase fails
- [ ] Notes unavailable data explicitly
---
Documentation
SKILL.md (Implementation-Agnostic)
- [ ] NO Python/MCP code in SKILL.md (CRITICAL)
- [ ] Describes WHAT to do, not HOW in specific language
- [ ] Tool names listed
- [ ] Parameters described conceptually
- [ ] Decision logic documented
- [ ] Workflow phases clearly structured
- [ ] Fallback strategies documented
- [ ] Tool parameter reference table included
- [ ] Response format notes included
- [ ] Limitations section present
python_implementation.py
- [ ] Complete working pipeline
- [ ] Uses only tested tools
- [ ] Error handling for each phase
- [ ] Progressive report writing
- [ ] Clear status messages
- [ ] Example usage in
if __name__ == "__main__" - [ ] Docstrings for all functions
- [ ] Type hints where appropriate
QUICK_START.md
- [ ] Both Python SDK and MCP sections
- [ ] Equal treatment of both interfaces
- [ ] Concrete examples for both
- [ ] Tool parameter table notes "applies to all implementations"
- [ ] Common recipes in both formats
- [ ] Troubleshooting section
- [ ] Expected output examples
- [ ] Next steps section
test_skill.py
- [ ] Tests each input type
- [ ] Tests combined inputs
- [ ] Verifies report sections exist
- [ ] Checks error handling
- [ ] Returns proper exit codes
- [ ] Clear test names and descriptions
---
Quality Standards
Code Quality
- [ ] No hardcoded values (use parameters)
- [ ] Proper error messages
- [ ] Clean, readable code
- [ ] No debug print statements (except intentional status)
- [ ] Follows Python conventions
- [ ] No security vulnerabilities
Report Quality
- [ ] Reports are readable (not debug logs)
- [ ] All sections present even if "no data"
- [ ] Source databases clearly attributed
- [ ] Proper markdown formatting
- [ ] Tables formatted consistently
- [ ] No raw tool outputs dumped
Performance
- [ ] Completes in reasonable time (<5 min for basic examples)
- [ ] No unnecessary API calls
- [ ] Efficient data processing
- [ ] Progress updates at appropriate intervals
---
Content Completeness
Required Sections in SKILL.md
- [ ] YAML frontmatter (name + description)
- [ ] When to Use This Skill
- [ ] Core Databases Integrated table
- [ ] Workflow Overview diagram
- [ ] Phase descriptions for each step
- [ ] Tool Parameter Reference
- [ ] Response Format Notes
- [ ] Fallback Strategies
- [ ] Limitations & Known Issues
- [ ] Summary
Required Files
- [ ] SKILL.md
- [ ] python_implementation.py
- [ ] QUICK_START.md
- [ ] test_skill.py
Optional But Recommended
- [ ] Example output reports
- [ ] Additional test cases
- [ ] Performance benchmarks
- [ ] Known issues documentation
---
User Testing
Fresh Environment Test
- [ ] Load ToolUniverse in new environment
- [ ] Import python_implementation
- [ ] Run example from QUICK_START
- [ ] Verify output matches expectations
- [ ] No unexpected errors
Documentation Test
- [ ] Another person can follow QUICK_START
- [ ] Examples work without modification
- [ ] Parameter descriptions are clear
- [ ] Troubleshooting helps resolve issues
MCP Test
- [ ] Conversational examples work
- [ ] Direct tool calls work
- [ ] Parameter names match SDK
- [ ] Results are equivalent to SDK
---
Integration Standards
Compatibility
- [ ] Works with current ToolUniverse version
- [ ] No deprecated tool usage
- [ ] Python version compatibility noted
- [ ] Required packages documented
Integration with Other Skills
- [ ] devtu-create-tool referenced if tools needed
- [ ] devtu-fix-tool referenced for debugging
- [ ] devtu-optimize-skills principles applied
- [ ] Related skills cross-referenced
---
SOAP Tools (If Applicable)
- [ ] SOAP tools identified in testing
- [ ]
operationparameter added to all SOAP calls - [ ] SOAP tools prominently noted in documentation
- [ ] Side-by-side Python/MCP examples for SOAP tools
- [ ] Warning in QUICK_START about operation parameter
Example SOAP tools: IMGT_, SAbDab_, TheraSAbDab_*
---
Fallback Strategies (If Applicable)
For skills with external APIs:
- [ ] Primary tool identified
- [ ] Fallback tool identified
- [ ] Default behavior defined
- [ ] Fallback documented in SKILL.md
- [ ] Fallback implemented in python_implementation.py
- [ ] Fallback tested
---
Before Release
Final Checks
- [ ] All tests pass 100%
- [ ] Documentation reviewed for typos
- [ ] Examples verified to work
- [ ] Files in correct locations
- [ ] No unnecessary files included
- [ ] No sensitive information in code/docs
Summary Document
- [ ] Create NEW_SKILL_[DOMAIN].md
- [ ] Document key features
- [ ] List tools integrated
- [ ] Show test results
- [ ] Note any limitations
- [ ] Suggest future enhancements
---
Post-Release
Monitoring
- [ ] Track usage patterns
- [ ] Collect user feedback
- [ ] Note common issues
- [ ] Identify improvement opportunities
Maintenance
- [ ] Update when tools change
- [ ] Fix reported bugs
- [ ] Add requested features
- [ ] Keep documentation current
---
Red Flags (Must Fix Before Release)
❌ CRITICAL - Documentation before testing
- Tools not tested with real API calls
- Parameters assumed from function names
- Response formats not verified
❌ CRITICAL - Implementation-specific SKILL.md
- Python code in SKILL.md
- MCP prompts in SKILL.md
- Single implementation focus
❌ CRITICAL - No error handling
- No try/except blocks
- No fallback strategies
- Fails completely if one tool errors
❌ Test failures
- Tests don't pass 100%
- Tests not written
- Tests never run
❌ Incomplete documentation
- Missing QUICK_START
- No MCP examples
- Parameter table missing
❌ SOAP tools broken
- Missing
operationparameter - No warning in docs
- Untested SOAP calls
---
Success Metrics
High-quality skill has:
- ✅ 100% test coverage
- ✅ Implementation-agnostic SKILL.md
- ✅ Multi-implementation QUICK_START
- ✅ Complete error handling
- ✅ Tool parameters verified
- ✅ Response formats documented
- ✅ Fallback strategies implemented
- ✅ All files present and correct
Quality score: Count checkboxes above ÷ total checkboxes
Target: ≥95% before release
Tool Testing Workflow
CRITICAL: Always test tools BEFORE writing documentation
Why Test First?
Lesson from real failures: All 4 broken skills (DDI, Clinical Trial, Antibody, CRISPR) had excellent documentation but 0-20% functionality because tools were never tested.
Problems testing prevents:
- Parameter name mismatches (function name ≠ actual parameter)
- SOAP tools missing
operationparameter - Response format variations (standard, direct list, direct dict)
- Tools that don't work or return errors
- Incorrect assumptions about tool behavior
Test-Driven Workflow
1. Read tool configs →
2. Create test script →
3. Run tests →
4. Document findings →
5. Fix issues →
6. Re-test →
7. THEN write skill documentationTest Script Template
#!/usr/bin/env python3
"""
Test script for [Domain] tools
Following TDD: test ALL tools BEFORE creating skill documentation
"""
from tooluniverse import ToolUniverse
import json
def test_database_tools():
"""Test [Database] tools"""
print("\n" + "="*80)
print("TESTING [DATABASE] TOOLS")
print("="*80)
tu = ToolUniverse()
tu.load_tools()
# Test 1: [Tool purpose]
print("\n1. Testing TOOL_NAME...")
result = tu.tools.TOOL_NAME(param1="value1", param2="value2")
# Check response format
if isinstance(result, dict) and result.get('status') == 'success':
print(f"Status: {result.get('status')}")
data = result.get('data', [])
print(f"Found {len(data)} results")
if data:
print(f"First result: {data[0]}")
elif isinstance(result, list):
print(f"Status: success (direct list response)")
print(f"Found {len(result)} results")
elif isinstance(result, dict) and 'field_name' in result:
print(f"Status: success (direct dict response)")
print(f"Keys: {result.keys()}")
else:
print(f"ERROR: Unexpected response format: {type(result)}")
print(f"Response: {result}")
return True
def main():
"""Run all tests"""
print("\n" + "="*80)
print("[DOMAIN] TOOLS TEST SUITE")
print("Following TDD: Test tools FIRST before creating skill documentation")
print("="*80)
tests = [
("Database 1", test_database_tools),
]
results = {}
for name, test_func in tests:
try:
success = test_func()
results[name] = "✅ PASS" if success else "❌ FAIL"
except Exception as e:
print(f"\n❌ EXCEPTION in {name}: {e}")
results[name] = f"❌ EXCEPTION: {str(e)[:100]}"
# Summary
print("\n" + "="*80)
print("TEST SUMMARY")
print("="*80)
for name, result in results.items():
print(f"{name:25} {result}")
print("\n✅ All tests completed. Tool parameters verified.")
print("Ready to create working pipeline → then documentation")
if __name__ == "__main__":
main()What to Test
1. Tool Accessibility
- Tool loads in ToolUniverse
- Tool name is correct
- No import errors
2. Parameter Names
- Verify actual parameter names (don't assume from function name!)
- Check required vs optional parameters
- Note any special parameters (like
operationfor SOAP tools)
3. Response Format
Test returns:
- Standard:
{status: "success", data: [...]} - Direct list:
[...] - Direct dict:
{field1: ..., field2: ...}
4. Data Structure
- Verify expected fields exist
- Check data types
- Note nested structures
5. Error Handling
- Test with invalid inputs
- Check error message format
- Verify graceful failure
Documenting Test Results
Create parameter corrections table:
| Tool | Common Mistake | Correct Parameter | Evidence |
|------|----------------|-------------------|----------|
| Reactome_map_uniprot_to_pathways | `uniprot_id` | `id` | Test output |
| drugbank_get_drug_info | `drug_name` | `query` | Test output |Document response formats:
**Response Format Notes**:
- **Reactome_list_top_pathways**: Returns list directly (not wrapped)
- **pc_search_pathways**: Returns dict with `total_hits` and `pathways`
- **enrichr_gene_enrichment**: Standard `{status, data}` formatExample: Systems Biology Skill Testing
Test file: test_pathway_tools.py
Discoveries: 1. Reactome tools return lists directly (no status wrapper) 2. Pathway Commons returns dict with total_hits field 3. Parameter: Reactome_map_uniprot_to_pathways uses id not uniprot_id 4. Enrichr tool name: enrichr_gene_enrichment_analysis (not Enrichr_enrich) 5. GO tools: Capital GO_search_terms (not lowercase GO_search_terms)
Result: All issues caught before documentation, 100% functional skill created
Red Flags in Testing
❌ Tool returns empty consistently - Wrong parameters ❌ Error about 'operation' required - SOAP tool missing operation parameter ❌ Unexpected response type - Response format different than assumed ❌ Tool not found - Tool name incorrect ❌ Timeout or API errors - Need fallback strategy
After Testing
Only after 100% tool verification: 1. Create python_implementation.py with tested tools 2. Write SKILL.md documenting verified workflow 3. Create QUICK_START.md with working examples 4. Create test_skill.py for end-to-end testing
Never reverse this order!
#!/usr/bin/env python3
"""
Test script for [DOMAIN] tools
Following TDD: test ALL tools BEFORE creating skill documentation
INSTRUCTIONS:
1. Replace [DOMAIN] with your domain name
2. Replace [DATABASE] with actual database names
3. Replace TOOL_NAME with actual tool names from ToolUniverse
4. Add test functions for each database
5. Run this script BEFORE implementing python_implementation.py
6. Document all discoveries in parameter corrections table
7. Only proceed to implementation after 100% tool verification
"""
from tooluniverse import ToolUniverse
def _load_tools() -> ToolUniverse:
"""Load ToolUniverse once and return the instance."""
tu = ToolUniverse()
tu.load_tools()
return tu
def test_database1_tools(tu: ToolUniverse):
"""Test [Database 1] tools"""
print("\n" + "="*80)
print("TESTING [DATABASE 1] TOOLS")
print("="*80)
# Test 1: [Tool purpose]
print("\n1. Testing TOOL_NAME_1...")
result = tu.tools.TOOL_NAME_1(
param1="test_value",
param2="test_value2"
)
# Check response format and document
if isinstance(result, dict) and result.get('status') == 'success':
print(f"Status: {result.get('status')}")
data = result.get('data', [])
print(f"Found {len(data)} results")
if data:
print(f"First result: {data[0]}")
print(f"Data structure: {data[0].keys() if isinstance(data[0], dict) else type(data[0])}")
elif isinstance(result, list):
print(f"Status: success (direct list response)")
print(f"Found {len(result)} results")
if result:
print(f"First result: {result[0]}")
elif isinstance(result, dict) and 'field_name' in result:
print(f"Status: success (direct dict response)")
print(f"Keys: {result.keys()}")
else:
print(f"ERROR: Unexpected response format: {type(result)}")
print(f"Response: {result}")
# Test 2: [Another tool]
print("\n2. Testing TOOL_NAME_2...")
result = tu.tools.TOOL_NAME_2(param="test_value")
# Similar format checks
return True
def test_database2_tools(tu: ToolUniverse):
"""Test [Database 2] tools"""
print("\n" + "="*80)
print("TESTING [DATABASE 2] TOOLS")
print("="*80)
# Test tools from Database 2
print("\n1. Testing TOOL_NAME_3...")
result = tu.tools.TOOL_NAME_3(param="test_value")
# Check if SOAP tool (requires operation parameter)
if isinstance(result, dict) and 'error' in result:
error_msg = str(result.get('error', ''))
if "'operation' is a required property" in error_msg:
print("⚠️ SOAP TOOL DETECTED - Requires 'operation' parameter")
print("Retrying with operation parameter...")
result = tu.tools.TOOL_NAME_3(
operation="method_name", # Add operation
param="test_value"
)
print(f"Status with operation: {result.get('status')}")
return True
def test_database3_tools(tu: ToolUniverse):
"""Test [Database 3] tools"""
print("\n" + "="*80)
print("TESTING [DATABASE 3] TOOLS")
print("="*80)
# Test tools
print("\n1. Testing TOOL_NAME_4...")
try:
result = tu.tools.TOOL_NAME_4(param="test_value")
print(f"Status: {result.get('status') if isinstance(result, dict) else 'success'}")
except Exception as e:
print(f"ERROR: {e}")
print("⚠️ Tool may not work - document for fallback strategy")
return True
def main():
"""Run all tests"""
print("\n" + "="*80)
print("[DOMAIN] TOOLS TEST SUITE")
print("Following TDD: Test tools FIRST before creating skill documentation")
print("="*80)
tu = _load_tools()
tests = [
("Database 1", test_database1_tools),
("Database 2", test_database2_tools),
("Database 3", test_database3_tools),
]
results = {}
for name, test_func in tests:
try:
success = test_func(tu)
results[name] = "PASS" if success else "FAIL"
except Exception as e:
print(f"\nEXCEPTION in {name}: {e}")
results[name] = f"EXCEPTION: {str(e)[:100]}"
# Summary
print("\n" + "="*80)
print("TEST SUMMARY")
print("="*80)
for name, result in results.items():
print(f"{name:25} {result}")
# Document discoveries
print("\n" + "="*80)
print("DISCOVERIES - DOCUMENT THESE IN SKILL.md")
print("="*80)
print("\n## Parameter Corrections Needed:")
print("| Tool | Common Mistake | Correct Parameter | Evidence |")
print("|------|----------------|-------------------|----------|")
print("| TOOL_NAME_1 | assumed_param | actual_param | Test output |")
print("| [Add more as discovered] | | | |")
print("\n## Response Format Notes:")
print("- **TOOL_NAME_1**: [Standard / Direct list / Direct dict] - [Description]")
print("- **TOOL_NAME_2**: [Format] - [Description]")
print("\n## SOAP Tools Detected:")
print("- **TOOL_NAME_X**: Requires operation='method_name'")
print("\n## Failing Tools:")
print("- **TOOL_NAME_Y**: [Error description] - Need fallback strategy")
print("\n" + "="*80)
print("NEXT STEPS:")
print("1. Document all discoveries above in SKILL.md Tool Parameter Reference")
print("2. Add SOAP tool warnings to QUICK_START.md")
print("3. Design fallback strategies for failing tools")
print("4. Create python_implementation.py using VERIFIED tools only")
print("5. Create test_skill.py for end-to-end testing")
print("6. ONLY THEN write SKILL.md and QUICK_START.md documentation")
print("="*80)
print("\n✅ Tool testing completed. Ready to proceed to implementation.")
if __name__ == "__main__":
main()
SKILL.md Template
Use this template when writing the implementation-agnostic SKILL.md for a new ToolUniverse skill.
Key Rule: SKILL.md must have ZERO Python/MCP specific code. Describe WHAT to do, not HOW in a specific language.
---
---
name: tooluniverse-[domain-name]
description: [What it does]. [Capabilities]. [Databases used]. Use when [triggers].
---
# [Domain Name] Analysis
[One paragraph overview]
## When to Use This Skill
**Triggers**:
- "Analyze [domain] for [input]"
- "Find [data type] related to [query]"
- "[Domain-specific action]"
**Use Cases**:
1. [Use case 1 with description]
2. [Use case 2 with description]
## Core Databases Integrated
| Database | Coverage | Strengths |
|----------|----------|-----------|
| **Database 1** | [Scope] | [What it's good for] |
| **Database 2** | [Scope] | [What it's good for] |
## Workflow Overview
Input -> Phase 1 -> Phase 2 -> Phase 3 -> Report
---
## Phase 1: [Phase Name]
**When**: [Conditions]
**Objective**: [What this phase achieves]
### Tools Used
**TOOL_NAME**:
- **Input**:
- `parameter1`: Description
- `parameter2`: Description
- **Output**: Description
- **Use**: What it's used for
### Workflow
1. [Step 1]
2. [Step 2]
3. [Step 3]
### Decision Logic
- **Condition 1**: Action to take
- **Empty results**: How to handle
- **Errors**: Fallback strategy
---
## Phase 2, 3, 4... (similar structure)
---
## Output Structure
[Description of report format]
### Report Format
**Required Sections**:
1. Header with parameters
2. Phase 1 results
3. Phase 2 results
...
---
## Tool Parameter Reference
**Critical Parameter Notes** (from testing):
| Tool | Parameter | CORRECT Name | Common Mistake |
|------|-----------|--------------|----------------|
| TOOL_NAME | `param` | actual_param | assumed_param |
**Response Format Notes**:
- **TOOL_1**: Returns [format]
- **TOOL_2**: Returns [format]
---
## Fallback Strategies
[Document Primary -> Fallback -> Default for critical tools]
---
## Limitations & Known Issues
### Database-Specific
- **Database 1**: [Limitations]
- **Database 2**: [Limitations]
### Technical
- **Response formats**: [Notes]
- **Rate limits**: [If any]
---
## Summary
[Domain] skill provides:
1. [Capability 1]
2. [Capability 2]
**Outputs**: [Description]
**Best for**: [Use cases]#!/usr/bin/env python3
"""
Test script for [DOMAIN] tools
Following TDD: test ALL tools BEFORE creating skill documentation
INSTRUCTIONS:
1. Replace [DOMAIN] with your domain name
2. Replace [DATABASE] with actual database names
3. Replace TOOL_NAME with actual tool names from ToolUniverse
4. Add test functions for each database
5. Run this script BEFORE implementing python_implementation.py
6. Document all discoveries in parameter corrections table
7. Only proceed to implementation after 100% tool verification
"""
from tooluniverse import ToolUniverse
def _load_tools() -> ToolUniverse:
"""Load ToolUniverse once and return the instance."""
tu = ToolUniverse()
tu.load_tools()
return tu
def test_database1_tools(tu: ToolUniverse):
"""Test [Database 1] tools"""
print("\n" + "="*80)
print("TESTING [DATABASE 1] TOOLS")
print("="*80)
# Test 1: [Tool purpose]
print("\n1. Testing TOOL_NAME_1...")
result = tu.tools.TOOL_NAME_1(
param1="test_value",
param2="test_value2"
)
# Check response format and document
if isinstance(result, dict) and result.get('status') == 'success':
print(f"Status: {result.get('status')}")
data = result.get('data', [])
print(f"Found {len(data)} results")
if data:
print(f"First result: {data[0]}")
print(f"Data structure: {data[0].keys() if isinstance(data[0], dict) else type(data[0])}")
elif isinstance(result, list):
print(f"Status: success (direct list response)")
print(f"Found {len(result)} results")
if result:
print(f"First result: {result[0]}")
elif isinstance(result, dict) and 'field_name' in result:
print(f"Status: success (direct dict response)")
print(f"Keys: {result.keys()}")
else:
print(f"ERROR: Unexpected response format: {type(result)}")
print(f"Response: {result}")
# Test 2: [Another tool]
print("\n2. Testing TOOL_NAME_2...")
result = tu.tools.TOOL_NAME_2(param="test_value")
# Similar format checks
return True
def test_database2_tools(tu: ToolUniverse):
"""Test [Database 2] tools"""
print("\n" + "="*80)
print("TESTING [DATABASE 2] TOOLS")
print("="*80)
# Test tools from Database 2
print("\n1. Testing TOOL_NAME_3...")
result = tu.tools.TOOL_NAME_3(param="test_value")
# Check if SOAP tool (requires operation parameter)
if isinstance(result, dict) and 'error' in result:
error_msg = str(result.get('error', ''))
if "'operation' is a required property" in error_msg:
print("⚠️ SOAP TOOL DETECTED - Requires 'operation' parameter")
print("Retrying with operation parameter...")
result = tu.tools.TOOL_NAME_3(
operation="method_name", # Add operation
param="test_value"
)
print(f"Status with operation: {result.get('status')}")
return True
def test_database3_tools(tu: ToolUniverse):
"""Test [Database 3] tools"""
print("\n" + "="*80)
print("TESTING [DATABASE 3] TOOLS")
print("="*80)
# Test tools
print("\n1. Testing TOOL_NAME_4...")
try:
result = tu.tools.TOOL_NAME_4(param="test_value")
print(f"Status: {result.get('status') if isinstance(result, dict) else 'success'}")
except Exception as e:
print(f"ERROR: {e}")
print("⚠️ Tool may not work - document for fallback strategy")
return True
def main():
"""Run all tests"""
print("\n" + "="*80)
print("[DOMAIN] TOOLS TEST SUITE")
print("Following TDD: Test tools FIRST before creating skill documentation")
print("="*80)
tu = _load_tools()
tests = [
("Database 1", test_database1_tools),
("Database 2", test_database2_tools),
("Database 3", test_database3_tools),
]
results = {}
for name, test_func in tests:
try:
success = test_func(tu)
results[name] = "PASS" if success else "FAIL"
except Exception as e:
print(f"\nEXCEPTION in {name}: {e}")
results[name] = f"EXCEPTION: {str(e)[:100]}"
# Summary
print("\n" + "="*80)
print("TEST SUMMARY")
print("="*80)
for name, result in results.items():
print(f"{name:25} {result}")
# Document discoveries
print("\n" + "="*80)
print("DISCOVERIES - DOCUMENT THESE IN SKILL.md")
print("="*80)
print("\n## Parameter Corrections Needed:")
print("| Tool | Common Mistake | Correct Parameter | Evidence |")
print("|------|----------------|-------------------|----------|")
print("| TOOL_NAME_1 | assumed_param | actual_param | Test output |")
print("| [Add more as discovered] | | | |")
print("\n## Response Format Notes:")
print("- **TOOL_NAME_1**: [Standard / Direct list / Direct dict] - [Description]")
print("- **TOOL_NAME_2**: [Format] - [Description]")
print("\n## SOAP Tools Detected:")
print("- **TOOL_NAME_X**: Requires operation='method_name'")
print("\n## Failing Tools:")
print("- **TOOL_NAME_Y**: [Error description] - Need fallback strategy")
print("\n" + "="*80)
print("NEXT STEPS:")
print("1. Document all discoveries above in SKILL.md Tool Parameter Reference")
print("2. Add SOAP tool warnings to QUICK_START.md")
print("3. Design fallback strategies for failing tools")
print("4. Create python_implementation.py using VERIFIED tools only")
print("5. Create test_skill.py for end-to-end testing")
print("6. ONLY THEN write SKILL.md and QUICK_START.md documentation")
print("="*80)
print("\n✅ Tool testing completed. Ready to proceed to implementation.")
if __name__ == "__main__":
main()
Testing Guide
Comprehensive testing procedures for ToolUniverse skills. This phase is MANDATORY -- no skill is complete without passing comprehensive tests.
Comprehensive Test Suite Template
File: test_skill_comprehensive.py
Test ALL use cases from documentation + edge cases.
#!/usr/bin/env python3
"""
Comprehensive Test Suite for [Domain] Skill
Tests all use cases from SKILL.md + edge cases
"""
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
from python_implementation import skill_function
from tooluniverse import ToolUniverse
def test_1_use_case_from_skill_md():
"""Test Case 1: [Use case name from SKILL.md]"""
print("\n" + "="*80)
print("TEST 1: [Use Case Name]")
print("="*80)
print("Expected: [What should happen]")
tu = ToolUniverse()
result = skill_function(tu=tu, input_param="value")
# Validation
assert isinstance(result, ExpectedType), "Should return expected type"
assert result.field_name is not None, "Should have required field"
print(f"\nPASS: [What passed]")
return result
def test_2_documentation_accuracy():
"""Test Case 2: QUICK_START.md example works exactly as documented"""
print("\n" + "="*80)
print("TEST 2: Documentation Accuracy")
print("="*80)
# Exact copy-paste from QUICK_START.md
tu = ToolUniverse()
result = skill_function(tu=tu, param="value") # From docs
# Verify documented attributes exist
assert hasattr(result, 'documented_field'), "Doc says this field exists"
print(f"\nPASS: Documentation examples work")
return result
def test_3_edge_case_invalid_input():
"""Test Case 3: Error handling with invalid inputs"""
print("\n" + "="*80)
print("TEST 3: Error Handling")
print("="*80)
tu = ToolUniverse()
result = skill_function(tu=tu, input_param="INVALID")
# Should handle gracefully, not crash
assert isinstance(result, ExpectedType), "Should still return result"
assert len(result.warnings) > 0, "Should have warnings"
print(f"\nPASS: Handled invalid input gracefully")
return result
def test_4_result_structure():
"""Test Case 4: Result structure matches documentation"""
print("\n" + "="*80)
print("TEST 4: Result Structure")
print("="*80)
tu = ToolUniverse()
result = skill_function(tu=tu, input_param="value")
# Check all documented fields
required_fields = ['field1', 'field2', 'field3']
for field in required_fields:
assert hasattr(result, field), f"Missing field: {field}"
print(f"\nPASS: All documented fields present")
return result
def test_5_parameter_validation():
"""Test Case 5: All documented parameters work"""
print("\n" + "="*80)
print("TEST 5: Parameter Validation")
print("="*80)
tu = ToolUniverse()
result = skill_function(
tu=tu,
param1="value1", # All documented params
param2="value2",
param3=True
)
assert isinstance(result, ExpectedType), "Should work with all params"
print(f"\nPASS: All parameters accepted")
return result
def run_all_tests():
"""Run all tests and generate report"""
print("\n" + "="*80)
print("[DOMAIN] SKILL - COMPREHENSIVE TEST SUITE")
print("="*80)
tests = [
("Use Case 1", test_1_use_case_from_skill_md),
("Documentation Accuracy", test_2_documentation_accuracy),
("Error Handling", test_3_edge_case_invalid_input),
("Result Structure", test_4_result_structure),
("Parameter Validation", test_5_parameter_validation),
]
results = {}
passed = 0
failed = 0
for test_name, test_func in tests:
try:
result = test_func()
results[test_name] = {"status": "PASS", "result": result}
passed += 1
except Exception as e:
results[test_name] = {"status": "FAIL", "error": str(e)}
failed += 1
print(f"\nFAIL: {test_name}")
print(f" Error: {e}")
# Summary
print("\n" + "="*80)
print("TEST SUMMARY")
print("="*80)
print(f"Passed: {passed}/{len(tests)}")
print(f"Failed: {failed}/{len(tests)}")
print(f"Success Rate: {passed/len(tests)*100:.1f}%")
if failed == 0:
print("\nALL TESTS PASSED! Skill is production-ready.")
else:
print("\nSome tests failed. Review errors above.")
return passed, failed
if __name__ == "__main__":
passed, failed = run_all_tests()
sys.exit(0 if failed == 0 else 1)Test Requirements Checklist
- [ ] Test ALL use cases from SKILL.md (typically 4-6 use cases)
- [ ] Test QUICK_START.md example (exact copy-paste must work)
- [ ] Test error handling (invalid inputs don't crash)
- [ ] Test result structure (all fields present, correct types)
- [ ] Test all parameters (documented params accepted)
- [ ] Test edge cases (empty results, partial failures)
Running Tests
cd skills/tooluniverse-[domain]
python test_skill_comprehensive.py > test_output.txt 2>&1Pass criteria:
- 100% test pass rate
- All use cases pass
- Documentation examples work exactly as written
- No exceptions or crashes
- Edge cases handled gracefully
Test Report Template
File: SKILL_TESTING_REPORT.md
# [Domain] Skill - Testing Report
**Date**: [Date]
**Status**: PASS / FAIL
**Success Rate**: X/Y tests passed (100%)
## Executive Summary
[Brief summary of testing results]
## Test Results
### Test 1: [Use Case Name] - PASS
**Use Case**: [Description from SKILL.md]
**Result**: [What happened]
**Validation**: [What was verified]
### Test 2-5: [Similar format]
## Quality Metrics
- **Code quality**: [Assessment]
- **Documentation accuracy**: [All examples work / Issues found]
- **Robustness**: [Error handling assessment]
- **User experience**: [Assessment]
## Recommendation
PRODUCTION-READY / NEEDS FIXESManual Verification
Test with fresh environment: 1. Load ToolUniverse 2. Import python_implementation 3. Run exact example from QUICK_START (copy-paste) 4. Verify output matches expectations 5. Verify all documented fields accessible
CRITICAL: If documentation example doesn't work, fix EITHER:
- The documentation (update to match implementation), OR
- The implementation (update to match documentation)
NEVER release with documentation that doesn't work.
Validation Checklist
Complete this checklist before marking a skill as production-ready.
Implementation & Testing
- [ ] All tool calls tested with real ToolUniverse instance
- [ ] Test script passes with 100% success
- [ ] Working pipeline runs without errors
- [ ] ALL use cases from SKILL.md tested
- [ ] QUICK_START examples tested (exact copy-paste works)
- [ ] Edge cases tested (invalid inputs, empty results)
- [ ] Result structure validated (all fields present)
- [ ] All parameters tested
- [ ] Error cases handled gracefully
- [ ] SOAP tools have
operationparameter (if applicable) - [ ] Fallback strategies implemented and tested
- [ ] Test report created (SKILL_TESTING_REPORT.md)
Documentation
- [ ] SKILL.md is implementation-agnostic (NO Python/MCP code)
- [ ] python_implementation.py contains working code
- [ ] QUICK_START.md includes both Python SDK and MCP
- [ ] Tool parameter table notes "applies to all implementations"
- [ ] SOAP tool warnings displayed (if applicable)
- [ ] Fallback strategies documented
- [ ] Known limitations documented
- [ ] Example reports referenced
- [ ] Documentation examples verified to work
Quality
- [ ] Reports are readable (not debug logs)
- [ ] All sections present even if "no data"
- [ ] Source databases clearly attributed
- [ ] Completes in reasonable time (<5 min)
- [ ] Test suite comprehensive (5+ test cases)
- [ ] Test report documents quality metrics
Related skills
How it compares
Use create-tooluniverse-skill for rigorous ToolUniverse domain skills with tested tools; generic skill-creator templates skip ToolUniverse-specific tool verification and SOAP handling.
FAQ
How long does create-tooluniverse-skill take to complete?
create-tooluniverse-skill defines a 7-phase workflow totaling about 1.5–2 hours when no new tools must be created. Phases span domain analysis, tool discovery and testing, implementation, agnostic documentation, validation, and packaging.
Why must ToolUniverse tools be tested before writing SKILL.md?
create-tooluniverse-skill mandates test-first development: developers search 186 JSON tool configs, run test_tools_template.py with known-good parameters, and verify response schemas before authoring SKILL.md. Documenting untested tools is listed as a red-flag quality failure.