Parallel Work and Result Synthesis
Explore how to efficiently run multiple specialist agents concurrently, handle various outcome types including access failures and empty results, and merge these into a coherent final synthesis. This lesson teaches you to validate and reconcile parallel results using Python, ensuring robust multi-agent orchestration and production-ready reporting.
In the previous lesson, we designed the coordinator-specialist split and the handoff packet. This lesson covers the runtime: dispatching specialists simultaneously, handling the full range of outcomes (success, partial result, access failure, empty result), and building the synthesis step that turns multiple structured results into a single coherent output. By the end of this lesson, we will be able to:
Dispatch multiple specialists in parallel and collect all results before synthesis
Distinguish access failures from empty results and handle each correctly
Merge specialist results into a synthesis payload
Build a coordinator synthesis step that is complete only when all expected fields are accounted for
Dispatching specialists in parallel
When specialist subtasks are independent, the coordinator dispatches all of them before waiting for any results. This is the primary performance benefit of a multi-agent architecture: total wait time equals the slowest specialist, not the sum of all specialists. In Python, this pattern uses concurrent.futures:
from concurrent.futures import ThreadPoolExecutor, as_completeddef run_specialist(system: str, prompt: str) -> dict:response = client.messages.create(model="claude-opus-4-8",max_tokens=1024,system=system,messages=[{"role": "user", "content": prompt}])for block in response.content:if block.type == "text":return json.loads(block.text)return {"error": "no_text_block", "data_gaps": ["specialist returned no content"]}def dispatch_all_specialists(company: str, fiscal_year: int) -> dict:handoffs = {"financial": build_financial_handoff(company, fiscal_year),"legal": build_legal_handoff(company),"news": build_news_handoff(company, days=90),}results = {}with ThreadPoolExecutor(max_workers=3) as executor:futures = {executor.submit(run_specialist,SPECIALIST_SYSTEMS[name],packet_to_prompt(packet)): namefor name, packet in handoffs.items()}for future in as_completed(futures):name = futures[future]try:results[name] = future.result()except Exception as exc:results[name] = {"error": "specialist_exception","message": str(exc),"data_gaps": [f"All {name} data unavailable — specialist raised an exception"]}return results
Lines 3–13:
run_specialistruns one specialist. It calls the API with the specialist’s system prompt and handoff-packet prompt, parses ...