blaxel

Blaxel - AI development platform SDK

260 个版本 Python <3.15,>=3.10
安装
pip install blaxel
poetry add blaxel
pipenv install blaxel
conda install blaxel
描述

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.

Base image contents: The default blaxel/base-image:latest is Alpine Linux with Node.js 22 and git pre-installed. It does not include Python or other language runtimes. To use Python, either specify blaxel/py-app:latest as your image (Python 3.12) or install it in the base image with apk add --no-cache python3 py3-pip.

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

Data collection

Error tracking

The SDK includes error tracking that captures exceptions originating from the SDK itself (not your application code). It collects data including the error type, message, stack trace, SDK version, workspace name, and so on. No user or application data is collected.

Error tracking is off by default since v0.2.46. To explicitly disable it in older versions:

export DO_NOT_TRACK=1

Or add to ~/.blaxel/config.yaml:

tracking: false

Where both settings exist, the DO_NOT_TRACK variable takes precedence.

Telemetry

Telemetry, delivered via OpenTelemetry, is controlled by the BL_ENABLE_OPENTELEMETRY environment variable.

When you deploy an agent to Blaxel, the platform automatically injects BL_ENABLE_OPENTELEMETRY=true into the environment.

When developing locally, this environment variable is not set and therefore defaults to false.

To explicitly disable telemetry, override the variable in your Blaxel deployment:

export BL_ENABLE_OPENTELEMETRY=false

For more information, refer to our documentation.

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