AI Development Guide

TypeSafe Patterns in 2026: Fan-Out, Intent Routing, Confidence Gating and Composite Scoring

The primitives are easy. The architecture is where the value is. These are the four patterns TypeSafe documents, the code behind each, and the order they belong in when you put them together.

Distk Editorial Sep 2026 12 min read

TypeSafe documents four architectural patterns for 2026. Speculative fan-out sends every question a workflow might need in one request and lets code decide what is relevant, measured in TypeSafe's own cookbook at 12.2 times cheaper and 10.0 times faster than separate calls. Intent routing puts a fast classifier in front of expensive handlers so some requests reach deterministic code with no model involved. Confidence-gated routing uses confidence as a second axis, with a floor for genuine uncertainty and higher thresholds for irreversible actions than read-only ones. Composite scoring splits a complex judgment into independent dimensions and combines them with weights that live in reviewable code, so one set of answers can produce different rankings for different purposes. In production most systems use three of the four in a single request.

What Are the TypeSafe Patterns in 2026?

TypeSafe documents four architectural patterns for building systems around its primitives: speculative fan-out, confidence-gated routing, composite scoring, and intent routing. Each one is a way of composing typed answers in code, and the company frames the underlying skill plainly: learning to think in terms of discrete, atomic decisions that compose into complex system behaviour is what gets the most out of the model.

PatternWhat it doesBenefits TypeSafe claims
Speculative fan-outSend many questions in a single call, including speculative ones, and let your code decide what is relevantCost, speed
Confidence-gated routingUse confidence as a second decision axis to build safer systemsReliability, safety
Composite scoringCombine several dimensions of analysis into a single scoreCost, reliability, speed
Intent routingClassify a user's intent and route to the appropriate handlerCost, speed

Explain It Like I Am Five: The Airport Desk

Picture the person at the front of an airport who sorts everyone out before they go anywhere.

You walk up. They ask you several quick things at once: where are you flying, do you have bags, is this a connection, do you need help getting to the gate. It takes about four seconds, because they ask all of it in one go rather than sending you round the corner and back for each question.

Some of what they ask will turn out not to matter. They ask about bags even if you have none. That is fine. Asking is quicker than working out whether asking was worth it. That is speculative fan-out.

Then they point. Bag drop, security, or the special assistance desk. That is intent routing.

If they cannot work out what you need, they do not guess and send you somewhere random. They wave over a supervisor. That is confidence-gated routing.

And if the airline needs to decide who gets the last upgrade, they do not ask one big question. They take a few small scores, frequent flyer level, fare type, how full the cabin is, and add them up with their own rules. That is composite scoring.

Four patterns. Ask everything at once, point people the right way, call a supervisor when unsure, and add small numbers together with rules you wrote.

How Does Speculative Fan-Out Work in 2026?

Put every question your system might need into one request and use code to decide what is relevant afterwards. All questions are evaluated in parallel, so adding more usually has little effect on response time, and each extra question only costs its own tokens.

TypeSafe's worked example is support ticket triage. A ticket needs a category, and if it is a bug report it also needs a severity. Rather than asking for the category first and the severity in a follow-up, you ask for both at once and ignore the severity if the ticket turns out not to be a bug. The documented request carries five questions: a Choice for the category, a Score for bug severity, Nouls for reproducible steps and for a refund request, and a Score for frustration.

category    = response.answers["category"]
bug_severity = response.answers["bug_severity"]
bug_repro    = response.answers["has_reproducible_steps"]
refund       = response.answers["refund_requested"]
frustration  = response.answers["frustration"]

if category.choice == "bug_report":
    if bug_severity.score > 1.5 and bug_repro.noul > 0.6:
        escalate_to_engineering(ticket_id, severity="high")
    else:
        add_to_bug_backlog(ticket_id)

elif category.choice == "billing":
    if refund.noul > 0.7:
        route_to_billing_with_flag(ticket_id, refund_likely=True)
    else:
        route_to_billing(ticket_id)

elif category.choice == "feature_request":
    log_feature_request(ticket_id)

# Frustration is useful regardless of category
if frustration.score > 1.5:
    flag_for_priority_response(ticket_id)

Everything needed for the full decision tree comes from one call. Two of those five questions are speculative: bug severity and reproducible steps only matter for a bug report, and the refund question only matters for billing. When they are irrelevant, the code ignores them. When they are relevant, you have saved a round trip.

The economics are measured rather than asserted. TypeSafe's parallel questions cookbook ran a 13-question regulatory briefing over the GDPR Wikipedia article and reported one batched call at 0.000497 US dollars and 0.27 seconds against 13 separate calls at 0.006090 US dollars and 2.71 seconds, making batching 12.2 times cheaper and 10.0 times faster with no change in answers. The reason is simply that the separate calls re-send the article 13 times.

How Does Intent Routing Work in 2026?

Classify the incoming request first, then send it to the right handler: deterministic code, a specialist model, or a person. TypeSafe positions this as putting a fast, cheap classifier in front of everything else rather than sending every message through an expensive model just to work out what kind of request it is.

The documented example is customer service routing, and it asks two questions: a Choice for intent across order status, product question, return or exchange, and complaint, plus a Score for complexity.

def route_ticket(ticket_id, response):
    intent = response.answers["intent"]
    complexity = response.answers["complexity"]

    if intent.confidence < 0.5:
        # Not enough confidence to classify: route to a human agent
        return route_to_human_agent(ticket_id)

    if intent.choice == "order_status":
        handle_order_status(ticket_id)

    elif intent.choice == "product_question":
        handle_with_llm(ticket_id, PRODUCT_SPECIALIST)

    elif intent.choice == "return_exchange":
        handle_with_llm(ticket_id, RETURNS_SPECIALIST)

    elif intent.choice == "complaint":
        low_confidence = complexity.confidence < 0.5
        if complexity.score > 1 or low_confidence:
            # Too complex for safe automation, or unsure about complexity
            route_to_human_agent(ticket_id)
        else:
            handle_with_llm(ticket_id, COMPLAINT_RESOLUTION)

Look at where each branch goes. One intent reaches deterministic code with no model involved at all. Two reach different specialist models loaded with different context. One uses a complexity score to choose between a model and a person. The classification is a single quick call, and the expensive resources only get invoked for the requests that genuinely need them.

The detail most people miss is the second confidence check. The code does not only gate on intent confidence; it also escalates when the complexity answer itself is uncertain. TypeSafe's note is that it is always important to consider what a low confidence score means in the context of the system and the stakes of the decision.

How Does Confidence-Gated Routing Work in 2026?

Treat confidence as a second axis. The answer tells you what; confidence tells you whether to act on it. TypeSafe's example is a voice banking interface, chosen because the available actions have obviously different consequences, and one Choice question feeds several different thresholds.

action = response.answers["intent"]

if action.confidence < 0.6:
    route_to_support_agent(account_id)

elif action.choice == "check_balance":
    # Low stakes. 0.6 confidence is sufficient.
    show_balance(account_id)

elif action.choice == "approve_transfer":
    if action.confidence > 0.85:
        approve_transfer(account_id)
    else:
        ask_user_to_confirm("Just to confirm: you would like to approve this transfer?")

else:
    route_to_support_agent(account_id)

The 0.6 floor catches anything genuinely uncertain. Checking a balance clears at 0.6 because the worst case is a customer hearing their balance needlessly. Approving a transfer needs above 0.85, and anything in between triggers a confirmation rather than an action or a refusal. The risk tolerance is encoded in your code, where it can be reviewed, rather than in a prompt.

Our confidence and calibration guide covers how to pick those numbers from your own labelled data rather than by feel.

How Does Composite Scoring Work in 2026?

Break a complex judgment into independent dimensions, score each one separately, and combine them with weights you control in code. TypeSafe's worked example is resume screening, asking four Score questions in one request: Python depth, team leadership, system design, and generalist breadth, each on a five-level rubric.

py      = response.answers["python_depth"].score / 4
lead    = response.answers["team_leadership"].score / 4
arch    = response.answers["system_design"].score / 4
general = response.answers["generalist"].score / 4

# Senior IC
ic_score = (0.40 * py) + (0.10 * lead) + (0.40 * arch) + (0.10 * general)

# Engineering Manager
em_score = (0.15 * py) + (0.40 * lead) + (0.20 * arch) + (0.25 * general)

Each score is normalised to 0 to 1 by dividing by the top level number, then weighted. One set of model answers produces two different rankings for two different roles, because the weights differ and the weights are yours. TypeSafe's stated benefit is visibility: you can see exactly how the final number is made, and when the top-ranked candidates do not match expectations you adjust the weights rather than rewriting a prompt.

The same shape appears in the Score documentation for ticket priority, combining severity, frustration and report quality at 0.6, 0.3 and 0.1 with a comment explaining that a detailed report helps an engineer investigate, so it raises priority slightly. That comment is the point of the pattern: the reasoning is in the code, in words a colleague can argue with.

Why this beats one big question in 2026

Ask "rate this candidate out of 10" and you get one number whose internal reasoning you cannot inspect, adjust, or explain to a hiring manager. Ask four dimensions and weight them, and every part of the result is visible, tunable, and separately testable. TypeSafe makes the same argument about startup pitches: ask about market size, technical feasibility and differentiation separately, then combine with your own formula.

How Do the Patterns Combine in a Real System?

They stack, and in most production systems you will use three of the four in a single request. The fan-out is how you get the answers cheaply, intent routing is what you do with the categorical ones, composite scoring is what you do with the ordinal ones, and confidence gating sits over all of it deciding when code acts alone.

StagePatternWhat happens
1. One requestSpeculative fan-outEvery question the workflow might need, including ones that only matter for some inputs
2. Safety checkConfidence-gated routingAnything below the floor goes to a person before any branch runs
3. BranchIntent routingCategorical answers select the handler: code, a specialist model, or a human
4. PrioritiseComposite scoringOrdinal answers combine with your weights into a rank or a priority
5. ActConfidence-gated routing againEach action clears its own threshold, higher for irreversible operations

What Is the Design Process TypeSafe Recommends?

Its build guide sets out an ordered workflow, and the order matters as much as the content. The summary line is that you build a normal software workflow and insert System One only where AI is needed.

  1. Use code when you can. Keep deterministic work in code because it is reliable and cheap, and avoid agent while loops when a software workflow expresses the same behaviour.
  2. Decompose the input state. Include only the context relevant to the current questions, and do not rely on knowledge stored in model weights when current information can come from your own knowledge base.
  3. Use structure in the input state. Nested JSON, with questions pointing at specific values by backticked path when that removes ambiguity.
  4. Decompose the questions. Ask the most explicit, narrow, specific, atomic questions you can, breaking complex judgments into separate questions that each evaluate one property.
  5. Use structure in the questions. Keep them short; add object or array structure when a question needs supporting data or several kinds of guidance.
  6. Ask a lot of questions. Many narrow independent questions about the same state in one request, which is how you maximise intelligence per dollar.
  7. Combine outputs in code. Deterministic rules, weighted sums, or the probabilities as features in a downstream classical machine learning model.
  8. Route on uncertainty. Different actions for confident and unconfident answers, with thresholds tested by plotting confidence against accuracy on your data.

What Are the Common Pattern Mistakes in 2026?

Key Takeaways for 2026

Distk designs these flows with teams, including the part that decides which branches need no model at all, which is usually where the cost savings actually come from.

Sources

TypeSafe Patterns in 2026: FAQs

What is speculative fan-out?

Sending many questions in a single TypeSafe call, including ones whose answers only matter for some inputs, then letting your code decide what is relevant. Questions run in parallel so adding more has little effect on response time, and irrelevant answers are simply ignored.

How much cheaper is batching questions?

TypeSafe's parallel questions cookbook ran a 13-question briefing over the GDPR Wikipedia article and measured one batched call at 0.000497 US dollars and 0.27 seconds against 13 separate calls at 0.006090 US dollars and 2.71 seconds, making batching 12.2 times cheaper and 10.0 times faster with no change in answers.

What is intent routing?

Classifying an incoming request with a cheap model call, then routing it to the right handler: deterministic code, a specialist model, or a person. In TypeSafe's documented example one branch uses no model at all, which is the cheapest path in the system.

What is confidence-gated routing?

Using the confidence value as a second decision axis. The answer tells you what, and confidence tells you whether to act. TypeSafe's example uses a 0.6 floor for everything, then requires above 0.85 before approving a financial transfer automatically.

What is composite scoring?

Breaking a complex judgment into independent dimensions, scoring each with its own Score question in the same request, then combining them with weights you control in code. One set of answers can produce different rankings by applying different weights.

Can I use several patterns together?

Yes, and most production systems do. A typical stack is one fan-out request, a confidence floor before any branch runs, intent routing on the categorical answers, composite scoring on the ordinal ones, and a per-action confidence threshold before anything irreversible.

The savings come from the branches with no model in them

Distk designs decision flows that route cheaply, escalate honestly, and keep the weights and thresholds in code a colleague can review. If you are architecting one in 2026, that is where we start.

Start the conversation →