Choose an approach
The approaches go from lightest to heaviest:- Playground: ask the Customer Agent one question at a time in a private chat. Use it to spot check an answer after you change something.
- Test mode: the Customer Agent runs on your real threads and adds private timeline entries showing what it would have replied, without sending anything. Use it to see how your current setup behaves on real traffic before you assign the Customer Agent in live mode.
- Staging workspace: run the same set of test questions against a candidate version of your instructions and knowledge in a second workspace, through the API. Use it when the Customer Agent already replies to customers and you want repeatable evals of a change before it goes live.
Run evals in a staging workspace
A staging workspace is a second Plain workspace that holds the version of your instructions and knowledge you want to test. Your eval script starts a chat thread for each test question, assigns it to the Customer Agent in live mode, and reads the Customer Agent’s reply and agent status. Chat keeps the setup small: the Customer Agent replies on the thread, so you don’t need to set up email in the staging workspace.1
Set up the staging workspace
Create a second Plain workspace and add the knowledge sources and custom instructions you want to test. The workspace needs live chat and the headless portal on its plan, and credits, because the Customer Agent uses credits in live mode. Enterprise customers can ask Plain to set this up on a staging workspace.
2
Create a machine user and API key
In the staging workspace, create a machine user and an API key. The steps below need these permissions:
customer:createandcustomer:editthread:create,thread:read, andthread:assignchat:createandtimeline:read
3
Set the candidate instructions
Set the instructions you want to test with
updateSetting, as shown in set instructions with the API. Setting them from your eval script keeps each run tied to the exact text it tested.4
Find the Customer Agent's machine user
The Customer Agent is the machine user of type
AI_AGENT that isn’t a connected agent. Look up its ID once and reuse it for every assignment.5
Start a chat thread for each test case
For each test question, create a customer with
upsertCustomer, create a thread for that customer with channel: CHAT, then send the question as the customer with sendCustomerChat.6
Assign the thread to the Customer Agent in live mode
Call
assignThread with the Customer Agent’s machine user ID and agentMode: LIVE.7
Read the result
Poll the thread until
agentStatus is HANDLED or HANDED_OFF, or the Customer Agent is no longer assigned, then read the reply from the timeline.8
Apply the change to production
When the evals pass, copy the same custom instructions and knowledge sources to your production workspace.
Find the Customer Agent’s machine user ID
This query returns the Customer Agent’s machine user by filtering out connected agents:Start and assign a test thread
These four mutations create a test customer, start a chat thread, send the test question as the customer, and assign the thread to the Customer Agent in live mode:Read the Customer Agent’s result
This query returns the thread’s agent status, its assignee, and the chat messages on its timeline:agentStatus is empty until the Customer Agent picks up the thread, then IN_PROGRESS while it works. The run has finished when one of these is true:
agentStatusisHANDLED: the Customer Agent replied. Its reply is theChatEntrywith aMachineUserActoragentStatusisHANDED_OFF: the Customer Agent passed the thread to your team.agentStatusDetail.reasonholds a code such asKNOWLEDGE_GAP,TALK_TO_HUMAN_REQUESTED, orNO_RESPONSE_NEEDED, and any hand-off message is aChatEntrywith aMachineUserActor- The Customer Agent is no longer assigned and
agentStatushasn’t changed: the Customer Agent stopped without replying, for example after an error. It leaves a note on the thread saying why
Caveats when running evals
Three things decide whether an eval gets a reply:- Run the script with a machine user’s API key:
sendCustomerChatonly accepts a machine user, so you can’t send test questions through the Plain MCP server, which acts as the signed in user. - Send the question as a chat: a thread started with
createThreadcomponents gets its reply by email. Until you set up email in the staging workspace, the Customer Agent can’t send that reply, so the thread gets no reply andagentStatusstaysIN_PROGRESS. - Keep credits in the staging workspace: when the workspace runs out of credits, the Customer Agent hands off with the reason
OUT_OF_CREDITSinstead of answering.

