Generate, upload, and push scripted scenarios from the browser, then open the room it creates — no terminal needed
The Z-Agent Author tab covers the whole scripted-scenario loop without
leaving the browser: draft or upload a .zas script, push it under a handle,
create a room from it, and either drive that room by hand or run the entire
scenario automatically with its assertions. The same panel is still on the
standalone Playground as a Zauthor tab next to DevCon.
Nothing here is a separate implementation — it is the same
author/compile/upload/create-room/replay pipeline the CLIs use. zauthor's
drafting and zreplay's turn-driving loop and assertions both live in shared
modules that the CLI and these routes call, so a fix for one is a fix for both.
A script pushed from the tab replays identically under zreplay, and a script
authored by zauthor can be pasted straight into the tab's textarea.
On the Z-Agent admin dashboard (/admin/z-agent), open the Author tab.
The same panel is still on the standalone Playground (/z-agent/playground)
as a Zauthor tab next to DevCon.
The tab needs no session beyond the one the Playground already has: it is
admin-only, same as every other Playground endpoint, and it is only reachable
at all when the server has Z_AGENT_MOCK_ENABLED=true. No bearer token — that
exists for zpush, which has no browser session to carry.
Two separate model calls, so you can review the people before paying for a script, and regenerate the script after a hand-edit without inventing new personas.
Generate briefs calls POST /api/z-agent/mock-tapes/briefs. That invents
talent.md and brand.md in the same guide shape as
packages/z-agent/srv/scripts/test-scenario/ — second-person sheets with
floors, ceilings, deliverables, and a voice. Numbers from the sketch stay
exact; names and texture are filled in. Each brief can be edited and
downloaded.
Generate script / Regen script calls
POST /api/z-agent/mock-tapes/author with those briefs (not a folder on
disk). Outcome, turn count, and extra direction apply only to this second
call. The draft lands in the Script box, which can also be edited and
downloaded.
Open in Push & create a room pushes the script, creates the room, and opens it in a new browser tab — the same as the Push tab's Push & create room button. Account / real-room options still live on that tab if you need them first; use the tab itself rather than this shortcut.
These two generate actions are the ones that spend real tokens. Uploading, pushing, and creating a room are all free.
If the script draft fails validation — say, an abandoned outcome that still
minted an offer — the error is shown, and the invalid draft is loaded into
the Script box anyway. It is usually one beat away from correct, and fixing
it by hand there is cheaper than generating again.
One shared textarea underneath, fed by whichever of these you used:
.zas. Works on Vercel as well as locally; details
under Push & create room belowDownload saves whatever is currently in the box as a .zas file, with no
server call at all — useful if you only wanted the CLI-equivalent output to
commit by hand.
Load an existing scenario lists every checked-in folder under
packages/z-agent/srv/scripts/test-scenario/ that already ships a .zas
(MaraVsDev, KenjiVsSolstice, and so on). Picking one fills the script box
and the handle from that folder — the same as uploading the file by hand.
That picker works on a Vercel deploy, not only on a machine with the repo
checked out. The scenario folder itself is not copied into the serverless
function, so at build time the files are inlined into
packages/z-agent/srv/src/mock/bundled-scenarios.generated.ts. Locally the
server still prefers the files on disk, so an unsaved edit shows up without
rebuilding. If you add a new scenario folder, run:
npm run bundle-scenarios --workspace @zooly/z-agent-srv
The zooly-app production build also runs that step, so a deploy picks up
new folders even if it was skipped. A unit test fails when the generated
copy is stale relative to the folder.
GET /api/z-agent/mock-tapes to
show later@offer beat's effect is
skipped rather than failingdeal room instead of a playground one, so the
conversation shows up in both accounts' own /dashboard/conversations
instead of only the admin playground. Needs both accounts above bound;
disabled while Guest brand is checked. An offer minted this way is
still flagged isDemo and appears marked Demo in Offers & Deals — see
Zreplay's --real-roomPush & create room does two calls in sequence:
POST /api/z-agent/mock-tapes?id=<handle> — stores the script's source
under the handle. Compiled first, so a malformed script is rejected here
with its line number, not later as a confusing mid-conversation error.POST /api/z-agent/mock-tapes/<handle>/rooms — creates a room that reads
its replies from that handle, with the accounts bound if you gave any, and
with realRoom / guestBrand / sendEmails applied as checked.On success, the new room opens in a new browser tab at
/z-agent/playground?room=<id> (Talent view), so this Zauthor tab keeps the
script, the public z-link, and Run full flow. An Open room button
appears as well if you need another tab of the same room. The room is added
to this Playground's room list without leaving Zauthor. A failed push closes
the extra tab instead of navigating it.
The last section runs the whole scenario for you instead of leaving you to
drive it — the same walk zreplay gives a scenario from the terminal, and the
same assertions, reported in the browser.
It takes a room id, prefilled from the room the section above just created,
but editable so you can point it at any scripted room — one made earlier by
zpush --create-room, or one you replayed last week. An optional force
ZGuard + Arvist checkbox exercises the quiet-room chain at the end, the
CLI's --guard. ZGuard then kicks Arvist as a separate request; the
replay result reports whether that kick was dispatched, not the promotion
outcomes.
POST /api/z-agent/rooms/<id>/replay rewinds the room's mock cursors, sends
every scripted human line through the real chat pipeline, adopts each planner
push as it lands in the other conversation, and then checks:
isDemo
so Offers & Deals can mark it Demomock:The result renders as a pass/fail banner, the problems if any, the goal and offer comparison, and a collapsible transcript with each pushed message marked so you can see the cross-pane wakes land.
Cursors are rewound, but stored messages are not cleared — so this is best run
on a room fresh from Push & create room. Run it on a room you have already
chatted in and the whole script is appended after that history, exactly as
zreplay --room behaves on a reused room.
A real cost showing up here is worth reading carefully: if the offending run's
model id still starts with mock:, that agent was routed correctly and simply
ran past the end of its script, so the script needs another beat. If it does
not, that agent was never routed through the mock at all — which is the bug the
whole scripted-replay exercise exists to catch.
The room the tab creates is left exactly where the script starts — nothing is sent automatically, so you drive it by hand in the Talent/Brand tabs.
A scripted agent ignores whatever you actually type and serves its next scripted line regardless, which is what makes the room usable for a demo as well as a test: you can type anything and the conversation still goes where the script says it goes.
If you keep going past the end of the script, the room does not error — it
falls back to a real model for that one call and keeps the conversation
running, logging a warning server-side. That is a deliberate difference from
zreplay, whose headless runs assert that nothing costs anything; a
fallback there is a signal the script needs another beat, not something to
paper over. In the Playground, past the end of a script is simply past the
end of a demo.
| If you want to... | Use |
|---|---|
| Draft or push a script from a terminal, in CI, or against a remote server | Zauthor and Zpush |
| Run a scenario headless in CI, with a non-zero exit code on failure | Zreplay |
| Draft, upload, or push a script and click into the room | This tab |
| Run a whole scenario and read its assertions without a terminal | This tab's Run full flow |
The script format itself — panes, human blocks, beats, @offer — is the same
everywhere and is documented once, on the Zauthor
page.