Create custom tools using the @tool decorator for domain-specific agents. Use when building agent-specific tools, implementing MCP servers, or creating in-memory tools with the Agent SDK.
View on GitHubmelodic-software/claude-code-plugins
tac
January 21, 2026
Select agents to install to:
npx add-skill https://github.com/melodic-software/claude-code-plugins/blob/main/plugins/tac/skills/tool-design/SKILL.md -a claude-code --skill tool-designInstallation paths:
.claude/skills/tool-design/# Tool Design Skill
Create custom tools for domain-specific agents using the @tool decorator.
## Purpose
Design and implement custom tools that give agents specialized capabilities for domain-specific operations.
## When to Use
- Agent needs capabilities beyond default tools
- Domain requires specialized operations
- Building focused, efficient agents
- Creating reusable tool libraries
## Prerequisites
- Understanding of @tool decorator syntax
- Knowledge of MCP server creation
- Clear definition of tool purpose
## Design Process
### Step 1: Define Tool Purpose
Answer:
- What operation does this tool perform?
- What inputs does it need?
- What output does it produce?
- When should the agent use this tool?
### Step 2: Design Tool Interface
**Tool Signature**:
```python
@tool(
"tool_name", # Unique identifier
"Description for agent", # How agent knows when to use
{"param1": type, "param2": type} # Parameter schema
)
async def tool_implementation(args: dict) -> dict:
pass
```
**Naming Convention**:
- Use snake_case for tool names
- Be descriptive: `calculate_compound_interest` not `calc`
- Prefix with domain: `db_query`, `api_call`
**Description Guidelines**:
- Explain WHEN to use the tool
- Explain WHAT it does
- Include any constraints
### Step 3: Define Parameters
**Parameter Types**:
```python
{
"text_param": str, # String
"number_param": int, # Integer
"decimal_param": float, # Float
"flag_param": bool, # Boolean
}
```
**Required vs Optional**:
```python
async def my_tool(args: dict) -> dict:
# Required - must exist
required = args["required_param"]
# Optional - with default
optional = args.get("optional_param", "default")
```
### Step 4: Implement Tool Logic
**Basic Template**:
```python
@tool(
"tool_name",
"Description",
{"param1": str, "param2": int}
)
async def tool_name(args: dict) -> dict:
try:
# 1. Extract and validate in