Tool Schemas
Define the JSON Schema the LLM uses to decide when and how to call a tool
Overview
Every tool carries a JSON Schema that defines its arguments. The LLM reads this schema — along with the tool's name and description — to decide whether to call the tool and what arguments to send. The schema is OpenAI function-calling compatible and validated when the tool is created.
This page applies to both server and client tools. The schema lives on the tool definition; how the tool runs is decided by its config.type. See the API reference for the full list of fields and constraints.
Schema Object
The schema field has one property — parameters — and it must conform to OpenAI's function-calling spec.
{
"schema": {
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, e.g. \"Tokyo\""
},
"units": {
"type": "string",
"enum": ["metric", "imperial"],
"description": "Unit system to return temperatures in"
}
},
"required": ["city"],
"additionalProperties": false
}
}
}Two rules to keep in mind:
parameters.typemust be"object"— other types are rejected.additionalPropertiesmust befalseif set. This is strict mode;trueis not allowed.
Each entry in properties is a standard JSON Schema fragment. Use type, enum, description, minimum, maximum, pattern, and so on. Keep parameter description text short and concrete — it directly affects how the LLM fills in the value.
Writing a Description the LLM Will Use Well
The tool's description is the single biggest lever you have. Treat it like a prompt:
- Lead with the action. "Get the current weather…" beats "A weather tool."
- Spell out the trigger. "Use this when the user asks about weather, temperature, or conditions in a specific location." The LLM uses this to decide; without it, the tool may be called too often or not at all.
- Mention the output shape if it's non-obvious. "Returns temperature in Celsius and a one-word condition."
- Avoid implementation noise. Don't mention the URL, the auth, or whether it's a server or client tool — none of that reaches the LLM.
The same logic applies to each parameter's description. Vague descriptions produce vague arguments.
The same discipline applies to tool results. The LLM reads the result verbatim and it counts against the conversation context. Project responses down to the fields the LLM actually needs — a 10 KB JSON dump on every call adds up fast.
Complete Example
curl -X POST "https://api.d-id.com/tools" \
-H "Authorization: Basic <YOUR KEY>" \
-H "Content-Type: application/json" \
-d '{
"name": "search_orders",
"description": "Search the customer'\''s past orders by date range or status. Use this when the user asks to find, list, or check the status of an order they placed.",
"provider": "Storefront",
"schema": {
"parameters": {
"type": "object",
"properties": {
"from": {
"type": "string",
"format": "date",
"description": "Start date (inclusive), YYYY-MM-DD"
},
"to": {
"type": "string",
"format": "date",
"description": "End date (inclusive), YYYY-MM-DD"
},
"status": {
"type": "string",
"enum": ["pending", "shipped", "delivered", "cancelled"],
"description": "Filter to a single order status"
}
},
"required": [],
"additionalProperties": false
}
},
"config": {
"type": "server",
"url": "https://api.example.com/orders/search",
"method": "GET"
},
"auth": {
"secret_id": "sec_o0kaqea3v"
}
}'{
"id": "tool_orders_search",
"name": "search_orders",
"provider": "Storefront",
"schema": {
"parameters": {
"type": "object",
"properties": {
"from": { "type": "string", "format": "date" },
"to": { "type": "string", "format": "date" },
"status": { "type": "string", "enum": ["pending", "shipped", "delivered", "cancelled"] }
},
"required": [],
"additionalProperties": false
}
},
"config": {
"type": "server",
"url": "https://api.example.com/orders/search",
"method": "GET"
},
"created_at": "2026-05-20T12:00:00.000Z"
}FAQ
Updated 2 months ago
