Chapter 11
The multiplexer
The multiplexer lets one call to a surface land on several vendors at once — a primary whose reply the agent actually uses, and one or more observers running the same input in parallel. It's how you compare vendors head-to-head on speed, price, and accuracy, without changing a line of agent code.
What it is
Multiplexing is declared in the surface contract, in the routings block. A single routing entry with an array-valued lightSourceId is a multiplex: the first entry is the primary, and every subsequent entry is an observer. Each vendor's call goes through the lens as its own event, and all events for the one call share a correlationId so they group cleanly at read time.
The agent sees only the primary's response. The observers happen alongside it.
Why it matters
Comparing vendors in production is normally either destructive (you swap and observe production traffic without a control) or duplicative (you build a second call path). Multiplexing makes the comparison a property of your contract instead of your agent code — swap the routing, redeploy the contract, and every subsequent call captures a per-vendor record. Because both sides of every observed call flow through the same lens, you can compare vendors on any dimension your evaluations already record: cost, latency, correctness, tool-invocation shape.
How to use it
Declare a multiplex in the contract
Register a contract whose routing for the surface uses an array for lightSourceId:
await client.contract.register({
agentId: "billing-triage",
surfaces: [
{
id: "classify-intent",
dimensions: [ /* ... */ ],
routings: [
{
surfaceId: "classify-intent",
lightSourceId: [
"anthropic/claude-sonnet-5",
"openai/gpt-5",
"google/gemini-2-pro"
],
activeRunModes: ["eval", "production"]
}
]
}
]
});
Three vendors, listed in priority order. Claude Sonnet 5 is the primary; GPT-5 and Gemini 2 Pro are observers. The activeRunModes field restricts multiplexing to the modes where you want it — typically eval and production, keeping test and local_dev single-vendor for reproducibility and cost.
Fallback in array order
If the primary vendor is unavailable, the lens falls back through the array in order. The role tag reflects what actually happened on this call, so a fallback shows up in the data as its own vendor answering as primary — not as the primary's declared identity attributed to a call it did not answer.
Grade every vendor's result
On the SDK side, the primary's response is handle.result. Observer captures come back on handle.observerRecords[]. Grade the observers before reportOutcome so all vendors' outcomes land in the same evaluation.
const handle = await client.messages.create({
surfaceId: "classify-intent",
messages: [ /* ... */ ]
});
const primaryAnswer = handle.result;
for (const rec of handle.observerRecords) {
await handle.gradeObserver(rec, {
dimensions: [{
dimensionId: "correctness",
passed: isCorrect(rec.result),
expected: "a correct answer to the user's question",
actual: summarize(rec.result)
}]
});
}
await handle.reportOutcome({
dimensions: [{
dimensionId: "correctness",
passed: isCorrect(primaryAnswer),
expected: "a correct answer to the user's question",
actual: summarize(primaryAnswer)
}]
});
Reading the output
Each vendor's call is captured as a separate event. The events share a correlationId (the call's) and each carries a multiplex.role cohort tag with one of two values:
| Tag value | Meaning |
|---|---|
multiplex.role=primary | The vendor whose reply the agent used. |
multiplex.role=observer | A vendor running the same input in parallel; the agent never saw this reply. |
To pull one multiplex call back as a group, query events by correlationId:
GET /lens/events?correlationId=corr_01H...&provenance=all
You'll get one event per vendor, each with its own light_source_identifier, its own timings, and its own reported outcome.
Comparing vendors
The compare-heads-up view is a simple group-by-and-difference on those events. Pick your dimensions (correctness, latency, cost), group by light_source_identifier, and read the deltas straight from the substrate. There's no separate multiplex report — the events already carry everything you need.
Cost and latency
Per-vendor cost and latency are captured on each event without any operator work. When you multiplex three vendors, you get three vendors' cost and latency for the same input — the piece of the head-to-head that's normally hardest to compare fairly.
Reference
Routing shape
Each routing entry on the contract has this shape:
| Field | Shape | Notes |
|---|---|---|
surfaceId | string | Which surface this routing applies to. |
lightSourceId | string \| string[] | Single string = single-vendor. Array = multiplex (first primary, rest observers). Fallback follows array order. |
activeRunModes | enum[] (opt) | Which run modes the multiplex is active in. Absent = active in all modes. Restrict to eval/production to keep test and local_dev cheap. |
Per-event cohort tag
multiplex.role=primary— the vendor whose response was returned to the agent.multiplex.role=observer— a vendor whose response was captured but not returned.
Grouping key
correlationId— shared across all vendors' events for one call.