Blog AI / JSON Schema

Warum brauchen AI Agents JSON Schema? Tool Calling bis Structured Output erklärt

You're wiring an LLM Agent and the docs mention tools[].function.parameters, response_format.json_schema, and MCP's inputSchema—they all look like JSON, but what does each constrain and guarantee?

JSON Schema is the standard for describing JSON data structures (current mainstream: 2020-12). In AI Agent development, it's not an optional doc format—it's the contract language between models and the outside world: Tool Calling uses it for tool parameters, Structured Output for final answers, MCP for tool I/O.

This article covers:

Keep this in mind: The model outputting JSON and outputting schema-conformant JSON are two different things. JSON Schema defines the latter—field names, types, required fields, enums. Below we walk through why it's needed → Tool Calling → Structured Output → MCP → how to write → how to validate.

Why Agents can't live without JSON Schema

The Agent core loop: model reasoning → decide tool call or structured answer → execute → feed result back → continue. Every I/O step in this loop should be machine-parseable, validatable, and auditable.

Plain natural language output has two fatal problems:

JSON Schema solves the format contract problem: before the model generates, you declare which fields, types, and required items the output must have. This is key infrastructure for Agents going from demo to production.

The 2026 Agent stack is highly aligned: OpenAI Function Calling, Anthropic Tool Use, DeepSeek Function Calling, MCP Tools—all use JSON Schema to describe tool parameters.

Where schema appears in the Agent stack

One table to see where JSON Schema sits in Agent development:

Layer Schema field Constrains Who validates
LLM API — Tool Calling tools[].function.parameters Model-generated tool_calls[].function.arguments Model (soft) + your code (hard validate)
LLM API — Structured Output response_format.json_schema Model final answer JSON structure Model (Strict hard) + your code
MCP Server inputSchema / outputSchema Tool call params / Server structuredContent Client SDK + your code
Business layer Custom schema files Final gate before DB / API response ajv / jsonschema / your validate function

Key insight: API-layer schema guides model generation; business-layer schema rejects bad data. You need both—they don't replace each other.

Tool Calling: parameters IS JSON Schema

With OpenAI-compatible APIs, you declare a tools array; each tool's function.parameters is a JSON Schema object:

Function Calling tool definition (parameters = JSON Schema)
{
  "model": "deepseek-v4-pro",
  "messages": [
    { "role": "user", "content": "查一下北京今天天气" }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "parameters": {
          "type": "object",
          "properties": {
            "city": {
              "type": "string",
              "description": "City name, e.g. Beijing"
            },
            "unit": {
              "type": "string",
              "enum": ["celsius", "fahrenheit"],
              "default": "celsius"
            }
          },
          "required": ["city"],
          "additionalProperties": false
        }
      }
    }
  ]
}

In the model's tool_calls, function.arguments is a JSON string, not a parsed object:

Model tool_call response (arguments is a string)
{
  "tool_calls": [
    {
      "id": "call_abc123",
      "type": "function",
      "function": {
        "name": "get_weather",
        "arguments": "{\"city\": \"Beijing\", \"unit\": \"celsius\"}"
      }
    }
  ]
}

This means you must do two things in the business layer:

  1. 1
    JSON.parse + try/except

    arguments may be syntactically broken (missing quotes, trailing commas)—ensure valid JSON first.

  2. 2
    JSON Schema validate

    Validate the parsed object against your declared parameters schema—check fields, types, and enum values.

The full tool loop: request with schema → model picks tool and generates arguments → you parse and validate → execute tool → feed result as tool message → model continues. Schema quality directly affects whether the model generates correct arguments on the first try.

Three Structured Output paths compared

Besides Tool Calling, you can have the model output structured JSON as the final answer. Three common paths:

Path API config Guarantees Best for
JSON Mode response_format: { "type": "json_object" } Valid JSON object output Free-form extraction, simple classification, flat structures
Function Calling tools + model returns tool_calls arguments roughly match parameters schema Agent tool calls, combined with MCP
Strict Schema response_format.json_schema + strict: true Output strictly conforms to given schema Production, complex schemas, strict field types

Strict Schema example (OpenAI / DeepSeek compatible):

Strict Structured Output request
{
  "model": "deepseek-v4-pro",
  "messages": [
    { "role": "user", "content": "分析这段用户反馈的情感和关键问题" }
  ],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "sentiment_analysis",
      "strict": true,
      "schema": {
        "type": "object",
        "properties": {
          "sentiment": {
            "type": "string",
            "enum": ["positive", "neutral", "negative"]
          },
          "issues": {
            "type": "array",
            "items": { "type": "string" }
          },
          "confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": ["sentiment", "issues", "confidence"],
        "additionalProperties": false
      }
    }
  }
}

Best practice is defense in depth: pick Strict or Function Calling at API layer → JSON Schema validate in business logic → format / diff / schema check locally with JSONNote. See DeepSeek V4-Pro explained for the JSON output chapter.

MCP and JSON Schema 2020-12

Model Context Protocol (MCP) is the standard protocol between Agents and external services. The 2026-07-28 spec upgrades tool inputSchema and outputSchema to full JSON Schema 2020-12, supporting oneOf, anyOf, $ref and other composition features.

MCP tool definition (inputSchema + outputSchema)
{
  "name": "search_docs",
  "description": "Search documentation by keyword",
  "inputSchema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "properties": {
      "query": { "type": "string", "minLength": 1 },
      "limit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 10 }
    },
    "required": ["query"]
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "results": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "title": { "type": "string" },
            "url": { "type": "string", "format": "uri" }
          },
          "required": ["title", "url"]
        }
      }
    },
    "required": ["results"]
  }
}

Server structuredContent must conform to outputSchema when defined. Same engineering problem as parsing tool_calls.arguments from LLM APIs—except the data source is an MCP Server. More MCP background in AI Conference 2026 hot topics.

How to write a good tool schema

Schema quality directly affects tool calling success rate. Production-proven tips:

  1. 1
    Write description for every property

    Models read description to fill values. city as "City name, e.g. Beijing, Shanghai" beats a bare field name.

  2. 2
    Use enum to limit options, don't hint in description

    "enum": ["low", "medium", "high"] beats writing "optional low/medium/high" in description.

  3. 3
    Set additionalProperties: false

    Prevents the model from "creatively" adding undeclared fields. Strict Schema mode usually enforces this.

  4. 4
    Use oneOf / $ref for complex params, don't flatten all combinations

    E.g. "lookup by ID" vs "lookup by name" are two param shapes—oneOf is clearer than one big object.

  5. 5
    Tool description: when to call and when NOT to call

    Models use description for tool selection. "Only call when user explicitly asks about weather" reduces false triggers.

Validation workflow: from API to business layer

Recommended Agent JSON validation pipeline:

Python validation example (parse + validate)
import json
from jsonschema import validate, ValidationError

TOOL_SCHEMA = {
    "type": "object",
    "properties": {
        "city": {"type": "string"},
        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
    },
    "required": ["city"],
    "additionalProperties": False
}

def parse_tool_arguments(raw: str) -> dict:
    try:
        data = json.loads(raw)
    except json.JSONDecodeError as e:
        raise ValueError(f"Invalid JSON in arguments: {e}") from e
    try:
        validate(instance=data, schema=TOOL_SCHEMA)
    except ValidationError as e:
        raise ValueError(f"Schema validation failed: {e.message}") from e
    return data

# 用法
args = parse_tool_arguments(tool_call["function"]["arguments"])
weather = get_weather(args["city"], args.get("unit", "celsius"))

Whether data comes from model arguments or MCP structuredContent, use the same parse → validate → business logic. During development, paste schema and actual output into JSONNote for visual validation—faster than print debugging.

Debug schema and model output with JSONNote

The slowest part of Agent development is often not writing prompts—it's debugging model JSON. JSONNote runs locally in the browser, ideal for API responses and MCP messages:

  1. 1
    Format model output

    Paste tool_calls[].function.arguments into JSON Formatter to instantly see syntax errors and indentation issues.

  2. 2
    Validate tool schema

    Paste tool definitions and model arguments into JSON Schema for validation.

  3. 3
    Compare two calls

    Use JSON Diff to diff structured output before and after prompt iterations for regression checks.

  4. 4
    Share debug context

    Use URL Hash sharing to embed a tool call JSON in a link—colleagues open it to reproduce, data never hits a server.

FAQ

What is the relationship between JSON Schema and Function Calling?

Function Calling's tools[].function.parameters IS JSON Schema. The model generates arguments JSON strings based on the schema; your code parses and validates conformance. They're not parallel concepts—they're the call mechanism and the parameter contract.

What is the difference between JSON Mode and Strict Schema?

JSON Mode only guarantees valid JSON object output, not field/type conformance. Strict Schema constrains token generation so output strictly conforms to the given schema. Use JSON Mode for simple extraction; Strict Schema for complex production structures.

Which JSON Schema version do MCP tool inputSchemas use?

MCP 2026-07-28 requires inputSchema and outputSchema to use JSON Schema 2020-12 with full oneOf, anyOf, and $ref support. outputSchema describes the Server's structuredContent structure.

The model already returned JSON—do I still need manual validation?

Yes. Even with Strict Schema, production code should try/except parse + JSON Schema validate. tool_calls.arguments may miss fields or have wrong types—validation is your business layer's job.

What is the difference between JSON Schema and OpenAPI?

OpenAPI is a full REST API description spec (paths, methods, auth, status codes); its request/response bodies use JSON Schema. Agent Tool Calling only needs a single function's parameter schema—use JSON Schema directly, no need for a full OpenAPI document.

Summary

The core signal of AI Agent development can be summarized as:

Agent I/O goes JSON, tool contracts go Schema, validation goes multi-layer.

JSON Schema runs through Tool Calling parameters, Structured Output response_format, and MCP inputSchema/outputSchema—it's the universal contract language between models and the outside world. Write good schemas, add business-layer validate, debug locally with JSONNote—that's the path from demo to production.

← Zurück zum Blog