Every agent framework pitches the same story: give the LLM a system prompt, a bag of tools, and let it figure out the routing. This works for demos. It fails in production.
The routing problem
When your agent has 15+ tools, the LLM spends tokens deciding what to do instead of doing it. Worse, the routing logic is trapped inside a black box — you can’t audit it, version it, or test it without running the full model.
An agent that can’t explain its routing is an agent you can’t trust in production.
The fix is to extract routing into a skills.toml DAG — a directed acyclic graph where each node is a skill, each edge is a condition, and the traversal is deterministic:
# skills.toml
[nodes.classify]
tool = "intent_classifier"
routes = { booking = "search_flights", info = "knowledge_base" }
[nodes.search_flights]
tool = "flight_search"
routes = { found = "book", empty = "fallback" }
Why TOML over YAML
YAML’s implicit typing is a footgun. TOML is explicit, git-friendly, and parses the same way everywhere. Your router.py reads the DAG, walks the graph, and dispatches to skill handlers — no LLM in the loop for routing decisions.
The result: agents that route in microseconds, with decisions you can unit test.