xAI (Grok)#
A first-party model-provider reference for PluggableHarness Agent: xAI's model lineup, reasoning/caching behavior, and wire-protocol shape, as they bear on building the docs/specifications/model/ plugin adapter for this vendor. Descriptive reference, not a protocol spec — see docs/specifications/model/ for PluggableHarness Agent's own design authority.
1. Overview#
xAI is Grok's vendor, and in the coding-agent context its lineup splits into a numbered grok-4-* flagship line (grok-4-5, grok-4-3, grok-4-20) and a separate grok-build model whose name pattern suggests a coding-specialized variant, though that framing is inferred, not confirmed in the underlying data. xAI's stated API philosophy is explicit OpenAI-compatibility: request/response shapes, tool-call structure, and header conventions all track the OpenAI Chat-Completions style closely enough that a plugin author familiar with an OpenAI adapter should recognize most of the surface immediately. That compatibility claim is stronger for the call-emission half of tool calling than for the result-submission half — see §4. A further wrinkle worth knowing up front: xAI ships multiple reasoning-branded variants under related names (e.g. grok-4.5 alongside a grok-4-fast-reasoning variant), so a plugin author enumerating "the" reasoning model for a given tier should not assume a single canonical ID per capability tier.
2. Model roster & capabilities#
| Model | Context window | Max output | Tool use | Vision | Streaming | Notes |
|---|---|---|---|---|---|---|
grok-4-5 | 500,000 tokens | Uncertain | Yes | Uncertain | Yes | Current flagship; reasoning defaults to high effort and cannot be disabled (see §3). |
grok-4-3 | 1,000,000 tokens | Uncertain | Yes | Yes | Yes | Most fully confirmed model in the family — vision is a firm "yes" here, unlike its siblings. |
grok-4-20 | 2,000,000 tokens | Uncertain | Yes | Uncertain | Yes | Claimed context window is a sharp outlier against the 500K/1M siblings; paired with unconfirmed vision support. Treat both as needing independent verification, not confirmed fact — see §5. |
grok-build | 256,000 tokens | Uncertain | Uncertain | Uncertain | Uncertain | Name pattern suggests a coding-specialized variant, but this is unconfirmed — every capability field beyond context window is unconfirmed for this model. |
Max output tokens is unconfirmed across the entire roster, including the flagship — this is not a gap specific to one model. No xAI model in this roster is flagged as retired or deprecated.
3. Reasoning & prompt caching#
Reasoning. All four models expose reasoning via discrete effort levels ("low", "medium", "high") set through a reasoning_effort parameter, and the vendor default when a request omits that parameter is "high." Grok's reasoning models do not offer an off switch: the underlying reasoning behavior cannot be disabled once a reasoning-capable model is selected, regardless of what reasoning_effort value the caller supplies. A related constraint: when reasoning is active, the presencePenalty, frequencyPenalty, and stop sampling parameters cannot be used and will cause the request to error — a plugin adapter needs to strip or reject these params on reasoning calls rather than passing them through unconditionally.
Prompt caching. Caching is automatic and implicit — there are no explicit cache-breakpoint markers for the caller to place. The cacheable prefix covers all messages up to and including tool-call results, and caching works identically for streaming and non-streaming requests. Cache retention is not guaranteed: entries can be evicted under server load or on a server restart, and xAI exposes an x-grok-conv-id HTTP header whose purpose is purely to improve retention odds by routing repeat requests for the same conversation to the same backend server — it is not a correctness mechanism, just a hit-rate optimization. Cache validity also depends on strict append-only history: editing, removing, or reordering any existing message breaks the cache for that conversation, so a plugin adapter (or the kernel state backend feeding it) must only ever append new messages, never mutate history in place, if it wants to preserve cache hits.
No model-to-model differences in reasoning or caching behavior are called out in the data — all four roster models are documented as sharing the same discrete-effort-level reasoning and automatic-caching behavior, though for grok-build this is an assumption carried over from the flagship rather than independently confirmed.
4. Wire format & auth#
Auth. Bearer token in the Authorization header, in the form Authorization: Bearer xai-<key>.
Tool calls — call-emission half (confirmed). Tools are declared as an array of {type: "function", name, description, parameters} entries, with parameters given as JSON Schema. When the model wants to call a tool, the response sets finish_reason to "tool_calls" and includes a tool_calls array on the message, each entry shaped as {id, type: "function", function: {name, arguments}} — this mirrors OpenAI's assistant-side shape closely.
Tool calls — result-submission half (unconfirmed). How a plugin should send a tool's result back to xAI is not directly documented in the underlying research. It is presumed — based only on xAI's general OpenAI-compatibility claims and the shared response shape above — to follow OpenAI's pattern of a new message with role: "tool" and a tool_call_id matching the original call's id. That is an inference, not a confirmed fact, and a plugin adapter should verify the actual result-submission shape against a live request before shipping rather than assuming OpenAI parity holds all the way through. Whether tool-call arguments arrive as a JSON-encoded string (OpenAI's style) or an already-parsed object is likewise presumed string-encoded by extension of the same OpenAI-compatibility claim, but is not independently confirmed either.
Rate limits. Default per-key limits are 500,000 tokens-per-minute and 500,000 requests-per-minute, scaling upward with a team's spend tier. Response headers x-ratelimit-remaining-requests, x-ratelimit-remaining-tokens, and x-ratelimit-reset-requests carry current standing. Exceeding a limit returns HTTP 429 with a rate_limit_exceeded error body and retry timing in the rate-limit headers.
5. Confirmed vs. uncertain#
Solidly confirmed: the auth scheme (Authorization: Bearer xai-<key>); the tool-call-emission wire shape (tool_calls array, finish_reason: "tool_calls", {id, type, function: {name, arguments}}); the reasoning control mechanism (discrete reasoning_effort levels, default "high", no disable option) and its interaction with sampling params; the automatic/ implicit caching model, its append-only-history requirement, and the x-grok-conv-id retention header; and the rate-limit header/tier shape.
Genuinely uncertain — spot-check before an adapter depends on them:
- Max output tokens for every model in the roster, including the flagship
grok-4-5— no figure was confirmed for any of the four models. grok-4-20's claimed 2,000,000-token context window. It is a sharp outlier against its 500K (grok-4-5) and 1M (grok-4-3) siblings, and the same model's vision support is also unconfirmed — the combination of an outlier headline figure and an unconfirmed secondary capability is exactly the pattern worth independently verifying against xAI's live model catalog before a plugin ships it as fact.- Vision support on
grok-4-5andgrok-4-20— both "uncertain," in contrast togrok-4-3, which is confirmed to support vision. Do not assume vision parity across thegrok-4-*line just because one sibling has it. grok-buildalmost entirely — only its context window (256,000 tokens) is confirmed; tool use, vision, and streaming support are all uncertain, and its presumed coding specialization is an inference from the model name, not a documented fact.- The tool-result-submission wire shape (§4) — this is inferred from xAI's general OpenAI-compatibility claim, not directly documented, and should be treated as the least-confirmed part of the wire protocol for this vendor. Whether tool arguments arrive as a JSON string or a parsed object is uncertain for the same reason.
6. Implications for PluggableHarness Agent#
Reasoning that cannot be turned off. Grok's inability to disable reasoning on its reasoning-capable models is precisely the case ThinkingSpec's disable field exists to capture — the spec explicitly cites "a researched Grok model" that "defaults reasoning on with no off switch" as the motivating example. An xAI adapter's GetCapabilities response MUST set thinking.disable = never for the grok-4-* models, an effort control with levels: ["low", "medium", "high"] and default: "high" — and the adapter itself must never allow a caller to construct a request that attempts to turn reasoning off outright, only to select among effort levels. Combined with the constraint that presencePenalty, frequencyPenalty, and stop are rejected whenever reasoning is active, the adapter needs request-building logic that strips or errors on those sampling params whenever it's talking to a reasoning-active Grok model, rather than passing the canonical request through unmodified.
Caching mode and keepalive. xAI's automatic, marker-free caching maps to CachingSpec's implicit_automatic: true, with explicit_markers: false — there are no caller-placed markers to honor. Because cache entries can be evicted under server load and the x-grok-conv-id header only improves retention odds rather than guaranteeing it, an xAI adapter is a reasonable candidate for declaring keepalive_supported: true and implementing an internal keepalive strategy (e.g. periodically re-sending the header-tagged conversation) per the keepalive note in that same section — this is squarely adapter-owned behavior, not something the kernel orchestrates. The append-only-history requirement (any edit/removal/reorder breaks the cache) also means the adapter should treat the canonical message list it receives from the kernel as append-only when building requests, not attempt to compact or rewrite prior turns.
Uncertain fields feeding ModelSpec. Because max_output_tokens is a MUST field on ModelSpec but is unconfirmed for every model in this roster, an xAI adapter author will need to source a real figure from xAI's live API or docs before GetCapabilities can populate this field correctly — shipping a guessed value would violate the MUST without the kernel having any way to detect it. The same applies, with more urgency, to grok-4-20's outlier 2M context_window and unconfirmed supports_vision: an adapter author should independently verify both before encoding them into the shipped capability spec, since GetCapabilities is meant to be a trustworthy, cheaply-requeryable source of truth (per protocol.md), not a passthrough of unverified research.
Tool-argument encoding is a real open question, not just documentation noise. The tool schema section of the data-types spec already flags xAI's argument encoding as presumed-string, unconfirmed pending verification — this report doesn't resolve that gap, it just corroborates that it's real. Per that same section, the kernel's internal ToolCall/ToolResult representation stores arguments as already-parsed JSON regardless of wire shape, so the xAI adapter's translation boundary needs to determine — empirically, against a live call, before shipping — whether it must json.Unmarshal a string (OpenAI's pattern) or accept an already-parsed object, and implement whichever turns out to be true rather than assuming the OpenAI-compatibility marketing claim extends all the way through the result-submission side.
Streaming. All four models report supports_streaming: true, and xAI's StreamCompletion implementation can be built as a normal server-streaming adapter without the batch-only fallback path the spec provides for non-streaming backends.