A check in your CI: flow test
Early access. Make your agent’s CI key in the Observe dashboard (Get access); if Observe isn’t on for you yet, write to the Flow team at samyak@flow.engineer or prabal@flow.engineer. The
flow binary is a public download (below).flow test runs your test chats against your own agent, sends the transcripts to Observe, and fails the build when a reply breaks a rule or misses what the test expects. Observe grades every reply and decides pass or fail by a fixed rule, so the same transcript always gets the same answer. Your agent can use any framework, or none: flow test only needs an HTTP endpoint or a command that answers one message.
1. Write test chats
Put them in.flow/tests.yaml in your repo. Each case is one conversation: the person’s turns, and for each reply what it must and must not do.
expect: plain sentences a grader checks.includesandmust_not: exact text, case-insensitive.rubrics: rule ids from your check set that must pass.
2. Let flow test reach your agent
Start your agent in the CI job, and give flow test one of two ways to send it a message:
-
--http URL:flow testposts each turn as JSON:Your agent answers with{"replies": [{"text": "..."}]},{"reply": "..."}, or a plain-text body. Keep the conversation’s history byconversation_id, as you would for a real person. -
--cmd "...":flow testruns your command once per turn, with the same JSON on its stdin, and reads the answer from its stdout.
flow.conversation_id to the conversation_id it was given. Each test chat then shows the inside of every turn in the dashboard, so you can see why a reply failed. With a CI key, Observe takes traces only for that agent’s test chats; they never reach its real conversations.
3. Run it in CI
GitHub Actions
flow is published for Linux and macOS, on x86-64 and arm64, on the SDK’s releases page, with a SHA256SUMS file to check it against. Any other CI works the same way, as shell steps.
flow test prints a line per case, and for a failure, which expectation it missed and which rules failed:
0 when every case passes, 1 when one fails, and 2 when it couldn’t run (your agent didn’t answer, or Observe couldn’t be reached). --junit writes a report your CI can show.
- The key. Use your agent’s CI key (
oci_...), kept in your CI’s secret store asFLOW_CI_KEY. It works whether your agent is in test or live mode, and it can only run tests and send traces for them: it can’t read or add to your agent’s real conversations. Trace keys are refused.flow testnever prints the key. - Limits.
- Up to 50 cases per run, 20 turns per case and 2,000 characters per message. Replies can be up to 8,000 characters.
- A few runs per agent at once, and a daily budget of graded test replies.
- When Observe is busy,
flow testwaits and retries.
Also today
Every test conversation is graded. Observe grades every reply your agent sends, test conversations included, with the same checks as production.-
On Flow Messaging: simulated contacts play chats through the real send gate. Each reply’s verdict shows in the Observe dashboard.
TypeScript
-
Failures become issues. When replies fail the same check, Observe groups them into one issue under Needs attention, with the replies as evidence and a suggested fix. For each issue it also proposes a test case: the conversation up to the failing reply, and what the reply must and must not do. Copy it into
.flow/tests.yaml.
Coming
These are being built with the first early-access teams. Their shape may change before they open.
- Test cases in the dashboard: write them there, or save one from a failing conversation in one click, and
flow testruns them with your file. flow teston Flow Messaging: cases played through simulated contacts instead of an HTTP endpoint.