The choices behind the mediator, the alternatives rejected, and what they cost
Each decision below states what we chose, what we chose it over, and why. Several were reversals — we built the obvious thing first, watched it fail, and changed it. Those are marked, because the reason is usually more instructive than the conclusion.
Chosen: every participant talks to their own agent, inside a room, and never to each other.
Over: a single conversation, or a single agent handling both sides.
Why: confidentiality stops being a matter of discretion and becomes a property of the structure. The brand-facing agent cannot reveal the talent's real floor because it was never told it in those terms. It also decouples the parties in time — the talent does not need to be awake for their interests to be represented.
The room started as a hard-coded "talent side and brand side" and was generalised: a room now holds any number of participants under the same rules. The two-party negotiation is the first product on it, not the shape of it.
Cost: something has to carry information between the conversations, which is the planner, and that is a substantial piece of machinery.
Chosen: one role reads everything and makes every judgement; the agents that talk to people hold conversations and record nothing.
Over: letting each agent maintain its own understanding.
Why: two writers produce two versions of the truth, and the moment they disagree the system has no way to choose. It also concentrates the hard reasoning in one place, which can use a stronger model, while the conversational work runs on whatever is best at conversation.
Cost: the planner is a single point of quality failure. If it records something wrong, both conversations inherit the error. This is not hypothetical — see "agents are reviewed, not trusted" and "guidance cannot deliver" below; the guard exists largely to catch this class of failure after the fact.
Chosen: a message arrives, the fast steering stage (PlannerGuidAg) reads it
and writes the active persona's guidance instructions, and only then does the agent
start streaming its answer. Simultaneously, the background distillation stage
(PlannerDistilMemAg) updates facts, evaluates goals, and queues pushes in parallel
with the reply.
Over: the agent replies and the planner catches up afterwards (or running a single heavy planner call that blocks the entire reply).
Why (reversal): we built it as a single catch-up pass afterwards first. The result was that the agent answered the message in front of it using an understanding that predated that message, and any instruction the planner produced only took effect a turn later. The talent would state their budget and the agent's reply would be composed as though they had not.
Splitting the planner into PlannerGuidAg (fast blocking instructions on gpt-5.6-sol-fast
at medium reasoning) and PlannerDistilMemAg (deep background distillation on
gpt-5.6-sol-fast in parallel with the persona stream) gives the best of both worlds:
immediate, same-turn steering on the very reply being composed, with minimal delay
before the first token streams.
Cost: the turn still waits on the fast guidance stage before the first word appears, and DistilMemAg writes must not clobber GuidAg's active guidance branch.
Chosen: when something must be told now — a deal came together, awaited information arrived — the planner pushes the substance to a participant, and that participant's persona agent is woken to deliver it in its own voice.
Over: letting the planner write to people directly, or making every update wait until the person next opens the conversation.
Why: a mediator that only ever reacts loses the deals where timing matters, but the planner writes like a system, not like someone's agent. Splitting the what (planner) from the how (persona) keeps one consistent voice per participant. One rule proved essential: the substance is written from the recipient's point of view. Participants do not know other conversations exist, and an early push that referred to "the brand chat" was flatly rejected by the recipient — correctly, since from their side no such thing exists.
Cost: an interruption channel that must be used sparingly; the planner is instructed that a push has to earn the interruption.
Chosen: two hard rules for the planner — guidance never makes an agent speak, so anything a waiting participant is owed must be a push; and nothing may be recorded as sent or in-flight unless the same run actually sends it. Every planner run also receives the dispatch record: the system's ground-truth list of messages actually delivered, so the planner cannot trust its own diary about what it did.
Over: trusting the planner to know the difference between instructing an agent and delivering a message.
Why (reversal): a talent authorised a counter-offer and their agent promised "I'll get that to them right now." The planner wrote excellent guidance for the brand-side agent — "deliver this to Dev now" — recorded the counter as being delivered, and pushed nothing. But guidance only takes effect when that participant next writes, and the brand was waiting for us, so nobody would ever speak: a perfect instruction sat unread, the memory said delivery was in progress, and the talent had been told it was done. The model had conflated writing an instruction with executing it — and its own memory then confirmed the false belief on every later run. The rules close the wrong branch; the dispatch record makes the false belief impossible to sustain.
Cost: a little more prompt, a little more context per run — and the admission that a model's account of its own actions is not evidence.
Chosen: a dedicated agent, ZGuard, runs a few minutes after a room's last exchange and audits the whole room — every pane's recent conversation, the memory, and the dispatch record. It verifies that nothing is claimed done that never happened, nobody is left waiting for an undelivered message, goal statuses match the transcripts, and stale guidance is cleared. It repairs with the smallest possible edits, through the same mechanism the planner acts through, and its expected verdict is "healthy — no action."
Over: trusting that the per-turn planner catches everything, or running a reviewer in front of every reply.
Why: the planner runs before each reply, so the last agent message of every sitting is reviewed by nobody — and that message is exactly where promises live ("I'll take this to them now"). A reviewer in front of every reply would double latency and cost on every turn; a debounced audit pays once per sitting, off the latency path, and only when the room actually went quiet. The trigger is a real debounce: every reply re-arms a per-room timer, and a database row is the authority the timer is validated against, so a stale or duplicated timer fires nothing. Two loop guards keep it safe: a wake caused by the guard's own push never re-arms the timer, and a run that finds nothing writes nothing.
The tension worth naming: the guard is a second writer in a design built on a single writer. It is allowed because it is constrained to repairs — correct false state, clear stale instructions, deliver what is owed — and explicitly forbidden from strategy, reorganisation, or second-guessing judgement calls. A proofreader with a red pen, not a co-author. AccUpdate is the same kind of exception on the inbound path: a courier that may write only one participant's branch from durable memory, never guidance or goals.
Cost: one planner-scale model call per sitting, and one more agent whose judgement can itself be wrong — which is why every verdict is logged and shown to operators rather than acted on silently.
Chosen: rooms are permanent — a talent keeps exactly one home room for life, and every conversation a brand starts with a talent stays open forever — and the Arvist's promotion into durable memory fires after ZGuard audits a quiet room, kicked as a separate request rather than on the room ending.
Over: a room that closes when a negotiation concludes, with the Arvist running once at that close.
Why (reversal): the product outgrew "room equals one negotiation" the moment a talent needed an ongoing home conversation and a brand needed to return to the same thread days later instead of starting over. Once rooms stopped closing, closing could no longer be the signal for anything — durable memory would simply never update again after the first sitting. The fix reused the mechanism already built for the guard: the same per-room watch, armed by every reply, validated against a database row rather than trusted blindly. Arvist is chained to that audit, not given its own timer.
Cost: a returning participant has to correctly restart the Guard chain, and a room that never goes quiet never promotes anything to durable memory, which is the trade for permanence: an unusually long, continuous sitting has to actually end before its lessons travel anywhere else.
Chosen: every conversation a visitor starts through a talent's link is
its own permanent deal room. A bare visit reuses the visitor's newest room
with that talent only while it is still empty; once they have spoken, a new
visit starts a new room, and a signed-in brand with several conversations
picks between them (or starts another) on the chat page. Deep links —
/z/:slug/:roomId, /dashboard/agent/update/:roomId — make each one addressable
from an email.
Over: the earlier rule of exactly one deal room per talent-brand pair, looked up by the two account ids and resumed forever.
Why (reversal): one-room-per-pair assumed the brand was signed in before the room existed — the pair was the lookup key. Once anonymous visitors could start chatting, the room had to exist before any account did, and forcing every later conversation back into one thread turned distinct approaches (a spring campaign, an unrelated autumn one) into a single tangled negotiation. What actually needed continuity — the agent knowing the brand across conversations — is durable account memory's job, not the room's.
Cost: "which conversation am I in" becomes a real question, answered by the picker and by room ids in URLs; and the empty-room-reuse rule has to hold or bare revisits would litter the list with blank rooms.
Chosen: anyone can chat with a talent's agent anonymously. While the
room's brand side is an unclaimed guest, every outbound send and every offer
run is held as a durable pending effect — the persona's message is composed
at hold time and parked, the offer mint waits — and held effects are exactly
what flips the brand view's loginRequired. Claiming the room (signing in)
binds the account, seeds durable memory, and replays everything held, in
order.
Over: a login wall at the page before any chat starts (the first release's behaviour), or gating inside the chat component by client-side rules.
Why (reversal): the wall-at-the-page answer was always meant to be temporary, and the intended flow — chat first, sign in when the agent actually needs to move the deal — needs the gate to be a fact about the room (something is waiting that cannot be delivered), not a page's opinion. Held effects give the gate an honest trigger ("I was just about to share an update — sign in"), survive restarts, and double as the replay queue for the claim. A guest message cap rides on the same gate for cost control, with its own gentler copy.
Cost: everything that leaves a room now has one choke point that must stay correct — a new kind of outbound effect that forgot to check the guest state would leak past the gate — and pending effects are one more durable table whose replay order matters.
Chosen: the planner owns the shape of what it records and reorganises it as needed.
Over: a fixed structure with defined fields.
Why (reversal): the fixed version could not hold anything unanticipated. The example that broke it: a talent mentioning they are unavailable every October. Not a preference, not an offer, but decisive for any offer with an autumn timeline. A schema turns every new kind of human fact into an engineering task.
Cost: nothing downstream can assume a field exists — which is exactly why the few things code must read are carved out as reserved parts (next decision).
Chosen: the room declares its goals; the planner tracks each in a small fixed envelope with a status — open, met, blocked, abandoned — and code fires effects the moment a status flips: notify a participant, generate the formal offer.
Over: free-form completion flags scattered wherever the planner put them, or a fully engineered workflow outside the memory.
Why: the product needs to act on conclusions — a concluded negotiation must produce an offer document — and code cannot act on prose it has to interpret. The envelope is the compromise: the judgement stays with the planner, the trigger becomes mechanical. Two refinements came from watching it run: a goal can end in failure ("abandoned" is as terminal as "met", so a rejection stops steering the room), and a goal is about substance, not follow-up chores — a signature still needed from the talent does not hold a negotiation open, it becomes a push to the talent.
Cost: a small fixed island inside the otherwise planner-owned document.
Chosen: three stages — terms settled with the counterparty, approved by the talent, executed — and every role is required to use language that matches the actual stage.
Over: treating the end of the negotiation as the end of the deal.
Why (reversal): the system once told a talent their deal was "officially locked" — about a brand the talent had never heard of, before they had approved anything. The root cause was recorded state: the planner had written the deal into memory as final, and every agent downstream repeated the overstatement as fact, because agents trust the memory. The fix was made at the source: the planner may not record a deal ahead of its actual stage, terms are pushed to the talent framed as pending ("here is what I negotiated — do you approve?"), and nothing is called final until the talent's explicit yes.
The deeper lesson generalises: an overstatement written into memory does not stay one agent's mistake — the memory is the truth for everyone downstream, so honesty has to be enforced where the writing happens.
Cost: the language is less triumphant at the moment of closing, and one more round-trip (the talent's approval) stands between agreement and execution — by design.
Chosen: if an offer meets everything the talent asked for, the agent settles the terms without checking — but what it settles is explicitly subject to the talent's approval, which happens in the talent's own conversation afterwards.
Over: treating the talent's confirmation as a precondition of negotiating.
Why (reversal, twice): we watched a negotiation reach fully agreed terms and then stall indefinitely, because the agent kept waiting for the talent's sign-off — and the talent is deliberately unreachable during a brand conversation, so the condition could never be satisfied. The same instinct then reappeared in the planner, which refused to call a negotiation done while it still needed a shipping address. The distinction that fixed both: the negotiation concluding and the deal concluding are different events, and the stage model above is the explicit representation of that difference.
Cost: the system commits to terms before the talent has seen them, which is why the stage is named "pending approval" rather than anything stronger.
Chosen: persona agents are told that the conversation and the memory are the only things that exist — no inbox, no document viewer, no signing tool — and that they may confirm nothing on their own authority. The planner is explicitly responsible for catching an agent's unsupported claim and instructing it to walk the claim back.
Over: trusting the models not to invent.
Why (reversal): in one negotiation the brand-facing agent claimed to have received and reviewed a contract draft that was never in the system — the counterparty had merely said one was "sent over". The planner then recorded the review as fact, and fiction became state. Two changes fixed it: agents may not claim off-screen actions, and anything a counterparty says happened elsewhere is recorded as a claim, not a fact, until its content is actually in the chat.
Cost: occasional pedantry — an agent asking for text to be pasted into the conversation when a human might have let it slide. We consider that a feature: the chat is the record, so everything the deal rests on must pass through it.
Chosen: the planner's instructions to each agent live in a reserved part of memory, keyed per participant; the mechanism strips the whole branch from what any filter or agent can see and re-attaches to each agent exactly its own entry.
Over: keeping guidance in the general memory and trusting the context filter to give each agent the right part.
Why (reversal): the filter delivered one persona's guidance to another — the talent-side instructions, including references to a specific negotiation, went to the wrong agent. This is the same lesson the planner's private notes taught earlier, now applied a second time: a confidentiality guarantee should not depend on a model's judgement. If it matters, it belongs in the mechanism.
Cost: one more fixed part of the structure.
Chosen: room memory is transient and generous; what outlives the room is decided by a dedicated agent (the Arvist), which promotes what is durable about an account — including the deals it has closed — into a single long-term document per account.
Over: one ever-growing memory per person, or keeping nothing between rooms.
Why: the two layers want opposite virtues. Within a room, generosity wins — any detail might matter to this negotiation. Across rooms, selectivity wins — most of a negotiation's detail is noise a month later. One document cannot be both, so the promotion step is a deliberate act with its own judge.
Cost: a person's understanding is assembled from two places, and the Arvist is one more judgement that can be wrong.
Reversal — the private-notes sidecar: the durable layer was originally two documents, the second holding counterparty intelligence that could never enter another room. It was removed. The split looked like a confidentiality boundary but was not one: everything in it concerned the account it was stored on, and the real boundary — what a persona may see — is enforced per turn by recall, which selects branches rather than receiving the whole document. What the sidecar actually did was strand learnings. A closed deal's price would land in notes, never reach a future room, and the next negotiation would re-anchor from nothing. Confining the other party's profile to its own account is a rule the Arvist follows; it does not need a separate table to live in.
Chosen: when a bound account's durable memory is newer than the last seed or merge, AccUpdate runs before the planner, writes only that participant's branch (account wins on conflict), and announces the merge in the transcript as a system line. The playground shows a banner with the change list; product panes ignore the part.
Over: seed once at bind and never again; or merge silently so the planner sees new branches with no source.
Why: rooms are permanent, so a seed at bind goes stale the next time the Arvist writes. A silent merge looks like unsourced contamination to a planner told that everything must come from the transcript — it deleted the branch. Provenance plus a planner note treats the merge as verified standing knowledge from previous rooms.
Cost: one more model call when durable memory has changed, and a lock around the memory write so a concurrent planner cannot be clobbered.
Chosen: every agent runs the prompt that lives in code. Rooms and the ops dashboard can still pick models. The playground no longer edits prompts; ops shows them read-only.
Over: snapshotted prompts per room and per agent record, editable in the playground and ops, version-bumped on save.
Why: a prompt change is a behaviour change. It belongs in reviewable code so every room — including ones created weeks ago — picks it up on the next turn. Snapshotted prompts meant a talent-home room kept running an old planner that treated account-memory merges as contamination. The database columns stay for history; they are not read at run time. Named persona records still supply scripted personas that are not talent or brand.
Cost: you cannot tweak a prompt in the playground without a deploy. That is the point.
Chosen: the Arvist does not promote from a room that is running a mock tape. The skip is recorded as a run with no writes.
Over: relying on the scripted Arvist no-op, or promoting after a tape falls through to a live model.
Why: a demo tape is fiction. Promoting it writes a fake profile onto a real account, which then seeds every later room. The same spirit as suppressing push email from scripted rooms.
Cost: a scripted room teaches the account nothing, even if an operator later continues the conversation with live models.
Chosen: when a negotiation concludes, a dedicated agent (Offer-Gen) extracts the agreed terms into a formal offer document — the thing the parties sign and pay against. Memory keeps only a reference; the offer's live status, like a bound account's real facts, is shown to the agents at call time instead of being written into memory.
Over: letting the planner write the formal record through its free-form memory, or copying physical facts into memory.
Why: the record has exact fields and legal weight; the memory is deliberately opaque and interpretive. Coupling them means either constraining the memory to a schema (rejected above) or trusting an interpretive document as a contract. And any physical fact copied into memory starts aging the moment it is written — projecting it in at call time means it can never be stale.
Cost: one more model call at the moment of conclusion, and agents' knowledge of physical state is only as fresh as what is projected to them.
Chosen: the planner names the specific parts of its understanding that changed.
Over: returning a rewritten copy of everything it knows.
Why: a model rewriting a long document will occasionally drop an unrelated part, and the loss is silent. A targeted change cannot damage what it did not name. It also makes every change individually reviewable.
Cost: slightly more constrained output from the planner.
Chosen: a fast, simple filter that includes anything plausibly relevant, and selects existing sections rather than summarising them.
Over: a similarity-based retrieval system that fetches the closest-matching fragments.
Why: two reasons. An agent missing one crucial fact behaves confidently and wrongly, which is worse than an agent carrying some irrelevant detail. And because the filter can only point at recorded sections, it cannot fabricate a memory — a summarising step can.
Cost: more context than strictly necessary reaches the agents. The filter is also, by the same generosity, not trusted with confidentiality — that is enforced structurally (see guidance above).
Chosen: the conversation is partitioned into sessions — a new one starts when the planner reaches out unprompted or a participant returns after a long pause — and the planner and agents read only the current session. Everything earlier was already distilled into memory by the planner runs that followed each turn.
Over: re-reading the whole history on every turn, or trimming to a fixed count of recent messages.
Why: the full history makes each planner run cost grow with the square of the room's length, and it re-litigates exchanges that were already judged. A fixed message count is arbitrary and can cut mid-thought. The session boundary is the natural seam — it is how humans work too: an assistant remembers the relationship, not every word of every past meeting. A continuous sitting is never cut, however long.
Cost: the planner's view of the distant past is its own memory document, so anything it failed to record is genuinely gone from its working context.
Chosen: the planner watches every transcript for a participant losing patience — deflected asks, "is this a bot?", requests for a human — and raises a flag with a level and evidence, visible to operators and to no agent.
Over: a "talk to a human" button, or automatic behaviour changes on detection.
Why: there may be no human available to hand off to, and a promise of one that does not arrive is worse than none. The flag makes the situation visible to whoever is operating the system without changing any conversation on its own; if the agent should also behave differently, the planner writes that as ordinary guidance, separately and deliberately.
Cost: frustration handling is only as good as the operators watching the flags.
Chosen: the talking agents write like a busy human: a few sentences, one question at a time, and never repeating back what the person just said.
Over: the earlier instruction to reflect each answer back "so the person can correct you", and the default model tendency to recap the state of the deal in every message.
Why (reversal): the recaps were noise. Terms get restated many times and end in a written agreement anyway, so confirming each one in chat added length without adding safety — and long, formal replies read like a system, not an agent.
Cost: the occasional correction now happens a turn later than it might have.
The design trades compute for quality. Every model call is recorded with its token counts and its actual billed price, so this is measured rather than estimated. What the measurements say:
PlannerGuidAg run —
around 1-2 seconds — while the heavier PlannerDistilMemAg rewrite runs in
parallel with the persona's stream. We accepted that small delay deliberately
(see "the planner runs before the reply").A single-model design would be a fraction of the cost and noticeably faster. It would also leak between conversations, forget the talent between sessions, and have no auditable account of why it did anything.
Honest gaps, rather than a roadmap:
Escalation. Frustration is now flagged to operators, but there is still no defined point at which the system stops and fetches a human, and no guarantee an operator is watching. High-value or unusual situations arguably deserve a defined escalation path, not just visibility.
Guardrails on commitment. The agent settles terms and the talent approves. The boundary between those is now an explicit stage model, but it is still enforced by prompt and review rather than by a hard limit on what the agent can say yes to.
Memory quality over time. Session trimming means the planner's working context for the past is its own memory document. Anything it failed to record well is gone from view. The Arvist compounds this across rooms. The guard now audits a room's record against its transcripts and dispatch history, which catches false state — but it cannot recover detail that was never recorded, and nothing yet watches the durable memory for quiet degradation across rooms.
Operator tooling. Flags, run histories, goal events, and now the guard's health verdicts are recorded and visible, but acting on them — correcting a memory, overriding a goal, taking over a conversation — is still manual and ad hoc.
On This Page
Firewalled conversations in a room, not one shared threadA planner that decides, and agents that only talkThe planner runs before the reply, not after (and is split into two stages)The planner can reach out, but never speaksGuidance cannot deliver, and memory may not claim it didA guard audits quiet roomsRooms never close; a quiet-room Guard chain replaced closing as Arvist's triggerA deal room per conversation started, not one forced room per pair (reversal)The login gate lives in the mechanism, as held effects — not at the pageFree-form memory, not a defined schemaGoals are structured envelopes inside the free-form documentDeals move through explicit stagesThe negotiating agent settles, the talent approvesAgents are grounded, and the planner reviews themGuidance is routed by code, not by the filterTwo memory layers, with a gatekeeper between themStanding knowledge is merged in, and announcedPrompts are the code, not a settingScripted rooms never write durable memoryRecords are made by a specialist, and projected rather than copiedTargeted changes, not document rewritesA generous context filter, not clever retrievalThe transcript is read by session, not in fullFrustration is flagged to operators, not handled by a handoffReplies are short, and never echoCost and latency, measuredOpen questions