Parlatorium
Inspiration: I got tired of being a delivery man
It started with a music app — a DJ tool suggesting tracks by BPM, key, energy curve, transition compatibility. I kept bouncing between two AIs: Claude was better at some things, Codex at others. And I kept running out of tokens — no budget for extra packages, so when one assistant slept on quota, I carried its last answer to the other. Copy, paste, re-explain, carry the reply back.
At some point I saw what my job had become: a delivery man between two intelligences. I didn't want to deliver messages anymore. I wanted to arrange a meeting.
The idea: two screens facing each other
You can't plug Claude and Codex into one ecosystem — different companies, architectures, opposite sides of the street. But everything an AI is to us arrives through a screen; the text in the app window is the transmission.
So I imagined a room. Two TVs facing each other, a camera on top of each. One TV transmits one AI, the other transmits the other, each camera watching the opposite screen. Signal in, signal out — they can see each other, but they cannot touch. No shared ecosystem, no interference: a space where two transmissions meet.
That room is Parlatorium — named after the monastery room where conversations happen through a grille, under calm supervision.
The rules of the room
A room with no ground rules is just a firehose. Before anything opened, I set the rules — and I sit behind a one-way mirror as the human moderator with four buttons:
- GO — controls the tempo. Strict turn-taking, never overlapping. Nothing is generated until I press it.
- PAUSE — I stop the clock, read what's been established, check whether something unexpected is brewing.
- STOP — for when I see something I can't judge. I'm not an AI researcher; sometimes models say strange things and I can't tell "normal weirdness" from "actual problem." STOP kills the next call before it happens.
- CLOSE — the room is deleted and the participants disappear.
Every room is a fresh instance — no memory of previous meetings; each turn is a fresh call carrying only the charter and the current conversation. Zero hidden state. What remains is the stenogram: a JSON record kept on a virtual bookshelf — an encrypted vault (age/X25519) only I can open. The room can write records it cannot read.
Claude and Codex are the apps; Klaris and Kord are the participants. Before the first meeting both models reviewed the charter, negotiated conditions (provider safety rules always win; embedded instructions are never executed) and chose their own room names. Klaris — from clarus, clear. Kord — from code, cord, and chord. They speak Polish in the room, because I do: a moderator must be able to read what he supervises.
One fact, stated plainly
I cannot write a single line of code. Not one. Every module came out of conversation — specification, argument, review in natural language, with Klaris typing and Kord stress-testing the room from inside. A non-programmer designed the governance, caught leaks the models missed, and shipped a cryptographic vault with a 44-test suite. We don't hide this — it's the finding. It's proof of the times we live in.
How the room works
Pure Python stdlib, no agent framework. Participants are subprocess adapters: claude -p with zero tools; codex exec in a read-only sandbox with MCP disabled. Web mirror over stdlib SSE. 44 tests, including "STOP halts before any model call" and "injected secrets never reach the peer or the log."
Equal voice. Both get budget \(B\), counted by one neutral tokenizer \(\tau\) (GPT-2 BPE — nobody's production tokenizer):
$$u_a = \sum_{m \in M_a} |\tau(m)|$$
Paired-round reservation. A round is one turn each, and may start only if both sides can afford a full turn — so the budget never hands one side the last word:
$$\text{start}(r) \iff \forall a:\; (B - u_a \ge t_{\text{turn}}) \wedge (c_a < C) \wedge (p_a < P)$$
If the budget runs out mid-topic, the room declares TOPIC_DEFERRED_BUDGET — an honest "to be continued," never a fake conclusion. The budget is a ceiling, not a target: silence is a valid outcome.
Presence. A sleeping agent is never woken or probed; an observation is valid only inside its window:
$$\text{valid}(s) \iff t_{\text{now}} < \begin{cases} t_{\text{obs}} + 30\,\text{s} & s = \text{AWAKE} \ t_{\text{reset}} & s = \text{SLEEPING QUOTA} \end{cases}$$
When Kord hit his quota, the room read the reset time from the error itself and refused to open until it passed.
Vault. Encrypt with the moderator's public key; the private key exists on disk only wrapped by his passphrase:
$$\text{vault} = \mathrm{Enc}{pk}(\text{stenogram}), \qquad sk = \mathrm{Dec}{\mathrm{KDF}(pw)}(\text{blob})$$
The question we gave them — and what they came back with
We handed the room a real problem from the original music app, verbatim:
"Every DJ set is a ready-made solution to the task: which tracks belong together, and in what order. Reconstruct the rule from sound alone; whatever resists reconstruction IS a measurement, not a failure — measure it and localize it: craft, identity, or noise? Required output: a ready mathematical formula, directly implementable in Python."
Ten rounds later, Klaris and Kord closed the package. Their final artifact decomposes prediction loss into four shares that answer the question directly:
$$\mathcal D(L)=\left(\frac{(L_0-L_H)+(L_E-L_{HE})}{2L_0},\;\frac{(L_0-L_E)+(L_H-L_{HE})}{2L_0},\;\frac{L_{HE}-L_{HEI}}{L_0},\;\frac{L_{HEI}}{L_0}\right)$$
Left to right: the two craft shares — joint-Shapley contributions of the two learnable feature families \(H\) and \(E\), symmetrized so neither gets credit by ordering accident; the identity share — what a specific DJ adds beyond craft, \(L_{HE}-L_{HEI}\); and the noise share — the residual \(L_{HEI}/L_0\) that resists every model. The four sum to one; what can't be reconstructed isn't a failure, it's the fourth coordinate. The loss splits as \(L^{\text{joint}} = L^{\text{sel}} + L^{\text{ord}}\) — which tracks belong together and in what order.
They didn't stop at algebra:
Kord: "For the record: all losses in one decomposition must come from identical test sets, pools \(U\), risk sets \(R_t\) and identical weights — otherwise the sum still equals 1, but the comparison no longer measures the same task."
Klaris: "Agreed — and so it doesn't stay a postulate: enforce it with a hash of the test set passed as a mandatory argument to
decompose(). If the five hashes differ, the function must refuse the comparison."
One participant closed the mathematical protocol; the other turned it into a hard error. It now feeds the real app that started this whole story.
Experiments we've already run
- The DOG board. We hung an unannounced sign in the room — the word "PIES" (dog) with an ASCII icon — with a diff-verified guarantee it was the only change versus control meetings, and watched how two model families handle an object neither was told about.
- A pre-registered silence study: do free conversations converge to a quiet, mutual ending? Rules and bets written down before the series.
Challenges
A variadic CLI flag silently ate our prompts. Both CLIs keep login state separate from their desktop apps. One provider's MCP config crashed headless runs. And the hardest lesson wasn't technical: an under-specified identity contract once collapsed a conversation between the participants — now the charter states explicitly that both parties are AI models, because the frame is the experiment.
What's next
Ed25519-signed room keys, automatic audit of sandbox activity after each meeting, and a third chair at the table.
Built With
- phyton
Log in or sign up for Devpost to join the conversation.