hermes-agent/website/docs/guides/xai-grok-oauth.md
Jaaneek b62c997973 feat(xai-oauth): add xAI Grok OAuth (SuperGrok Subscription) provider
Adds a new authentication provider that lets SuperGrok subscribers sign
in to Hermes with their xAI account via the standard OAuth 2.0 PKCE
loopback flow, instead of pasting a raw API key from console.x.ai.

Highlights
----------
* OAuth 2.0 PKCE loopback login against accounts.x.ai with discovery,
  state/nonce, and a strict CORS-origin allowlist on the callback.
* Authorize URL carries `plan=generic` (required for non-allowlisted
  loopback clients) and `referrer=hermes-agent` for best-effort
  attribution in xAI's OAuth server logs.
* Token storage in `auth.json` with file-locked atomic writes; JWT
  `exp`-based expiry detection with skew; refresh-token rotation
  synced both ways between the singleton store and the credential
  pool so multi-process / multi-profile setups don't tear each other's
  refresh tokens.
* Reactive 401 retry: on a 401 from the xAI Responses API, the agent
  refreshes the token, swaps it back into `self.api_key`, and retries
  the call once. Guarded against silent account swaps when the active
  key was sourced from a different (manual) pool entry.
* Auxiliary tasks (curator, vision, embeddings, etc.) route through a
  dedicated xAI Responses-mode auxiliary client instead of falling back
  to OpenRouter billing.
* Direct HTTP tools (`tools/xai_http.py`, transcription, TTS, image-gen
  plugin) resolve credentials through a unified runtime → singleton →
  env-var fallback chain so xai-oauth users get them for free.
* `hermes auth add xai-oauth` and `hermes auth remove xai-oauth N` are
  wired through the standard auth-commands surface; remove cleans up
  the singleton loopback_pkce entry so it doesn't silently reinstate.
* `hermes model` provider picker shows
  "xAI Grok OAuth (SuperGrok Subscription)" and the model-flow falls
  back to pool credentials when the singleton is missing.

Hardening
---------
* Discovery and refresh responses validate the returned
  `token_endpoint` host against the same `*.x.ai` allowlist as the
  authorization endpoint, blocking MITM persistence of a hostile
  endpoint.
* Discovery / refresh / token-exchange `response.json()` calls are
  wrapped to raise typed `AuthError` on malformed bodies (captive
  portals, proxy error pages) instead of leaking JSONDecodeError
  tracebacks.
* `prompt_cache_key` is routed through `extra_body` on the codex
  transport (sending it as a top-level kwarg trips xAI's SDK with a
  TypeError).
* Credential-pool sync-back preserves `active_provider` so refreshing
  an OAuth entry doesn't silently flip the active provider out from
  under the running agent.

Testing
-------
* New `tests/hermes_cli/test_auth_xai_oauth_provider.py` (~63 tests)
  covers JWT expiry, OAuth URL params (plan + referrer), CORS origins,
  redirect URI validation, singleton↔pool sync, concurrency races,
  refresh error paths, runtime resolution, and malformed-JSON guards.
* Extended `test_credential_pool.py`, `test_codex_transport.py`, and
  `test_run_agent_codex_responses.py` cover the pool sync-back,
  `extra_body` routing, and 401 reactive refresh paths.
* 165 tests passing on this branch via `scripts/run_tests.sh`.
2026-05-15 12:11:32 -07:00

214 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
sidebar_position: 16
title: "xAI Grok OAuth (SuperGrok Subscription)"
description: "Sign in with your SuperGrok subscription to use Grok models in Hermes Agent — no API key required"
---
# xAI Grok OAuth (SuperGrok Subscription)
Hermes Agent supports xAI Grok through a browser-based OAuth login flow against [accounts.x.ai](https://accounts.x.ai), using your existing **SuperGrok subscription**. No `XAI_API_KEY` is required — log in once and Hermes automatically refreshes your session in the background.
The transport reuses the `codex_responses` adapter (xAI exposes a Responses-style endpoint), so reasoning, tool-calling, streaming, and prompt caching work without any adapter changes.
The same OAuth bearer token is also reused by every direct-to-xAI surface in Hermes — TTS, image generation, video generation, and transcription — so a single login covers all four.
## Overview
| Item | Value |
|------|-------|
| Provider ID | `xai-oauth` |
| Display name | xAI Grok OAuth (SuperGrok Subscription) |
| Auth type | Browser OAuth 2.0 PKCE (loopback callback) |
| Transport | xAI Responses API (`codex_responses`) |
| Default model | `grok-4.3` |
| Endpoint | `https://api.x.ai/v1` |
| Auth server | `https://accounts.x.ai` |
| Requires env var | No (`XAI_API_KEY` is **not** used for this provider) |
| Subscription | [SuperGrok](https://x.ai/grok) (any active tier) |
## Prerequisites
- Python 3.9+
- Hermes Agent installed
- An active SuperGrok subscription on your xAI account
- A browser available on the local machine (or use `--no-browser` for remote sessions)
## Quick Start
```bash
# Launch the provider and model picker
hermes model
# → Select "xAI Grok OAuth (SuperGrok Subscription)" from the provider list
# → Hermes opens your browser to accounts.x.ai
# → Approve access in the browser
# → Pick a model (grok-4.3 is at the top)
# → Start chatting
hermes
```
After the first login, credentials are stored under `~/.hermes/auth.json` and refreshed automatically before they expire.
## Logging In Manually
You can trigger a login without going through the model picker:
```bash
hermes auth add xai-oauth
```
### Remote / headless sessions
On servers, containers, or SSH sessions where no browser is available, Hermes detects the remote environment and prints the authorization URL instead of opening a browser. Open the URL on any device with a browser, complete the consent flow, and Hermes finishes the loopback exchange when the redirect comes back.
If you need to force this behaviour explicitly:
```bash
hermes auth add xai-oauth --no-browser
```
## How the Login Works
1. Hermes opens your browser to `accounts.x.ai`.
2. You sign in (or confirm your existing session) and approve access.
3. xAI redirects back to Hermes and the tokens are saved to `~/.hermes/auth.json`.
4. From then on, Hermes refreshes the access token in the background — you stay signed in until you `hermes auth remove xai-oauth` or revoke access from your xAI account settings.
## Checking Login Status
```bash
hermes doctor
```
The `◆ Auth Providers` section will show the current state of every provider, including `xai-oauth`.
## Switching Models
```bash
hermes model
# → Select "xAI Grok OAuth (SuperGrok Subscription)"
# → Pick from the model list (grok-4.3 is pinned to the top)
```
Or set the model directly:
```bash
hermes config set model.default grok-4.3
hermes config set model.provider xai-oauth
```
## Configuration Reference
After login, `~/.hermes/config.yaml` will contain:
```yaml
model:
default: grok-4.3
provider: xai-oauth
base_url: https://api.x.ai/v1
```
### Provider aliases
All of the following resolve to `xai-oauth`:
```bash
hermes --provider xai-oauth # canonical
hermes --provider grok-oauth # alias
hermes --provider x-ai-oauth # alias
hermes --provider xai-grok-oauth # alias
```
## Direct-to-xAI Tools (TTS / Image / Video / Transcription)
Once you're logged in via OAuth, every direct-to-xAI tool reuses the same bearer token automatically — there is **no separate setup** unless you'd rather use an API key.
To pick a backend for each tool:
```bash
hermes tools
# → Text-to-Speech → "xAI TTS"
# → Image Generation → "xAI Grok Imagine (image)"
# → Video Generation → "xAI Grok Imagine"
```
If OAuth tokens are already stored, the picker confirms it and skips the credential prompt. If neither OAuth nor `XAI_API_KEY` is set, the picker offers a 3-choice menu: OAuth login, paste API key, or skip.
:::note Video generation is off by default
The `video_gen` toolset is disabled by default. Enable it in `hermes tools``🎬 Video Generation` (press space) before the agent can call `video_generate`. Otherwise the agent may fall back to the bundled ComfyUI skill, which is also tagged for video generation.
:::
### Models
| Tool | Model | Notes |
|------|-------|-------|
| Chat | `grok-4.3` | Default; auto-selected when you log in via OAuth |
| Chat | `grok-4.20-0309-reasoning` | Reasoning variant |
| Chat | `grok-4.20-0309-non-reasoning` | Non-reasoning variant |
| Chat | `grok-4.20-multi-agent-0309` | Multi-agent variant |
| Image | `grok-imagine-image` | Default; ~510 s |
| Image | `grok-imagine-image-quality` | Higher fidelity; ~1020 s |
| Video | `grok-imagine-video` | Text-to-video and image-to-video; up to 7 reference images |
| TTS | (default voice) | xAI `/v1/tts` endpoint |
The chat catalog is derived live from the on-disk `models.dev` cache; new xAI releases appear automatically once that cache refreshes. `grok-4.3` is always pinned to the top of the list.
## Environment Variables
| Variable | Effect |
|----------|--------|
| `XAI_BASE_URL` | Override the default `https://api.x.ai/v1` endpoint (rarely needed). |
| `HERMES_INFERENCE_PROVIDER` | Force the active provider at runtime, e.g. `HERMES_INFERENCE_PROVIDER=xai-oauth hermes`. |
## Troubleshooting
### Token expired — not re-logging in automatically
Hermes refreshes the token before each session and again reactively on a 401. If refresh fails with `invalid_grant` (the refresh token was revoked, or the account was rotated), Hermes surfaces a typed re-auth message instead of crashing.
**Fix:** run `hermes auth add xai-oauth` again to start a fresh login.
### Authorization timed out
The loopback listener has a finite expiry window (default 180 s). If you don't approve the login in time, Hermes raises a timeout error.
**Fix:** re-run `hermes auth add xai-oauth` (or `hermes model`). The flow starts fresh.
### State mismatch (possible CSRF)
Hermes detected that the `state` value returned by the authorization server doesn't match what it sent.
**Fix:** re-run the login. If it persists, check for a proxy or redirect that is modifying the OAuth response.
### Logging in from a remote server
On SSH or container sessions Hermes prints the authorization URL instead of opening a browser. Open the URL on any device with a browser and complete the consent there — the loopback callback comes back to your remote host.
You can also force this behaviour:
```bash
hermes auth add xai-oauth --no-browser
```
### "No xAI credentials found" error at runtime
The auth store has no `xai-oauth` entry and no `XAI_API_KEY` is set. You haven't logged in yet, or the credential file was deleted.
**Fix:** run `hermes model` and pick the xAI Grok OAuth provider, or run `hermes auth add xai-oauth`.
## Logging Out
To remove stored xAI Grok OAuth credentials:
```bash
hermes auth remove xai-oauth
```
This clears both the singleton `loopback_pkce` entry in `auth.json` and any matching credential-pool rows.
## See Also
- [AI Providers reference](../integrations/providers.md)
- [Environment Variables](../reference/environment-variables.md)
- [Configuration](../user-guide/configuration.md)
- [Voice & TTS](../user-guide/features/tts.md)