Skip to main content

Configuration

The pages for Task board and Binding skills teach the shape. The tables below list each field: name, type, default, what it does.

Flow, runtime, and environment knobs that are not orchestration-specific live next to those concepts in Core. The Configuration map is the index.

import { taskBoard } from "@flow-state-dev/orchestration/task-board";

const board = taskBoard({
name: "research",
workers: researcher,
concurrency: 4,
dispatcher: "topological",
onIdle: "complete-or-blocked",
initialTasks: [{ id: "brief", goal: "Write the research brief" }],
});

taskBoard options​

taskBoard(config) returns a handle. Mount board.drain as a sequencer step. The capability on board.capability is what sibling blocks put in uses to add or list tasks.

FieldTypeDefaultWhat it does
namestringrequiredOuter sequencer name and prefix for internal blocks. Unique inside a flow if you mount more than one board.
boardIdstringomittedStable id. Required when any seat holds a task dispatcher. Renaming orphans live work keyed on the old value.
dispatchdispatch objectomitted (inline)Dispatch mode for a uniform worker (a single block). Do not set this on a registry board; declare it per worker instead.
collectionrequest spec, sequencer spec, defineTaskCollection, or factoryrequest-backed, collectionId = nameWhere the task list lives. Omit it for the request default.
workersone block, or a name → worker maprequiredA single worker runs every claimed task. A registry routes by task.assignee.
defaultWorkerblock or task dispatcheromittedRegistry fallback for an unknown or missing assignee. A task dispatcher here hands each of those tasks off under the assignee it names, its flowKind may be a function of the task, and a task with no assignee fails. Omit it and a miss fails the task per onError.
concurrencynumber4How many workers run in parallel.
maxEnqueuedTasksnumber | null100Cap on tasks added while others are still pending. null is unbounded. Only when the board builds its own collection.
maxTotalTasksnumber | null500Cap including completed and failed tasks. Those still count after they finish. Same supplied-collection rule as maxEnqueuedTasks.
maxTotalRetriesnumber | null50Cumulative failure retries across every task. 0 means run once, never retry. unblock / unpark / reclaim do not spend this.
dispatcher"fifo" | "topological" | "priority" | instance"topological"How a ready task is picked.
onIdle"complete-or-blocked" | "complete" | "wait""complete-or-blocked"When the pool stops. See Task board.
onReview"hold" | "exit""hold"Whether a task parked with awaitReview keeps the drain open. "exit" lets the drain return and leaves the task parked; board.unparkAndDrain hands the answer back and drains in the same request. Needs a defineTaskCollection collection, the default onIdle, and ids on initialTasks. See Task board.
initialTasksTaskInit[]omittedTasks seeded at board start.
onError"skip" | "fail""skip""skip" records the failure and lets siblings continue. "fail" fails the board.
maxIterationsnumber10000Per-worker loop cap. A circuit breaker if enqueue cycles never drain.
shouldExit(collection) => booleanomittedExtra stop rule for onIdle: "wait". Ignored in the other modes.
idlePollMsnumber50Sleep when a claim returns nothing.
toolCacheboolean | objecton when any worker tool is cacheablePer-run tool-result memoization. false turns it off.
flowPolicyTaskFlowPolicydeclaredDepsOnly()Which prior-task observations a worker sees. See Flow policy.

maxEnqueuedTasks, maxTotalTasks, and maxTotalRetries apply only when the board constructs the collection (the request or sequencer forms). Passing any of them next to a supplied defineTaskCollection or factory is a construction error: that collection already has its own caps.

toolCache object​

FieldTypeDefaultWhat it does
enabledbooleantrue when any tool is cacheableMaster switch.
defaultTtlnumberomittedTTL in ms for cacheable tools that do not set their own.
maxEntriesnumber5000LRU eviction ceiling.
defaultScope"run" | "request" | "session""run"Scope for tools that do not set their own. "run" lasts for one board run.

Narrative for termination, dispatchers, registries, and backing: Task board.

goalSeekLoop options​

goalSeekLoop is a drain-then-judge loop over a board. planAndExecute and parallelTasks are built on it. The board must be request- or resource-backed.

FieldTypeDefaultWhat it does
namestringrequiredOuter sequencer name and prefix for internal blocks.
inputSchemaZod schemaz.unknown()Public input of the outer sequencer.
activeStatusMessagestringomittedStatus text emitted before the loop runs.
boardTaskBoardHandlerequiredThe board this loop drains. Request- or resource-backed only.
stateSchemaZod schemaomittedExtra fields merged into loop state. They do not collide with the loop's own keys.
seedblock or sequenceromittedWrites the first tasks onto the board before the first drain. Optional when initialTasks already seeded the board.
afterDrainblockomittedRuns after each drain, before the judge.
judgeblock, sequencer, or functionrequiredReturns a verdict: done, continue, or replan.
replannerblockomittedRuns on a replan verdict that did not include an inline tasks array.
maxAttemptsPerTasknumberomittedDefault attempts for tasks the replanner adds.
taskContextcontext supplyomittedContext attached to replanned tasks.
maxIterationsnumberrequiredHard backstop: total drains. Must be a finite integer greater than 0.
finalizeblock or sequenceromittedSynthesizes the settled board. Omit to return the board projection as-is.
onError"skip" | "fail""skip"Judge (and replanner) errors only. "skip" records { done, "judge-error" }. "fail" fails the request. A seed or drain failure always fails the request.

Narrative: GoalSeekLoop.

createSkillsLibrary options​

createSkillsLibrary(options) builds the shared catalog. Bind it per generator with skills.with({ ... }).

FieldTypeDefaultWhat it does
collectionstring"skills"Resource key for the skills collection.
catalogtool mapomittedThe tools a bound generator can call, and the set a skill's allowed-tools is validated against. Which bindings contribute it, and what registerCatalogTools: false leaves you to do yourself: What tools the generator gets.
registerCatalogToolsbooleantrueWhether a binding contributes catalog to the generator. false validates a skill's allowed-tools against the catalog without granting any of it, leaving registration to you. See What tools the generator gets.
initialSkillsbundled skillsomittedSeeded the first time a generator binds this library. Required if you bind skills by name.
scope"org" | "user" | "session""org"Where the skills collection lives. "org" shares seeded skills across users.
collectionConfig{ maxInstances?, prefix? }omittedCollection sizing and mount prefix.
itemVisibilityvisibility or listomittedRestrict bindings to blocks with a matching visibility.
workerModelIdstringneutral defaultModel for delegation agents that omit model.
maxTotalTasksnumber | null500Lifetime task ceiling on the delegation board. null is unbounded.
maxEnqueuedTasksnumber | null100How many tasks a coordinator may add while others are still pending.
agentRegistryAgentRegistryomittedYour own agent catalog, resolving agent-ref entries by name. A statically-active skill with agent-ref and no registry fails at build time.
materializeAgentfunctionomittedYour own function turning a resolved agent into a board worker. Required alongside agentRegistry; neither works without the other. See Borrowing an agent from a registry.
capabilityCatalogname → capabilityomittedForwarded to materializeAgent.
toolSeatFence(ctx) => string[] | undefinedomittedA ceiling on which catalog keys a delegated board worker may be seated with. It only ever narrows; [] means no catalog seats. Called each time the delegation surface resolves, so keep it cheap and free of side effects. Reach for it when the generator's own tools are fenced and it runs skills you didn't author, so a skill's agents can't be seated with tools the generator itself can't call.

skills.with options​

Per-generator binding. Two generators, two different active sets, and neither sees the other's skill.

FieldTypeDefaultWhat it does
activestring[]omittedSkills preloaded from the start. Unknown names fail at build time.
allowedstring[]omittedSkills the load tool may pull; omitted, it may pull any skill in the library. Also the skills an activeState field may render with tools: an activeState binding with neither allowed nor dynamicActivation gets no catalog tools at all. When the catalog is contributed it is the whole catalog, not these skills' allowed-tools. See What tools the generator gets.
activeState{ scope, field }this generator's block stateWhere dynamic activations live. Set a named scope to share across generators or persist across turns.
delegationbooleanon iff a bound skill declares agents:false suppresses the board + taskTools + runBoard surface. true installs it even with an empty roster.
guidancebooleanon when delegation installsDelegation playbook + live agent roster in context. false turns that context off.

dynamicActivation and catalogContext are presets on the same .with({ ... }) call, not fields on this table. dynamicActivation installs the loadSkill tool. catalogContext is on by default and puts the loadable skills' names and descriptions into the prompt beside it; set catalogContext: false to take that listing out and let the agent find skills through discovery instead. Both belong in the same call — preset overrides replace rather than merge, so chaining .presets() and .with() drops whichever came first. See Binding skills.

Narrative for authoring a skill and the delegation surface: Authoring, Delegation.