Blackboard
Shared typed scratchpad for multi-agent coordination.
A blackboard gives multiple agents a shared, typed state object. One agent writes findings, another reads them, all validated per-field with Zod so each write is checked without requiring the full board.
const board = blackboard({
id: "research-board",
schema: z.object({
query: z.string(),
findings: z.array(z.string()),
status: z.enum(["planning", "researching", "done"]),
}),
records: sharedRecords,
});
// Write individual fields (validated per-field)
await board.set("status", "researching");
await board.patch({ findings: ["Finding 1"], status: "researching" });
// Read
const status = await board.get("status"); // 'researching'
const all = await board.getAll(); // full board state
// Subscribe to changes (in-process)
const unsubscribe = board.subscribe((fields) => {
console.log("Changed:", fields); // ['findings', 'status']
});Board writes are in-process only. For cross-process coordination (e.g.,
separate serverless invocations), provide persistent records, see
Memory for storage options.
Prompt and tool integration
Use the board directly in a prompt when the agent should both see shared state and be able to update it:
const agentPrompt = prompt({
use: [board],
});Crux expands that into blackboard context plus four focused tools:
readBlackboard;
writeBlackboard;
patchBlackboard;
clearBlackboard;If you only want the current board state in the system message, use
board.asContext(). If you only want to manually choose tools, use
board.asTools():
prompt({ use: [board.asContext()] }); // context only
const tools = board.asTools();When multiple blackboards are used by the same prompt, prefix their tools:
const research = blackboard({
id: "research",
schema,
tools: { prefix: "research" },
});
const writing = blackboard({
id: "writing",
schema,
tools: { prefix: "writing" },
});
prompt({ use: [research, writing] });
// readResearchBlackboard, writeResearchBlackboard, readWritingBlackboard, ...