Unofficial guide · Grok / xAI API

Grok function calling and structured outputs: how they work on the xAI API, and the quirks to know

By Ben (BenX) · Published · Last checked against official sources

Grok is xAI's model family, and the xAI API supports both function calling (the model asks your code to run a tool) and structured outputs (the model's answer follows a JSON Schema). Both are documented for grok-4.7, with a few differences worth knowing before you ship: a streamed tool call arrives whole in one chunk, xAI's docs disagree on whether tool arguments are strict, additionalProperties defaults to false, and stop and the penalty parameters return an error.

Independent guide. aiedu.guide is not affiliated with xAI (SpaceXAI), Grok, OpenRouter, Vercel or any other company named here, and is not endorsed or sponsored by any of them. Product names belong to their owners, and the official pages we checked are listed at the end.

No affiliate links on this page. See our disclosure.

Everything here comes from xAI's documentation, checked on 8 Oct 2026. We haven't made test calls. New to the API? Start with the Grok API quickstart, or see the Grok developer guide for the full series.

How does function calling work with Grok?

Short answer: You describe your tools with a JSON Schema for their parameters and send them with the request. When grok-4.7 needs one, it returns a function call; your code runs it and sends the result back, and the model continues.

A request with one tool, on the Responses API:

curl https://api.x.ai/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -d '{
  "model": "grok-4.7",
  "input": [
    {"role": "user", "content": "Where is order A1234?"}
  ],
  "tools": [
    {
      "type": "function",
      "name": "get_order_status",
      "description": "Look up the shipping status of an order",
      "parameters": {
        "type": "object",
        "properties": {
          "order_id": {"type": "string", "description": "The order ID"}
        },
        "required": ["order_id"]
      }
    }
  ]
}'

The loop, step by step:

  1. Send the request with your tools.
  2. If the response contains a function call, read its arguments and run your function.
  3. Send the result back in a follow-up request, and include the reasoning items from the previous response unchanged (see below).
  4. The model uses your result to continue, and may call another tool.

Limits and defaults from xAI's function-calling page:

  • Up to 350 tools per request.
  • Parallel function calling is on by default, so one response can contain several calls. Handle all of them before you continue, or send parallel_tool_calls: false to turn it off.

How many tools can I send to Grok in one request? Up to 350, according to xAI's function-calling docs. Parallel function calling is on by default; send parallel_tool_calls: false to turn it off.

Why does my streamed Grok tool call arrive all at once?

Short answer: That's how xAI documents it. With streaming, the function call is returned whole in a single chunk, not spread across chunks.

If your streaming handler builds up tool-call arguments piece by piece, expect the full arguments in one event instead. Don't wait for more argument chunks after the call arrives.

Does Grok stream function call arguments? No. xAI's docs say that with streaming, the function call is returned whole in a single chunk, not streamed across chunks.

Are Grok tool arguments strict?

Short answer: xAI's docs disagree. xAI's structured-outputs page says tool call arguments always conform to the tool's JSON Schema, and "the strict flag is implicitly always true". xAI's API reference lists strict as "Not supported. Only maintained for compatibility reasons."

The API reference also says the model "_should_ follow the schema, however, this is not enforced at the moment". We don't pick between the two sources. Either way, there's no reason to set strict yourself: one source says it's always on, and the other says it isn't supported. Write precise parameter schemas, and check tool arguments in your code before you act on them.

Are Grok tool arguments always strict? xAI's docs disagree. xAI's structured-outputs page says "the strict flag is implicitly always true", while xAI's API reference lists strict as "Not supported. Only maintained for compatibility reasons."

How do I get JSON output that matches a schema?

Short answer: It depends on the API. On the Responses API, which every sample on this page uses, put your schema in text.format with the json_schema type; in the OpenAI Python SDK that's client.responses.parse(..., text_format=...). On Chat Completions and in xai-sdk, the field is response_format.

xAI's structured-outputs page says response_format also accepts json_object, for well-formed JSON with no fixed structure, and text, which is the default.

Which field sets the JSON schema on the xAI API? text.format on the Responses API, and response_format on Chat Completions and in xai-sdk. In the OpenAI Python SDK on Responses, use client.responses.parse(..., text_format=...).

An example schema:

{
  "type": "object",
  "properties": {
    "customer_email": { "type": "string", "format": "email" },
    "order_date": { "type": "string", "format": "date" },
    "summary": { "type": "string", "maxLength": 500 }
  },
  "required": ["customer_email", "order_date"]
}

Three schema rules that differ from what you might expect:

  • additionalProperties defaults to false. The schema above allows no extra keys, even though it doesn't say so. xAI says it "must be set to true explicitly" if you want extra keys.
  • Only some format values are enforced: date, time, date-time, email, uuid, ipv4, ipv6 and uri. Other format values are accepted but not enforced.
  • Size limits for enforcement: minLength and maxLength up to 2,048, and minItems and maxItems up to 256. Schemas beyond those limits are accepted, but only on a best-effort basis.

Can I combine structured outputs with tools? Yes, on supported models. xAI says "Structured outputs with tools is only available for supported Grok 4 family models."

Why doesn't my Grok JSON output include extra keys? Because additionalProperties defaults to false on the xAI API. Set it to true explicitly in your schema if you want the model to add keys you didn't list.

Why does my Grok request fail when I send stop or a penalty?

Short answer: On reasoning models, presencePenalty, frequencyPenalty and stop return an error. grok-4.7 always reasons (reasoning can't be turned off), so don't send them to it.

Check code ported from other APIs for these parameters, and remove them from requests to grok-4.7. xAI's API reference also marks stop as "(Not supported by reasoning models)".

Can I use the stop parameter with Grok 4.7? No. xAI's docs say presencePenalty, frequencyPenalty and stop return an error on reasoning models, and grok-4.7's reasoning can't be disabled.

Why are logprobs missing from my Grok response?

Short answer: xAI doesn't support logprobs or top_logprobs on grok-4.20 and newer models. If you send them, they're silently ignored, with no error.

Gateway catalogs don't always agree. OpenRouter lists logprobs and top_logprobs as supported for x-ai/grok-4.7, and Vercel lists stop as a supported parameter for spacexai/grok-4.7. xAI's own docs say otherwise, so follow xAI's rules on every channel. More differences are on the Grok 4.7 channels page.

Do I need to pass reasoning back in a tool loop?

Short answer: Yes, if you manage the conversation yourself. On the Responses API, grok-4.7 always returns reasoning.encrypted_content; pass it back unchanged in the next request so the model keeps its reasoning between tool calls.

Encrypted outputs of server-side tools come back the same way. This applies to the Responses API; Chat Completions doesn't return encrypted reasoning. For more on encrypted reasoning and store, see the Grok API quickstart.

Can Grok call remote MCP servers?

Short answer: Yes. xAI can connect to remote MCP servers for you, but only over Streamable HTTP or SSE transports, and the OpenAI Responses parameters require_approval and connector_id aren't supported.

Remote MCP has no per-call tool fee; you pay only for tokens. Plan approvals in your own code, because require_approval isn't available.

Does Grok support MCP approval with require_approval? No. xAI's remote MCP docs say the require_approval and connector_id parameters aren't currently supported. Only Streamable HTTP and SSE transports are supported.

What about code execution?

Short answer: xAI runs code server-side with the code_execution tool, called code_interpreter on the Responses API. It costs $5 per 1,000 calls.

One SDK catch: the code_interpreter and file_search alias names aren't supported in xAI's gRPC Python SDK (xai-sdk). Use code_execution there. Search tools are covered in moving from Live Search to web_search and x_search, and tool prices in Grok API pricing.

Grok tool and schema quirks at a glance

Short answer: A handful of documented behaviours cover most surprises: whole-chunk streamed tool calls, conflicting docs on strict arguments, parallel calls by default, additionalProperties false by default, partial format enforcement, errors on stop and penalties, ignored logprobs, and remote MCP limits.

Table: Grok quirks and what to do (last checked 8 Oct 2026)

BehaviourWhat to do
Streamed function call arrives whole in one chunkDon't wait for more argument chunks
Strict tool arguments: "implicitly always true" per the structured-outputs page; "Not supported" per the API referenceWrite precise parameter schemas and check arguments in your code; no need to set strict
Parallel function calling on by defaultHandle every call in a response, or send parallel_tool_calls: false
Up to 350 tools per requestSplit large tool sets
additionalProperties defaults to falseSet it to true where you want extra keys
Only date, time, date-time, email, uuid, ipv4, ipv6, uri formats enforcedValidate other formats in your code
presencePenalty, frequencyPenalty, stop return an error on reasoning modelsRemove them for grok-4.7
logprobs, top_logprobs silently ignored on grok-4.20 and newerDon't rely on them
Remote MCP: Streamable HTTP and SSE only; no require_approval or connector_idHandle approvals in your own code

FAQ

How many tools can I send to Grok in one request?

Up to 350, according to xAI's function-calling docs. Parallel function calling is on by default; send parallel_tool_calls: false to turn it off.

Does Grok stream function call arguments?

No. xAI's docs say that with streaming, the function call is returned whole in a single chunk, not streamed across chunks.

Are Grok tool arguments always strict?

xAI's docs disagree. xAI's structured-outputs page says "the strict flag is implicitly always true", while xAI's API reference lists strict as "Not supported. Only maintained for compatibility reasons."

Which field sets the JSON schema on the xAI API?

text.format on the Responses API, and response_format on Chat Completions and in xai-sdk. In the OpenAI Python SDK on Responses, use client.responses.parse(..., text_format=...).

Why doesn't my Grok JSON output include extra keys?

Because additionalProperties defaults to false on the xAI API. Set it to true explicitly in your schema if you want the model to add keys you didn't list.

Can I use the stop parameter with Grok 4.7?

No. xAI's docs say presencePenalty, frequencyPenalty and stop return an error on reasoning models, and grok-4.7's reasoning can't be disabled.

Can I combine structured outputs with tools?

Yes, on supported models. xAI says "Structured outputs with tools is only available for supported Grok 4 family models."

Does Grok support MCP approval with require_approval?

No. xAI's remote MCP docs say the require_approval and connector_id parameters aren't currently supported. Only Streamable HTTP and SSE transports are supported.

Next steps

Official sources

Facts on this page come from these pages. Grok 4.7 launched in September 2026 and details change often, so check the official page before you rely on a detail.

Checked 8 October 2026