Harness engineering / practical series
Build a small Markov agent router from transition counts
By Sandeep Belgavi · 18 October 2026
Calculate interpretable route scores, apply smoothing and preserve an explicit fallback.
A routing model is not the language model
A language model interprets or generates text. A small routing model selects a destination from a fixed role catalogue. In this proposed design, an intent classifier identifies a task category and a count table estimates which specialist should receive it. The table is inexpensive to query and easy to inspect, but it does not understand every nuance of a request. It also does not establish permission to act.
Start with conditional frequencies
Imagine ten independently reviewed testing requests: eight belong to Tester, one to Coder and one to Reviewer. The unsmoothed estimate for Tester is eight divided by ten. Add-one smoothing gives each destination one additional count, producing nine divided by thirteen for Tester. Smoothing avoids exact zeros for unseen destinations but can materially change decisions with limited data. Show the denominator and sample support beside any displayed route score.
Add prior-agent context carefully
A first-order policy may condition on the preceding agent as well as the task category. Testing after a code edit differs from an initial request to design a test strategy. However, splitting the table by prior agent makes individual cells sparser. Use a minimum support rule and back off to category-only counts when a cell is too small. Evaluate both variants on identical task groups before assuming additional state improves decisions.
Keep an honest fallback path
The exercise routes directly only when both support and confidence pass fixed thresholds. Otherwise it selects a coordinator. This fallback is still subject to the same permissions and execution limits. Also measure the actual surrounding path: a routing function that uses no LLM does not prove that the application bypasses a coordinator model request. A rewritten delegation prompt may still incur coordinator inference before reaching the chosen specialist.
Separate the reference from our experiment
MKPro documents conditional agent routing and optional prior-agent context. Those are useful reference ideas. The smoothing rule, counts and support threshold below are original teaching choices, not assertions about MKPro defaults. The local team extension now executes a bounded count-based router with explicit confidence fallback. Treat the exercise as a way to inspect how a statistical choice changes a route before integrating adaptive behavior into a real team.
Inspect failure as well as confidence
An apparently confident route can reflect biased historical labels. If a coordinator always selected Coder, the counts will reproduce that habit even for tasks better handled by Tester. Retain reviewed outcomes and compare predicted routes with correct destinations. Investigate errors by category and previous agent, not only aggregate accuracy. A stable alphabetical tie-break makes the exercise reproducible; it does not resolve an underlying lack of evidence.
Run the exercise
Save the code as 08-markov-router-from-counts.py and run python 08-markov-router-from-counts.py with Python 3.11 or newer. This standard-library exercise uses synthetic data. It does not invoke a model or require an account, network connection or API key.
# Author: Sandeep Belgavi. Synthetic exercise; no network or provider calls.
def choose(counts,threshold=0.65,minimum=10):
total=sum(counts.values())
if total<minimum:return "Coordinator"
scores={a:(n+1)/(total+len(counts)) for a,n in counts.items()}
best=sorted(scores,key=lambda a:(-scores[a],a))[0]
return best if scores[best]>=threshold else "Coordinator"
counts={"Tester":8,"Coder":1,"Reviewer":1}
assert choose(counts)=="Tester"
assert choose(counts,0.75)=="Coordinator"
assert choose({"Tester":2,"Coder":0})=="Coordinator"
print("Tester; fallback at stricter threshold; fallback with sparse data")
Expected output:
Tester; fallback at stricter threshold; fallback with sparse dataChange one assumption
Calculate nine divided by thirteen by hand, then raise the threshold to 0.70 and explain the fallback. Introduce a previous-agent column and identify cells that lack support. Do not treat a high historical selection frequency as evidence that the destination was correct or that the resulting action is authorized.
Implementation scope and further reading
This is an original AICassindra teaching design. The exercise demonstrates the stated invariant; it is not a complete production implementation. The local Harness Studio extension supports saved read-only agent teams, reviewed count-based routing and bounded sequential execution. Arbitrary imported graphs, effectful tools and automatic self-promotion remain unsupported.
All harness articles · Interactive boundary labs · Our public lab code
Primary reference: MKPro Markov-router documentation. MKPro describes category routing with optional previous-agent context. Our smoothed estimator and fixture values are independent teaching choices.