Skip to content

Blackboard planner

make_blackboard_planner returns an agent whose state is a flat to-do list (set_plan / get_plan / mark_done tools). Simpler than a DAG for exploratory work where the structure isn't known up front and the LLM iterates on a checklist.

Canonical name: make_blackboard_planner is a backward-compat alias for blackboard_orchestrator_agent (in lazybridge.ext.planners). New code can use either; both resolve to the same factory.

Source

"""Demo: ``lazybridge.ext.planners.make_blackboard_planner`` with three sub-agents.

The factory itself lives in :mod:`lazybridge.ext.planners.blackboard` — this
file just shows a minimal usage pattern. The blackboard planner manages
a flat to-do list (``set_plan`` / ``get_plan`` / ``mark_done``) instead
of composing a DAG; less precise but easier to prompt for exploratory work.
"""

from lazybridge import Agent, LLMEngine
from lazybridge.ext.planners import make_blackboard_planner


def web_search(query: str) -> str:
    """Look up current facts (stub — wire to a real search API)."""
    return f"[stub web result for {query!r}]"


def add(a: float, b: float) -> float:
    """Add two numbers."""
    return a + b


def main() -> None:
    research = Agent(
        engine=LLMEngine("gemini-3-flash-preview", system="Look up facts via web_search."),
        tools=[web_search],
        name="research",
        description="Web lookups. No math.",
    )
    math = Agent(
        engine=LLMEngine("gemini-3-flash-preview", system="Solve arithmetic with add."),
        tools=[add],
        name="math",
        description="Arithmetic only.",
    )
    writer = Agent(
        engine=LLMEngine("gemini-3-flash-preview", system="Synthesise prior results into prose."),
        name="writer",
        description="Turns prior results into a short paragraph.",
    )

    planner = make_blackboard_planner([research, math, writer], verbose=True)

    queries = [
        "What does FAANG stand for?",
        "What is 17 * 23 + 5?",
        "Research recent agent frameworks and write a one-paragraph summary.",
    ]
    for q in queries:
        print(f"\n>>> {q}")
        print(planner(q).text())


if __name__ == "__main__":
    main()

Walkthrough

  • make_blackboard_planner() wires up an Agent with three tools (set_plan, get_plan, mark_done) and a Store-backed scratch space. The LLM treats the to-do list as state it can read and update.
  • No DAG validation — the LLM is free to revise the plan, reorder tasks, or insert new ones at any point. This is what makes it "exploratory" relative to the typed PlanSpec pattern in Agent builds a plan.
  • Pair with Memory to give the planner a running record of what's been tried, why a previous attempt failed, what the current state of the world looks like — useful for tasks that span many iterations.

Variations

  • Persist the blackboard via Store(db="planner.sqlite") so a long-running task can be paused and resumed. The to-do list survives across runs.
  • Add a verify=judge to gate mark_done — useful when the planner tends to over-claim completion.
  • Wrap as a sub-agent (tools=[planner]) of a higher-level orchestrator that dispatches between blackboard planning and other strategies.

See also

  • Plan tool — sibling factory; structured decision tree instead of a flat list.
  • Agent builds a plan — typed PlanSpec alternative when the structure IS known.
  • Store — backs the blackboard state.