Third-Party SDKs (qlam-core)
qlam-core is the Python SDK for integrating with QLAM services. It provides authentication, configuration management, and type-safe API clients for building custom applications or integrating third-party quantum frameworks.
Overview
qlam-core is a standalone library that handles:
- Multi-flow OAuth 2.0 - Device code, authorization code (PKCE), client credentials
- Automatic token refresh - Seamless credential management
- Type-safe API clients - Pydantic models with full type hints
- Shared credentials - Works with
qshCLI authentication - Context-based config - Multiple environments with easy switching
Note
qlam-core is included as a dependency of qlam-shell. If you have QLAM Shell installed, QLAM Core is already available. For SDK-only usage, install qlam-core directly.
SDK Reference Available
See the QLAM Core SDK Reference for full API documentation generated from source.
Installation
uv pip install qlam-core
pip install qlam-core
Quick Start
First, ensure you have a configuration file at ~/.qsh/config.json (see Configuration below).
from qlam_core.common import AppContext
from qlam_core.plugins.tasks import TasksClient
# Create context (uses ~/.qsh/config.json)
ctx = AppContext()
# Use the Tasks API
with TasksClient(ctx) as client:
tasks = client.list()
print(f"Found {len(tasks)} tasks")
Core Concepts
AppContext
The central object that manages configuration, authentication, and HTTP clients.
from qlam_core.common import AppContext
# Use default context from config
ctx = AppContext()
# Use a specific named context
ctx = AppContext(context_name="staging")
# Access configuration
print(ctx.config.api_base_url)
print(ctx.config.qpu)
API Clients
All API clients follow the same pattern using context managers:
from qlam_core.plugins.tasks import TasksClient
from qlam_core.plugins.results import ResultsClient
from qlam_core.plugins.compilations import CompilationsClient
from qlam_core.plugins.definitions import DefinitionsClient
ctx = AppContext()
# Use as context manager (recommended)
with TasksClient(ctx) as client:
tasks = client.list()
task = client.get(id="a1b2c3d4-e5f6-7890-abcd-ef1234567890")
# Or manage lifecycle manually
client = TasksClient(ctx)
tasks = client.list()
client.close()
API Reference
TasksClient
Manage quantum computing tasks.
from qlam_core.plugins.tasks import TasksClient
with TasksClient(ctx) as client:
# List all tasks
tasks = client.list()
# Get a specific task
task = client.get(id="b2c3d4e5-f6a7-8901-bcde-f23456789012")
# Create a new task
new_task = client.create(body=task_request)
ResultsClient
Retrieve task execution results.
from qlam_core.plugins.results import ResultsClient
with ResultsClient(ctx) as client:
# Get results for a task
results = client.get(
id="b2c3d4e5-f6a7-8901-bcde-f23456789012",
qpu_mode="squin-256q",
shots_page=0,
shots_size=100
)
CompilationsClient
Manage quantum program compilations.
from qlam_core.plugins.compilations import CompilationsClient
with CompilationsClient(ctx) as client:
compilations = client.list()
compilation = client.get(id="c3d4e5f6-a7b8-9012-cdef-345678901234")
new_comp = client.create(body=compilation_request)
DefinitionsClient
Manage reusable task definitions.
from qlam_core.plugins.definitions import DefinitionsClient
with DefinitionsClient(ctx) as client:
definitions = client.list()
definition = client.get(id="d4e5f6a7-b8c9-0123-def0-456789012345")
new_def = client.create(body=definition_request)
Configuration
Config File Location
Default: ~/.qsh/config.json
This directory is shared with the qsh CLI, so credentials from qsh auth login are automatically available.
Configuration Schema
{
"current_context": "production",
"contexts": [
{
"name": "production",
"qpu": "gemini",
"defaults": {
"api_base_url": "https://api.quera.com"
},
"auth_providers": [
{
"name": "oauth",
"provider": "oauth",
"client_id": "your-client-id",
"grant_type": "device_code",
"scope": "openid profile offline_access",
"issuer": "https://auth.quera.com"
}
],
"plugins": {
"tasks": { "auth_provider": "oauth" },
"results": { "auth_provider": "oauth" }
}
}
]
}
Authentication
Programmatic Login
Trigger an interactive login flow directly from Python:
from qlam_core.common import AppContext
from qlam_core.auth import AuthClient
ctx = AppContext()
auth = AuthClient(ctx)
# Check if already authenticated
if not auth.is_authenticated("oauth"):
# Triggers OAuth flow (opens browser for Authorization Code,
# or displays code for Device Code flow)
auth.login("oauth")
# Now use authenticated clients
from qlam_core.plugins.tasks import TasksClient
with TasksClient(ctx) as client:
tasks = client.list()
Using Existing Credentials
If you've already authenticated with qsh auth login, QLAM Core uses those credentials automatically:
ctx = AppContext()
with TasksClient(ctx) as client:
# Credentials are loaded from ~/.qsh/credentials/
tasks = client.list()
Get Current Credential
Retrieve the current credential for an authentication provider. This is useful for inspecting auth status, checking token expiry, or building custom refresh logic:
from qlam_core.common import AppContext
from qlam_core.sdk import get_credential
ctx = AppContext()
credential = get_credential(ctx, provider="oauth")
if credential is None:
print("No credential data found for this provider")
elif credential.status == "Authenticated":
print(f"Token expires at {credential.expires_at}")
# Use the token for custom requests
token = credential.access_token
else:
print(f"Status: {credential.status}")
Returns None when no credential data exists for the given provider. Otherwise, returns a credential model whose status field is "Authenticated" or "Not authenticated".
Programmatic Token Refresh
Refresh credentials non-interactively (useful for long-running applications):
from qlam_core.common import AppContext
from qlam_core.sdk import refresh_credentials
ctx = AppContext()
# Refresh all providers
result = refresh_credentials(ctx)
# Refresh a specific provider
result = refresh_credentials(ctx, provider="oauth", force=True)
M2M (Client Credentials)
For automated systems that authenticate without user interaction, configure a context with grant_type: "client_credentials":
{
"auth_providers": [
{
"name": "m2m",
"provider": "oauth",
"client_id": "your-m2m-client-id",
"client_secret": "your-m2m-client-secret",
"grant_type": "client_credentials",
"audience": "https://v2/your-deployment",
"issuer": "https://auth.quera.com"
}
],
"plugins": {
"tasks": { "auth_provider": "m2m" },
"results": { "auth_provider": "m2m" }
}
}
Then authenticate and use the API clients:
from qlam_core.common import AppContext
from qlam_core.auth import AuthClient
from qlam_core.plugins.tasks import TasksClient
ctx = AppContext()
auth = AuthClient(ctx)
# Authenticate using M2M credentials (non-interactive)
auth.login("m2m")
# Use authenticated clients
with TasksClient(ctx) as client:
tasks = client.list()
for task in tasks:
print(task.id, task.status)
Cache Tokens Until Expiration
The identity provider enforces a monthly limit on M2M token requests. QLAM Core caches tokens in ~/.qsh/credentials/ after login, and API clients reuse the cached token automatically. Avoid calling auth.login() before every request—call it once at startup and let the SDK handle the rest.
Securing the Client Secret
Avoid storing client_secret directly in config.json for production use. Instead, inject it via an environment variable or secret manager and write the config file as part of your job startup script.
Supported OAuth Flows
| Flow | Use Case | Grant Type |
|---|---|---|
| Device Code | CLI, headless environments | device_code |
| Authorization Code + PKCE | Web applications | authorization_code |
| Client Credentials | Service-to-service (M2M) | client_credentials |
Error Handling
Exception Hierarchy
QlamCoreError (base exception)
├── ConfigurationError # Config file issues
│ └── AuthConfigurationError # Missing/invalid auth settings
├── AuthenticationError # Auth failed (401/403)
├── APIError # API response errors
├── ValidationError # Input validation failed (422)
├── NetworkError # Connection/timeout issues
└── FileSystemError # File I/O errors
Handling Errors
from qlam_core.errors import (
QlamCoreError,
AuthenticationError,
NetworkError,
ValidationError,
)
try:
with TasksClient(ctx) as client:
task = client.get(id="a1b2c3d4-e5f6-7890-abcd-ef1234567890")
except AuthenticationError as e:
print(f"Auth failed: {e.message}")
print("Run: qsh auth login")
except NetworkError as e:
print(f"Network error: {e.message}")
except ValidationError as e:
print(f"Invalid request: {e.message}")
except QlamCoreError as e:
print(f"Error: {e.message}")
Environment Variables
| Variable | Description |
|---|---|
QSH_CONFIG_DIR |
Override config directory (default: ~/.qsh) |
QSH_CONFIG |
Override config file path directly |
QSH_AUTH_TOKEN |
Override auth token for all requests |
QSH_QPU |
Override default QPU |
Precedence: Environment variables > Config file > Defaults
When to Use QLAM Core
Use QLAM Core when:
- Building a custom Python SDK that needs QLAM access
- Integrating a third-party quantum framework with QLAM
- Writing Python scripts that need authenticated API access
- Building applications that need programmatic control
Use QLAM Shell instead when:
- Working interactively from the command line
- Need quick task submission and monitoring
- Writing shell scripts
Use Direct API instead when:
- Working in non-Python environments
- Need complete control over HTTP requests
- Building applications with custom auth flows
Next Steps
- QLAM Shell - CLI for interactive use
- Authentication Guide - Understanding auth flows
- Direct API - Raw API access without SDK