Tool Design
When this skill activates
This skill activates when designing tools (functions, APIs, MCP servers) that AI agents will invoke. It covers input schema design, output contracts, idempotency, error handling, batching, composition, and discoverability. Use this skill whenever building interfaces between AI models and executable capabilities.
Mandatory actions when this skill is active
Before
- Identify the consumer — Determine which AI model(s) will use this tool. Different models have different tool-calling behaviors and schema support.
- Define the capability boundary — One tool should do one thing well. If describing the tool requires "and" twice, split it into multiple tools.
- Survey existing tools — Check if an existing tool already covers this capability. Duplicate tools confuse AI selection.
- Assess side effects — Classify the tool as read-only (safe to retry) or write (requires idempotency). This drives the entire error handling strategy.
During
Tool Anatomy
Every tool must define these components:
{
name: string, // verb_noun format: "search_files", "create_user"
description: string, // 1-2 sentences: what it does, when to use it, when NOT to use it
inputSchema: Schema, // Typed, validated, documented
outputSchema: Schema, // Typed, consistent across success/error
sideEffects: boolean, // Does it change state?
idempotent: boolean // Safe to call twice with same input?
}
- Name — Use
verb_noun format. Be specific: search_codebase not search. The model uses the name for selection.
- Description — This is the most important field for AI tool selection. Include: what it does, when to use it, when NOT to use it, and what it returns.
- Negative guidance — Tell the model when NOT to use the tool: "Do not use this for file reads; use read_file instead." Prevents misuse.
Schema Design
TypeScript (Zod):
const inputSchema = z.object({
query: z.string().min(1).describe("Search query, supports regex"),
maxResults: z.number().int().min(1).max(100).default(10).describe("Max results to return"),
filePattern: z.string().optional().describe("Glob pattern to filter files, e.g. '*.ts'")
});
Schema principles:
- Every field has a
description. The AI reads descriptions to understand how to populate fields.
- Use constrained types:
min, max, enum, pattern. Tighter schemas = fewer invalid calls.
- Required fields first, optional fields with sensible defaults after.
- Prefer flat schemas over deeply nested objects. AI models handle flat structures more reliably.
- Use
enum for fixed option sets. Never rely on the AI guessing valid values from a description alone.
Output Contract
// Success
{ success: true, data: T, metadata: { duration_ms: number, cached: boolean } }
// Error
{ success: false, error: { code: string, message: string, retryable: boolean, context: object } }
- Consistent shape — Success and error responses must share a common discriminator field (
success). The AI parses both paths.
- Typed error codes — Use machine-readable codes:
FILE_NOT_FOUND, PERMISSION_DENIED, RATE_LIMITED. Not just human messages.
- Retryable flag — Tell the AI whether retrying might work. This drives agent retry logic.
- Context in errors — Include what was attempted and why it failed:
{ attempted: "read /foo/bar.ts", reason: "file does not exist" }.
Idempotency
- Read operations — Inherently idempotent. Safe to retry without side effects.
- Write operations — Require explicit idempotency design. Two approaches:
- Idempotency key — Client provides a unique key. Server deduplicates. Same key = same result.
- Natural idempotency — "set X to Y" is idempotent; "increment X" is not.
- Implementation — Store idempotency keys with TTL (24hr). Return cached result for duplicates. Critical because AI agents retry on network errors — non-idempotent tools create duplicates.
Error Semantics
| Error Category |
Retryable |
Agent Action |
| Validation error (bad input) |
No |
Fix input, call again |
| Not found |
No |
Report to user or try alternative |
| Permission denied |
No |
Escalate, request auth |
| Rate limited |
Yes |
Wait and retry with backoff |
| Timeout |
Yes |
Retry with longer timeout |
| Internal error |
Maybe |
Retry once, then escalate |
| Conflict (optimistic lock) |
Yes |
Re-read state, retry |
- Never return bare strings for errors. Always return typed error objects.
- Include remediation hints — If the error is fixable, tell the AI how:
"hint": "File path must be absolute. Received relative path.".
Batching Strategy
- When to batch — Multiple independent calls that could be combined (e.g., reading 5 files in one call).
- Batch input — Accept arrays:
{ files: ["a.ts", "b.ts", "c.ts"] } instead of 3 separate calls.
- Partial success — Report per-item results. Never all-or-nothing for batches.
- Size limits — Max 20 items per batch. Unbounded batches cause timeouts.
- When NOT to batch — Items with dependencies on each other's results require sequential calls.
Composition (Tools Calling Tools)
- Max 2-depth — Tool A can call Tool B, but B should not call C. Deep composition is impossible to debug.
- Composition contracts — Inner tools must have strict schemas. Outer tool validates intermediate results.
- Transparency — Document when tools call other tools internally.
- Failure isolation — Inner tool failures must be handled gracefully, not propagated raw.
Discovery Mechanism
- Tool registry — Catalog all tools with name, description, capability tags. Group by domain (file, search, git).
- Descriptions for AI — Optimize for AI selection ("when to use"), not human documentation.
- Dynamic registration — Tools added/removed at runtime must update the AI's available tool list.
After
- Test with AI — Verify the model selects correctly, provides valid inputs, and handles outputs properly.
- Test edge cases — Invalid, empty, and max-size inputs. Verify error responses are informative.
- Measure latency — Target <5 seconds for interactive use. Document selection criteria vs alternatives.
Self-check before task completion
1---2name: tool-design3description: Tool Design4---56# Tool Design78## When this skill activates910This skill activates when designing tools (functions, APIs, MCP servers) that AI agents will invoke. It covers input schema design, output contracts, idempotency, error handling, batching, composition, and discoverability. Use this skill whenever building interfaces between AI models and executable capabilities.1112## Mandatory actions when this skill is active1314### Before15161. **Identify the consumer** — Determine which AI model(s) will use this tool. Different models have different tool-calling behaviors and schema support.172. **Define the capability boundary** — One tool should do one thing well. If describing the tool requires "and" twice, split it into multiple tools.183. **Survey existing tools** — Check if an existing tool already covers this capability. Duplicate tools confuse AI selection.194. **Assess side effects** — Classify the tool as read-only (safe to retry) or write (requires idempotency). This drives the entire error handling strategy.2021### During2223#### Tool Anatomy2425Every tool must define these components:2627```typescript28{29 name: string, // verb_noun format: "search_files", "create_user"30 description: string, // 1-2 sentences: what it does, when to use it, when NOT to use it31 inputSchema: Schema, // Typed, validated, documented32 outputSchema: Schema, // Typed, consistent across success/error33 sideEffects: boolean, // Does it change state?34 idempotent: boolean // Safe to call twice with same input?35}36```3738- **Name** — Use `verb_noun` format. Be specific: `search_codebase` not `search`. The model uses the name for selection.39- **Description** — This is the most important field for AI tool selection. Include: what it does, when to use it, when NOT to use it, and what it returns.40- **Negative guidance** — Tell the model when NOT to use the tool: "Do not use this for file reads; use read_file instead." Prevents misuse.4142#### Schema Design4344**TypeScript (Zod):**45```typescript46const inputSchema = z.object({47 query: z.string().min(1).describe("Search query, supports regex"),48 maxResults: z.number().int().min(1).max(100).default(10).describe("Max results to return"),49 filePattern: z.string().optional().describe("Glob pattern to filter files, e.g. '*.ts'")50});51```5253**Schema principles:**54- Every field has a `description`. The AI reads descriptions to understand how to populate fields.55- Use constrained types: `min`, `max`, `enum`, `pattern`. Tighter schemas = fewer invalid calls.56- Required fields first, optional fields with sensible defaults after.57- Prefer flat schemas over deeply nested objects. AI models handle flat structures more reliably.58- Use `enum` for fixed option sets. Never rely on the AI guessing valid values from a description alone.5960#### Output Contract6162```typescript63// Success64{ success: true, data: T, metadata: { duration_ms: number, cached: boolean } }6566// Error67{ success: false, error: { code: string, message: string, retryable: boolean, context: object } }68```6970- **Consistent shape** — Success and error responses must share a common discriminator field (`success`). The AI parses both paths.71- **Typed error codes** — Use machine-readable codes: `FILE_NOT_FOUND`, `PERMISSION_DENIED`, `RATE_LIMITED`. Not just human messages.72- **Retryable flag** — Tell the AI whether retrying might work. This drives agent retry logic.73- **Context in errors** — Include what was attempted and why it failed: `{ attempted: "read /foo/bar.ts", reason: "file does not exist" }`.7475#### Idempotency7677- **Read operations** — Inherently idempotent. Safe to retry without side effects.78- **Write operations** — Require explicit idempotency design. Two approaches:79 - **Idempotency key** — Client provides a unique key. Server deduplicates. Same key = same result.80 - **Natural idempotency** — "set X to Y" is idempotent; "increment X" is not.81- **Implementation** — Store idempotency keys with TTL (24hr). Return cached result for duplicates. Critical because AI agents retry on network errors — non-idempotent tools create duplicates.8283#### Error Semantics8485| Error Category | Retryable | Agent Action |86|---------------|-----------|--------------|87| Validation error (bad input) | No | Fix input, call again |88| Not found | No | Report to user or try alternative |89| Permission denied | No | Escalate, request auth |90| Rate limited | Yes | Wait and retry with backoff |91| Timeout | Yes | Retry with longer timeout |92| Internal error | Maybe | Retry once, then escalate |93| Conflict (optimistic lock) | Yes | Re-read state, retry |9495- **Never return bare strings for errors.** Always return typed error objects.96- **Include remediation hints** — If the error is fixable, tell the AI how: `"hint": "File path must be absolute. Received relative path."`.9798#### Batching Strategy99100- **When to batch** — Multiple independent calls that could be combined (e.g., reading 5 files in one call).101- **Batch input** — Accept arrays: `{ files: ["a.ts", "b.ts", "c.ts"] }` instead of 3 separate calls.102- **Partial success** — Report per-item results. Never all-or-nothing for batches.103- **Size limits** — Max 20 items per batch. Unbounded batches cause timeouts.104- **When NOT to batch** — Items with dependencies on each other's results require sequential calls.105106#### Composition (Tools Calling Tools)107108- **Max 2-depth** — Tool A can call Tool B, but B should not call C. Deep composition is impossible to debug.109- **Composition contracts** — Inner tools must have strict schemas. Outer tool validates intermediate results.110- **Transparency** — Document when tools call other tools internally.111- **Failure isolation** — Inner tool failures must be handled gracefully, not propagated raw.112113#### Discovery Mechanism114115- **Tool registry** — Catalog all tools with name, description, capability tags. Group by domain (file, search, git).116- **Descriptions for AI** — Optimize for AI selection ("when to use"), not human documentation.117- **Dynamic registration** — Tools added/removed at runtime must update the AI's available tool list.118119### After1201211. **Test with AI** — Verify the model selects correctly, provides valid inputs, and handles outputs properly.1222. **Test edge cases** — Invalid, empty, and max-size inputs. Verify error responses are informative.1233. **Measure latency** — Target <5 seconds for interactive use. Document selection criteria vs alternatives.124125## Self-check before task completion126127- [ ] Tool name follows verb_noun convention and is distinct from existing tools128- [ ] Description includes what, when to use, and when NOT to use129- [ ] Input schema has descriptions on every field with appropriate constraints130- [ ] Output contract is consistent (success/error discriminator, typed error codes)131- [ ] Write operations are idempotent (idempotency key or natural idempotency)132- [ ] Errors include retryable flag and remediation hints133- [ ] Batch operations support partial success/failure reporting134- [ ] Composition depth does not exceed 2 levels135- [ ] Tool tested with an AI model for correct selection and invocation