API / combine-structured-outputs-with-tools

API

Combine structured outputs with tools on the Grok API

Combine structured outputs with tools on the Grok API

On supported Grok 4 family models, you can let the model call tools and still return a typed JSON object that matches your schema. That covers server-side tools (web_search, x_search, code execution) and your own client-side functions. Plain structured output without tools lives in Return structured JSON from the Grok API.

Agentic tools + typed result

Ask for a search, then parse into a Pydantic (or Zod) model. Responses API:

curl https://api.x.ai/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -d '{
    "model": "grok-4.6",
    "input": "Find the latest machine-checked proof of the four color theorem.",
    "tools": [{ "type": "web_search" }],
    "text": {
      "format": {
        "type": "json_schema",
        "name": "proof_info",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {
            "name": { "type": "string" },
            "authors": { "type": "string" },
            "year": { "type": "string" },
            "summary": { "type": "string" }
          },
          "required": ["name", "authors", "year", "summary"],
          "additionalProperties": false
        }
      }
    }
  }'

Python SDK (chat.parse after tools are enabled):

import os
from pydantic import BaseModel, Field
from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import web_search

class ProofInfo(BaseModel):
    name: str = Field(description="Name of the proof or paper")
    authors: str = Field(description="Authors of the proof")
    year: str = Field(description="Year published")
    summary: str = Field(description="Brief summary of the approach")

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(model="grok-4.6", tools=[web_search()])
chat.append(user("Find the latest machine-checked proof of the four color theorem."))
response, proof = chat.parse(ProofInfo)
print(proof.name, proof.year, proof.summary)

OpenAI SDK on https://api.x.ai/v1: client.responses.parse(..., tools=[{"type": "web_search"}], text_format=ProofInfo).

Client-side functions + typed result

Run your function loop until there are no more tool_calls, then request the structured parse on the final turn:

import os, json
from pydantic import BaseModel, Field
from xai_sdk import Client
from xai_sdk.chat import tool, tool_result, user

class CollatzResult(BaseModel):
    starting_number: int
    steps: int

def collatz_steps(n: int) -> int:
    steps = 0
    while n != 1:
        n = n // 2 if n % 2 == 0 else 3 * n + 1
        steps += 1
    return steps

collatz_tool = tool(
    name="collatz_steps",
    description="Compute Collatz steps to reach 1",
    parameters={
        "type": "object",
        "properties": {"n": {"type": "integer"}},
        "required": ["n"],
    },
)

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(model="grok-4.6", tools=[collatz_tool])
chat.append(user("Use collatz_steps for 20250709."))

while True:
    response = chat.sample()
    if not response.tool_calls:
        break
    chat.append(response)
    for tc in response.tool_calls:
        args = json.loads(tc.function.arguments)
        chat.append(tool_result(str(collatz_steps(args["n"]))))

response, result = chat.parse(CollatzResult)
print(result.starting_number, result.steps)

Tool argument objects always follow the tool’s input JSON Schema (strict is always on for tools). Your final answer schema is separate — that is what parse / json_schema constrains.

Pitfalls

  • Structured outputs with tools need a supported Grok 4 family model (use grok-4.6 unless a model page says otherwise).
  • additionalProperties defaults to false on schemas. Set it true only when you need extra keys.
  • Streaming structured JSON: pass the Pydantic model as response_format and use stream(), then Model.model_validate_json(response.content) after the stream finishes — see the structured-outputs guide.