You can develop agents in Python using any framework (LangChain, LlamaIndex, CrewAI, OpenAI Agents, PydanticAI, Google ADK or any custom framework) and deploy them on Blaxel by integrating a few lines of the Blaxel SDK and leveraging our other developer tools (Blaxel CLI, GitHub action, etc.).

Check out this Getting Started tutorial in order to develop and deploy your first Hello World AI agent globally in less than 5 minutes.

Quickstart

It is required to have uv installed to use the following command.

You can quickly initialize a new project from scratch by using CLI command bl create-agent-app. This will create a pre-scaffolded local repo where your entire code can be added. You can choose the base agentic framework for the template.

In the generated folder, you’ll find a standard server in the entrypoint file main.py. While you typically won’t need to modify this file, you can add specific logic there if needed. Your main work will focus on the agent.py file. Blaxel’s development paradigm lets you leverage its hosting capabilities without modifying your agent’s core logic.

Connect to a model API

Blaxel SDK provides a helper to connect to a model API defined on Blaxel from your code. This allows you to avoid managing a connection with the model API by yourself. Credentials remain stored securely on Blaxel.

from blaxel.models import bl_model

model = await bl_model("Model-name-on-Blaxel").to_...();

Convert the retrieved model to the format of the framework you want to use with the .to_...() function.

Available frameworks :

For example, to connect to model my-model in a LlamaIndex agent:

from blaxel.models import bl_model

model = await bl_model("my-model").to_llamaindex()

Connect to tools

Blaxel SDK provides a helper to connect to pre-built or custom tool servers (MCP servers) hosted on Blaxel from your code. This allows you to avoid managing a connection with the server by yourself. Credentials remain stored securely on Blaxel. The following function retrieves all the tools discoverable in the tool server.

from blaxel.tools import bl_tools

await bl_tools(['Tool-Server-name-on-Blaxel']).to_...()

Like for a model, convert the retrieved tools to the format of the framework you want to use with the .to_...() function. Available frameworks are to_langchain() (LangChain), to_llamaindex() (LlamaIndex), to_crewai() (CrewAI), to_openai() (OpenAI Agents), to_pydantic() (PydanticAI Agents) and to_google_adk() (Google ADK).

You can develop agents by mixing tools defined locally in your agents, and tools defined as remote servers. Using separated tools prevents monolithic designs which make maintenance easier in the long run. Let’s look at a practical example combining remote and local tools. The code below uses two tools:

  1. blaxel-search: A remote tool server on Blaxel providing web search functionality (learn how to create your own MCP servers here)
  2. weather: A local tool that accepts a city parameter and returns a mock weather response (always “sunny”)

from typing import AsyncGenerator

from blaxel.models import bl_model
from blaxel.tools import bl_tools
from langchain.tools import tool
from langchain_core.messages import AIMessageChunk
from langgraph.prebuilt import create_react_agent

@tool
def weather(city: str) -> str:
    """Get the weather in a given city"""
    return f"The weather in {city} is sunny"

async def agent(input: str) -> AsyncGenerator[str, None]:
    prompt = "You are a helpful assistant that can answer questions and help with tasks."
    tools = await bl_tools(["blaxel-search"]).to_langchain() + [weather]
    model = await bl_model("gpt-4o-mini").to_langchain()
    agent = create_react_agent(model=model, tools=tools, prompt=prompt)
    messages = {"messages": [("user", input)]}
    async for chunk in agent.astream(messages, stream_mode=["updates", "messages"]):
        type_, stream_chunk = chunk
        # This is to stream the response from the agent, filtering response from tools
        if type_ == "messages" and len(stream_chunk) > 0 and isinstance(stream_chunk[0], AIMessageChunk):
            msg = stream_chunk[0]
            if msg.content:
                if not msg.tool_calls:
                   yield msg.content
        # This to show a call has been made to a tool, usefull if you want to show the tool call in your interface
        if type_ == "updates":
            if "tools" in stream_chunk:
                for msg in stream_chunk["tools"]["messages"]:
                    yield f"Tool call: {msg.name}\n"

Connect to another agent (multi-agent chaining)

Rather than using a “quick and dirty” approach where you would combine all your agents and capabilities into a single deployment, Blaxel provides a structured development paradigm based on two key principles:

  • Agents can grow significantly in complexity. Monolithic architectures make long-term maintenance difficult.
  • Individual agents should be reusable across multiple projects.

Blaxel supports a microservice architecture for agent chaining, allowing you to call one agent from another using bl_agent().run() rather than combining all functionality into a single codebase.

from blaxel.agents import bl_agent

first_agent_response = await bl_agent("first_agent").run(input);
second_agent_response = await bl_agent("second_agent").run(first_agent_response);

Instrumentation

Instrumentation happens automatically when workloads run on Blaxel. To enable telemetry, simply require the SDK at your project’s root level.

import blaxel

When agents and tools are deployed on Blaxel, request logging and tracing happens automatically.

To add your own custom logs that you can view in the Blaxel Console, use the Python default logger.

import logging

logger = getLogger(__name__)
logger.info("Hello, world!");

Blaxel agent template file structure

Overview

pyproject.toml          # Mandatory. This file is the standard pyproject.toml file, it defines dependencies.
blaxel.toml             # This file lists configurations dedicated to Blaxel to customize the deployment. It is not mandatory.
.blaxel                 # This folder allows you to define custom resources using the Blaxel API specifications. These resources will be deployed along with your agent.
├── blaxel-search.yaml  # Here, blaxel-search is a sandbox Web search tool we provide so you can develop your first agent. It has a low rate limit, so we recommend you use a dedicated MCP server for production.
src/
└── main.py             # This file is the standard entrypoint of the project. It is used to start the server and create an endpoint bound with agent.py file.
├── agent.py            # This file is the main file of your agent. It is loaded from main.py. In the template, all the agent logic is implemented here.

blaxel.toml

This file is used to configure the deployment of the agent on Blaxel. It’s not mandatory, but it allows you to customize the deployment.

name = "my-agent"
workspace = "my-workspace"
type = "agent"

agents = []
functions = ["blaxel-search"]
models = ["gpt-4o-mini"]

[entrypoint]
prod = "python src/main.py"
dev = "fastapi dev"

[env]
DEFAULT_CITY = "San Francisco"

The name, workspace, and type fields are optional and serve as default values. Any bl command run in the folder will use these defaults rather than prompting you for input.

The agents, functions, and models fields are also optional. They specify which resources to deploy with the agent. These resources are preloaded during build, eliminating runtime dependencies on the Blaxel control plane and dramatically improving performance.

The entrypoint section defines how we are going to start your server:

  • prod: this is the command that will be used to serve your agent
python src/main.py
  • dev: same as prod in dev mode, it will be used with the command hotreload. Example:
fastapi dev

entrypoint section is not required, if not set we will use an auto-detect of your agent content

The env section defines environment variables that the agent can access via the SDK. Note that these are NOT secrets.

Deploy an agent

Learn how to deploy your custom AI agents on Blaxel as a serverless endpoint.