SoulFire LogoSoulFire
AutomationSDKGuidesWorkflows

Behavior composition

Combine SoulFire tasks into scoped TypeScript and Python Effect workflows.

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

Both SDKs run parallel behaviors in scoped fibers with bounded concurrency. A failure interrupts sibling work and waits for cleanup.

race means first successful result. A failed contender does not end the race while another contender can still succeed. The runtime interrupts losing fibers and waits for their cleanup.

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,
});

Interruption stops retries and cancels the active operation. Retry and fallback handle typed failures. Defects and interruption pass through. Use while in TypeScript or while_ in Python to restrict retries.

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);

Use bot.acquireControlScoped() in TypeScript or bot.acquire_control() in Python for a direct scoped lease. The scope releases the lease after success, failure, or interruption. Behavior callbacks and finalizers return effects.

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