| name | agent-tool-design |
| description | The Agent Tool Contract — 5 principles for designing tools agents call reliably: predictable signature, rich errors, token-efficient output, idempotency, graceful degradation. Includes anti-pattern table with 8 common mistakes. |
| version | 1.2.0 |
| category | Development |
| agents | ["developer","architect","tool-creator"] |
| user_invocable | true |
| invoked_by | both |
| tools | ["Read","Write","Bash"] |
| verified | true |
| lastVerifiedAt | "2026-03-01T00:00:00.000Z" |
| tags | ["tools","design","api","contract","idempotency","errors","agent-tools"] |
| best_practices | ["Parameters are named not positional","Errors include machine-readable code plus human message plus context","Output is structured data only — no prose","Tools are idempotent (safe to retry)","Partial failure returns partial results rather than throws"] |
| error_handling | graceful |
| source | builtin |
| trust_score | 100 |
| provenance_sha | 4e11dcf3976f7b80 |
Agent Tool Design
The Agent Tool Contract — 5 principles for designing tools that agents call reliably.
The 5 Principles
Principle 1: Predictable Signature
Tools must have typed, named parameters with clear required/optional distinction. No positional ambiguity.
Good:
function searchCode({ query, limit = 20, type = 'semantic' }) { ... }
Bad:
function searchCode(q, n, t) { ... }
Principle 2: Rich Errors
Errors must include: error code (machine-readable), message (human-readable), context (debugging data).
Good:
throw {
code: 'FILE_NOT_FOUND',
message: `File not found: ${path}`,
context: { path, cwd: process.cwd() },
};
Bad:
throw new Error('not found');
Principle 3: Token-Efficient Output
Tools return structured minimal data. No prose explanations, no redundant wrapping, no verbose status messages. Agents format output themselves.
Good:
return { files: ['a.js', 'b.js'], total: 2 };
Bad:
return { status: 'success', message: 'Found 2 files successfully', data: { files: [...], metadata: {...} } };
Rule of thumb: If the output contains prose an agent would re-read to extract facts, it's too verbose.
Principle 4: Idempotency
Tools must be safe to retry. Running a tool twice should produce the same result as running it once.
Good:
db.upsert({ id, ...data });
fs.mkdirSync(path, { recursive: true });
Bad:
db.insert({ id, ...data });
fs.mkdirSync(path);
Principle 5: Graceful Degradation
Partial success > hard failure. Return what succeeded with a clear indication of what didn't.
Good:
return {
succeeded: ['file1.js', 'file2.js'],
failed: [{ file: 'file3.js', reason: 'PERMISSION_DENIED' }],
partial: true,
};
Bad:
throw new Error('Failed to process file3.js');
Anti-Pattern Table
| Anti-Pattern | Problem | Fix |
|---|
| Verbose status wrapping | Wastes tokens; agent re-parses to extract data | Return data directly |
| Positional args | Ambiguous; breaks on refactor | Named params with types |
| Swallowed exceptions | Agent thinks success; work is lost | Always surface errors explicitly |
| Non-idempotent mutations | Retry causes duplicate data or errors | Upsert semantics; check-then-set |
| Hard failures on partial input | One bad item breaks entire batch | Return partial results |
| Side-effect-heavy reads | Read tools that trigger writes confuse agents | Separate reads from writes |
| String error messages only | Agent can't programmatically handle errors | Include machine-readable error codes |
| Untyped return shape | Agent can't reliably destructure output | Document and enforce return schema |
Review Checklist
Before shipping any tool:
[ ] Parameters are named (not positional)
[ ] Required vs optional params are explicit
[ ] All error paths return { code, message, context }
[ ] Output contains no prose — only structured data
[ ] Tool is idempotent (safe to retry)
[ ] Partial failure returns partial results, not throws
[ ] Return shape is documented in JSDoc or TypeScript types
[ ] Token budget for output estimated (< 500 tokens for standard tools)
Iron Laws
- ALWAYS use named parameters — never positional arguments in tool signatures; positional args break on refactor and create ambiguity for agents.
- ALWAYS include machine-readable error codes — never surface plain string errors only; agents need
{ code, message, context } to handle errors programmatically.
- NEVER mix reads and writes in the same tool — read tools that trigger side effects confuse agents and prevent safe retries.
- ALWAYS design for idempotency — retry must produce the same result as the first call; use upsert semantics and
mkdir -p patterns.
- ALWAYS return partial results on partial failure — never let one failing item abort the entire batch; return
{ succeeded, failed, partial: true }.
Integration
- Used by:
tool-creator skill when designing new tools
- Reviewed by:
code-reviewer agent during tool PRs
- Pairs with:
dynamic-api-integration skill (consuming external tools)
- Complements:
agent-evaluation skill (evaluating tool output quality)
Memory Protocol (MANDATORY)
Before starting:
Read .claude/context/memory/learnings.md
After completing:
- New pattern ->
.claude/context/memory/learnings.md
- Issue found ->
.claude/context/memory/issues.md
- Decision made ->
.claude/context/memory/decisions.md
ASSUME INTERRUPTION: If it's not in memory, it didn't happen.