Day 7
Tool Schemas
Design clean, unambiguous tool inputs and outputs.
Tool schemas define the contract between the LLM and the execution environment. A well-designed schema makes it easy for the LLM to call the tool correctly and for the system to validate the call before execution. Poor schemas are the leading cause of tool-calling failures.
Today’s Lesson
Read
Tool Creation
Typed schemas, resilient wrappers, and safe tool calls.
Practice
Apply what you learned by solving these coding problems.
Review
Test yourself with these interview-style questions.
1Design a JSON Schema for a `send_email` tool: recipient (required, email format), subject (required, max 200 chars), body (required, max 10000 chars), cc (optional array of emails), priority (optional enum: "low"/"normal"/"high", default "normal"). Explain how each choice guides the LLM.+
The schema uses format constraints ("email" for email fields), maxLength to prevent overflow, enum for constrained choices, and default for optional fields. The required array marks mandatory fields. The description for each property explains expected content, not just the name. Each constraint narrows the LLM's possible outputs, reducing hallucinated arguments and improving first-call success. For example, the enum on priority tells the LLM the only valid values, preventing "urgent" or "ASAP" from being passed.
Read full answer
The schema would be: `{"type": "object", "properties": {"to": {"type": "string", "format": "email", "description": "Recipient email address"}, "subject": {"type": "string", "maxLength": 200}, "body": {"type": "string", "maxLength": 10000}, "cc": {"type": "array", "items": {"type": "string", "format": "email"}}, "priority": {"type": "string", "enum": ["low", "normal", "high"], "default": "normal"}}, "required": ["to", "subject", "body"]}`. Each constraint serves a purpose. Format:email tells the LLM and validator the field must be a valid email. maxLength prevents extremely long subjects. Enum gives a clear choice set; the default lets the LLM omit it when the default suffices. The description for each property is the primary way the LLM understands the field's purpose. A good description explains expected content, like "The plain-text body of the email. Use \n for line breaks."
2A schema has "query" (string, desc: "the search query") and "max_results" (integer, desc: "max results"). The LLM swaps arguments — passes an integer as query and string as max_results. Analyse why and propose three schema improvements.+
The LLM confuses the fields because both descriptions are too brief and provide no disambiguation. Fix 1: improve descriptions with concrete examples — "The search query string, e.g. 'latest Python version'" and "Max results to return (1-50, default 10)". Fix 2: add explicit type hints in descriptions — "(type: string)" and "(type: integer)". Fix 3: reorder schema properties with the most commonly used parameter first — LLMs tend to map the first user-provided value to the first schema property. Combined, these make the schema self-explanatory.
Read full answer
This is a common schema confusion failure. The root cause is minimal descriptions — "the search query" and "max results to return" provide no disambiguation. My first fix is concrete examples: for query, "The natural-language search query, e.g. 'Python version features 2025'", and for max_results, "Maximum number of results (1-50, default 10). Must be an integer." Examples anchor the LLM's understanding. Second fix: explicit type contextualisation by appending "(type: string)" and "(type: integer)" to descriptions, reinforcing expected types. Third fix: property ordering — put "query" first as the primary argument and "max_results" second as a modifier. Adding a "default" for max_results also signals it can be omitted. The combination of examples, explicit type hints, and logical ordering typically resolves this in one or two iterations.
3Design a tool-schema registry for 50+ tools. How do you select which schemas to include in each LLM call given context window limits? Describe a dynamic schema selection strategy.+
Use a two-tier registry: a lightweight index with tool names and one-line descriptions for rapid filtering, plus full schemas stored separately. A schema selector embeds the user query and computes similarity against each tool's description embedding, selecting the top K (8-12) most relevant tools. Include a default set of 3-5 high-frequency tools in every call regardless of similarity score. Cache selections per session to avoid redundant computation. This keeps the LLM prompt compact and focused while ensuring relevance.
Read full answer
With 50+ tools, including all schemas in every call exceeds context budgets and dilutes the LLM's attention. I design a two-level registry. Level one is an index: a lightweight mapping of tool names to one-sentence descriptions and embedding vectors. Level two stores the full JSON Schema definitions. The schema selector embeds the current query or thought using the same model as tool descriptions, computes cosine similarity against all 50+ embeddings, and selects the top K (typically 8-12 depending on context budget). I always include a default set of the 3-5 most commonly used tools regardless of similarity — this prevents missing obvious tools due to embedding mismatch. The selector runs in O(N) with vectorised operations, under 10ms for 50 tools. Results are cached per session. This design keeps the prompt compact while maintaining high tool-selection accuracy. If the distribution of common tools changes over time, the default set is updated based on usage analytics.
Back to 30-Day Agentic AI Interview Prep Path