symfonic.core.grok_oauth_provider¶
grok_oauth_provider ¶
GrokOAuthProvider — DEV/TEST USE ONLY.
Calls xAI's subscription chat proxy using a grok.com subscription OAuth
token instead of a metered XAI_API_KEY.
Credential sources (two, mutually exclusive)¶
- Static token: supply
GROK_OAUTH_ACCESS_TOKEN(oraccess_token=). The provider sends it verbatim and NEVER refreshes — the caller owns the token's lifecycle. - grok CLI store (auto-refresh): when no static token is given and a
grokcredential file exists, the provider auto-loads it via :class:~symfonic.core.grok_credentials.GrokCredentialStoreand refreshes the short-lived (~6h) access token transparently — including mid-session, on every outgoing request. Usefrom_grok_cli()to request this path explicitly.
Side effect of the store path¶
Auto-refresh MUTATES the local grok credential file: the OAuth
refresh_token rotates on every refresh, so the new value is written back
(atomically, under a file lock, owner-only) or the developer's grok
login would break. This is a deliberate, necessary side effect of the
seamless-refresh posture and applies ONLY to the store path — the
static-token path touches no files.
When to use¶
- Local development against Grok models without provisioning a separate
metered
XAI_API_KEY. - Experimenting with the pipeline against a real LLM during development.
When NOT to use¶
- ❌ Production / multi-tenant SaaS — a subscription token doesn't bill per-tenant and its rate limits differ from API-key plans.
- ❌ Cost-tracking — subscription usage doesn't map to per-token pricing.
This provider explicitly refuses to work in production-like environments
(SYMFONIC_ENV/ENVIRONMENT/ENV/NODE_ENV set to
production/prod) to prevent accidental subscription billing under
multi-tenant load, and allow_production=True is the sole reviewed escape
hatch. This mirrors
:class:~symfonic.core.codex_provider.CodexOAuthProvider and
:class:~symfonic.core.kimi_oauth_provider.KimiOAuthProvider.
ToS caveat¶
Replaying a grok.com subscription token to xAI's chat proxy from a
third-party program is subscription-auth reuse. xAI ships its OAuth login
(auth.x.ai) for its own grok CLI — we deliberately do NOT run that
handshake. The adopter runs grok login themselves; this provider only
reuses the resulting local session (or an explicitly exported token) for
dev/test, in the same risk class as the Kimi and Codex OAuth providers.
Credentials (environment variables)¶
GROK_OAUTH_ACCESS_TOKEN(required for the static path) subscription access token, obtained by runninggroklogin yourself.GROK_OAUTH_BASE_URL(optional) override the endpoint; defaults to the subscription chat proxyhttps://cli-chat-proxy.grok.com/v1— the only endpoint a subscription OAuth token authenticates against (the meteredapi.x.aiplatform endpoint rejects it with 401).GROK_OAUTH_CREDENTIALS_FILE(optional) override the credential file path for the store path (default:$GROK_HOME/auth.json, else~/.grok/auth.json).
You obtain the token by signing in with grok yourself, e.g.::
grok login # then just construct the provider; the store auto-loads
GrokCredentialError ¶
Bases: RuntimeError
Raised when a Grok subscription token cannot be resolved or refreshed.
GrokCredentialStore ¶
GrokCredentialStore(credentials_path: Path | None = None, *, token_url: str = _DEFAULT_TOKEN_URL, expiry_skew_seconds: int = 300)
Yields an always-valid grok CLI access token, refreshing as needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
credentials_path
|
Path | None
|
Override the credential file. Defaults to the
|
None
|
token_url
|
str
|
OAuth token endpoint. Defaults to |
_DEFAULT_TOKEN_URL
|
expiry_skew_seconds
|
int
|
Refresh this many seconds BEFORE the cached
token's |
300
|
Source code in src/symfonic/core/grok_credentials.py
access_token ¶
Return a valid access token, refreshing if within the skew window.
Source code in src/symfonic/core/grok_credentials.py
peek_access_token ¶
Return the cached token without refreshing; None if unavailable.
For logging / fingerprinting at construction time — must never raise or trigger a network refresh.
Source code in src/symfonic/core/grok_credentials.py
GrokOAuthProvider ¶
GrokOAuthProvider(*, access_token: str | None = None, base_url: str | None = None, allow_production: bool = False, _store: GrokCredentialStore | None = None)
DEV/TEST provider that calls xAI via a subscription token.
Mirrors the OpenAI-compatible ChatOpenAI wiring shared by the other
OAuth providers (same defaults, sampling parity, capability flags); the
ONLY differences are auth (a grok.com subscription token rather than
XAI_API_KEY), the chat-proxy endpoint, and the production guard.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
access_token
|
str | None
|
Grok subscription access token. Defaults to the
|
None
|
base_url
|
str | None
|
xAI backend base URL. Defaults to
|
None
|
allow_production
|
bool
|
Skip the production-env guard. Default False. Set True only if you have an explicit, ToS-reviewed reason. |
False
|
Raises:
| Type | Description |
|---|---|
GrokCredentialError
|
No static token (arg/env) AND no grok CLI credential file to auto-load. |
GrokProductionMisuseError
|
A production env var is set and
|
Source code in src/symfonic/core/grok_oauth_provider.py
token_fingerprint
property
¶
Short, non-leaking identifier for the active token.
from_grok_cli
classmethod
¶
from_grok_cli(*, credentials_path: Any = None, base_url: str | None = None, allow_production: bool = False) -> GrokOAuthProvider
Build a provider backed by the grok CLI credential store.
Auto-loads ~/.grok/auth.json (or GROK_HOME /
credentials_path / GROK_OAUTH_CREDENTIALS_FILE) and refreshes
the short-lived access token transparently on every request — so a
developer runs grok login ONCE and never exports or refreshes a
token by hand. The production guard still fires on this path.
Source code in src/symfonic/core/grok_oauth_provider.py
get_chat_model ¶
Return a ChatOpenAI pointed at the xAI chat proxy.
Static-token path: the token is passed as api_key — LangChain sends
it as Authorization: Bearer <token> — verbatim, no refresh.
Store-backed path: api_key is a placeholder and a per-request httpx
event hook rewrites Authorization with a FRESHLY-valid token on
every outgoing request (sync + async), so a token that expires
mid-session refreshes transparently without rebuilding the model.
Source code in src/symfonic/core/grok_oauth_provider.py
GrokProductionMisuseError ¶
Bases: RuntimeError
Raised when GrokOAuthProvider is used in a production-like env.