Skip to content

Blackboard Pattern

Agents communicate indirectly via a shared, asynchronous state store. Each agent reads specific keys and writes its outputs back — no direct messaging.

Best for: Financial intelligence, data enrichment pipelines, multi-expert analysis where outputs feed each other.
LLM calls: N agents × R rounds.


Sequence Diagram

sequenceDiagram
    participant BB as Blackboard
    participant A as Alpha Agent
    participant R as Risk Agent
    participant P as Portfolio Agent

    BB->>A: reads: [task]
    A->>BB: writes: alpha_signals
    BB->>R: reads: [task, alpha_signals]
    R->>BB: writes: risk_metrics
    BB->>P: reads: [alpha_signals, risk_metrics]
    P->>BB: writes: portfolio_weights

Use Case 1 — Financial Portfolio Construction (OpenAI)

Agents chain through the blackboard — each builds on the previous agent's committed state.

import asyncio
from pyagent_patterns.base import Agent
from pyagent_patterns.structural import Blackboard
from pyagent_patterns.structural.blackboard import BlackboardAgent
from pyagent_providers import OpenAILLM

pattern = Blackboard(
    agents=[
        BlackboardAgent(
            agent=Agent(
                "alpha_generator",
                OpenAILLM("gpt-4o"),
                system_prompt="Generate alpha signals for each asset in the watchlist. "
                              "For each asset: state direction (long/short/neutral), "
                              "conviction (high/medium/low), and 2-sentence rationale. "
                              "Format as structured data.",
            ),
            reads=["task"],
            writes=["alpha_signals"],
        ),
        BlackboardAgent(
            agent=Agent(
                "risk_manager",
                OpenAILLM("gpt-4o"),
                system_prompt="Given the alpha signals, assess portfolio-level risk: "
                              "calculate correlation exposure, sector concentration, "
                              "tail risk scenarios, and max position sizes. "
                              "Recommend position limits for each asset.",
            ),
            reads=["task", "alpha_signals"],
            writes=["risk_metrics"],
        ),
        BlackboardAgent(
            agent=Agent(
                "portfolio_optimizer",
                OpenAILLM("gpt-4o"),
                system_prompt="Given alpha signals AND risk constraints, "
                              "construct the optimal portfolio allocation. "
                              "Respect position limits. Maximise risk-adjusted return. "
                              "Output allocation as percentages summing to 100%.",
            ),
            reads=["alpha_signals", "risk_metrics"],
            writes=["portfolio_weights"],
        ),
        BlackboardAgent(
            agent=Agent(
                "order_generator",
                OpenAILLM("gpt-4o-mini"),
                system_prompt="Given the portfolio weights, "
                              "generate execution orders: asset, direction, size, "
                              "and suggested order type (market/limit). "
                              "Flag any large moves that need staged execution.",
            ),
            reads=["portfolio_weights", "risk_metrics"],
            writes=["trade_orders"],
        ),
    ],
    rounds=1,
)

result = asyncio.run(pattern.run(
    "Watchlist: NVDA, MSFT, AMZN, META, GOOGL. "
    "Portfolio size: $10M. Max single position: 25%. "
    "Optimise for risk-adjusted return over 3-month horizon."
))
print(result.output)
print("Final blackboard state:")
for key, value in result.metadata["final_state"].items():
    print(f"  [{key}]: {str(value)[:80]}...")
print(f"Cost: ${result.cost_estimate:.4f}")

Use Case 2 — Competitive Intelligence Pipeline (Anthropic + Gemini)

Each specialist enriches the shared knowledge base before the synthesiser runs.

from pyagent_providers import AnthropicLLM, GeminiLLM

intelligence = Blackboard(
    agents=[
        BlackboardAgent(
            agent=Agent(
                "product_analyst",
                GeminiLLM("gemini-2.5-flash"),
                system_prompt="Analyse the competitor's product: features, pricing, "
                              "UX, and technical capabilities. Extract structured data.",
            ),
            reads=["task"],
            writes=["product_analysis"],
        ),
        BlackboardAgent(
            agent=Agent(
                "market_analyst",
                GeminiLLM("gemini-2.5-flash"),
                system_prompt="Analyse market position: market share, customer segments, "
                              "GTM strategy, and partnerships.",
            ),
            reads=["task"],
            writes=["market_analysis"],
        ),
        BlackboardAgent(
            agent=Agent(
                "strategic_analyst",
                AnthropicLLM("claude-sonnet-4-20250514"),
                system_prompt="Given both product and market analyses, "
                              "identify competitive gaps we can exploit, "
                              "threats to our position, and strategic recommendations.",
            ),
            reads=["product_analysis", "market_analysis"],
            writes=["strategic_assessment"],
        ),
        BlackboardAgent(
            agent=Agent(
                "report_writer",
                AnthropicLLM("claude-sonnet-4-20250514"),
                system_prompt="Write an executive competitive intelligence report "
                              "from all available analyses. Include: "
                              "Executive Summary, Key Threats, Opportunities, Recommended Actions.",
            ),
            reads=["product_analysis", "market_analysis", "strategic_assessment"],
            writes=["final_report"],
        ),
    ],
    rounds=1,
)

result = asyncio.run(intelligence.run("Competitor analysis: Salesforce Einstein AI"))
print(result.metadata["final_state"]["final_report"])

OTel Trace Output

Trace: pyagent.pattern.blackboard (6.8s, $0.022)
├── Round 1
│   ├── pyagent.agent.alpha_generator (2.1s, gpt-4o)
│   │   └── writes: alpha_signals
│   ├── pyagent.agent.risk_manager (1.9s, gpt-4o) [reads: alpha_signals]
│   │   └── writes: risk_metrics
│   ├── pyagent.agent.portfolio_optimizer (1.6s, gpt-4o) [reads: alpha_signals, risk_metrics]
│   │   └── writes: portfolio_weights
│   └── pyagent.agent.order_generator (1.2s, gpt-4o-mini) [reads: portfolio_weights, risk_metrics]
│       └── writes: trade_orders
└── final_state: {alpha_signals: ..., risk_metrics: ..., portfolio_weights: ..., trade_orders: ...}

When to Use

Condition Recommendation
Agents need to share and build on each other's outputs ✅ Use Blackboard
Output dependencies are complex (A→C, B→C, both→D) ✅ Use Blackboard
A central coordinator routes all communication ❌ Use Orchestrator-Workers
Sequential stages with no shared state ❌ Use Pipeline
Agents communicate directly with neighbours ❌ Use Swarm

See Also

  • Orchestrator-Workers — central coordinator, not shared state
  • Swarm — peer-to-peer agent communication
  • Layered — layered processing without persistent shared state