Tone Dark
Tint
07 Parallel collaboration · many lenses, one product

Different perspectives. Same thing being built.

One of the most useful setups in production: agents that all look at the same thing at the same time, each one bringing a different perspective. It's not a pipeline (there's no fixed order). It's not a swarm (there's no chaos). It's "fan out, then merge": send the work to several agents at once, then combine their answers.

The product-build pattern

Picture five agents looking at a new feature proposal at the same time, each in its own thread, each producing its own structured response. None of them wait on the others. A coordinator agent then merges their outputs into one final document.

Five POVs build the same feature spec, in parallel
Click "run parallel build" to watch each agent contribute. Each starts at the same time; finish times differ by depth of work.
SHARED ARTIFACT feature_spec.json FRONTEND UX · A11Y BACKEND API · DATA SECURITY THREAT · AUTHZ DEVOPS DEPLOY · OBS PRODUCT SCOPE · METRICS MERGE
Feature: "two-factor authentication via authenticator apps"
live build · 5 agents working in parallel

Why parallel-with-merge beats sequential

Implementing parallel collaboration in Python

import asyncio
from pydantic import BaseModel
from typing import Literal

# ─── Each POV agent emits a TYPED contribution ───
class FrontendView(BaseModel):
    ux_flow: list[str]
    accessibility_notes: list[str]
    components_needed: list[str]

class BackendView(BaseModel):
    api_endpoints: list[dict]
    data_model_changes: list[str]
    migration_strategy: str

class SecurityView(BaseModel):
    threat_model: list[dict]    # [{threat, severity, mitigation}]
    authz_rules: list[str]
    data_classification: Literal["public", "internal", "sensitive"]

class DevOpsView(BaseModel):
    rollout_plan: str
    metrics_to_emit: list[str]
    rollback_strategy: str

class ProductView(BaseModel):
    user_stories: list[str]
    success_metric: str
    out_of_scope: list[str]

class FeatureSpec(BaseModel):
    name: str
    frontend: FrontendView
    backend: BackendView
    security: SecurityView
    devops: DevOpsView
    product: ProductView
    conflicts: list[dict] = []   # surfaced disagreements

# ─── Parallel build with per-agent timeout ───
async def _run_with_timeout(name, coro, timeout_s):
    # Wrap a single agent call so one slow agent can't block the others.
    try:
        return name, await asyncio.wait_for(coro, timeout=timeout_s)
    except asyncio.TimeoutError:
        return name, None                   # agent missed the window
    except Exception as e:
        return name, {"error": str(e)}      # surface, don't crash

async def build_feature_spec(feature_brief: str, timeout_s: float = 15) -> FeatureSpec:
    tasks = {
        "frontend": frontend_agent.run(feature_brief),
        "backend":  backend_agent.run(feature_brief),
        "security": security_agent.run(feature_brief),
        "devops":   devops_agent.run(feature_brief),
        "product":  product_agent.run(feature_brief),
    }

    # gather runs all coroutines in parallel; each has its own timeout wrapper
    pairs = await asyncio.gather(
        *[_run_with_timeout(name, coro, timeout_s) for name, coro in tasks.items()]
    )
    results = dict(pairs)

    # ─── MERGE step: detect conflicts, build canonical spec ───
    spec = merge_views(feature_brief, results)
    return spec

def merge_views(brief, views) -> FeatureSpec:
    conflicts = []

    # Cross-check 1: storage mentions vs data classification
    if views["frontend"] and views["security"]:
        ux = " ".join(views["frontend"].ux_flow).lower()
        if "localstorage" in ux and views["security"].data_classification == "sensitive":
            conflicts.append({
                "type": "storage_classification",
                "frontend": "uses localStorage",
                "security": "data classified sensitive",
                "resolution_required": True,
            })

    # Cross-check 2: API endpoints vs auth rules
    if views["backend"] and views["security"]:
        endpoints = {ep["path"] for ep in views["backend"].api_endpoints}
        guarded = {r.split()[-1] for r in views["security"].authz_rules}
        ungoverned = endpoints - guarded
        if ungoverned:
            conflicts.append({
                "type": "missing_authz",
                "endpoints": list(ungoverned),
            })

    return FeatureSpec(
        name=brief,
        frontend=views["frontend"] or _empty_view(FrontendView),
        backend=views["backend"]   or _empty_view(BackendView),
        security=views["security"] or _empty_view(SecurityView),
        devops=views["devops"]    or _empty_view(DevOpsView),
        product=views["product"]  or _empty_view(ProductView),
        conflicts=conflicts,
    )

Two things in this code worth noticing: (1) each agent fills in its own typed section, so if one agent goes off the rails, it can only mess up its own field instead of corrupting the whole document. (2) The merge step actively looks for conflicts instead of just concatenating outputs. The list of conflicts ships along with the document, so a human or a higher-level agent has to deal with them on purpose.

The "show the conflicts" idea applies broadly. Whenever multiple agents work on the same thing, the merge step should look for places where they disagree. Don't quietly average their outputs. Surface the conflicts and treat them as part of the result. This one habit is one of the highest-impact design choices in multi-agent systems.
Further reading on parallel agent setups: MetaGPT, Hong et al. ICLR 2024 introduced standardized procedures for role-based collaboration. AutoGen, Wu et al. 2023 made conversational multi-agent programming popular. MAS-GPT, Ye et al. 2025 explores building a whole agent system per request. Lin et al., arXiv 2025 (Agentic Neural Networks) treats the agent system itself as something you can train end-to-end. For a careful review of when multi-agent setups actually help versus hurt, see Becker, arXiv 2024, which documents three common failure modes (drift, alignment collapse, and monopolization).