SDKs & Developer Experience

Defining Tool Schemas in the SDK

A tool schema is the API contract between your code and the model. Write it well and Claude calls your tools correctly; write it loosely and you debug hallucinated arguments.

Claude 3P 101 · Updated July 2026 · Unofficial guide

When you give Claude tools, each tool is described by three things: a name, a natural-language description, and an input schema written in JSON Schema — the same open standard used to validate JSON documents everywhere else in the software world. The model reads the schema the way a developer reads API documentation, and produces a tool_use block whose arguments are meant to conform to it. The schema is therefore doing double duty: it is documentation for the model and a validation contract for your code. Most tool-calling bugs trace back to a schema that was ambiguous in one of those two roles.

JSON Schema in five minutes

A tool's input schema is almost always an object schema: a type: "object" declaration, a properties map describing each parameter, and a required array listing which parameters must be present. A minimal example:

{
  "type": "object",
  "properties": {
    "city": {
      "type": "string",
      "description": "City name, e.g. 'Berlin'"
    },
    "units": {
      "type": "string",
      "enum": ["celsius", "fahrenheit"],
      "description": "Temperature units; defaults to celsius"
    }
  },
  "required": ["city"]
}

The building blocks you will use constantly: primitive types (string, number, integer, boolean), array with an items schema, nested object types, and enum for closed sets of allowed values. Per-property description fields are not decoration — they are the highest-leverage text in the whole definition, because they tell the model what a value means, with format examples.

Required vs optional — and what "optional" implies

Everything in properties that is not listed in required is optional, and the model may omit it. That has two design consequences. First, your implementation must supply a sensible default for every optional parameter and say what it is in the description — an undocumented default is a coin-flip. Second, resist making parameters optional just to seem flexible: each optional parameter is a decision you are delegating to the model. A good discipline is to keep tools narrow, require what is genuinely essential, and split "power user" variants into separate tools rather than one mega-tool with twelve optional knobs.

Rule of thumb: validate the model's arguments against your schema at runtime, every time, even though the model saw the schema. Structured outputs and strict tool use — supported across platforms, though still beta on Microsoft Foundry — tighten conformance considerably, but boundary validation is still your job, exactly as with any external caller.

Type mapping across the SDK languages

Each official SDK lets you express the same schema; what differs is how your language's type system participates.

Python (anthropic on PyPI): schemas are typically plain dictionaries, as in the JSON above. Teams that want static safety generate the JSON Schema from dataclasses or model classes so schema and function signature share one source of truth.

TypeScript (@anthropic-ai/sdk): the sweet spot, since JSON Schema is just typed object literals, and schema-inference libraries can derive both the schema and the function's parameter type from a single declaration — see the TypeScript tool loop.

Java (com.anthropic:anthropic-java), Go (github.com/anthropics/anthropic-sdk-go), C# (Anthropic on NuGet), Ruby (anthropic gem), and PHP (anthropic-ai/sdk on Composer): each provides its idiomatic request-building types for tool definitions — builder classes in Java, structs in Go, parameter objects in C#. The exact helper types evolve with releases, so treat each repository's README (for example the Java and Go repos) as the reference for current names rather than any blog post, this one included.

Schemas cost tokens

Tool definitions travel inside the prompt on every request, so schema size is a recurring cost, not a one-time one. Anthropic's pricing documentation quantifies the fixed overhead: enabling tool use adds a system-prompt cost (for example 290 tokens on Claude Opus 4.8 with auto tool choice, 410 with forced tool choice), and each tool's own definition adds tokens on top — Anthropic's predefined bash tool, for instance, adds 325 input tokens on Opus 4.8. Verbose schemas multiplied by every iteration of an agentic loop add up; prompt caching (available on all four platforms) is the standard mitigation for large, stable tool sets.

Where to go next

Put the schema to work in the Python tool loop, then scale up with multi-tool orchestration. The feature matrix shows which server-side tools each platform adds on top of your own.

Sources