Why We Built an Orchestrator, Not More Routing Rules
Static trigger/transform rules scale badly once your canvas grows past a couple of agents. Here's why MadoHub now routes through a real tool-calling loop instead — and when you should still use rules.
For most of MadoHub's life, routing between agents was a rules engine. A connection had a trigger (on-idle, on-complete, on-keyword, always), a transform (AI routing, prompt-wrap, full-output, raw, summary), and loop-protection knobs. Configure it once and it fires the same way every time. That model still exists — it's what Agent Routing and Flows document, and it's still the fastest way to wire two tiles for a known pattern like peer review. But it has a scaling problem worth being specific about.
The problem isn't any single rule. It's the count.
A connection with "on idle → prompt-wrap" is easy to reason about: did the source finish? If so, forward it. The trouble starts once the canvas grows past a couple of tiles and connections stop being independent.
With five agents and eight connections, every rule interacts with every other rule. Does A's output count as a keyword match for B's on-keyword trigger? Should C wait for D's cooldown so the same target isn't hit twice in a second? None of these have wrong answers — you can resolve any one by adding another trigger type, transform, or priority flag. But each answer is a new rule, and rules don't compose, they multiply. A topology with N agents doesn't need N rules, it needs closer to N² of edge-case handling, because a rule has no model of what's happening elsewhere on the canvas — it pattern-matches on output text and fires blind.
That's the real argument for an orchestrator: not that rules are bad, but that a fixed rule can't look at the rest of the workspace before deciding what to do, and a workspace with more than a couple of agents increasingly needs exactly that.
How MadoHub handles it
A tool loop, not a bigger rule
The alternative isn't "add an AI transform" — MadoHub already had that. It's giving the routing decision access to the workspace. By default, a fired connection now opens a MadoAgent sub-turn: a real tool-calling loop that looks at a snapshot of your canvas — every tile, every connection's trigger and transform and round state, recent output — and makes one routing decision, then stops.
That decision is narrow on purpose: it can read files, check git status, list connections, inspect routing history, search sessions, and recall memory, plus take exactly one action — forward the message, or skip it. It can't rewrite your canvas, mutate connections, or run workflows. The instruction is simple: forward when there's substantive content (a plan, code, a review), skip when the source output is just a question to the user or empty chatter. A judgment call against the actual conversation, not a pattern match.
Loop protection still applies, regardless of path
Replacing a deterministic dispatcher with a model call isn't a change you make with full confidence on day one, so the guardrails from the rule-based system carry over unchanged. Loop protection caps how many cycles a connection runs before it auto-deactivates (default 5), enforces a minimum gap between triggers (default 3 seconds), and can end the loop the moment a stop keyword like LGTM appears. A sub-turn that decides to forward on every round still can't run away — the cap and cooldown are enforced independently of its decision.
Shadow mode, for building confidence
If you want to try the new path without changing behavior, shadow mode runs the legacy router live and its decision is what gets forwarded — user-facing behavior doesn't change — while a MadoAgent sub-turn runs in parallel on the same trigger, purely as a comparison signal. You can see where the new path agrees with the old one on real traffic before trusting it to make the live call. The legacy path stays selectable in Settings for as long as it takes to build that confidence.
Practical guidance
- Use Flows for known-good shapes. The three built-ins (Peer review, Pipeline, Watcher) remain fixed rule sets, because a template dropped for a repeatable pattern shouldn't be second-guessed by a model on every fire.
- Use the orchestrator for bespoke or large topologies. When no fixed rule set describes your canvas well, a tool-calling loop that can look at the rest of the workspace before deciding generalizes better than another rule.
- Use manual wiring for one-off precision. Dragging a connection between two tiles is still the fastest path when you want full control over a single link and don't need a template or a conversation.
- Keep loop protection on. An LLM in the routing loop can misjudge whether output is substantive, skip something a rule would have forwarded, and add a round-trip of latency and tokens a template match doesn't. Loop protection and the delivery gate guarantee that a wrong decision can't spiral into an unbounded loop, and a forward can't be silently swallowed by a tile that's no longer there to receive it.