Try it in the playground
PlaygroundTest the same agent across channels and inspect every tool call.
The playground runs your actual messaging agent with test people. Switch between WhatsApp, SMS, iMessage, Telegram and web to see how the same agent replies on each interface.
Start it
Section titled “Start it”From your project folder, with a model key set in .env:
npm startOpen the URL it prints. The starter uses PORT, else 8788 or the next available port.
Choose a person and a channel
Pick one of the test people and send a request such as “What’s on the menu?” The playground uses that person’s identity and history on the agent’s declared channels.
Inspect the tool call
Turn on Debug to see which tools ran and how long the reply took. For the menu request,
look for get_menu and a reply based on its result.
Try a change of mind
Send “a large latte” and then “oat milk actually.” Watch how the agent combines the messages or reads a new message while a tool is running.
Start a fresh conversation
Use Clear history before repeating a case from the beginning. Switching channels keeps the person’s conversation; it does not reset the test.
Who can the playground play?
Section titled “Who can the playground play?”Declare test people on the agent. For example, include these options when building it:
testPeople: [ { name: "Sam", phone: "+15555550102" },],A test person is resolved the same way as someone writing from a real channel. Replies return to where the person last wrote, in the playground or on their phone.
From Framework 0.8.1, traces of playground turns (and of
flow chat) carry chinwag.via = "playground", so the dashboard keeps them apart from real
traffic. Turns from the person’s phone have none.
Build your own playground
Section titled “Build your own playground”The starter wires this up already. For your own entry point, pass the playground’s event sink when building the agent:
import { simulators } from "@flow-engineer/flow/simulators";import { buildAgent } from "./agent.ts";
const play = simulators({ title: "My agent" });const agent = buildAgent({ events: [play.events] });const { url } = await play.listen(agent, 8788);console.log("Playground: " + url);Your buildAgent must declare the channels and test people you want to exercise.
Time, reminders and nudges
Section titled “Time, reminders and nudges”The Person view lets you inspect scheduled and held messages and the agent’s wake-ups, set the person’s time zone and quiet hours, and send nudges. To move time, connect the playground clock to both the simulator and the agent:
import { playgroundClock, simulators } from "@flow-engineer/flow/simulators";
const clock = playgroundClock();const play = simulators({ clock });// Supply now: clock.now when creating the agent.See reminders and nudges for delivery rules and scenario testing for repeatable checks.
The agent’s records
Section titled “The agent’s records”For an agent that declares collections, the Records tab lists its own records,
every person’s, by collection. It shows the newest 200 with each collection’s full count and how
many older records it leaves out (flow records export lists every one). It is read only and
refreshes after each turn. Clear history forgets the person, which also deletes
the records that name them in a people field.
Test sign-in
Section titled “Test sign-in”Give simulators an authentication({ channel, visitor }) hook. The person picker then offers
New user · signed out. The hook returns a sign-in URL until your app verifies the visitor,
then the account’s key and channel address.
Each interface authenticates independently. Existing test people keep their identity shortcut. The authentication guide has the complete setup.
Serve the playground on a deployed agent
Local previews accept requests from localhost and the playground’s own page. On a deployed
agent, mount play.handler(agent, { token }) with a token of at least 32 characters.
The handler exchanges a ?token= link for a cookie scoped to the playground path and limits
wrong-token attempts. Keep that link private.
Thanks, we read every comment.