Skip to content

Ask the docs

Answers come only from these docs and are written by an AI model (Gemini), so check the linked pages. Your question is not kept. Do not include personal details or keys.

Test 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.

From your project folder, with a model key set in .env:

Terminal
npm start

Open 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.

Declare test people on the agent. For example, include these options when building it:

Agent options
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.

The starter wires this up already. For your own entry point, pass the playground’s event sink when building the agent:

src/main.ts
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.

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:

Shared test clock
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.

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.

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.