Python SDK for automating SoulFire bots over gRPC-Web.
Project description
SoulFire Python SDK
Use soulfire to control bots through a SoulFire server from synchronous
or asyncio Python applications. The SDK always uses gRPC-Web.
Install
pip install soulfire
Connect and stream events
Create a client with an API token, then select an operator-provisioned instance and bot:
import asyncio
import os
from soulfire import SoulFire
async def main() -> None:
async with SoulFire.connect(
"https://soulfire.example.com",
token=os.environ["SOULFIRE_TOKEN"],
) as soulfire:
bot = soulfire.instance("instance-uuid").bot("bot-uuid")
await bot.start()
async for event in bot.events():
print(event)
asyncio.run(main())
The default event filter includes status, state, inventory, damage, chat, and lifecycle events. The stream stays open while the bot is stopped and follows the configured account across reconnects.
Control bots
Bot intent is persistent. Calling start() sets the bot's desired state to
running, while stop() sets it to stopped:
instance = soulfire.instance("instance-uuid")
bot = instance.bot("bot-uuid")
await bot.start()
await bot.restart()
await bot.stop()
Control a group by explicit ID or count:
await instance.start(count=25)
await instance.stop(bot_ids=["bot-uuid-1", "bot-uuid-2"])
await instance.restart()
With no selection, start() targets stopped bots, stop() targets desired
bots, and restart() targets desired bots. A count selection follows the
instance's account.shuffle-accounts setting. Explicit bot_ids always use
the IDs you provide.
Watch bot status
watch_bot_statuses() first yields a complete snapshot, then incremental
updates and removals:
async for event in instance.watch_bot_statuses():
event_type = event.WhichOneof("event")
if event_type == "snapshot":
print(event.snapshot.bots)
elif event_type == "update":
print(event.update.profile_id, event.update.runtime_state)
elif event_type == "removed_bot_id":
print("Removed", event.removed_bot_id)
Use await bot.status() when you only need the current state of one bot. The
synchronous client exposes the same methods without await.
Provision a local server
SoulFire.install() downloads and verifies the latest SoulFire dedicated
server and a Temurin 25 runtime, starts the server, and returns an authenticated
client:
import asyncio
from soulfire import SoulFire
async def main() -> None:
soulfire = await SoulFire.install(
directory=".soulfire",
on_log=print,
)
try:
print(soulfire.local_server.base_url)
bot = soulfire.instance("instance-uuid").bot("bot-uuid")
# Use the operator-provisioned bot.
finally:
await soulfire.close()
asyncio.run(main())
Pass version to pin a release tag. Existing verified downloads are reused.
Send a chat message
await bot.send_chat("Hello from the SoulFire SDK")
Action calls return after the bot game thread executes them. Failed or
cancelled actions raise SoulFireActionError, which includes the action ID and
server result.
Control inventory and movement
from soulfire.bot_pb2 import LEFT_CLICK
inventory = await bot.inventory()
print(inventory.slots)
await bot.select_hotbar(0)
await bot.click_inventory(12, LEFT_CLICK)
await bot.transfer_inventory_slot(12)
await bot.move_inventory_stack(12, 36)
await bot.set_movement(forward=True, sprint=True)
await bot.look(90, 0)
await bot.reset_movement()
The synchronous bot exposes the same methods without await.
Coordinate multiple controllers
lease = await bot.acquire_control(ttl_seconds=30)
try:
await bot.send_chat("This action carries the lease token")
await lease.renew(ttl_seconds=30)
finally:
await lease.release()
Control leases are optional. Acquiring one prevents other clients from issuing actions until the lease is released or expires.
Use composable behaviors
from soulfire import AttackNearest, CollectBlocks, run_behaviors
await run_behaviors(
bot,
[
CollectBlocks(["minecraft:oak_log"], max_count=16),
AttackNearest(["minecraft:zombie"]),
],
)
The package includes CollectBlocks, FollowEntity, AttackNearest,
AutoEat, and Build.
Provision instances and accounts
from soulfire.common_pb2 import MICROSOFT_JAVA_DEVICE_CODE
instance = await soulfire.create_instance("automation")
async for step in instance.login_device_code(MICROSOFT_JAVA_DEVICE_CODE):
if step.WhichOneof("data") == "device_code":
print(step.device_code.verification_uri, step.device_code.user_code)
elif step.WhichOneof("data") == "account":
await instance.add_accounts([step.account])
Instance listing, settings, account and proxy batches, credentials login, device-code login, and account refresh are available on async and synchronous clients.
Manage an installed server
print(soulfire.local_server.version)
print(soulfire.local_server_logs)
await soulfire.restart_local_server()
await soulfire.stop_local_server()
Restart keeps the same directory, port, release, and root API token.
Use the synchronous client
import os
from soulfire import SoulFireSync
with SoulFireSync.connect(
"https://soulfire.example.com",
token=os.environ["SOULFIRE_TOKEN"],
) as soulfire:
bot = soulfire.instance("instance-uuid").bot("bot-uuid")
bot.send_chat("Hello from Python")
Generated request messages and service clients are importable from the
soulfire package when an RPC does not have a high-level wrapper:
from soulfire.instance_connect import InstanceServiceClient
instances = soulfire.service(InstanceServiceClient)
Instances are not lifecycle units. They compartmentalize accounts, settings, proxies, permissions, scripts, and automation. Each bot can be controlled independently.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file soulfire-0.1.1.tar.gz.
File metadata
- Download URL: soulfire-0.1.1.tar.gz
- Upload date:
- Size: 154.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db13186afda3a9c55cee45dd6b95f2e18d827baeebbd2529448d037d4926d28c
|
|
| MD5 |
b076867f5ab272ee5decd3c55f4ec320
|
|
| BLAKE2b-256 |
165c239f1debc32fc3f1af6617ad06bdb054c055a8870c2eb7a9e4534c7f1d2b
|
Provenance
The following attestation bundles were made for soulfire-0.1.1.tar.gz:
Publisher:
publish-sdk.yml on soulfiremc-com/SoulFire
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
soulfire-0.1.1.tar.gz -
Subject digest:
db13186afda3a9c55cee45dd6b95f2e18d827baeebbd2529448d037d4926d28c - Sigstore transparency entry: 2256245570
- Sigstore integration time:
-
Permalink:
soulfiremc-com/SoulFire@54a90fda55b598825ef6d8ff4a84784e6b21dac5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/soulfiremc-com
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-sdk.yml@54a90fda55b598825ef6d8ff4a84784e6b21dac5 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file soulfire-0.1.1-py3-none-any.whl.
File metadata
- Download URL: soulfire-0.1.1-py3-none-any.whl
- Upload date:
- Size: 184.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c05eedf4108b76283ba0f0245f64f2288d988a8b17238c369a44991d2caa7ee2
|
|
| MD5 |
ee547b84736227b7df401da5c0c314f0
|
|
| BLAKE2b-256 |
c0e564efb063347b6a08215829d23dbbb9801dff624ad61849645c2f5e7d1544
|
Provenance
The following attestation bundles were made for soulfire-0.1.1-py3-none-any.whl:
Publisher:
publish-sdk.yml on soulfiremc-com/SoulFire
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
soulfire-0.1.1-py3-none-any.whl -
Subject digest:
c05eedf4108b76283ba0f0245f64f2288d988a8b17238c369a44991d2caa7ee2 - Sigstore transparency entry: 2256245591
- Sigstore integration time:
-
Permalink:
soulfiremc-com/SoulFire@54a90fda55b598825ef6d8ff4a84784e6b21dac5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/soulfiremc-com
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-sdk.yml@54a90fda55b598825ef6d8ff4a84784e6b21dac5 -
Trigger Event:
workflow_dispatch
-
Statement type: