How to Add Custom Tools and Permissions in Claude Agent SDK
Custom tools in the Claude Agent SDK are functions with a name, a description, and a JSON input schema. The model decides which tool to call based only on those descriptions, so the description is the most important line of code you will write.
Beginners obsess over the tool’s implementation. The model never sees it. It sees the name and description, and if those are vague, your carefully written function will be called at the wrong time or not at all. Everything below flows from that fact about Claude Agent SDK.
How do you write a tool description that works?
State what it does and when to use it. “search_docs: searches the internal documentation index and returns matching passages. Use when the user asks about product behavior or configuration. Do not use for general web questions.”
That last sentence — when not to use it — is the highest-leverage part. Ambiguous boundaries are what cause wrong tool selection.
What does a tool definition look like?
- Pick a clear snake_case name that describes the action.
- Write a description covering purpose, inputs, and when to invoke.
- Define an input schema with types and required fields.
- Return a structured result the model can reason over, not a raw dump.
- Handle errors inside the tool so the agent receives a readable message.
Point four matters more than people expect. Returning 50KB of raw HTML will blow your context budget and confuse the model. Return the three relevant fields.
How should permissions work?
Default deny. Every tool that can mutate state — writing files, running shell commands, calling a payment API — should require explicit permission. Read-only tools can usually be allowed freely.
| Tool capability | Default |
|---|---|
| Read a file | Allow |
| Search an index | Allow |
| Write a file | Ask |
| Run shell command | Ask |
| Send external request | Ask |
For unattended runs you cannot prompt a human, so instead restrict the tool set itself. A batch job that only needs to read and summarize should simply not be given write tools.
How many tools is too many?
Three to five is the practical sweet spot. Past roughly ten, models start picking near-miss tools and accuracy drops, while input tokens rise because every schema ships on every turn. If you need twenty capabilities, group them behind a smaller number of dispatcher tools.
What costs should you expect?
Tool schemas are sent as input tokens on every turn of the loop. Five tools with detailed schemas might add 800-1,200 tokens per turn, and a fifteen-turn run multiplies that. Trimming over-verbose descriptions is a genuine cost optimization, not just a readability one.
Where do people go wrong?
Giving the agent shell access “just for now” and forgetting to remove it. Writing descriptions from the developer’s perspective instead of the model’s. Returning unstructured blobs. And skipping error handling, so a failed tool call crashes the loop instead of letting the agent adapt.
This approach suits developers building internal agents where reliability and control matter. It is overkill for simple single-turn automation that does not need tool selection at all.
Quick Summary
- Tool name and description drive model selection; implement details are invisible to it.
- Say explicitly when not to use a tool to reduce wrong calls.
- Return small structured results, not raw data dumps.
- Default to deny for anything that writes or executes.
- Keep tool count around 3-5; schemas cost input tokens every turn.
