7 Principles for AI Agent Tool Design — Lessons from Daily Production Use

12 min readTech

When you start running AI agents in production, the first wall you hit is tool design.

I use Claude Code daily for development and operations, and I’ve run into bad tool definitions more times than I can count — the agent picks the wrong tool, misreads a parameter, and the whole chain falls apart. Anthropic and OpenAI have both published official guides on tool design principles. These aren’t armchair theory; for anyone who’s been burned in production, reading them feels like someone finally put words to your pain.

This article extracts seven design principles from both guides and works them through my own experience.

1. Single Responsibility — “Does Everything” Tools Do Nothing

One tool should do one thing.

If you bundle “search files, read them, and edit them” into a single tool, the LLM has to guess when to reach for it. Split search, read, and edit into independent tools and the agent’s selection accuracy goes up immediately.

In my own Claude Code setup I once tried to build a general-purpose “project operation” tool — it failed. The setup that actually holds up is the simple split: Glob for finding files, Read for reading them, Edit for changing them. Anthropic calls the failure mode the “God Tool” problem and explicitly warns that an all-in-one tool degrades the LLM’s selection accuracy.

2. Idempotency — Design for Safe Retries

Agents fail and retry. That’s not a bug; it’s the design.

The problem is duplicate side effects on retry. A payment tool that double-charges on a retry is catastrophic. Use the idempotency_key pattern so that running the same request multiple times leaves the outcome unchanged.

In practice, any tool with side effects — Slack posts, file writes — gets an “already executed?” check in my codebase. Claude Code sub-agents time out and re-run more often than you’d think. Idempotency isn’t a nice-to-have; it’s required infrastructure.

3. Semantic Clarity — the Docstring Is an Instruction Manual for the LLM

This is the most overlooked principle and the one with the highest payoff.

A tool’s docstring is not documentation for a human developer. It’s the instruction the LLM uses to decide when to call this tool. Anthropic’s guide recommends spelling out USE THIS TOOL WHEN... / DO NOT USE THIS TOOL WHEN... explicitly, and showing parameter formats with concrete examples.

One study found that applying this rigorously lifted parameter accuracy from 72% to 90%. I write tool-usage rules in .claude/rules/ myself, and the difference between vague descriptions and specific ones shows up immediately in agent behavior.

4. Schema Constraints — Structure Narrows the Options

When you accept free-form output from an LLM, unexpected values will show up.

OpenAI’s strict mode uses enum constraints and additionalProperties: false to restrict what the LLM can output at the structural level. If a parameter can only be “Tokyo”, “Osaka”, or “Nagoya”, define it as an enum and hallucinated values have nowhere to land.

In Claude Code, defining the input_schema for Tool Use tightly achieves the same effect. Think of it the same way as TypeScript’s type system: catching errors at call time (the “compile” phase) is far more efficient than catching them at runtime.

5. Error Prevention (Poka-yoke) — Build in Failure Modes That Can’t Happen

Toyota’s manufacturing concept of poka-yoke — mistake-proofing — applies directly to tool design.

Example: a tool that accepts file paths will produce different results depending on the execution environment if it allows relative paths. Accept only absolute paths and the problem is structurally impossible.

In my Claude Code setup, I include “what to do next” in every error message. Not “file not found” but “file not found — use the Glob tool to search for the filename.” When the next action is spelled out, the agent’s recovery accuracy improves noticeably.

6. Composability — Tools That Connect Naturally

Design tool outputs so they can feed directly into the next tool’s inputs.

The same Unix philosophy: just as you pipe grep into wc -l, a tool that returns a list of file paths should produce exactly what the next tool expects as input.

In the AI agent context this means being deliberate about schema compatibility between tools. A tool that returns its own custom data structure forces you to add a translation layer before the next tool can consume it — and that layer is where errors live.

7. Defense in Depth — Trust but Verify

Granting an AI agent real authority means security is unavoidable.

Anthropic’s guide recommends three layers of defense: input validation, permission control, and execution limits. Destructive operations — file deletion, production deploys — require blast-radius limitation and a human approval step.

In my settings.json I restrict destructive Bash commands and run work inside worktrees to cap the blast radius. A widely-discussed case of “8 PRs in a day with Claude Code” cited the same pattern: risk-based classification (high risk → skip with notification, medium risk → worktree + diff review, low risk → fully automated) was the key to making it work.

The 2026 Pattern: Handling Tool Explosion

Following the principles and splitting tools into small units creates a new problem: the number of tools explodes.

The answer is the Tool Search Tool pattern. Keep three to five tools loaded permanently; lazy-load everything else only when needed. Anthropic’s own implementation reportedly cut context consumption by 85% with this approach.

Claude Code itself uses exactly this pattern. Core tools (Read, Edit, Bash, Grep, Glob) are always available; specialist tools via MCP servers load on demand. As your tool design matures, the meta-level question — which tools to expose and when — becomes as important as the tools themselves.

Summary: Tool Design Matters More Than Prompt Engineering

Anthropic’s claim that tool design is “more important than prompt engineering” is not an exaggeration.

Prompts can be tuned session by session. Tool design is the foundation of the system. A non-idempotent tool will risk double execution no matter how many times you adjust the prompt. A semantically ambiguous tool will misfire no matter how precise your instructions are.

The path from an agent that “works” to one you can genuinely trust starts with revisiting the tools. Here’s how I frame the principles in practice:

  • One tool, one responsibility — when in doubt, split
  • Write usage conditions in the docstring — the LLM is the reader
  • Design for retry safety — idempotency keys from the start
  • Put the next action in error messages — poka-yoke by default
  • Require human approval for destructive operations — defense in depth

Tightening your tool design is often all it takes to make an agent’s behavior dramatically more stable. Whether you’re just starting with agent development or already running something in production, these seven principles are worth coming back to.

About this site

Personal blog by Amane Inoue. Writing about tech, books, culture, travel, and university life.