---
title: grokBuild()
description: >-
  The Grok Build harness, its options and id, its xAI API key, the requests it's
  brokered on, and how its settings, MCP servers and skills are set up.
---
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reeval.ai/llms.txt
> Use this file to discover all available pages before exploring further.

`grokBuild()` runs xAI's [Grok Build](https://www.npmjs.com/package/@xai-official/grok) CLI in the Docker sandbox over its ACP server (`grok agent stdio`), on an xAI API key. `model` is required.

```ts title="reeval.config.ts"
import { defineConfig } from '{{ pkg }}'
import { grokBuild } from '{{ pkg }}/harness'

export default defineConfig({
  harness: grokBuild({ model: 'grok-4.6' }),
})
```

## Options

<Property name="model" type="string">
  An xAI model id, such as `grok-4.6`, without a provider. Required: it's the model the session starts on and the one Grok names the session with.
</Property>

<Property name="effort" type="string" optional>
  Reasoning effort as Grok's `default_reasoning_effort`, such as `low`, `medium` or `high`, for a model that takes one. It isn't the measured [effort](/concepts/lift#effort-next-to-lift).
</Property>

<Property name="id" type="string" optional>
  The harness's id in cell keys, filters and the record. Default `grok-build:<model>`, or `grok-build:<model>[effort=<value>]` when `effort` is set.
</Property>

<Property name="gateway" type="'direct' | Gateway" optional>
  The gateway this harness's model calls go through, by name or helper, such as `direct()`. It skips the config's `gateway` fallback: the plan refuses a gateway that isn't listed or can't serve this harness. See [Gateways](/reference/gateway#pinning-a-harness).
</Property>

<Property name="maxConcurrent" type="number" optional>
  The most Grok Build attempts at once across the run, for example for your key's rate limits.
</Property>

<Property name="startTimeout" type="Duration" optional>
  How long its session may take to become ready (bootstrap and session start) before the attempt is an infra error, such as `'3m'`. Default `'90s'`. A start that times out is aborted and started once more; a second timeout fails the attempt.
</Property>

## At a glance

| | |
|---|---|
| Import | `'{{ pkg }}/harness'` |
| Credential | `XAI_API_KEY` (an xAI API key), `vercel()`'s on Vercel AI Gateway, or `openrouter()`'s (`OPENROUTER_API_KEY`) on OpenRouter |
| Adapter | `@reeval/harness-grok-build` 0.1.5 (over `@ai-sdk/harness-acp`), bundled with reeval |
| CLI | Grok Build 1.0.70, from npm's `@xai-official/grok-linux-*`, checked against its sha512 |
| Sandbox | `docker()` only |
| Image | `reeval-sandbox:grok-build-0.1.5` |
| Rules file | `AGENTS.md` |
| Skills (default placement) | `.grok/skills` in Grok's own home (below) |
| Skills (`placement: 'workspace'`) | `.grok/skills` in the workspace |
| Plugins | Every part but `rules`, with `--plugin-dir` (below) |
| Egress hosts added | `api.x.ai` |
| Tokens | The turn's, from Grok's prompt response |

Build its image once with `reeval image build` in a project whose config uses `grokBuild()`.

## The key

reeval passes `XAI_API_KEY` to the adapter explicitly, and Grok gets a placeholder in its place; the real key never enters the container. The gateway swaps it into the `Authorization` header on the requests Grok 1.0.70 sends it on:

| Host | Endpoint |
|---|---|
| `api.x.ai` | `GET /v1/models` and `GET /v1/api-key`, as a session starts |
| `api.x.ai` | `POST /v1/responses` and `POST /v1/chat/completions`, its model calls |

The served model comes from each model call's response, which the gateway reads: Grok's ACP server doesn't name it. The adapter refuses to run in a sandbox that can't broker the key.

On a [`gateway` list](/reference/gateway#vercel-ai-gateway) that resolves the harness to `vercel()`, the key is `AI_GATEWAY_API_KEY` (else `VERCEL_OIDC_TOKEN`). Grok's `config.toml` gets a `[model."xai/<model>"]` table on Vercel's Chat Completions API (`base_url = "https://ai-gateway.vercel.sh/v1"`, `env_key = "AI_GATEWAY_API_KEY"`), so Grok calls nothing on `api.x.ai`. The gateway brokers the key as a Bearer token on `POST /v1/chat/completions` at `ai-gateway.vercel.sh` only, and reads the served model from each response, in Vercel's name: `spacexai/grok-4.6` where direct records `grok-4.6`, so `reeval compare` across the two shows different served models. Grok also probes the gateway's root, which Vercel redirects to `vercel.com`; that block is expected. `effort` isn't taken on `vercel()` yet, so a cell with it falls through to the next gateway.

On [`openrouter()`](/reference/gateway#openrouter), the key is `OPENROUTER_API_KEY`, and Grok's `config.toml` gets a `[model."x-ai/<model>"]` table on OpenRouter's Chat Completions API (`base_url = "https://openrouter.ai/api/v1"`, `env_key = "OPENROUTER_API_KEY"`), so Grok calls nothing on `api.x.ai`. The gateway brokers the key as a Bearer token on `POST /api/v1/chat/completions` at `openrouter.ai` only, and reads the served model, the upstream provider and the cost from each response. `effort` isn't taken there yet.

## Settings

```toml title="~/.grok/config.toml (in Grok's own home)"
[models]
default = "grok-4.6"
session_summary = "grok-4.6"

[features]
telemetry = false
feedback = false
managed_config = false
campaigns = false
title_refresh = false
turn_summary = false
session_recap = false

[cli]
auto_update = false
```

Every call, the session's title included, is on the run's model, and Grok makes no telemetry, summary or recap calls, so a turn contacts only `api.x.ai`. Its process also gets `GROK_FOLDER_TRUST=false`, so it reads the workspace's `AGENTS.md` and skills without asking, and `GROK_DISABLE_AUTOUPDATER=1`.

Grok runs with a private home, `~/.ai-sdk-harness/.harness-bootstrap/grok-build/implementation/home`, so its config and home skills live there, not in the sandbox user's `~/.grok`. The attempt's `context` lists them under that path.

MCP servers go to Grok over ACP's `session/new`, as stdio, `http` or `sse` servers. Grok offers them to the model through its `search_tool` and `use_tool` tools; the transcript names each call `mcp__<server>__<tool>`, with the tool's own input.

## Plugins

```sh
grok agent --no-leader --plugin-dir /home/reeval/.reeval/plugins/review stdio
```

reeval copies each plugin to `~/.reeval/plugins/<name>/` and starts Grok with a `--plugin-dir` for each, which Grok trusts, so its hooks and MCP servers start unprompted. `--no-leader` keeps the session in its own process, which is the one that reads the flag. Grok loads each plugin whole, namespaced: the subagent `review:reviewer`.

Grok starts a plugin's MCP servers itself, under the plugin's own server names, so reeval leaves them out of `session/new`; the transcript still names a call `mcp__<server>__<tool>`. Grok keeps only one of two servers with the same name, so the plan refuses a plugin server named like one in `mcp` or in another plugin. As for [Claude Code](/reference/harness/claude-code#plugins), the placed `.mcp.json` runs each through reeval's MCP timer, and a host variable can't go in it, so a plugin server that reads one is refused at plan time; declare that server in `mcp`. Grok doesn't read a plugin's `rules/`, so the plan refuses a plugin that keeps them, as for [Claude Code](/reference/harness/claude-code#plugins).

## Errors

| Situation | Message |
|---|---|
| No model, or one with a provider | `grokBuild() needs an xAI model id, without a provider, since it runs on an xAI API key, e.g. grokBuild({ model: 'grok-4.6' }) (got …)` |
| An empty `effort` | `grokBuild({ effort }) is the value that CLI takes, e.g. grokBuild({ effort: 'high' }) (got "")` |
| No key when the attempt starts | `XAI_API_KEY isn't set, so the Grok Build harness can't authenticate. Set it in the environment or .env.local.` |
| xAI refuses the key | The turn fails with `The API rejected XAI_API_KEY: set a valid key in the environment or .env.local` |
| A non-Docker sandbox | `The Grok Build harness needs the Docker sandbox: set sandbox: docker() …` |
| Grok doesn't start | `Grok Build harness failed to start: …` |

## Related

- [Harnesses](/guide/harnesses)
- [Secrets and egress](/guide/secrets-and-egress)
- [Transcripts](/reference/transcript)
