Skip to content

Grok Build runtime spawns bare grok (TUI) instead of grok agent --always-approve stdio — agents fail with ENXIO #3457

Description

@madhu-korada

Summary

Selecting Grok Build as the managed-agent runtime starts Fizz/Honey/Bumble with:

agent_cmd=/Users/.../grok

and empty agent_args. That launches the interactive TUI, not the ACP server. Under Buzz (no controlling TTY) every pool worker exits immediately:

Error: Device not configured (os error 6)
ERROR buzz_acp: agent initialize failed: Agent process exited unexpectedly
Error: all 10 agents failed to start — cannot continue

Claude / other ACP-native adapters work on the same machine. The Grok CLI is installed and authenticated; this is a harness arg wiring bug, not auth.

Environment

  • Buzz: 0.5.0 (macOS, desktop)
  • Grok CLI: 0.2.114 (~/.local/bin/grok~/.grok/bin/grok)
  • OS: macOS arm64
  • Config: preferred_runtime: "grok" in global-agent-config.json
  • Managed agents end up with:
"agent_command": "claude-agent-acp",
"agent_command_override": "grok",
"agent_args": []

Steps to reproduce

  1. Install Grok CLI (grok on PATH / ~/.grok/bin) and grok login (or set XAI_API_KEY).
  2. Install latest Buzz desktop; create/start Welcome Team agents (Fizz etc.).
  3. Set agent runtime / preferred runtime to Grok Build.
  4. Start agents and open the harness log.

Expected

Spawn should match the preset harness definition on main:

// desktop/src-tauri/src/managed_agents/discovery.rs — PRESET_HARNESSES
PresetHarness {
    id: "grok",
    label: "Grok Build",
    command: "grok",
    args: &["agent", "--always-approve", "stdio"],
    ...
}

i.e. effectively:

grok agent --always-approve stdio

ACP initialize should succeed (same as a manual pipe of JSON-RPC over stdio).

Actual

  • Log line: agent_cmd=.../grok with no agent stdio args.
  • Child prints Error: Device not configured (os error 6) (ENXIO) and exits.
  • All parallel workers fail; harness exits status 1: all 10 agents failed to start.

Manual repro of the bad spawn:

# bare TUI, no TTY — same ENXIO Buzz sees
/Users/$USER/.local/bin/grok </dev/null
# → Error: Device not configured (os error 6)

# correct ACP entrypoint — works
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":1,"clientCapabilities":{},"clientInfo":{"name":"test","version":"0"}}}' \
  | grok agent stdio
# → initialize result with protocolVersion 1, authMethods, models, etc.

Root cause (from current main)

Two related gaps:

1. Preset args are not applied when only the command override is set

UI / preferred_runtime = "grok" pins agent_command_override: "grok" but leaves agent_args: [] on the managed agent record. Spawn uses the override binary + the stored (empty) args, so the preset's ["agent", "--always-approve", "stdio"] never reach the process.

2. default_agent_args("grok") does not fill in the preset defaults

In both:

  • desktop/src-tauri/src/managed_agents/discovery.rsdefault_agent_args
  • crates/buzz-acp/src/config.rsdefault_agent_args

only goose / Claude / Codex / buzz-agent are special-cased. grok falls through to None, so normalize_agent_args("grok", []) returns [] instead of the preset ACP args.

Same class of risk for other Tier-2 presets that need non-empty args when the agent record has empty agent_args (ompacp, opencodeacp, kimiacp, etc.) if spawn only sees the command + empty stored args.

Suggested fix

  1. Include Grok (and other preset harnesses) in default_agent_args, mirroring PRESET_HARNESSES, e.g.:

    "grok" => Some(vec![
        "agent".into(),
        "--always-approve".into(),
        "stdio".into(),
    ]),
    "omp" | "opencode" | "kimi" | "cursor" | "cursor-agent" => Some(vec!["acp".into()]),
    // ...

    Prefer a single source of truth: derive defaults from PRESET_HARNESSES rather than a second match table.

  2. When applying preferred_runtime / command override from a preset, also persist (or resolve at spawn) that preset's args, not only the command.

  3. Regression test: spawn path / normalize_agent_args("grok", vec![]) must yield ["agent", "--always-approve", "stdio"]; integration smoke that BUZZ_ACP_AGENT_COMMAND=grok with empty args can complete ACP initialize without a TTY.

Workaround (works today)

Edit managed agents so args are set explicitly, then restart agents:

"agent_command_override": "/Users/<you>/.local/bin/grok",
"agent_args": ["agent", "stdio"]

or point the override at a tiny wrapper:

#!/bin/bash
exec "$HOME/.local/bin/grok" agent stdio "$@"

(--always-approve is recommended for managed agents so Grok-side tool prompts do not deadlock headless ACP; Buzz already documents this in the Grok preset PRs.)

Related

Acceptance criteria

  • Selecting Grok Build as preferred/agent runtime starts agents without ENXIO
  • Harness log shows ACP init for Grok (agentInfo / capabilities), not TUI ENXIO
  • Empty agent_args + command grok normalizes to agent --always-approve stdio (or equivalent from preset)
  • Unit coverage for normalize_agent_args("grok", [])

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions