Skip to content
Learn Agentic AI14 min read0 views

Blackboard Architecture for Multi-Agent Systems: Shared Knowledge Spaces

Learn the blackboard architectural pattern for multi-agent AI coordination. Build a shared knowledge space where specialized agents contribute partial solutions that converge into complete answers.

What Is the Blackboard Architecture?

The blackboard architecture is a problem-solving pattern where multiple specialist agents (called knowledge sources) collaborate by reading from and writing to a shared data structure — the blackboard. A control shell decides which agent should act next based on the current state of the blackboard.

Originally developed in the 1970s for speech recognition (the Hearsay-II system), this pattern maps perfectly to modern multi-agent AI systems. Instead of agents communicating directly with each other through messages, they communicate indirectly through the shared blackboard. This decouples agents from one another and makes it easy to add or remove specialists without changing the rest of the system.

Core Components

A blackboard system has three parts:

  1. The Blackboard — a structured shared memory holding the current problem state, partial solutions, and metadata
  2. Knowledge Sources — specialist agents that can read the blackboard and contribute updates when their expertise is relevant
  3. The Control Shell — an orchestrator that monitors the blackboard and activates the appropriate knowledge source at each step

Python Implementation

from dataclasses import dataclass, field
from typing import Any, Callable
from datetime import datetime
import json

@dataclass
class BlackboardEntry:
    key: str
    value: Any
    source: str
    confidence: float
    timestamp: str = field(
        default_factory=lambda: datetime.now().isoformat()
    )

class Blackboard:
    def __init__(self):
        self._state: dict[str, BlackboardEntry] = {}
        self._history: list[dict] = []

    def read(self, key: str) -> BlackboardEntry | None:
        return self._state.get(key)

    def write(self, key: str, value: Any, source: str, confidence: float):
        entry = BlackboardEntry(
            key=key, value=value, source=source, confidence=confidence
        )
        self._state[key] = entry
        self._history.append({
            "action": "write",
            "key": key,
            "source": source,
            "timestamp": entry.timestamp,
        })

    def read_all(self) -> dict[str, Any]:
        return {k: v.value for k, v in self._state.items()}

    def has_key(self, key: str) -> bool:
        return key in self._state

    def get_history(self) -> list[dict]:
        return list(self._history)

Knowledge Sources (Specialist Agents)

Each knowledge source declares what conditions must be true on the blackboard before it can contribute (its preconditions) and what it produces (its contributions).

@dataclass
class KnowledgeSource:
    name: str
    preconditions: Callable[[Blackboard], bool]
    action: Callable[[Blackboard], None]
    priority: int = 0

# Example: an entity extraction agent
def entity_extractor_precondition(bb: Blackboard) -> bool:
    return bb.has_key("raw_text") and not bb.has_key("entities")

def entity_extractor_action(bb: Blackboard):
    raw_text = bb.read("raw_text").value
    # In production, call an LLM or NER model here
    entities = {
        "people": ["Alice", "Bob"],
        "organizations": ["Acme Corp"],
        "dates": ["March 2026"],
    }
    bb.write("entities", entities, source="entity_extractor", confidence=0.88)

entity_ks = KnowledgeSource(
    name="entity_extractor",
    preconditions=entity_extractor_precondition,
    action=entity_extractor_action,
    priority=10,
)

# Example: a sentiment analysis agent
def sentiment_precondition(bb: Blackboard) -> bool:
    return bb.has_key("raw_text") and not bb.has_key("sentiment")

def sentiment_action(bb: Blackboard):
    raw_text = bb.read("raw_text").value
    bb.write("sentiment", {"label": "positive", "score": 0.82},
             source="sentiment_analyzer", confidence=0.82)

sentiment_ks = KnowledgeSource(
    name="sentiment_analyzer",
    preconditions=sentiment_precondition,
    action=sentiment_action,
    priority=5,
)

The Control Shell

The control shell is the orchestration loop. It inspects the blackboard, finds all knowledge sources whose preconditions are met, selects the highest-priority one, and runs it.

See AI Voice Agents Handle Real Calls

Book a free demo or calculate how much you can save with AI voice automation.

class ControlShell:
    def __init__(
        self,
        blackboard: Blackboard,
        knowledge_sources: list[KnowledgeSource],
        max_iterations: int = 50,
    ):
        self.bb = blackboard
        self.sources = knowledge_sources
        self.max_iterations = max_iterations

    def run(self) -> dict:
        for i in range(self.max_iterations):
            eligible = [
                ks for ks in self.sources
                if ks.preconditions(self.bb)
            ]
            if not eligible:
                return {
                    "status": "complete",
                    "iterations": i,
                    "result": self.bb.read_all(),
                }

            eligible.sort(key=lambda ks: ks.priority, reverse=True)
            selected = eligible[0]
            selected.action(self.bb)

        return {
            "status": "max_iterations_reached",
            "result": self.bb.read_all(),
        }

Running the Full Pipeline

# A summarizer that depends on both entities and sentiment
def summarizer_precondition(bb: Blackboard) -> bool:
    return (bb.has_key("entities") and bb.has_key("sentiment")
            and not bb.has_key("summary"))

def summarizer_action(bb: Blackboard):
    entities = bb.read("entities").value
    sentiment = bb.read("sentiment").value
    summary = (
        f"Document mentions {len(entities['people'])} people and "
        f"{len(entities['organizations'])} orgs. "
        f"Overall sentiment: {sentiment['label']}."
    )
    bb.write("summary", summary, source="summarizer", confidence=0.90)

bb = Blackboard()
bb.write("raw_text", "Alice from Acme Corp reported great Q1 results.",
         source="user_input", confidence=1.0)

shell = ControlShell(bb, [entity_ks, sentiment_ks,
    KnowledgeSource("summarizer", summarizer_precondition,
                    summarizer_action, priority=1)])
result = shell.run()
print(result["result"]["summary"])

The blackboard pattern shines when the order of agent execution depends on what is already known. Agents self-select based on preconditions, making the system naturally adaptive.

FAQ

How is the blackboard pattern different from a simple shared database?

A shared database stores data but has no control logic. The blackboard architecture includes the control shell that selects which agent to run based on the current state. This makes the execution order dynamic and data-driven rather than hardcoded. Agents do not need to know about each other — they only know about the blackboard.

Can multiple knowledge sources run in parallel?

Yes. If two knowledge sources have met preconditions and operate on different keys, they can run concurrently. Add a locking mechanism to the blackboard (per-key locks or optimistic concurrency) to prevent write conflicts, then run eligible sources with non-overlapping outputs in parallel.

When should I choose blackboard over direct agent-to-agent messaging?

Choose blackboard when you have many specialists with complex dependencies between their outputs and when the problem-solving order is not known in advance. Direct messaging works better for linear pipelines or when agents have simple handoff relationships. If your agent graph looks more like a web than a chain, the blackboard pattern usually produces cleaner code.


#BlackboardArchitecture #MultiAgentSystems #KnowledgeSharing #DesignPatterns #Python #AgenticAI #LearnAI #AIEngineering

Share this article
C

CallSphere Team

Expert insights on AI voice agents and customer communication automation.

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.