> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Train agents with AI roleplay in Practice Studio

> Practice Studio lets an agent rehearse a hard conversation against an AI that plays the customer, then read an automatic score with coaching feedback. Supervisors curate the scenario library; agents run sessions from Quality → Practice.

# Train agents with AI roleplay in Practice Studio

Practice Studio is AI-simulated-customer roleplay training for human agents. It flips the roles of a normal QA loop: instead of scoring an agent after a real call, it gives the agent a safe sandbox to rehearse the hard conversation *before* it happens. An AI stays in character as the customer — frustrated, confused, or angry — and the agent practices handling it. When the session ends, an automatic score with written coaching feedback shows the agent what landed and what to work on.

Everything runs inside the dashboard and the API. No real customer is ever contacted — the roleplay is an in-app simulation, so no calls, messages, or charges result from a session.

## Who uses it

Two roles work in Practice Studio, mirroring the agent/supervisor split across the Quality section:

* **Agents** rehearse. They open **Quality → Practice**, pick a scenario, run a session turn by turn, and read their score and coaching feedback afterwards. An agent sees only their own session history.
* **Supervisors** (owner, admin, or supervisor roles) curate the scenario library. They pick which built-in scenarios are available to the team and can define custom scenarios with a persona, an objective, and a scoring rubric. A supervisor sees the whole team's session history.

A session never feeds an agent's evaluation record, the acknowledge/appeal lifecycle, or the gamification leaderboard. It is training data only.

## 1. The dashboard: Quality → Practice

Open **Quality → Practice**. The surface has two working areas:

### Scenario library

The library lists every scenario your team can run. Each scenario card shows its title, the channel it simulates (chat, voice, or email), its difficulty tier (intro, intermediate, or advanced), and a summary of the situation. Three built-in scenarios ship with the product, covering the classic hard conversations:

| Scenario                 | Persona                                         | What it drills                                                         |
| ------------------------ | ----------------------------------------------- | ---------------------------------------------------------------------- |
| Duplicate charge dispute | A frustrated small-business owner charged twice | De-escalation, empathy, offering a concrete resolution with a timeline |
| Login loop               | A non-technical user stuck signing in           | Plain-language, step-by-step troubleshooting, confirming the fix       |
| Enterprise outage        | An angry IT admin demanding accountability      | Taking ownership without deflecting, next steps without over-promising |

Supervisors manage the library from the same surface: add a scenario, retire one (`is_active` off removes it from the picker without losing history), and review how each one is performing.

### Running a session

An agent picks a scenario and starts a session. The AI opens as the customer; the agent replies in chat as they would on a live conversation, and the AI answers in character — warming up when the agent helps, staying difficult when they don't. Session signals (mood, satisfaction, resolved) drive the in-session indicator so the agent can see how the customer is reacting before the score arrives.

When the conversation wraps up, the session is scored and the agent reads the result: an overall 0–100 score, a per-criterion breakdown (empathy, discovery, resolution, communication), the strengths they demonstrated, the gaps to work on, and a short coaching summary.

## 2. The API walkthrough

The feature is stateless at the API level: you hold the transcript and replay it each turn. All routes sit under `/api/v1/practice-studio` and require an authenticated API key.

### List the built-in scenarios

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/practice-studio/scenarios \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

The response returns the catalog:

```json theme={null}
{
  "data": {
    "scenarios": [
      {
        "id": "billing-overcharge-frustrated",
        "title": "Frustrated customer disputes a duplicate charge",
        "channel": "chat",
        "difficulty": "medium",
        "persona": {
          "name": "Dana Rivera",
          "mood": "frustrated",
          "background": "Long-time Pro-plan customer, usually calm, but was charged twice this month…",
          "style": "Direct and a little terse; wants action, not apologies.",
          "language": "en"
        },
        "situation": "I was billed twice this month for my Pro subscription and I want the duplicate charge refunded.",
        "objective": "De-escalate, confirm the duplicate charge, and set a clear expectation for the refund without over-promising a timeline.",
        "rubric": [
          { "key": "empathy", "label": "Empathy", "description": "Acknowledged the customer's feelings…", "weight": 1 }
        ]
      }
    ]
  }
}
```

The catalog deliberately omits each scenario's `hiddenContext` — the private facts the simulated customer only reveals when the agent asks the right questions. Shipping it would spoil the discovery the exercise is designed to reward.

### Advance a turn

Pass the scenario (by id) and the running transcript; the response is the customer's next message plus the session signals:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/practice-studio/turn \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "scenarioId": "billing-overcharge-frustrated",
    "transcript": [
      { "role": "customer", "content": "I'\''ve just been charged twice for my subscription this month and I want the extra charge refunded." },
      { "role": "agent", "content": "I'\''m sorry you were charged twice — let me pull up your account right now and confirm the duplicate." }
    ]
  }'
```

Response:

```json theme={null}
{
  "data": {
    "message": "Okay — the invoice number is INV-2041. How long is the refund going to take?",
    "mood": "frustrated",
    "satisfaction": 0.6,
    "resolved": false,
    "ended": false
  }
}
```

The `transcript` array accepts an empty list on the very first call — the customer speaks first, so the opening turn returns the scenario's opener. You can also pass a full inline `scenario` object instead of `scenarioId` to roleplay against a custom rubric of your own.

### Score a finished session

When the conversation is over, send the same scenario and the full transcript to be graded. A session needs at least one turn to score (`422` otherwise):

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/practice-studio/score \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "scenarioId": "billing-overcharge-frustrated",
    "transcript": [
      { "role": "customer", "content": "I'\''ve just been charged twice for my subscription this month and I want the extra charge refunded." },
      { "role": "agent", "content": "I'\''m sorry you were charged twice — let me pull up your account and confirm the duplicate right now." },
      { "role": "customer", "content": "Okay — the invoice number is INV-2041. How long is the refund going to take?" },
      { "role": "agent", "content": "I'\''ve verified the second charge on your account. I'\''m processing the refund now — you'\''ll see it back on your card in 3–5 business days. I'\''ll also send you a confirmation email so you have it in writing." },
      { "role": "customer", "content": "Alright, thank you for sorting it out." }
    ]
  }'
```

Response (deterministic per the rubric and scoring engine built into the feature — the model suggests, the server computes the weighted overall from the rubric weights and never trusts the model's arithmetic):

```json theme={null}
{
  "data": {
    "overallScore": 84,
    "criteria": [
      { "key": "empathy", "label": "Empathy", "score": 90, "feedback": "Acknowledged the frustration directly and apologized without a script." },
      { "key": "discovery", "label": "Discovery", "score": 70, "feedback": "Confirmed the charge but missed asking about the add-on the customer forgot." },
      { "key": "resolution", "label": "Resolution", "score": 95, "feedback": "Offered a concrete refund with a timeline and written confirmation." },
      { "key": "communication", "label": "Communication", "score": 85, "feedback": "Clear, professional, set accurate expectations; slight jargon in the last reply." }
    ],
    "strengths": ["Offered a concrete resolution with a timeline", "Confirmed the account before acting"],
    "improvements": ["Ask a discovery question before assuming the second charge was the duplicate"],
    "summary": "Strong resolution and tone; discovery was thinner than it should have been — the add-on was there to be found.",
    "objectiveMet": true
  }
}
```

## 3. What the score contains

The grade is four things, all derived from the scenario's own rubric:

* **A weighted overall (0–100)** — the rubric criteria combine by their weights, so a scenario can weight "resolution" higher than "empathy" and the overall reflects that. The server computes the weighted total itself; it never accepts a pre-computed overall from the model.
* **Per-criterion scores with feedback** — each rubric criterion gets a 0–100 score and a one-to-two sentence justification keyed to what the agent actually said.
* **Strengths and gaps** — the "what went well" and "work on this" lists, so the agent leaves the session with a concrete coaching takeaway rather than just a number.
* **An objective flag** — whether the agent accomplished what the scenario set out to train (de-escalate, resolve, retain), so a supervisor can scan a team's session history for capability, not just scores.

Scoring only ever counts the agent's own turns — what the simulated customer says never inflates the grade. Under the hood the score is built deterministically from the rubric: each criterion is graded against what the trainee actually wrote, the weights are combined by plain weighted arithmetic, and the weighted overall is recomputed on the server rather than taken from the model — so the same transcript always lands on the same grade. That is what makes a practice session a fair rehearsal: no judge drift, no surprise arithmetic, and feedback keyed to the specific sentences the agent used.

## 4. How it fits alongside Quality Management

Practice Studio and the QA program are the two halves of the coaching loop, at opposite ends of the conversation:

* **Practice Studio trains before real calls.** The agent rehearses a hard conversation in a safe sandbox and leaves with coaching feedback before the real customer ever dials in.
* **Quality Management grades after.** The scorecard, calibration, ack/appeal lifecycle, and leaderboard in the [Build a contact-center QA program guide](/guides/quality-management-program) score the calls that actually happened and put effort on the board.

Run both together: train the scenario in Practice Studio, then confirm the skill sticks by reading the agent's real-call QA scores against the same competencies. Practice scores never count toward an agent's evaluation record, so a bad practice run carries no risk — that is the point.

## 5. Supervisor workflow

A typical supervision loop:

1. Check **Quality → Practice** for the team's session history; sort by score to find the gaps.
2. Pick the scenario that drills the gap (e.g. the angry-outage scenario for escalation handling) and assign an agent to run it.
3. Read the per-criterion breakdown on the finished session — if `discovery` is the low criterion, coach the discovery skill on the next real call and re-run the scenario a week later.
4. Create or retire scenarios as the team's needs shift: add a custom scenario built around a real call type your queue handles, deactivate one the team has outgrown.

The same loop works over the API: list `GET /scenarios`, walk a session through `POST /turn`, grade with `POST /score`, and read the per-criterion feedback to target coaching.

## Role model

Practice Studio follows the agent/supervisor split used across the Quality section:

* **Owner / admin / supervisor** — curate the scenario library, see the whole team's session history, run a session themselves.
* **Agent** — browse the runnable library, run their own sessions, read their own session history. An agent sees no one else's scores.

The stateless `/api/v1/practice-studio/*` routes require any authenticated API key and are not role-scoped — what they return is the scenario catalog and the session you send them, nothing tenant-owned.

## See also

* [Build a contact-center QA program](/guides/quality-management-program) — the after-call side of the loop: scorecards, calibration, leaderboard
* [QA workload management](/guides/qa-workload-management) — assign reviews, cap quotas, track due dates
* [Quality Management API](/api-reference/quality) — the endpoint reference for the QA surfaces practice complements
* [Error codes](/api-reference/error-codes) — `422 VALIDATION_ERROR` shapes for the turn/score bodies
