Blackboard (shared state)
Pattern: multiple agents coordinate through a shared data structure. A parent creates shared state, spawns workers that connect to it, and workers read/write shared collections via auto-generated CRUD tools.
Source: examples/durable-agents-playground/src/blackboard/
Debate example
The canonical blackboard example: a moderator runs a structured debate between pro and con workers via shared state.
Schema
ts
const debateSchema = {
arguments: {
schema: z.object({
key: z.string(),
side: z.enum(["pro", "con"]),
text: z.string(),
round: z.number(),
}),
type: "shared:argument",
primaryKey: "key",
},
}Registration
ts
import { db } from "@durable-streams/darix-runtime"
export function registerDebate(registry: EntityRegistry) {
registry.define(`debate`, {
description: `Debate moderator that creates shared state, spawns pro and con workers, and writes a final ruling based on arguments written to shared state`,
state: {
status: { primaryKey: `key` },
},
async handler(ctx) {
if (ctx.firstWake) {
ctx.db.actions.status_insert({ row: { key: `current`, value: `idle` } })
ctx.mkdb(`debate-${ctx.entityUrl}`, debateSchema)
}
const shared = await ctx.observe(
db(`debate-${ctx.entityUrl}`, debateSchema)
)
// ... create tools that reference `shared` ...
ctx.useAgent({
systemPrompt: DEBATE_SYSTEM_PROMPT,
model: `claude-sonnet-4-5-20250929`,
tools: [...ctx.darixTools, startTool, checkTool, endTool],
})
await ctx.agent.run()
},
})
}How it works
- On first wake, the moderator creates shared state with
ctx.mkdb(). - The moderator connects to the shared state with
ctx.observe(db(...)). - The
start_debatetool spawns pro and con workers, each connected to the same shared state:
ts
const proWorker = await ctx.spawn(
`worker`,
`debate-pro-${Date.now()}-${spawnCounter}`,
{
systemPrompt: PRO_WORKER_PROMPT,
sharedDb: { id: `debate-${ctx.entityUrl}`, schema: debateSchema },
},
{ initialMessage: proInitialMessage, wake: `runFinished` }
)- Workers write arguments to the shared
argumentscollection using auto-generatedwrite_argumentstools (see Worker). - The
check_debatetool reads the shared state to see current arguments:
ts
const args = state.shared.arguments.toArray- The
end_debatetool reads all arguments and transitions todone.
State transitions
ts
type DebateStatus = "idle" | "debating" | "ruling" | "done"Other blackboard examples
The playground includes several other blackboard implementations:
- Wiki (
blackboard/wiki.ts) -- 7 specialist workers collaboratively build a knowledge base. Each writes articles to a sharedarticlescollection. - Peer Review (
blackboard/peer-review.ts) -- workers submit reviews with scores and feedback to a sharedreviewscollection. A coordinator summarizes the reviews. - Trading Floor (
blackboard/trading-floor.ts) -- trader agents submit buy/sell orders to a sharedorderscollection. Transitions through morning/afternoon sessions.
All follow the same structure: parent creates shared state, spawns workers with sharedDb in their args, workers use generated CRUD tools to coordinate.