Behavior composition
Combine SoulFire tasks into workflows with Effect, Promises, or asyncio.
Behavior combinators build application workflows. They choose the next action while durable tasks manage movement, combat, inventory, and survival timing.
Build a workflow
This workflow gathers logs, retries a bounded build, and guarantees cleanup:
import {
cleanup,
collectBlocks,
retry,
sequence,
} from "@soulfiremc/sdk";
const prepareShelter = cleanup(
sequence(
collectBlocks({
blockIds: [],
tags: ["minecraft:logs"],
count: 16,
}),
retry(buildShelter, {
attempts: 3,
delayMs: 500,
backoff: 2,
}),
),
releaseTemporaryClaims,
);
const results = yield* prepareShelter.run(bot);sequence preserves result order and stops at the first failure. Prefer a
durable server task inside each behavior instead of a client-side loop of
atomic movement calls.
Choose a combinator
| Combinator | Use it when |
|---|---|
sequence | Every step must run in order |
parallel | Run independent work at the same time |
race | Return the first successful strategy |
repeat | Run a step a fixed number of times |
retry | Retry a temporary error |
timeout | Work needs a hard application deadline |
until | Repeat until a result satisfies a predicate |
conditional | Choose a branch from current state |
fallback | Try alternatives in order until one succeeds |
cleanup | A finalizer must run after success, failure, or cancellation |
scopedLease / scoped_lease | A workflow needs exclusive bot control |
Effect parallel uses fibers and accepts Effect concurrency. Promise
parallel accepts a numeric concurrency limit and propagates a linked
AbortSignal. Python parallel uses asyncio.TaskGroup, so sibling work is
cancelled when one child fails.
race means first successful result. A failed contender does not end the race
while another contender can still succeed. Losing Effect fibers, Promise
operations, and Python tasks are interrupted or cancelled.
Bound retries
Always give retries a finite attempt count. Delay and backoff are optional:
const resilient = retry(operation, {
attempts: 5,
delayMs: 250,
backoff: 2,
maximumDelayMs: 4_000,
});Parent cancellation stops a retry before the next attempt. A timeout also cancels the running operation. The Promise timeout can return before custom behavior responds to cancellation. Native SDK operations receive the linked signal.
Hold exclusive control
Use a scoped lease when a workflow must exclude other SDK controllers:
const exclusive = scopedLease(prepareShelter, 30);
const result = yield* exclusive.run(bot);Effect users can also acquire a lease directly with
bot.acquireControlScoped(). Promise users can use await using with the
returned control lease. Python leases implement async with. Each form
releases the lease when its scope exits.
Behavior composition is an orchestration layer. A workflow does not move time-sensitive game logic back into the client process. Native and plugin tasks still own their server-side lifecycle, resource arbitration, reconnect policy, progress, and typed result.
How is this page?
Last updated on
