blaxel 0.2.47


pip install blaxel

  Latest version

Released: Mar 27, 2026


Meta
Author: cploujoux
Requires Python: <3.14,>=3.10

Classifiers

Blaxel Python SDK

Blaxel is a perpetual sandbox platform that achieves near instant latency by keeping infinite secure sandboxes on automatic standby, while co-hosting your agent logic to cut network overhead.

This repository contains Blaxel's Python SDK, which lets you create and manage sandboxes and other resources on Blaxel.

Installation

pip install blaxel

Authentication

The SDK authenticates with your Blaxel workspace using these sources (in priority order):

  1. Blaxel CLI, when logged in
  2. Environment variables in .env file (BL_WORKSPACE, BL_API_KEY)
  3. System environment variables
  4. Blaxel configuration file (~/.blaxel/config.yaml)

When developing locally, the recommended method is to just log in to your workspace with the Blaxel CLI:

bl login YOUR-WORKSPACE

This allows you to run Blaxel SDK functions that will automatically connect to your workspace without additional setup. When you deploy on Blaxel, this connection persists automatically.

When running Blaxel SDK from a remote server that is not Blaxel-hosted, we recommend using environment variables as described in the third option above.

Usage

Sandboxes

Sandboxes are secure, instant-launching compute environments that scale to zero after inactivity and resume in under 25ms.

import asyncio
from blaxel.core import SandboxInstance

async def main():

    # Create a new sandbox
    sandbox = await SandboxInstance.create_if_not_exists({
        "name": "my-sandbox",
        "image": "blaxel/base-image:latest",
        "memory": 4096,
        "region": "us-pdx-1",
        "ports": [{"target": 3000, "protocol": "HTTP"}],
        "labels": {"env": "dev", "project": "my-project"},
        "ttl": "24h"
    })

    # Get existing sandbox
    existing = await SandboxInstance.get("my-sandbox")

    # Delete sandbox (using class)
    await SandboxInstance.delete("my-sandbox")

    # Delete sandbox (using instance)
    await existing.delete()

if __name__ == "__main__":
    asyncio.run(main())

Preview URLs

Generate public preview URLs to access services running in your sandbox:

import asyncio
from blaxel.core import SandboxInstance

async def main():

    # Get existing sandbox
    sandbox = await SandboxInstance.get("my-sandbox")

    # Start a web server in the sandbox
    await sandbox.process.exec({
        "command": "python -m http.server 3000",
        "working_dir": "/app",
        "wait_for_ports": [3000]
    })

    # Create a public preview URL
    preview = await sandbox.previews.create_if_not_exists({
        "metadata": {"name": "app-preview"},
        "spec": {
            "port": 3000,
            "public": True
        }
    })

    print(preview.spec.url)  # https://xyz.preview.bl.run

if __name__ == "__main__":
    asyncio.run(main())

Previews can also be private, with or without a custom prefix. When you create a private preview URL, a token is required to access the URL, passed as a request parameter or request header.

# ...

# Create a private preview URL
private_preview = await sandbox.previews.create_if_not_exists({
    "metadata": {"name": "private-app-preview"},
    "spec": {
        "port": 3000,
        "public": False
    }
})

# Create a public preview URL with a custom prefix
custom_preview = await sandbox.previews.create_if_not_exists({
    "metadata": {"name": "custom-app-preview"},
    "spec": {
        "port": 3000,
        "prefix_url": "my-app",
        "public": True
    }
})

Process execution

Execute and manage processes in your sandbox:

import asyncio
from blaxel.core import SandboxInstance

async def main():

    # Get existing sandbox
    sandbox = await SandboxInstance.get("my-sandbox")

    # Execute a command
    process = await sandbox.process.exec({
        "name": "build-process",
        "command": "npm run build",
        "working_dir": "/app",
        "wait_for_completion": True,
        "timeout": 60000  # 60 seconds
    })

    # Kill a running process
    await sandbox.process.kill("build-process")

if __name__ == "__main__":
    asyncio.run(main())

Restart a process if it fails, up to a maximum number of restart attempts:

# ...

# Run with auto-restart on failure
process = await sandbox.process.exec({
    "name": "web-server",
    "command": "python -m http.server 3000 --bind 0.0.0.0",
    "restart_on_failure": True,
    "max_restarts": 5
})

Filesystem operations

Manage files and directories within your sandbox:

import asyncio
from blaxel.core import SandboxInstance

async def main():

    # Get existing sandbox
    sandbox = await SandboxInstance.get("my-sandbox")

    # Write and read text files
    await sandbox.fs.write("/app/config.json", '{"key": "value"}')
    content = await sandbox.fs.read("/app/config.json")

    # Write and read binary files
    with open("./image.png", "rb") as f:
        binary_data = f.read()
    await sandbox.fs.write_binary("/app/image.png", binary_data)
    blob = await sandbox.fs.read_binary("/app/image.png")

    # Create directories
    await sandbox.fs.mkdir("/app/uploads")

    # List files
    listing = await sandbox.fs.ls("/app")
    subdirectories = listing.subdirectories
    files = listing.files

    # Search for text within files
    matches = await sandbox.fs.grep("pattern", "/app", case_sensitive=True, context_lines=2, max_results=5, file_pattern="*.py", exclude_dirs=["__pycache__"])

    # Find files and directories matching specified patterns
    results = await sandbox.fs.find("/app", type="file", patterns=["*.md", "*.html"], max_results=1000)

    # Watch for file changes
    def on_change(event):
        print(event.op, event.path)

    handle = sandbox.fs.watch("/app", on_change, {
        "with_content": True,
        "ignore": ["node_modules", ".git"]
    })

    # Close watcher
    handle["close"]()

if __name__ == "__main__":
    asyncio.run(main())

Volumes

Persist data by attaching and using volumes:

import asyncio
from blaxel.core import VolumeInstance, SandboxInstance

async def main():

    # Create a volume
    volume = await VolumeInstance.create_if_not_exists({
        "name": "my-volume",
        "size": 1024,  # MB
        "region": "us-pdx-1",
        "labels": {"env": "test", "project": "12345"}
    })

    # Attach volume to sandbox
    sandbox = await SandboxInstance.create_if_not_exists({
        "name": "my-sandbox",
        "image": "blaxel/base-image:latest",
        "volumes": [
            {"name": "my-volume", "mount_path": "/data", "read_only": False}
        ]
    })

    # List volumes
    volumes = await VolumeInstance.list()

    # Delete volume (using class)
    await VolumeInstance.delete("my-volume")

    # Delete volume (using instance)
    await volume.delete()

if __name__ == "__main__":
    asyncio.run(main())

Batch jobs

Blaxel lets you support agentic workflows by offloading asynchronous batch processing tasks to its scalable infrastructure, where they can run in parallel. Jobs can run multiple times within a single execution and accept optional input parameters.

import asyncio
from blaxel.core.jobs import bl_job
from blaxel.core.client.models import CreateJobExecutionRequest

async def main():
    # Create and run a job execution
    job = bl_job("job-name")

    execution_id = await job.acreate_execution(CreateJobExecutionRequest(
        tasks=[
            {"name": "John"},
            {"name": "Jane"},
            {"name": "Bob"}
        ]
    ))

    # Get execution status
    # Returns: "pending" | "running" | "completed" | "failed"
    status = await job.aget_execution_status(execution_id)

    # Get execution details
    execution = await job.aget_execution(execution_id)
    print(execution.status, execution.metadata)

    # Wait for completion
    try:
        result = await job.await_for_execution(
            execution_id,
            max_wait=300,  # 5 minutes (seconds)
            interval=2     # Poll every 2 seconds
        )
        print(f"Completed: {result.status}")
    except Exception as error:
        print(f"Timeout: {error}")

    # List all executions
    executions = await job.alist_executions()

    # Delete an execution
    await job.acancel_execution(execution_id)

if __name__ == "__main__":
    asyncio.run(main())

Synchronous calls are also available.

Framework integrations

Blaxel provides additional packages for framework-specific integrations and telemetry:

# With specific integrations
pip install "blaxel[telemetry]"
pip install "blaxel[crewai]"
pip install "blaxel[openai]"
pip install "blaxel[langgraph]"
pip install "blaxel[livekit]"
pip install "blaxel[llamaindex]"
pip install "blaxel[pydantic]"
pip install "blaxel[googleadk]"

# Everything
pip install "blaxel[all]"

Model use

Blaxel acts as a unified gateway for model APIs, centralizing access credentials, tracing and telemetry. You can integrate with any model API provider, or deploy your own custom model. When a model is deployed on Blaxel, a global API endpoint is also created to call it.

The SDK includes a helper function that creates a reference to a model deployed on Blaxel and returns a framework-specific model client that routes API calls through Blaxel's unified gateway.

from blaxel.core import bl_model

# With OpenAI
from blaxel.openai import bl_model
model = await bl_model("gpt-5-mini")

# With LangChain
from blaxel.langgraph import bl_model
model = await bl_model("gpt-5-mini")

# With LlamaIndex
from blaxel.llamaindex import bl_model
model = await bl_model("gpt-5-mini")

# With Pydantic AI
from blaxel.pydantic import bl_model
model = await bl_model("gpt-5-mini")

# With CrewAI
from blaxel.crewai import bl_model
model = await bl_model("gpt-5-mini")

# With Google ADK
from blaxel.googleadk import bl_model
model = await bl_model("gpt-5-mini")

# With LiveKit
from blaxel.livekit import bl_model
model = await bl_model("gpt-5-mini")

MCP tool use

Blaxel lets you deploy and host Model Context Protocol (MCP) servers, accessible at a global endpoint over streamable HTTP.

The SDK includes a helper function that retrieves and returns tool definitions from a Blaxel-hosted MCP server in the format required by specific frameworks.

# With OpenAI
from blaxel.openai import bl_tools
tools = await bl_tools(["sandbox/my-sandbox"])

# With Pydantic AI
from blaxel.pydantic import bl_tools
tools = await bl_tools(["sandbox/my-sandbox"])

# With LlamaIndex
from blaxel.llamaindex import bl_tools
tools = await bl_tools(["sandbox/my-sandbox"])

# With LangChain
from blaxel.langgraph import bl_tools
tools = await bl_tools(["sandbox/my-sandbox"])

# With CrewAI
from blaxel.crewai import bl_tools
tools = await bl_tools(["sandbox/my-sandbox"])

# With Google ADK
from blaxel.googleadk import bl_tools
tools = await bl_tools(["sandbox/my-sandbox"])

# With LiveKit
from blaxel.livekit import bl_tools
tools = await bl_tools(["sandbox/my-sandbox"])

Here is an example of retrieving tool definitions from a Blaxel sandbox's MCP server for use with the OpenAI SDK:

import asyncio
from blaxel.core import SandboxInstance
from blaxel.openai import bl_tools

async def main():

    # Create a new sandbox
    sandbox = await SandboxInstance.create_if_not_exists({
        "name": "my-sandbox",
        "image": "blaxel/base-image:latest",
        "memory": 4096,
        "region": "us-pdx-1",
        "ports": [{"target": 3000, "protocol": "HTTP"}],
        "ttl": "24h"
    })

    # Get sandbox MCP tools
    tools = await bl_tools(["sandbox/my-sandbox"])

if __name__ == "__main__":
    asyncio.run(main())

Telemetry

Instrumentation happens automatically when workloads run on Blaxel.

Enable automatic telemetry by importing the blaxel.telemetry package:

import blaxel.telemetry

Requirements

  • Python 3.9 or later

Contributing

Contributions are welcome! Please feel free to submit a pull request.

License

This project is licensed under the MIT License. See the LICENSE file for details.

0.2.47 Mar 27, 2026
0.2.46 Mar 26, 2026
0.2.45 Mar 11, 2026
0.2.45rc124 Mar 06, 2026
0.2.44 Mar 02, 2026
0.2.43 Feb 27, 2026
0.2.42 Feb 20, 2026
0.2.41 Feb 20, 2026
0.2.41rc123 Feb 20, 2026
0.2.40 Feb 14, 2026
0.2.39 Feb 06, 2026
0.2.38 Feb 06, 2026
0.2.38rc122 Feb 05, 2026
0.2.37 Feb 03, 2026
0.2.36 Jan 23, 2026
0.2.35 Jan 10, 2026
0.2.34 Dec 17, 2025
0.2.33 Dec 13, 2025
0.2.32 Dec 09, 2025
0.2.31 Dec 06, 2025
0.2.31rc121 Dec 06, 2025
0.2.31rc120 Dec 05, 2025
0.2.30 Dec 03, 2025
0.2.29 Dec 03, 2025
0.2.28 Dec 03, 2025
0.2.27 Dec 02, 2025
0.2.26 Dec 02, 2025
0.2.26rc119 Dec 01, 2025
0.2.26rc118 Dec 01, 2025
0.2.26rc117 Dec 01, 2025
0.2.26rc116 Dec 01, 2025
0.2.26rc115 Dec 01, 2025
0.2.26rc114 Nov 26, 2025
0.2.26rc113 Nov 26, 2025
0.2.26rc112 Nov 26, 2025
0.2.26rc111 Nov 26, 2025
0.2.26rc110 Nov 26, 2025
0.2.26rc109 Nov 25, 2025
0.2.26rc108 Nov 25, 2025
0.2.26rc107 Nov 25, 2025
0.2.26rc106 Nov 25, 2025
0.2.26rc105 Nov 25, 2025
0.2.26rc104 Nov 25, 2025
0.2.25 Nov 20, 2025
0.2.24 Nov 14, 2025
0.2.24rc103 Nov 13, 2025
0.2.24rc102 Nov 13, 2025
0.2.23 Nov 05, 2025
0.2.23rc101 Nov 05, 2025
0.2.22 Nov 04, 2025
0.2.22rc100 Nov 04, 2025
0.2.21 Oct 21, 2025
0.2.21rc99 Oct 21, 2025
0.2.20 Oct 10, 2025
0.2.19 Sep 27, 2025
0.2.18 Sep 17, 2025
0.2.18rc98 Sep 13, 2025
0.2.17 Sep 04, 2025
0.2.17rc97 Aug 28, 2025
0.2.17rc96 Aug 25, 2025
0.2.16 Aug 24, 2025
0.2.15 Aug 20, 2025
0.2.14 Aug 18, 2025
0.2.14rc95 Aug 24, 2025
0.2.14rc94 Aug 18, 2025
0.2.14rc93 Aug 18, 2025
0.2.14rc92 Aug 14, 2025
0.2.13 Aug 13, 2025
0.2.13rc91 Aug 13, 2025
0.2.12 Aug 06, 2025
0.2.11 Aug 04, 2025
0.2.11rc90 Aug 06, 2025
0.2.11rc89 Aug 06, 2025
0.2.11rc88 Aug 04, 2025
0.2.10 Aug 03, 2025
0.2.9 Jul 19, 2025
0.2.8 Jul 15, 2025
0.2.7 Jul 10, 2025
0.2.7rc87 Jul 24, 2025
0.2.7rc86 Jul 19, 2025
0.2.7rc85 Jul 16, 2025
0.2.7rc84 Jul 15, 2025
0.2.7rc83 Jul 15, 2025
0.2.7rc82 Jul 15, 2025
0.2.7rc81 Jul 10, 2025
0.2.7rc80 Jul 10, 2025
0.2.6 Jul 10, 2025
0.2.5 Jul 05, 2025
0.2.4 Jul 04, 2025
0.2.3 Jul 03, 2025
0.2.2 Jul 03, 2025
0.2.2rc79 Jul 02, 2025
0.2.1 Jun 27, 2025
0.2.1rc78 Jul 02, 2025
0.2.1rc77 Jun 27, 2025
0.2.1rc76 Jun 27, 2025
0.2.1rc75 Jun 27, 2025
0.2.1rc74 Jun 27, 2025
0.2.1rc73 Jun 27, 2025
0.2.1rc72 Jun 24, 2025
0.2.1rc71 Jun 24, 2025
0.2.0 Jun 24, 2025
0.2.0rc7 Jun 24, 2025
0.1.22rc70 Jun 17, 2025
0.1.21 Jun 03, 2025
0.1.21rc69 Jun 03, 2025
0.1.20 May 30, 2025
0.1.20rc68 May 30, 2025
0.1.20rc67 May 30, 2025
0.1.19 May 28, 2025
0.1.19rc66 May 28, 2025
0.1.18 May 24, 2025
0.1.18rc65 May 23, 2025
0.1.18rc64 May 23, 2025
0.1.18rc63 May 23, 2025
0.1.18rc62 May 23, 2025
0.1.18rc61 May 20, 2025
0.1.17 May 20, 2025
0.1.16 May 16, 2025
0.1.16rc60 May 16, 2025
0.1.15 May 16, 2025
0.1.14 May 16, 2025
0.1.14rc59 May 15, 2025
0.1.14rc58 May 14, 2025
0.1.14rc57 May 14, 2025
0.1.14rc56 May 14, 2025
0.1.14rc55 May 14, 2025
0.1.14rc54 May 12, 2025
0.1.14rc53 May 12, 2025
0.1.14rc52 May 11, 2025
0.1.14rc51 May 11, 2025
0.1.14rc50 May 11, 2025
0.1.14rc49 May 11, 2025
0.1.14rc48 May 10, 2025
0.1.14.dev4 May 14, 2025
0.1.14.dev3 May 14, 2025
0.1.14.dev1 May 14, 2025
0.1.13 May 10, 2025
0.1.12 May 10, 2025
0.1.12rc47 May 10, 2025
0.1.12rc46 May 10, 2025
0.1.12rc45 May 10, 2025
0.1.12.dev1 May 10, 2025
0.1.11 May 09, 2025
0.1.11rc44 May 09, 2025
0.1.10 May 09, 2025
0.1.10rc42 May 08, 2025
0.1.10rc41 May 08, 2025
0.1.10rc40 May 07, 2025
0.1.10rc39 May 06, 2025
0.1.10rc38 May 02, 2025
0.1.9 May 01, 2025
0.1.9rc37 May 01, 2025
0.1.9rc36 May 01, 2025
0.1.9rc35 Apr 24, 2025
0.1.9rc34 Apr 24, 2025
0.1.9rc33 Apr 24, 2025
0.1.9.dev2 May 11, 2025
0.1.9.dev1 May 11, 2025
0.1.8 Apr 21, 2025
0.1.8rc32 Apr 21, 2025
0.1.8.dev16 Apr 23, 2025
0.1.8.dev15 Apr 23, 2025
0.1.8.dev14 Apr 23, 2025
0.1.8.dev13 Apr 22, 2025
0.1.8.dev12 Apr 22, 2025
0.1.8.dev11 Apr 22, 2025
0.1.8.dev10 Apr 22, 2025
0.1.8.dev9 Apr 22, 2025
0.1.8.dev8 Apr 22, 2025
0.1.8.dev7 Apr 22, 2025
0.1.8.dev6 Apr 22, 2025
0.1.8.dev5 Apr 22, 2025
0.1.8.dev4 Apr 21, 2025
0.1.8.dev3 Apr 21, 2025
0.1.8.dev2 Apr 21, 2025
0.1.8.dev1 Apr 21, 2025
0.1.7 Apr 19, 2025
0.1.7rc31 Apr 19, 2025
0.1.7rc30 Apr 18, 2025
0.1.6 Apr 17, 2025
0.1.6rc29 Apr 17, 2025
0.1.6rc28 Apr 14, 2025
0.1.6rc27 Apr 14, 2025
0.1.5 Apr 14, 2025
0.1.4 Apr 13, 2025
0.1.3 Apr 07, 2025
0.1.3rc26 Apr 13, 2025
0.1.3rc25 Apr 10, 2025
0.1.3rc24 Apr 09, 2025
0.1.3rc23 Apr 08, 2025
0.1.3rc22 Apr 08, 2025
0.1.3rc21 Apr 07, 2025
0.1.2 Apr 06, 2025
0.1.2rc20 Apr 06, 2025
0.1.2rc19 Apr 06, 2025
0.1.2rc18 Apr 05, 2025
0.1.1 Apr 03, 2025
0.1.1rc17 Apr 03, 2025
0.1.1rc16 Apr 03, 2025
0.1.0 Apr 03, 2025
0.1.0rc123 Apr 18, 2025
0.1.0rc1.post0 Apr 21, 2025
0.0.74 Mar 24, 2025
0.0.74rc154 Mar 26, 2025
0.0.74rc153 Mar 25, 2025
0.0.73 Mar 21, 2025
0.0.73rc152 Mar 14, 2025
0.0.72 Mar 12, 2025
0.0.71 Mar 07, 2025
0.0.70 Mar 06, 2025
0.0.70rc151 Mar 05, 2025
0.0.70rc150 Mar 05, 2025
0.0.70rc149 Mar 05, 2025
0.0.70rc148 Mar 05, 2025
0.0.69 Feb 28, 2025
0.0.69rc147 Feb 26, 2025
0.0.69rc146 Feb 25, 2025
0.0.69rc145 Feb 25, 2025
0.0.69rc144 Feb 25, 2025
0.0.68 Feb 24, 2025
0.0.68rc143 Feb 24, 2025
0.0.67 Feb 24, 2025
0.0.67rc142 Feb 24, 2025
0.0.67rc141 Feb 24, 2025
0.0.67rc140 Feb 20, 2025
0.0.66 Feb 20, 2025
0.0.66rc139 Feb 20, 2025
0.0.65 Feb 20, 2025
0.0.64 Feb 18, 2025
0.0.64rc138 Feb 19, 2025
0.0.64rc137 Feb 19, 2025
0.0.64rc1 Feb 18, 2025
0.0.2rc15 Apr 03, 2025
0.0.2rc14 Apr 02, 2025
0.0.2rc13 Apr 02, 2025
0.0.2rc12 Apr 02, 2025
0.0.2rc11 Apr 02, 2025
0.0.2rc10 Apr 02, 2025
0.0.2rc9 Apr 02, 2025
0.0.2rc8 Apr 02, 2025
0.0.2rc7 Apr 02, 2025
0.0.2rc6 Apr 02, 2025
0.0.2rc5 Apr 01, 2025
0.0.2rc4 Apr 01, 2025
0.0.2rc3 Apr 01, 2025
0.0.2rc2 Mar 31, 2025
0.0.2rc1 Mar 31, 2025

Wheel compatibility matrix

Platform Python 3
any

Files in release

Extras:
Dependencies:
attrs (>=21.3.0)
dockerfile-parse (>=2.0.0)
httpx (>=0.27.0)
mcp (>=1.9.4)
pydantic (>=2.0.0)
pyjwt (>=2.0.0)
python-dateutil (>=2.8.0)
pyyaml (>=6.0.0)
requests (>=2.32.3)
tomli (>=2.0.2)
websockets (<16.0.0)