Python SDK
Connect to SoulFire from asynchronous or synchronous Python 3.14 programs.
The Python SDK requires CPython 3.14 or newer.
Use AsyncSoulFire for asynchronous services.
Use the synchronous SoulFire client for scripts, notebooks, and command-line tools.
Install
python -m pip install soulfireConnect and send chat
import os
from soulfire import AsyncSoulFire
async with AsyncSoulFire.connect(
"https://soulfire.example.com",
token=os.environ["SOULFIRE_TOKEN"],
) as soulfire:
bot = soulfire.instance("instance-uuid").bot("bot-uuid")
await bot.start()
await bot.chat.send("Hello from SoulFire")The connection handshake rejects an incompatible server or missing required plugin before application work begins.
Use structured concurrency
Python 3.14 TaskGroup gives fleet operations one cancellation and failure
boundary:
async with asyncio.TaskGroup() as group:
for bot_id in bot_ids:
bot = soulfire.instance(instance_id).bot(bot_id)
group.create_task(bot.chat.send("Ready"))Use asyncio.timeout() when a workflow needs one scoped deadline.
Concurrent failures remain available through ExceptionGroup.
Stream events
async for event in bot.events():
print(event.WhichOneof("event"))The stream stays associated with the configured bot across Minecraft reconnects.
Observe synchronized state
Open a session
session = await bot.observe()Read state and consume changes
async with session:
print(session.state.player)
async for event in session.events():
print(event)The session merges snapshots and deltas, resumes streams when possible, and requests a new snapshot when continuity is lost.
Interact with blocks and beds
Use interact_block for doors, buttons, beds, redstone controls, and modded
interactive blocks:
await bot.interact_block(
button_position,
BLOCK_FACE_NORTH,
)
await bot.sleep(bed_position)
await bot.wake()SoulFire checks that the target block is loaded and reachable. sleep waits
for the server-confirmed sleeping state, so an occupied bed or an invalid
sleep attempt fails instead of appearing successful.
Run durable tasks
task = await bot.tasks.auto_eat(
["minecraft:bread", "minecraft:cooked_beef"],
food_level=14,
maximum_meals=1,
)
result = await task.result()
print(result.meals_eaten)The same operation is synchronous through bot.tasks.auto_eat(...) and
task.result(). See durable tasks for ownership,
cancellation, and progress.
Craft and smelt
Production operations live beside recipe discovery:
from soulfire.inventory_pb2 import ItemSelector
recipes = await bot.recipes.list(result_item_id="minecraft:iron_ingot")
task = await bot.recipes.smelt(
ItemSelector(item_ids=["minecraft:raw_iron"]),
count=8,
fuel=ItemSelector(tags=["minecraft:coals"]),
station=furnace_position,
)
result = await task.result()Use bot.recipes.craft(recipe_id, ...) for a recipe returned by list.
Inventory-sized recipes need no station. The synchronous client exposes the
same methods without await.
Use generated protocol clients
Generated protobuf messages and ConnectRPC clients remain available as an advanced escape hatch:
from soulfire.instance_connect import InstanceServiceClient
instances = soulfire.service(InstanceServiceClient)Generated clients expose the wire contract directly. Prefer the high-level object model when it covers the operation.
Continue with durable tasks or plugin-defined APIs.
How is this page?
Last updated on
