Skip to main content
Requires Python 3.9 or higher.

Installation

pip install glass-ai

Quick Start

from glass import init, trace, interaction
from openai import OpenAI

# Initialize Glass
init(api_key="your-glass-api-key")

# Your AI calls are now automatically traced
client = OpenAI()

@trace()
def generate_response(prompt: str) -> str:
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": prompt}]
    )
    return response.choices[0].message.content

# Track user interactions
with interaction(user_id="user_123", session_id="sess_abc") as ctx:
    result = generate_response("What is the meaning of life?")
    ctx.finish(output={"response": result})
That’s it. All your OpenAI, Anthropic, and Google Generative AI calls are now traced automatically.

API Reference

init()

Initializes the Glass SDK. Call this once at application startup.
from glass import init

# Basic initialization
init(api_key="your-api-key")

# With debug mode (logs traces to console)
init(api_key="your-api-key", debug=True)
api_key
string
Your Glass API key. Falls back to GLASS_API_KEY environment variable if not provided.
debug
boolean
default:"False"
Enable console output for local development.
skip_default_instrumentations
boolean
default:"False"
Disable automatic tracing of AI providers. See Instrumentations for details.
instrumentations
list
Custom OpenTelemetry instrumentors. See Instrumentations for details.

@trace()

Decorator that wraps any function with tracing. Automatically records arguments, return values, and exceptions.
from glass import trace

# Basic usage
@trace()
def process_data(data: dict) -> dict:
    return {"processed": True, **data}

# Custom span name
@trace(name="custom-operation")
def my_function():
    pass

# With attributes
@trace(attributes={"model": "text-embedding-3-small"})
def create_embedding(text: str) -> list[float]:
    return [0.1, 0.2, 0.3]
Works with async functions too:
@trace()
async def async_process(data: str) -> str:
    await asyncio.sleep(0.1)
    return f"processed: {data}"
name
string
Custom span name. Defaults to the function name.
attributes
dict
Additional attributes to attach to the span.

interaction()

Context manager for tracking user interactions. Propagates user context to all nested traces.
from glass import interaction, trace

@trace()
def call_llm(prompt: str) -> str:
    return "LLM response"

with interaction(user_id="user_123", session_id="sess_abc", project="conversational-chat", input="Hello!") as ctx:
    result = call_llm("Hello!")
    ctx.finish(output={"response": result})
Also works with async:
async with interaction(user_id="user_123") as ctx:
    result = await async_call_llm("Hello!")
    ctx.finish(output={"response": result})
user_id
string
Identifier for the user.
session_id
string
Session identifier.
project
string
In which project to classify traces.
input
string
The user’s input/query.
service
string
Service name for routing.
Methods on the context:
MethodDescription
finish(output)Record the final output of the interaction
set_attribute(key, value)Set a custom attribute
record_exception(exception)Record an exception

task_span()

Context manager for creating task spans with explicit input/output recording.
from glass import task_span

with task_span("embedding-task", attributes={"model": "ada-002"}) as task:
    task.record_input({"text": "Hello, world!"})
    embedding = compute_embedding("Hello, world!")
    task.record_output({"embedding": embedding, "dimensions": 1536})
name
string
required
The name of the task span.
attributes
dict
Additional attributes for the span.
Methods on the task:
MethodDescription
record_input(data)Record input data
record_output(data)Record output data
set_attribute(key, value)Set a custom attribute
record_exception(exception)Record an exception

Full Example: RAG Pipeline

Here’s how the primitives compose together:
from glass import init, trace, interaction, task_span
from openai import OpenAI

init(api_key="your-api-key")
client = OpenAI()

@trace()
def retrieve_context(query: str) -> list[str]:
    return ["context 1", "context 2"]

@trace()
def generate_response(query: str, context: list[str]) -> str:
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": f"Context: {context}"},
            {"role": "user", "content": query}
        ]
    )
    return response.choices[0].message.content

@trace(name="rag-pipeline")
def rag_query(query: str) -> str:
    with task_span("retrieval") as task:
        task.record_input({"query": query})
        context = retrieve_context(query)
        task.record_output({"num_docs": len(context)})
    
    return generate_response(query, context)

# Track the full user interaction
with interaction(user_id="user_123", input="What is quantum computing?") as ctx:
    result = rag_query("What is quantum computing?")
    ctx.finish(output={"answer": result})
This creates a trace hierarchy like:
interaction (user_id=user_123)
└── rag-pipeline
    ├── retrieval (task_span)
    │   └── retrieve_context
    └── generate_response
        └── OpenAI chat.completions.create (auto)

Environment Variables

VariableDescription
GLASS_API_KEYYour Glass API key (alternative to passing in code)
export GLASS_API_KEY="your-api-key"
from glass import init

# API key is read from environment
init()