designing tool schemas for AI agents is surprisingly different from
designing REST APIs for humans.
Here are some patterns that worked and didn’t work in production:
What didn’t work:
1. Fine-grained CRUD endpoints. I started with the obvious
get_request, update_request_status, update_request_assignee,
add_comment, etc. The agent would frequently call the wrong one
or chain them in the wrong order. Too many similar tools = confusion.
2. Generic parameter names. A field called “id” meant nothing to the
agent without context. It would hallucinate IDs or pass the wrong
entity’s ID.
3. Sparse error messages. Returning “404 Not Found” gave the agent
nothing to work with. It would retry the same bad call indefinitely.
What worked:
1. Fewer, wider tools. Instead of 8 CRUD endpoints, I collapsed them
into 3: search_requests, get_request_detail, update_request. The
agent made far fewer mistakes with a smaller tool set.
2. Descriptive schemas with examples. Adding “description” fields
with example values in the JSON schema dramatically improved
accuracy. The schema IS the prompt.
3. Rich error responses. Instead of “404”, returning
“No request found with ID ‘abc’. Did you mean to search first?
Available tool: search_requests” actually got the agent to
self-correct.
4. Read-before-write pattern. Structuring tools so the agent
naturally fetches context before making changes reduced
destructive mistakes significantly.
5. Confirmation fields for dangerous operations. Adding a required
“confirm: true” parameter for deletes/bulk updates acts as a
speed bump that makes the agent think twice.
The mental model shift: you’re not designing an API for a developer
reading docs. You’re designing an interface for a reasoning engine
that only sees the schema and the last few messages. Every field
name, description, and error message is a prompt.
Curious if others building MCP servers have found similar patterns
or discovered different approaches.