Skip to content

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 qsh CLI 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