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 visitor-facing agent cannot reveal the host's real floor because it was never told it in those terms. It also decouples the parties in time — the host 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 to host / visitor seats: a room now holds any number of participants under the same rules. The two-party inbound negotiation (Bouncer) is the first product on it, not the shape of it. Accounts themselves have no stored type — see Services, Seats, and Derived Role.
Cost: something has to carry information between the conversations. Today that is the agents themselves: each one sends what another participant is owed.
Chosen: the agent speaking in a conversation runs it. In the same turn as its reply it rules the room's goals, sends any message another participant is owed, and keeps its own working plan. A separate memory writer reads the conversation afterwards, in the background, and only records facts.
Over: a planner that read everything, made every judgement, and steered agents that only talked.
Why (reversal): the planner had to be slow to be good, so it ran beside the reply instead of before it, and the two ended up working from different pictures. In one rehearsal the brand-side agent told the brand "I'll take this to the talent now." The planner judged the brief incomplete, held the message on every run, and noted privately that the agent should keep asking who the brand was. The agent never saw that note, the talent never got the message, and the brand believed it had been sent. The channel that once carried the planner's instructions to the agents had already been retired (see "guidance cannot deliver"), so there was no way left for the two to agree. With the decisions made by the agent that speaks, what it says it will do and what it does happen in one turn.
Cost: the speaking agent now makes the goal and delivery calls, so its judgement matters more than it did. A goal can be ruled met before the background writer has recorded the details it rests on, so effects that need those details wait for them — a campaign is saved once its accepted name is recorded. The guard still audits every room that goes quiet.
Chosen: the reply starts at once. The memory writer runs alongside it, and what it records is ready for the next turn.
Over: a steering step that had to finish before every reply could begin.
Why (reversal, twice): the first version caught up after the reply, so the agent answered using an understanding that predated the message in front of it. A fast steering step in front of the reply fixed that, but it delayed the first word of every turn and was later removed for speed — which left the planner able to know the plan but unable to tell the agent. Moving the decisions to the speaking agent (above) closes both problems: it reads the message it is answering, and nothing has to run before it.
Cost: facts the person just stated reach memory one turn later. The agent's own plan carries its intentions between turns in the meantime.
Chosen: when something must be told now — a deal came together, awaited information arrived, the principal gave an instruction — the agent in the conversation where it happened sends the substance to the other participant, and that participant's agent is woken to deliver it in its own voice.
Over: letting one agent write into another participant's conversation 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. Splitting the what (the sending agent) from the how (the recipient's agent) 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 message that referred to "the brand chat" was flatly rejected by the recipient — correctly, since from their side no such thing exists. Before anything goes to the other side, the agent still asks once whether there is anything to add; after that answer, the message goes out in the same turn, with any missing terms named as open questions rather than held back.
Cost: an interruption channel that must be used sparingly; the agents are instructed that a message 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.
Guidance has since been retired entirely. The agent that promises a delivery now makes it, in the same turn.
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: nothing reviews an agent's reply as it goes out, 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 — an account keeps exactly one home room for its agent for life, and every conversation a visitor starts with a host stays open forever — and the Arvist's promotion into durable memory fires on the same debounced "room went quiet" signal ZGuard already uses, on a longer window, rather than on the room ending. Update Agent is the exception (ZLY-1897): after Distil lands on a live home room, Arvist promotes the host sitting immediately. The quiet chain stays as catch-up. A new deal room seeds the host from the home host branch when that document is newer than durable.
Over: a room that closes when a negotiation concludes, with the Arvist running once at that close; or making durable the only home document and projecting it back into the room.
Why (reversal): the product outgrew "room equals one negotiation" the moment a host needed an ongoing home conversation and a visitor 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. Hosts then tested z-link immediately after Update Agent, so the home room also promotes on Distil instead of waiting for quiet.
Cost: the two audits still share one chain with two different windows — ZGuard first (1 min), then Arvist (remainder of the 10 min quiet target) — so a deal room that never goes quiet still does not promote. Home pays one extra model call per Distil. Room memory stays the sitting's working document; Arvist stays the curator.
Chosen: every conversation a visitor starts through a host's link is
its own permanent deal room. A bare visit reuses the visitor's newest room
with that host only while it is still empty; once they have spoken, a new
visit starts a new room, and a signed-in visitor 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 host-visitor pair, looked up by the two account ids and resumed forever.
Why (reversal): one-room-per-pair assumed the visitor 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.
A booked offer still must not be rewritten in that room. A change after dual Approve (or a new campaign after 7 days of silence) is another always-insert deal room for the same pair — see Sibling rooms for a new offer.
Chosen: anyone can chat with a host's agent anonymously. While the
room's visitor side is an unclaimed guest, every outbound send and every offer
run is held as a durable pending effect — the planner stores the
substance, not a frozen spoken line; the offer mint waits — and held effects
are exactly what flips the visitor view's loginRequired. Claiming the room
(signing in) binds the account, seeds durable memory, and replays everything
held, in order. At delivery the persona composes against current memory and
the DEAL STAGE block (heldPushMustConvey), so news that waited on signup
is spoken as it stands now.
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 agent speaking in the conversation rules each one 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. (The planner ruled goals until the agents took over the decisions; see above.)
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 host does not hold a negotiation open, it
becomes a push to the host. Abandoned of new-offer still runs reject-offer
so the written row is closed (ZLY-1935); met of new-offer still mints.
Cost: a small fixed island inside the otherwise planner-owned document.
Chosen: the deal's stage is a physical-layer fact, derived by code from the
offers row (status + brandApprovedAt) and shown to every agent as one
canonical vocabulary in offer-stage.ts. No model infers a stage, and no
model writes one into memory. The same table is embedded in every prompt that
can name a stage (DEAL_STAGES).
| Stage | What it means |
|---|---|
NO_WRITTEN_OFFER | Chat only. Anything agreed in conversation is negotiation. |
WRITTEN_OFFER_DRAFT | A document is being drafted; the talent has not approved. |
WRITTEN_OFFER_AWAITING_TALENT | The brand submitted the written offer. The offers-system label is APPROVED — that word is never shown to agents as a stage. |
BRAND_ACKED_AWAITING_TALENT | Brand clicked Approve first (brand_approved_at). Acknowledgement only — not a booking and not pay. |
TALENT_COUNTERED | The written offer is in status COUNTERED (respond API / auto-counter). An Offer-tab Counter click is not this stage until Z rewrites the row. |
BOOKED_AWAITING_PAYMENT | The talent approved the written offer. This is the booking. The brand must now pay the phase that is due. |
BOOKED_PAYMENT_HELD / BOOKED_PAID / BOOKED_IN_DELIVERY | Talent approved and the brand has paid (held, captured, or in delivery). |
COMPLETED / DISPUTED | After a booking. |
DECLINED_BY_TALENT / CANCELLED / EXPIRED | No booking. |
How the offers row maps onto that vocabulary (deriveOfferStage in
offer-stage.ts):
Offers status | Canonical stage |
|---|---|
| (no row) | NO_WRITTEN_OFFER |
DRAFT | WRITTEN_OFFER_DRAFT |
APPROVED and brand_approved_at empty | WRITTEN_OFFER_AWAITING_TALENT |
APPROVED and brand_approved_at set | BRAND_ACKED_AWAITING_TALENT |
COUNTERED | TALENT_COUNTERED |
ACCEPTED | BOOKED_AWAITING_PAYMENT |
PENDING_PAY_CAPTURE | BOOKED_PAYMENT_HELD |
PAID | BOOKED_PAID |
DELIVERED / REVISION_REQUESTED | BOOKED_IN_DELIVERY |
COMPLETED | COMPLETED |
DISPUTED | DISPUTED |
REJECTED | DECLINED_BY_TALENT |
CANCELLED | CANCELLED |
EXPIRED | EXPIRED |
Only BOOKED_* (and COMPLETED / DISPUTED after them) are a booking. Agents
must never use the bare words "accepted", "approved", "terms settled", or
"principal approved" as a stage, and must never read offers-system labels
aloud.
The principal saying yes in chat is not a stage. Distil records it at
pendingPrincipalDecisions.<key>.principalInstruction. It authorises the
agent to settle terms and to have the written offer drawn; it exists for
either side; it can be withdrawn when the terms move; it never moves the
stage. Personas describe it as the principal instructing them to take the
terms, never as "the principal approved".
Over: treating the end of the negotiation as the end of the deal; calling settled terms "accepted"; treating a chat yes as the same thing as the talent approving the written offer; letting Distil invent a stage in memory that Guard and the personas then treat as ground truth.
Why (reversal): the system once told a brand counterparty that "Sophie Bell accepts these terms, and the performance is officially booked" — before Sophie had even opened the message, and right before she declined due to unavailability. Two bugs compounded to cause this:
APPROVED means
the brand submitted the offer to the talent (it is waiting on the
talent). When buildOfferFacts rendered live DB status as status APPROVED into planner context, the model read it as the talent's sign-off.A later room showed the same split in a new form: Distil wrote a free-text stage into memory, Guard raced Distil and told the brand no further sign-off was needed, and a persona walked back a true relay of the talent's chat instruction because SELF_REVIEW treated a planner push as its own claim. Two definitions of "yes" (chat vs written offer) and two memory writers in parallel made the record argue with itself.
The fix was applied across multiple layers:
OFFER_STAGE_VOCABULARY. Distil never writes a stage; memory may hold
offers.<key>.offerId only.describeOfferStage renders STAGE — gloss into
Distil, Guard, and both personas (DEAL STAGE — GROUND TRUTH). A room with
no written offer is NO_WRITTEN_OFFER.pendingPrincipalDecisions.<key>.principalInstruction, per side, never a
booking.personaIdentityDirective forbids declaring a
booking unless the DEAL STAGE block shows a BOOKED stage, even if memory
or guidance says otherwise. Planner deliveries marked [relayed …] are
never walked back.heldPushMustConvey), not frozen wording.Cost: the language is less triumphant at the moment of closing, and the written offer — not the chat — stands between agreement and a booking, by design.
After chat agreement, the product still collects two clicks on the
written offer and then brand payment. Brand Approve first is acknowledgement
(brand_approved_at, status stays APPROVED, no pay) —
BRAND_ACKED_AWAITING_TALENT. That stamp is version-specific: a material
rewrite (after Z is asked to change terms, including Add or Counter)
clears it, so the brand must Approve the new terms before talent can book
(ZLY-1932). Talent Approve on
the document is the booking (ACCEPTED → BOOKED_AWAITING_PAYMENT). Offer-tab
Counter, Reject, and Add are intelligent-only shortcuts into chat:
they post a chat line, switch to Conversation, and leave the row until Z
updates or closes it (ZLY-1935). Last-look still applies. Abandoned of a live
new-offer goal runs reject-offer.
The brand then opens View payment / Send Payment (due slice + 20% fee). A successful card is
PENDING_PAY_CAPTURE → BOOKED_PAYMENT_HELD. Personas are told those events
in this vocabulary; they must not collect cards or declare the offer paid in
chat. See
Offer approval and brand payment.
Chosen: if an offer meets everything the host asked for, the agent settles the terms without checking — but what it settles is explicitly not a booking. When no mandate covers the decision, Distil asks the principal and records their chat yes as an instruction. The booking happens only when the talent Approves the written offer in the product.
Over: treating the host's confirmation as a precondition of negotiating, or treating their chat yes as the booking itself.
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 visitor 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, the principal's chat instruction, and the written-offer booking are different events, and the stage model above is the explicit representation of that difference.
Cost: the system can agree terms in chat before the host has seen them, which is why a chat yes is an instruction, never a booking.
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: reading links in chat (scrapePublicUrl) uses Gemini URL Context (url_context)
with fail-closed verification of retrieval status and a manual HTTP fetch fallback, strictly
extracting the specific page's title and content without Google Search grounding.
Over: general search grounding or unconstrained web crawling for chat links.
Why: in a deal room, a counterparty pastes an unindexed brief, campaign deck, or private proposal. Open-ended search grounding would cause the model to pull in external, public web search results on similar brand topics and hallucinate terms that were never in the actual document. Perception in chat is strictly "read this exact URL", not "research this topic". Open web search grounding is reserved for Onboarding Profile Research where discovering external public sources is the explicit objective.
Cost: links that require authenticated logins or cannot be fetched by Google or the manual HTTP reader are treated as unreadable; the agent must ask the user to paste the relevant text.
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.
Guidance is retired now, but the rule carried over: each agent's working plan is kept in a hidden part of memory, and the mechanism shows each agent only its own plan. A plan is never shown to the person as a memory and never carried into the account's long-term memory.
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.
Chosen: when a leaf of durable account memory actually changes, code records one calendar date beside the document — when that value last changed — and projects it into the Arvist's prompt. Room memory is not stamped. First-created is not stored; the date exists so we can tell if a fact is extremely old.
Over: asking the Arvist to date its own writes; or stamping every planner write inside a room; or keeping both first-recorded and last-changed.
Why: the planner can date events (a close, a campaign) because those have a date in the conversation. Standing facts — a floor, a hard rule — do not. "When was this last treated as current knowledge" is a property of the write, and a model reporting on its own bookkeeping is the same class of claim as the dispatch record: memory holds what it meant to do, the physical layer holds what happened. Rooms are the length of one sitting, so staleness is only a durable-memory problem.
Cost: existing leaves stay unstamped until they next change; we do not invent a date for history written before the column existed. The planner never sees the dates, so a sitting can still act on a fact that has gone extremely old.
Later: two ways to put a human look on old facts are still open — project only the extremely old leaves into the planner when this room can verify them, and a monthly adviser that pushes only when something is actually stale. See Future work: asking whether old facts still hold.
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. Bind itself already prefers a newer home host branch over durable (ZLY-1897) so a z-link opened in the next second is not empty. 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 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 host or visitor.
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. A second specialist, AgreementAg, then turns that Offer into a lawyer-reviewable English draft. It receives only the Offer's commercial fields — never the transcript or memory — and must not invent a term the Offer did not already hold.
Over: letting the planner write the formal record through its free-form memory, or copying physical facts into memory, or letting the agreement draft re-interpret the chat.
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. The agreement draft is a later projection of the same Offer, so it stays current by fingerprinting those commercial fields rather than by reading the room again.
Cost: one more model call at the moment of conclusion, another when the Offer changes, 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:
A single-model design would be a fraction of the cost and noticeably faster. It would also leak between conversations, forget the host 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 in chat; a principal yes there is an instruction; the written offer is the booking. The physical stage is now code-owned, but what the agent may say yes to in chat is still prompt and review rather than a hard limit.
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 threadThe agent in each conversation decides and acts; memory is written in the background (reversal)Memory is distilled beside the reply, never in front of itAgents reach out to each other's participants, in the recipient's voiceGuidance cannot deliver, and memory may not claim it didA guard audits quiet roomsRooms never close; quiet remains Arvist's catch-up, Update Agent promotes on DistilA 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 physical stagesThe negotiating agent settles; the written offer booksAgents are grounded, and the planner reviews themLink perception uses URL Context, not open-ended web searchGuidance is routed by code, not by the filterTwo memory layers, with a gatekeeper between themRecording dates on durable memory are written by codeStanding 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