Library / SDK
xai-org/xai-sdk-python avatar
xai-org/xai-sdk-python

xai-sdk-python talks to xAI over gRPC, not REST

The official Python SDK for the SpaceXAI API

589 stars200 forksPythonApache-2.0

At a glance

What is it?
The xAI Python SDK is an Apache-2.0 library that talks to xAI's APIs over gRPC rather than HTTP, offering synchronous and asynchronous clients with chat, streaming, image understanding, video generation and video editing. The transport choice is the decision that shapes everything else about the SDK.
Who is it for?
xai-sdk-python suits Python developers who want xAI's chat, image and video models behind a typed client with sync and async variants and a shared conversation object, and it suits teams that already run gRPC infrastructure. It does not suit codebases built around plain HTTP clients and OpenAI style REST endpoints, where adopting it means a different transport and a different error surface.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The transport is gRPC, and that is the whole story

The README opens with the fact that matters most: the xAI Python SDK is a gRPC-based Python library for interacting with xAI's APIs. That single word separates it from the HTTP client libraries most Python developers reach for. A gRPC client speaks a binary protocol over HTTP/2, which means it needs a protobuf schema for the request and response types, and the dependency list confirms it. The pyproject requires grpcio at 1.72.1 or newer and below 2, protobuf at 5.29.4 or newer and below 7, and googleapis-common-protos, which is where the well known protobuf types come from. Pydantic at 2.5.3 or newer sits alongside, and requests and aiohttp are present too, so the HTTP libraries are there for the parts of the surface that are not gRPC. The practical consequences are that a corporate proxy that only allows HTTPS inspection may not pass gRPC traffic, that the typed schema gives you editor completion on request fields, and that error handling looks different from a JSON error body.

One key, two clients, one environment variable

Authentication is deliberately dull. By default the SDK looks for an environment variable named XAI_API_KEY, and if that variable is set you can instantiate the clients without passing a key explicitly.

python
from xai_sdk import Client, AsyncClient

# Synchronous client
sync_client = Client()

# Asynchronous client
async_client = AsyncClient()

If you prefer to be explicit, the key can be read with os.getenv or loaded from a .env file with python-dotenv, and passed to the constructor.

python
import os
from dotenv import load_dotenv
from xai_sdk import Client, AsyncClient

load_dotenv()

api_key = os.getenv("XAI_API_KEY")
sync_client = Client(api_key=api_key)
async_client = AsyncClient(api_key=api_key)

The documentation is explicit that you should set the environment variable or load it from a .env file rather than hardcoding the key into your codebase. The sync and async clients are separate types, xai_sdk.Client and xai_sdk.AsyncClient, and the two exist as peers rather than as a mode flag. The library is built for Python 3.10 and above, and the classifiers list 3.10 through 3.13, both CPython and PyPy, on MacOS, Linux and Windows.

The chat object owns the history for you

Conversation handling is where the SDK departs from the usual stateless request pattern. You create a chat instance with a model and a list of messages, then append to it, then call sample to get a response. The documentation is careful about the underlying reality, noting that the underlying APIs are still stateless and that the append approach simply makes it easy to manage the message history.

python
from xai_sdk import Client
from xai_sdk.chat import system, user

client = Client()
chat = client.chat.create(
    model="grok-4.6",
    messages=[system("You are a pirate assistant.")]
)

while True:
    prompt = input("You: ")
    if prompt.lower() == "exit":
        break
    chat.append(user(prompt))
    response = chat.sample()
    print(f"Grok: {response.content}")
    chat.append(response)

The response is appended back onto the chat, which is the part people miss when porting code from a stateless API. The async version is the same code with AsyncClient, an await on chat.sample, and an asyncio.run entry point, and the SDK also ships message helpers, with system and user imported from xai_sdk.chat. The example prompt is a pirate assistant, which tells you the sample is aimed at people reading it rather than at production, but the shape of the loop is what you will keep.

Streaming yields a tuple so the accumulated response stays available

Streaming is where the API shape is slightly unusual, and the reason is convenient. The stream method returns a tuple containing response and chunk. The chunk holds the text delta for that step, and the response variable accumulates the full response as the stream progresses, so you get the deltas for display and the complete object for free at the end.

python
from xai_sdk import Client
from xai_sdk.chat import user

client = Client()
chat = client.chat.create(model="grok-4.6")

while True:
    prompt = input("You: ")
    if prompt.lower() == "exit":
        break
    chat.append(user(prompt))
    print("Grok: ", end="", flush=True)
    for response, chunk in chat.stream():
        print(chunk.content, end="", flush=True)
    print()
    chat.append(response)

The loop variable response is what you append after the stream ends, which works because the tuple yields the same accumulating response object each iteration. The pattern is different from the common one of a separate accumulator object you build yourself, and it removes a class of bug where you forget to finalise the response before storing it. It also means you cannot easily get a partial response if you break out of the loop early, since the accumulation lives in the tuple.

Images and video cover generation on the same client

The same client carries the non-chat capabilities, and the README walks through them. Image understanding interleaves images and text in a single message, using an image helper alongside the user helper, so a question about two pictures is one message rather than two requests.

python
from xai_sdk import Client
from xai_sdk.chat import image, user

client = Client()
chat = client.chat.create(model="grok-4.6")

chat.append(
    user(
        "Which animal looks happier in these images?",
        image("https://images.unsplash.com/photo-1561037404-61cd46aa615b"),   # Puppy
        image("https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba") # Kitten
    )
)
response = chat.sample()
print(f"Grok: {response.content}")

Video generation is a separate namespace, client.video.generate, using the grok-imagine-video model, and the SDK handles the asynchronous polling workflow automatically, so you submit a prompt and receive the completed video response. The call takes a duration, an aspect_ratio and a resolution, and the response carries a url and a duration. Beyond text to video there is image to video through an image_url argument, reference images to guide style and content through a reference_image_urls list, and video editing by passing a video_url to generate. The README covers text, image, video, video editing, function calling and more, and the examples directory splits into aio and sync so you can see both client styles side by side.

Telemetry is an optional extra, not a default

Observability is present but kept out of the way. The dependency list includes opentelemetry-sdk at 1.36.0 or newer, and the optional dependency group telemetry-http adds the OTLP HTTP exporter at the same version floor. The structure of the packaging tells the story. The build backend is hatchling with hatch-fancy-pypi-readme, and the readme and version are dynamic, so the project metadata is assembled at build time rather than hand maintained. Telemetry being an extra rather than a hard dependency means that if you do not want tracing, you do not pull the exporter in, and the SDK itself will not send anything without configuration. There is a pre-commit configuration and a .gitleaks.toml in the repository, so secret scanning is enforced in the development workflow, which pairs sensibly with a library whose whole job is handling an API key. A SECURITY.md and a CLA.md are also present, alongside a CHANGELOG.md that records the release history.

What adopting a gRPC client costs you

There are cases where this SDK is the wrong choice, and the transport is the reason. If your codebase has a single HTTP client abstraction, a shared retry and timeout policy, and a mock layer built on responses, then this library sits outside all of that. gRPC needs an HTTP/2 capable proxy, and an environment that only permits outbound HTTPS on port 443 with a terminating proxy may simply not reach the endpoint. If your team is standardising on the OpenAI style REST client that many providers emulate, adopting a second transport for one provider is a decision with ongoing cost, because every proxy, mock, retry policy and interceptor you already have has to be rebuilt for it. Another limit is the surface. The README covers the main calls and points to docs.x.ai for the full reference, and the repository also has an examples folder, but there is no indication of a local emulator or a record-and-replay mode for tests, which is the kind of thing that makes an HTTP client pleasant to test and a binary protocol client awkward. If your use is a batch job calling chat once an hour, the transport difference costs you little. If it is a request path inside a large service with a strict infrastructure policy, the difference is the decision.

Editorial conclusion

xai-sdk-python suits Python developers who want xAI's chat, image and video models behind a typed client with sync and async variants and a shared conversation object, and it suits teams that already run gRPC infrastructure. It does not suit codebases built around plain HTTP clients and OpenAI style REST endpoints, where adopting it means a different transport and a different error surface. Before adopting it, confirm your network can reach a gRPC endpoint rather than an HTTPS API, check that the model identifiers in the README match the models your account has access to, and read the examples folder, which splits the samples into aio and sync directories.

Frequently asked questions

How do I install the xAI Python SDK?

Install it with pip install xai-sdk, or use uv with uv add xai-sdk. Python 3.10 or higher is required, and the package is published on PyPI as xai-sdk.

How does the xAI SDK authenticate?

By default it reads the XAI_API_KEY environment variable, so you can construct Client() or AsyncClient() without passing a key. You can also read the key with os.getenv or load it from a .env file with python-dotenv and pass it explicitly.

What protocol does the xAI Python SDK use?

It is a gRPC based library, and the dependencies include grpcio and protobuf along with googleapis-common-protos. The package also depends on requests and aiohttp, and on pydantic for the typed models.

How does streaming work in the xAI Python SDK?

The stream method returns a tuple of response and chunk. The chunk holds the text delta for that step and the response object accumulates the full response as the stream progresses, so you can print chunks and still append the complete response afterwards.

Can the xAI Python SDK generate video?

Yes. client.video.generate uses the grok-imagine-video model and the SDK handles the asynchronous polling workflow automatically. You can also generate from an input image with image_url, guide the result with reference_image_urls, and edit an existing video by passing video_url.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. xai-org/xai-sdk-python on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/xai-org-xai-sdk-python.svg)](https://hysenlabs.com/projects/xai-org-xai-sdk-python)

Was this useful?