SoulFire LogoSoulFire
SDK

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

CombinatorUse it when
sequenceEvery step must run in order
parallelRun independent work at the same time
raceReturn the first successful strategy
repeatRun a step a fixed number of times
retryRetry a temporary error
timeoutWork needs a hard application deadline
untilRepeat until a result satisfies a predicate
conditionalChoose a branch from current state
fallbackTry alternatives in order until one succeeds
cleanupA finalizer must run after success, failure, or cancellation
scopedLease / scoped_leaseA 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

On this page