Skip to content

[backend] Grok / xAI LLMBackend — OpenAI-compatible factory + pricing + key + doctor #326

@dep0we

Description

@dep0we

Parent

Part of meta-issue #325 (expand LLM provider catalog). Architectural decision to land in core (not separate package) is documented there.

Scope

Add Grok / xAI as a registered LLM backend. xAI's chat-completions endpoint is OpenAI-compatible (POST https://api.x.ai/v1/chat/completions with OpenAI request/response shape), so implementation is a thin factory over atomic_agents/llm/openai_compat.py mirroring moonshot.py.

Implementation

atomic_agents/llm/grok.py (new file, ~50 LOC)

"""GrokLLMBackend factory over OpenAICompatibleLLMBackend.

xAI's chat-completions API is OpenAI-shape with base URL https://api.x.ai/v1
and model strings grok-2, grok-2-mini, etc. (catalog at impl time pulled
from xAI docs). Mirrors moonshot.py's factory pattern.
"""

from .openai_compat import OpenAICompatibleLLMBackend, OpenAICompatibleConfig

GROK_BASE_URL = "https://api.x.ai/v1"
GROK_PROVIDER_NAME = "grok"

# Model catalog as of impl date. Update when xAI catalog changes.
GROK_MODEL_CATALOG = ("grok-2", "grok-2-mini", "grok-3", "grok-3-mini")


def make_grok_backend(api_key: str) -> OpenAICompatibleLLMBackend:
    """Construct a Grok backend with xAI base URL + catalog."""
    return OpenAICompatibleLLMBackend(
        config=OpenAICompatibleConfig(
            base_url=GROK_BASE_URL,
            api_key=api_key,
            provider_name=GROK_PROVIDER_NAME,
            model_catalog=GROK_MODEL_CATALOG,
        )
    )

Registration in atomic_agents/llm/__init__.py

Add to the _register_default_backends() block (mirroring make_moonshot_backend). Resolve the key via _llm._get_grok_key(); if no key, skip registration silently (matching existing pattern for OpenAI / Moonshot).

atomic_agents/_llm.py — key resolver

def _get_grok_key() -> str:
    return _get_key(
        env_vars=["ATOMIC_AGENTS_GROK_KEY", "XAI_API_KEY", "GROK_API_KEY"],
        keychain_name="atomic-agents-grok",
        config_key="grok",
    )

(XAI_API_KEY listed first as the canonical xAI env-var name; GROK_API_KEY accepted for operator convenience.)

atomic_agents/_costs.py — pricing table

# Grok / xAI pricing as of impl date. Source: https://x.ai/api (pricing page).
"grok/grok-2":      {"input": 2.00, "output": 10.00},   # USD per 1M tokens
"grok/grok-2-mini": {"input": 0.20, "output": 1.00},
"grok/grok-3":      {"input": 3.00, "output": 15.00},
"grok/grok-3-mini": {"input": 0.30, "output": 1.50},

Verify exact numbers at impl time; xAI pricing has moved. Spec/31 amendment should note "pricing snapshot date" so future implementers know when to refresh.

Doctor integration

atomic_agents/doctor.py::check_provider_keys extends to iterate registered backends. Each registered backend's backend_id resolves to a doctor row:

  • PASS: backend registered + key resolves
  • WARN: backend not registered but env var detected (operator may have a stale config)
  • FAIL: backend registered but key resolution raises

Mirrors the existing check_provider_keys shape for Anthropic / OpenAI / Moonshot. No new doctor primitive; extend the existing iteration.

Spec/31 amendment

Add GrokLLMBackend (via the make_grok_backend factory) to §"Reference implementations". Add a one-line note in §"Module layout" pointing at grok.py. Add the Grok pricing source + snapshot date in §"Default model" (or a new §"Pricing snapshot dates" subsection if pricing maintenance becomes a recurring concern).

Conformance suite parametrization

tests/test_llm_protocol_conformance.py should already be parametrized across registered backends. Verify the parametrization picks up Grok automatically once registered. Add a Grok-specific smoke test using respx or similar HTTP mock to verify the base URL is right + the request shape matches xAI's expectation.

Acceptance criteria

  • atomic_agents/llm/grok.py shipped with make_grok_backend factory.
  • Registration in _register_default_backends() skips silently when no Grok key resolves.
  • _get_grok_key() resolver in _llm.py with the 3-env-var ladder.
  • Pricing table entries for grok-2 / grok-2-mini / grok-3 / grok-3-mini (or current catalog at impl time) in _costs.py.
  • Doctor check_provider_keys enumerates Grok with PASS/WARN/FAIL.
  • Conformance suite passes against Grok backend.
  • Smoke test: make_grok_backend("test-key").call(messages=[...]) constructs a well-formed xAI request (verified via HTTP mock).
  • spec/31 §"Reference implementations" amended.
  • CHANGELOG entry.
  • Wizard work in init wizard: multi-provider support — Anthropic / OpenAI / Moonshot via flag, env-var autodetect, or question #324 will inherit this once the wizard --provider enum lands; not a blocker for this issue.

Out of scope

  • Grok-vision / image input (TBD whether xAI exposes; defer to a follow-up if needed).
  • Grok streaming (reserved Protocol per spec/31).
  • xAI tool-use quirks beyond what OpenAICompatibleLLMBackend already handles.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendProtocol-pattern backend abstractions (memory, logs, locks, etc.)enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions