Skip to content

Grok via subscription: grokAgent driver (Grok Build CLI over ACP) — no API key - #6

Merged
milind-soni merged 1 commit into
milind-soni:mainfrom
KesleyDavid:feat/grok-agent-driver
Aug 12, 2026
Merged

Grok via subscription: grokAgent driver (Grok Build CLI over ACP) — no API key#6
milind-soni merged 1 commit into
milind-soni:mainfrom
KesleyDavid:feat/grok-agent-driver

Conversation

@KesleyDavid

@KesleyDavid KesleyDavid commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Closes #3

What

A new grokAgent driver that runs the official Grok Build CLI (grok) headless over its ACP stdio interface (grok agent stdio, JSON-RPC 2.0/NDJSON), so bots ride the user's grok.com subscription login — no xAI API key anywhere.

This directly resolves the reason Grok sat outside the default fleet (the old comment in config.ts: the API key is a credential nobody wants to manage). The new driver plays by the same rule as claude/codex: no credential in the app, just the CLI installed and signed in — otherwise it degrades to the usual unavailable shadow in the model picker. The API-key driver stays registered (now labeled "Grok (API)") for anyone who brings a key via an instances entry.

One driver file + registration, per the contributing note in the README:

  • server/drivers/grokagent.ts — the driver (mirrors codex.ts structurally: per-turn child process, RPC pending map, permission asks map, native NDJSON tee, process-group teardown)
  • builtIn.ts / config.ts — registration + default fleet entry
  • ProviderIcons.tsx, Onboarding.tsx, README.md — Grok mark for the new kind, a "Grok Build" engine row, docs
  • dist-server/ regenerated via pnpm build:server

Protocol notes (all verified against grok CLI 1.0.0)

  • Handshake: initializeauthenticate {methodId: "cached_token"}session/load|newsession/prompt. The prompt RPC result is the turn-completion signal (stopReason + usage); ACP has no turn/completed notification.
  • session/load replays the whole history through the normal session/update channel, so resume is double-gated (nothing emitted before the prompt is sent + anything flagged _meta.isReplay is dropped) — old messages never duplicate into the chat. resumeCursor is the ACP sessionId.
  • --append-system-prompt / --rules are accepted-but-inert for agent stdio (proved with a passphrase probe), so personas are prepended codex-style. Recorded in a comment so nobody re-discovers this the hard way.
  • Permission requests arrive as server→client session/request_permission and surface as the canonical approval cards.

Security decisions

  • --permission-mode is always explicit. A user-level permission_mode = "always-approve" in ~/.grok/config.toml silently makes sessions yolo (verified: tools ran with zero permission requests until the flag forced it back). Bots always broker approvals through the chat regardless of the user's TUI config. fullAuto maps to bypassPermissions, default off.
  • Fail-closed approvals. Nothing is approved unless the agent explicitly offered an allow-kinded ACP option — option order is never treated as a security contract; malformed/unknown option sets answer cancelled. Only behavior === "allow" approves; unknown behaviors deny. 12/12 adversarial cases pass against a fake ACP agent (empty options, unknown kinds, reject-only sets, fullAuto without an allow option).
  • XAI_API_KEY is scrubbed from the child env (same spirit as the codex driver's OPENAI_API_KEY note) so billing can never silently flip from the subscription to pay-as-you-go.
  • Handshake/auth/session RPCs carry timeouts; session/prompt deliberately has none (turns legitimately run long; interrupt + process-exit guards cover hangs).

Verified

  • Driver SPI level: basic turn, resume (memory across turns, same sessionId), deny (no execution leaked), allow (command ran, tool card resolves), interrupt via session/cancel, snapshot with a missing CLI → unavailable shadow.
  • Harness E2E: bot on the grok instance → streamed reply → resume across a server restart (persisted resumeCursor) → approval card in chat → Allow via POST /respond → command output in the transcript. Both typecheck configs clean.

Known MVP gaps (documented in-code)

  • turn.integrations (Composio / cloud computer / local cua) is not wired yet — mcpServers: []. The agent advertises MCP http+sse capabilities, so mapping Composio onto an ACP mcpServer entry is a natural follow-up PR; until then bots on this driver have Grok Build's native tools only.
  • Model catalog is static (grok-4.5, what the CLI reports today); the initialize result carries modelState.availableModels for a future dynamic catalog.
  • cost: null — ACP reports costUsdTicks with no documented unit; passing a possibly-wrong number seemed worse than null.

…ACP stdio

New driver (server/drivers/grokagent.ts) runs the official `grok` CLI
headless over ACP — initialize → authenticate(cached_token) →
session/load|new → session/prompt — so bots ride the user's grok.com
subscription, no xAI API key. It joins the default fleet under the same
rule as claude/codex: no credential to manage, just the CLI installed and
signed in (unavailable shadow otherwise). The API-key driver stays
registered as "Grok (API)" for anyone who brings a key.

- Fail-closed permissions: --permission-mode is always explicit (a global
  always-approve in ~/.grok/config.toml would otherwise make sessions
  yolo and never fire session/request_permission), and nothing is ever
  approved without an explicitly allow-kinded ACP option — option order
  is not a security contract.
- XAI_API_KEY is scrubbed from the child env so billing can never
  silently flip from the subscription to pay-as-you-go.
- session/load replays history through the normal update channel, so
  resume is double-gated (prompt-sent + _meta.isReplay) to keep old
  messages out of the chat.
- --append-system-prompt/--rules are accepted-but-inert for agent stdio
  (verified against 1.0.0); personas are prepended codex-style.
- Onboarding gains a Grok Build engine row; README lists the third CLI;
  dist-server regenerated.

Known MVP gaps, documented in-code: turn.integrations (Composio/computer)
not wired yet (the agent advertises MCP http+sse, so it's a follow-up),
static model catalog, cost:null (ACP's costUsdTicks has no documented
unit).

Verified against grok 1.0.0: allow/deny/interrupt/resume at the driver
SPI, 12/12 fail-closed permission tests via a fake ACP agent, and harness
E2E including resume across a server restart and the approval-card allow
flow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Grok via subscription CLI (like Claude/Codex), not only API key

2 participants