Python API Client
Glean's Python API client provides a Pythonic interface to Glean's Client API, making it easy to integrate enterprise search and AI capabilities into your Python applications.
glean-api-client
Official Python client for Glean's Client API
Authentication Required: You'll need a Client API token to use this library.
Installation
- pip
- poetry
- uv
pip install glean-api-client
poetry add glean-api-client
uv add glean-api-client
Quick Start
Set up environment variables
export GLEAN_SERVER_URL="https://your-server-id-be.glean.com"
export GLEAN_API_TOKEN="your-token-here"
Basic usage
from glean.api_client import Glean
import os
with Glean(
api_token=os.getenv("GLEAN_API_TOKEN"),
server_url=os.getenv("GLEAN_SERVER_URL"),
) as client:
response = client.client.chat.create(
messages=[{
"fragments": [{"text": "What are our company values?"}]
}],
timeout_millis=30000
)
print(response)
Core Features
Chat API
Build conversational AI applications:
# Simple chat
response = client.client.chat.create(
messages=[{"fragments": [{"text": "Explain our Q4 strategy"}]}]
)
# Streaming chat for real-time responses
for chunk in client.client.chat.stream(
messages=[{"fragments": [{"text": "What are our priorities?"}]}]
):
print(chunk.text, end="", flush=True)
Search API
Integrate enterprise search:
results = client.client.search.search(
query="quarterly business review",
page_size=10
)
for result in results.results:
print(f"Title: {result.title}")
print(f"URL: {result.url}")
Agents API
Execute pre-built agents:
response = client.client.agents.create_and_wait_run(
agent_id="your-agent-id",
inputs={"query": "Analyze sales performance"}
)
Framework Integrations
FastAPI
from fastapi import FastAPI
from glean.api_client import Glean
from pydantic import BaseModel
app = FastAPI()
class ChatRequest(BaseModel):
message: str
@app.post("/chat")
async def chat_endpoint(request: ChatRequest):
with Glean(
api_token=os.getenv("GLEAN_API_TOKEN"),
server_url=os.getenv("GLEAN_SERVER_URL"),
) as client:
response = client.client.chat.create(
messages=[{"fragments": [{"text": request.message}]}]
)
return {"response": response.text}
Django
from django.http import JsonResponse
from glean.api_client import Glean
import json
def chat_view(request):
data = json.loads(request.body)
message = data.get('message')
with Glean(
api_token=os.getenv("GLEAN_API_TOKEN"),
server_url=os.getenv("GLEAN_SERVER_URL"),
) as client:
response = client.client.chat.create(
messages=[{"fragments": [{"text": message}]}]
)
return JsonResponse({'response': response.text})
Streamlit
import streamlit as st
from glean.api_client import Glean
st.title("Company Knowledge Assistant")
user_input = st.text_input("Ask a question:")
if user_input:
with Glean(
api_token=os.getenv("GLEAN_API_TOKEN"),
server_url=os.getenv("GLEAN_SERVER_URL"),
) as client:
response = client.client.chat.create(
messages=[{"fragments": [{"text": user_input}]}]
)
st.write(response.text)
Authentication
User-Scoped Tokens
client = Glean(
api_token="your-user-token",
server_url="https://your-server-id-be.glean.com"
)
Global Tokens with ActAs
response = client.client.chat.create(
messages=[{"fragments": [{"text": "Hello"}]}],
http_headers={"X-Glean-ActAs": "user@company.com"}
)
OAuth Access Tokens
An OAuth access token is a bearer credential, so it goes in the same api_token field:
client = Glean(
api_token=oauth_access_token,
server_url="https://your-server-id-be.glean.com",
)
Tokens issued by the Glean OAuth Authorization Server (including tokens obtained via Dynamic Client Registration) are detected automatically. Tokens issued by an external identity provider (Google, Okta, Azure, etc.) additionally require the X-Glean-Auth-Type: OAUTH header on each request:
response = client.client.chat.create(
messages=[{"fragments": [{"text": "Hello"}]}],
http_headers={"X-Glean-Auth-Type": "OAUTH"}
)
See the OAuth authentication guide for identity-provider setup.
Complete Example: Authorization Code with PKCE
This example uses Authlib with Flask. Setting code_challenge_method enables PKCE; Authlib stores the verifier and state in the session and verifies them on the callback. Point OAUTH_METADATA_URL at the Glean OAuth Authorization Server metadata (https://your-server-id-be.glean.com/.well-known/oauth-authorization-server) or your IdP's discovery document.
import os
from flask import Flask, jsonify, url_for
from authlib.integrations.flask_client import OAuth
from glean.api_client import Glean
app = Flask(__name__)
app.secret_key = os.urandom(24)
oauth = OAuth(app)
oauth.register(
name="glean",
client_id=os.environ["OAUTH_CLIENT_ID"],
client_secret=os.environ.get("OAUTH_CLIENT_SECRET"), # omit for a public client
server_metadata_url=os.environ["OAUTH_METADATA_URL"],
client_kwargs={
"scope": "openid offline_access SEARCH", # SEARCH lets the token call /search (a Glean scope); offline_access requests a refresh token
"code_challenge_method": "S256", # enable PKCE
},
)
@app.route("/login")
def login():
return oauth.glean.authorize_redirect(url_for("callback", _external=True))
@app.route("/callback")
def callback():
token = oauth.glean.authorize_access_token() # verifies state + PKCE, exchanges code
with Glean(
api_token=token["access_token"],
server_url=os.environ["GLEAN_SERVER_URL"],
) as glean:
results = glean.client.search.query(
query="quarterly reports",
page_size=10,
# Omit this header when the token is from the Glean Authorization Server.
http_headers={"X-Glean-Auth-Type": "OAUTH"},
)
titles = [r.title for r in (results.results or [])]
return jsonify({"titles": titles})
if __name__ == "__main__":
app.run(port=5000)
Access tokens expire. The token dict includes refresh_token when you request the offline_access scope; use it to obtain new access tokens before expiry.
Error Handling
from glean.api_client.exceptions import GleanAPIError
try:
response = client.client.chat.create(messages=[...])
except GleanAPIError as e:
print(f"API error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
Testing
Unit Testing with Mocks
import pytest
from unittest.mock import patch, MagicMock
@pytest.fixture
def mock_glean_client():
with patch('your_app.Glean') as mock:
client_instance = MagicMock()
mock.return_value.__enter__.return_value = client_instance
yield client_instance
def test_chat_service(mock_glean_client):
mock_response = MagicMock()
mock_response.text = "Test response"
mock_glean_client.client.chat.create.return_value = mock_response
result = send_message("Hello")
assert result == "Test response"