Part IV, The conductor
24The conductor in front of any backend
The conductor runs in front of other backends too: the router’s task class, the effort, the packages and skills as notes, the side requests’ caps, the loop guards, the empty-turn continue and the tool checks, the compaction section, the status lines and memory notes. In the engine’s server with --backends it is the engine’s own conductor. The standalone proxy keeps one of its own under --conductor-config (default ~/.tandemllm/conductor, off for none), with its journal in the usage ledger’s file, as on the engine.
24.1 Switching it on
| setting | where | values |
|---|---|---|
harness.mode | the backend’s form, TANDEM_BACKEND_<ID>_HARNESS | off (the default): the relay, byte for byte; shadow: journal what it would do; on |
harness.profile | the form, TANDEM_BACKEND_<ID>_HARNESS_PROFILE | the conductor profile for this backend’s requests; empty picks by client |
| a feature group per model | the model’s row | inherit, off, shadow, on; never above the mode |
Start with shadow, read what it would have done in the Conductor view’s journal and the Compare view’s precision per backend, then switch to on. With the conductor off for every backend, a relayed request is copied byte for byte apart from the model id and the usage frame.
24.2 The feature groups
Each feature group can be switched per model. What inherit means depends on the side: a local engine gets everything, while a cloud API gets the groups that cost tokens on every turn, or a second request, off or in shadow until a model is switched on.
inherit resolves to, and what each costs.| group | what it does | local | cloud | cost |
|---|---|---|---|---|
class | the router’s question, asked of the backend with its own constraint field | on | on | one short extra request per new user message |
effort | the backend’s thinking switch: chat_template_kwargs.enable_thinking, reasoning_effort, DeepSeek’s thinking.type | on | on | nothing; a level is a word or on/off, never a hard cap |
packages | the router’s note at the end of the newest user message, replayed at the same message index | on | off | input tokens every turn; a prefix cache keeps its match |
side | a client’s title or summary call capped, thinking off | on | on | saves tokens |
loops | D1 and D2 on the streamed words; the tool-argument guard | on | on | a reasoning close is a second request (vLLM and SGLang only) |
e1 | an empty answer to a request with tools gets a second request | on | off | one more full request |
tools | the tool-call checks; a regenerate is a second request | on | shadow | the checks are free, a regenerate is one more request |
compaction | the TandemLLM section appended to a client’s compaction request | on | on | nothing extra |
states | the status lines in the stream | on | on | nothing |
memory | the memory card and notes; the model’s blocks written; the background writer | on | shadow | the card’s tokens; the writer’s request |
The Backends screen shows, next to each switch, what it resolves to, one sentence on what it costs or loses on that backend, and what its extra requests cost over the last 24 hours. The class questions are ledger rows of the client harness, and a second request’s tokens and cost are in its journal row.
24.3 What is different from the engine
The note is text.
On the engine the note is token ids placed before the turn’s end token. Over HTTP it is text at the end of the user’s message, inside the <runtime-note> frame the router uses, so a model could quote it. The replay keeps the bytes of the conversation’s head the same from turn to turn, so a backend with a prefix cache (vLLM, SGLang, OpenAI’s and DeepSeek’s prompt caches) keeps its match: a hash covers each message’s role, content, name and tool calls up to the noted one. A client that rewrites its history breaks the hash; the note is gone, and the router adds its block again.
The class question is a request.
On the engine the class question costs nothing beside the turn. Over HTTP it is a request of its own, a few hundred prompt tokens, with the backend’s own way to constrain the answer: vLLM’s structured_outputs.choice, SGLang’s regex, an OpenAI JSON-schema enum, TandemLLM’s own grammar, else plain text. A new user message can ask up to three questions (the class, the package, a library skill); a tool turn asks none. With the conductor on, the proxy’s own time in the ledger includes the plan.
Second requests continue the first.
E1, the regenerate and the reasoning close are second requests. The client still gets one stream: the second answer goes out as the continuation of the first, with the first chunk’s id, no second role delta and one [DONE]. To make that possible the proxy holds the finish frame, the usage frame and [DONE] until the turn is settled, and holds the tool-call frames while a check can act. When the client asked for usage, the usage it gets is the sum of every request, and so is the ledger row. A reasoning close needs continue_final_message, which the vllm and sglang kinds have; on any other backend D1 and D2 are journaled in shadow. A request without a stream gets the plan and none of the monitor’s acts, which read the stream.
24.4 The word-level loop detector
D1’s three arms run over words instead of tokens over HTTP (server/conductor/monitor/tier0_words.py), with thresholds measured for words, never the token ones copied. On the reasoning of an opencode database (2,674 finished turns and 20 loops), the strictest of 32 settings fired on 6 of the finished turns and caught 11 of the 20 loops (measured, tools/loop_words_fp.py, 2026-10-04). The engine’s own D1 acted on that traffic, so some of those 6 may be loops it closed; the text alone does not say which. The shipped words block therefore says calibrated: false, and every D1 verdict over the proxy stays in shadow until the Compare view’s labels show its precision.
24.5 Laya, the library and the session address
The standalone proxy serves the library (GET /v1/library) and POST /v1/laya/ask when the conductor’s decider role names a decision model over HTTP. Both answer under /s/<token>/, the address the notes give the model, and are journaled to that session. The classifier role may name a backend (backend:<id>/<model>) to answer the class question instead of the request’s own backend, and the narrator role the same for the status lines; without one, the lines are the templates.
24.6 What was checked
Against the live engine as a backend of kind tandemllm: the class question was answered by the engine through its grammar, the note was added and replayed on the next turn at the same message, and a title was capped at 64 tokens with thinking off (tools/proxy_harness_check.py). The close by continue_final_message and the reasoning parsers’ output after it are tested on a fake backend. The cloud providers’ answers to the class question and to the effort switch are tested on their documented shapes, not on a paid call.