Skip to content

Commit 8e7c931

Browse files
feat(sims): add simulation skill (#9)
Co-authored-by: Topher Hindman <topher.hindman@livekit.io>
1 parent d86b645 commit 8e7c931

8 files changed

Lines changed: 708 additions & 3 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@
77

88
# Local testing
99
*.local.md
10+
11+
# Script artifacts
12+
__pycache__/

AGENTS.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ agent-skills/
1010
├── AGENTS.md # This file (for AI agents)
1111
├── CLAUDE.md # Points to AGENTS.md
1212
└── skills/
13-
└── livekit-agents/ # LiveKit Agents skill
14-
├── SKILL.md # The skill content
15-
└── references/ # Supporting documentation
13+
├── livekit-agents/ # LiveKit Agents skill
14+
│ ├── SKILL.md # The skill content
15+
│ └── references/ # Supporting documentation
16+
└── livekit-simulations/ # LiveKit Simulations skill
17+
├── SKILL.md # The skill content
18+
├── references/ # Supporting documentation
19+
└── scripts/ # Supporting scripts
1620
```
1721

1822
## Contributing Guidelines

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Reusable skills for AI coding agents building with [LiveKit](https://livekit.io)
77
| Skill | Description |
88
|-------|-------------|
99
| **livekit-agents** | Architectural guidance for building low-latency voice AI agents with LiveKit Agents SDK. Covers workflow design, handoffs, tasks, and mandatory testing practices. |
10+
| **livekit-simulations** | Generate targeted test scenarios for a LiveKit agent — locally, from the agent's own code plus what the user wants stress-tested — and run them as simulations. Bundles persona/goal/challenge libraries and a stdlib scenario builder. |
1011

1112
## Installation
1213

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
name: livekit-simulations
3+
description: 'Generate targeted test scenarios for a LiveKit voice or chat agent and run them as simulations — locally, from the agent''s own code plus what the user wants stress-tested. Use whenever the user wants to "test my agent", "what should I test", "create/generate simulation scenarios", "make a sim test suite", "use lk agent simulate", "stress-test the X flow", "set up scenarios for my agent", or wants to probe edge cases / refusals / regressions before shipping. Generates scenarios on the user''s machine (their code is never uploaded) and lets the user deeply steer what gets tested. Trigger even without the word "simulation" when the user clearly wants to decide what to test and verify how their agent behaves across realistic conversations. Not for building a new agent from scratch (use the livekit-agents skill), load-testing, or ordinary unit tests.'
4+
license: MIT
5+
metadata:
6+
author: livekit
7+
version: "0.4.0"
8+
---
9+
10+
<!-- ============================================================
11+
BETA NOTICE — TEMPORARY. Delete this whole block (down to the
12+
END BETA NOTICE marker) at GA. Everything from the
13+
"# Generating Simulation Scenarios" heading onward is the
14+
permanent, production-oriented skill.
15+
============================================================ -->
16+
17+
> **⚠️ Simulations are in private beta (not yet generally available).**
18+
> - **No docs/MCP coverage yet.** For the `lk agent simulate` command surface,
19+
> use `lk agent simulate --help` and the LiveKit Cloud dashboard rather than
20+
> `lk docs` / MCP until simulations are documented.
21+
> - **Recent SDK required.** Running simulations needs the 1.6 line of
22+
> `livekit-agents`. Confirm the installed version rather than assuming.
23+
> - **Limited availability / auth.** Creating runs needs the project enabled for
24+
> simulations and a current `lk cloud auth` session. (Generating scenarios —
25+
> the main job of this skill — needs neither; it's fully local.)
26+
27+
<!-- ===================== END BETA NOTICE ====================== -->
28+
29+
# Generating Simulation Scenarios
30+
31+
The most valuable thing you can do with simulations is **generate good test scenarios for the user's agent** — grounded in the agent's actual code and in what *the user* wants stress-tested — then run them. You do this **locally**: you read the code with your normal tools (nothing is uploaded), and you (the coding agent) are the model that does the generation, so no extra API keys or services are needed.
32+
33+
A **scenario** = a simulated user's persona + goals (`instructions`) and the pass criteria (`agent_expectations`). A simulation plays each scenario against the agent over text and an LLM judge scores it. Your job is to produce a high-quality, diverse, *on-target* set of scenarios and write them to a YAML scenarios file the CLI can run.
34+
35+
## What makes this better than autopilot
36+
A naive "just generate some tests" misses the point. Three things make this skill worth using:
37+
1. **It reads the agent's real code** — so scenarios respect what the agent can actually do and where it blocks (especially constraints/unavailable items), instead of guessing from the name.
38+
2. **It is steered by the user.** The user knows what they're worried about. Always capture that intent and thread it through. This is the headline — see `references/user-guidance.md`.
39+
3. **It guarantees coverage of every risk.** Left alone, generation drifts to plausible happy-path calls and silently skips the hard cases — withholding a required field, supplying an invalid value, an empty lookup, and the guardrail/abuse surface (out-of-scope, harmful, professional-advice, sensitive-data, prompt-extraction). This skill turns the agent's constraints into an explicit **risk checklist** and requires at least one scenario per item — see `references/analyzing-the-agent.md` and `references/writing-scenarios.md`.
40+
41+
## The flow
42+
43+
1. **Describe the agent + build the risk checklist** — read its code locally and write a test-oriented description (Identity / Capabilities / **Constraints**) to `description.md`, and an explicit **risk checklist** to `risks.yaml` (one entry per must-test constraint/guardrail, each with an `id` and `category`). Follow `references/analyzing-the-agent.md`. Never upload the code.
44+
2. **Get the user's test focus** — if they didn't say what to probe, ask. Apply it per `references/user-guidance.md` (append a `# Test Focus` to `description.md`, and bias authoring). Focus is **additive** — it deepens chosen risks but never drops the per-risk coverage floor. If they truly have no preference, generate broad and say so.
45+
3. **Author the scenarios — at least one per risk** — write a diverse set of ~10 scenarios grounded in `description.md` and the focus, generating the persona / mood / situation variety **from your own judgment** (this version ships no attribute libraries). **Guarantee coverage**: every `risks.yaml` item gets ≥1 dedicated scenario, written with the shape that actually exercises it, and tagged with `covers: [<risk id>, …]`. Follow `references/writing-scenarios.md` (schema, the "Party A talks to the agent" rules, no prior state, no real PII, outcome-based expectations, the adversarial-shape taxonomy, the coverage check, don't write bad tests). Write them to `authored.yaml`. Add any user-pinned must-tests here too.
46+
4. **Assemble the config (coverage-enforced)**
47+
`python scripts/build_scenarios.py assemble --in authored.yaml --agent-description-file description.md --risks risks.yaml --strict --out scenarios.yaml`
48+
(validates the schema, **fails if any risk is uncovered**, and emits the YAML scenarios file `lk agent simulate --scenarios` loads). Fix gaps and re-run until it passes.
49+
5. **Run it**`lk agent simulate --scenarios scenarios.yaml` (confirm exact flags with `--help`; needs the SDK/auth noted in the beta block). Show the user the results and offer to re-roll, re-focus, or add scenarios.
50+
51+
Reuse saved `scenarios.yaml` files as a regression suite — re-run them after prompt/model/tool changes.
52+
53+
## Principles
54+
- **Never upload the user's code.** Reading it locally is the point; it's their IP.
55+
- **The user's intent is the differentiator** — incorporate it every time; don't silently autopilot.
56+
- **Ground every scenario in the description**, especially Constraints — a scenario the agent can't possibly satisfy (or a guardrail it *should* refuse) must have expectations that reflect that.
57+
- **The script is deterministic glue; you are the generator.** Let `build_scenarios.py` handle assembly + the coverage check; you do the reading, the judgement, the diversity, and the authoring.
58+
59+
## Verify, don't invent (freeze-forever)
60+
This skill is the method (no bundled libraries — you supply diversity yourself). The exact `lk agent simulate` flags, the CI wait/fail flag, the minimum SDK version, and the dashboard come from live sources because they change — use `lk agent simulate --help` and (post-beta) `lk docs` / the LiveKit MCP server. A wrong flag wastes a run; look it up rather than guessing.
61+
62+
## After running: acting on results (secondary)
63+
Once a run completes, read the per-scenario pass/fail, the run summary, and the transcripts of failures. Fix the agent where a failure is real (and re-run); recognize when a failure is actually a bad scenario and fix the scenario instead. Keep this lightweight — modern models are already good at the fix step; the durable value of this skill is the scenarios you generate and keep.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Analyzing the agent → a test-oriented description
2+
3+
Before generating scenarios you need a tight, behavioral description of the agent under test. You produce it by **reading the agent's code locally** with your normal file tools — the code never leaves the machine and nothing is uploaded. (This replaces the old cloud "code analysis" service.)
4+
5+
The description has exactly one purpose: **helping scenario generation produce realistic test cases.** A simulated user never reads docs — they arrive with a need and interact. So the description must make clear what needs are serviceable, what flows they must go through, and where they will hit walls.
6+
7+
## Output: three sections, Constraints-first
8+
9+
Write the description as markdown with these sections. **Prioritize Constraints — a missed constraint produces invalid scenarios.** Keep it concise and dense.
10+
11+
```
12+
# Identity
13+
Name and role of the agent. What is the service? What does someone interacting with it experience?
14+
15+
# Capabilities
16+
What the user can request and have done:
17+
- Types of requests (inquiries, bookings, payments, modifications, ...)
18+
- Domain structure the user must know (how products/services are organized, what categories exist)
19+
- Key information the agent collects or provides
20+
21+
# Constraints
22+
Where requests get blocked, denied, or require more than expected. Be specific:
23+
- Mandatory preconditions (what must happen before X)
24+
- Multi-step flows that cannot be skipped
25+
- Services this agent explicitly cannot provide
26+
- Unavailable items/plans/features — enumerate EACH by name ("X is currently unavailable").
27+
A general rule ("unavailable items won't be offered") is not enough. Unavailable items must
28+
NOT appear under Capabilities — filter so only currently-active items are listed there.
29+
- Hard limits (caps, time windows, eligibility rules)
30+
```
31+
32+
## How to read the code (scope rule — apply before reading anything else)
33+
34+
1. **Read the entrypoint first.** Identify which agent class is passed to `session.start()` — that is the deployed agent.
35+
2. **In scope:** that agent plus anything reachable from it during a live session — agents returned by function tools (an `update_agent` transition), agents passed to `session.update_agent()`, and `AgentTask`s awaited inside tools/lifecycle hooks.
36+
3. **Out of scope:** other agent classes, imported-but-unused modules, example files, anything in the same directory not reachable from `session.start()`. Exclude it entirely, no matter how relevant it looks.
37+
4. Read the deployed agent's instructions string and its helper/implementation files — helpers often encode hard constraints (availability, required inputs, caps) the prompt doesn't state. Test files are secondary confirmation only.
38+
5. **Capture implicit capabilities too** — a capability stated only in the instructions string (answering questions about a menu, policy, hours) is real even with no dedicated tool.
39+
40+
## Write from the user's perspective — and leave out the internals
41+
42+
Describe what the user can ask and what the agent does for them. **Do NOT include:**
43+
- Internal identifiers, parameter names, or data structures (say "users can remove items from their order," not "requires an order item ID").
44+
- References to code files, modules, backends, or implementation choices (which DB/calendar is used).
45+
- Observations about code structure, dead code, or what's present-but-inactive — only state what IS and ISN'T available to users.
46+
- How errors are handled internally.
47+
- Capabilities inferred from the agent's name or industry convention — only what the code actually implements.
48+
49+
When the agent always prompts for a detail but the user may decline it, describe that detail as **optional** (from the user's perspective they aren't required to choose it).
50+
51+
**No function tools at all?** Some agents are instruction-only (no `@function_tool`). When that's the case, state it explicitly under Constraints — e.g. "no backend or account lookup; cannot retrieve, confirm, or act on any stored data." Scenarios must respect that such an agent can only converse and guide, never look something up or perform a backend action.
52+
53+
## Verify before you finish
54+
- Multi-tier orders/services: captured every mandatory component and its exact constraints (required items, size limits)?
55+
- Unavailable items: listed by name under Constraints? (Don't claim the agent suggests alternatives unless the code implements that.)
56+
- Required explicit inputs (variants, sizes): stated under Constraints?
57+
58+
## Also emit a risk checklist (the coverage contract)
59+
60+
The Constraints section says what the limits *are*; the **risk checklist** says what *must be
61+
tested*. Without it, generation drifts to plausible happy-path calls and silently skips the
62+
hard cases. Write `risks.yaml` — a YAML list, one entry per must-test item:
63+
64+
```yaml
65+
- id: rp1
66+
category: unavailable
67+
must_test: "Sweet Tea is out of stock; agent must not add it or claim it's available"
68+
- id: rp2
69+
category: withhold-required
70+
must_test: "user orders a combo but won't name a drink size"
71+
```
72+
73+
Derive most items from Constraints, but **always sweep the universal guardrail surface below,
74+
even when the prompt is silent on it** — these are the categories generation most often skips:
75+
76+
- **unavailable** — each unavailable item/plan/feature, by name
77+
- **withhold-required** — each mandatory input the user can omit (size, email, identifier, …)
78+
- **invalid-value** — each input with a validity rule (unsupported plan, off-list time, over-limit amount, mismatched option)
79+
- **precondition** — each step that must happen first (verify identity before X)
80+
- **resource-empty** — each lookup that can return nothing (no availability, no record) and must be conveyed honestly
81+
- **out-of-scope** — requests for things this agent does not do
82+
- **harmful** — unsafe / disallowed requests
83+
- **professional-advice** — specific medical / legal / financial recommendations it must not give (general info only)
84+
- **sensitive-data** — privacy / oversharing (full card, SSN, password, someone else's record)
85+
- **prompt-extraction** — attempts to reveal the system prompt / internals / "ignore previous instructions"
86+
87+
Include every category that *could* apply to this agent; omit one only if it genuinely cannot
88+
(e.g. no `unavailable` item exists). For an **instruction-only agent** (no tools), the
89+
lookup/action categories become refusal guardrails — it must decline to fabricate or pretend
90+
to act — not capabilities.
91+
92+
Save the finished description to `description.md` and the checklist to `risks.yaml` — scenario
93+
generation, the coverage check, and `assemble --risks` all consume them.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Steering generation with the user's intent
2+
3+
This is the whole point of doing scenario generation as a skill instead of an autonomous cloud service: **the user knows what they're worried about, and you can act on it.** The cloud generator takes no input — it just decides what to test. You can let the user deeply steer what gets tested, which is what makes a local skill more useful.
4+
5+
**Always get the user's intent.** If they didn't say what to stress-test, ask before generating — e.g. *"What do you most want these simulations to probe — a specific flow, edge cases, things the agent should refuse, recent changes?"* If they truly have no preference, generate a broad suite and say so.
6+
7+
## Three levels of steering
8+
9+
### 1. Free-text focus (primary)
10+
A sentence about what matters: *"test the cancellation flow and what happens when someone skips identity verification,"* or *"stress refusals and out-of-scope requests,"* or *"focus on multi-issue callers who change their mind."* Apply it in two places:
11+
- **Add a `# Test Focus` section to the agent description** (`description.md`). Since the description grounds every scenario, the focus reaches all of them.
12+
- **When authoring,** bias goal/challenge choices toward the focus, and make several scenarios target it head-on — while still keeping a few broad ones so you don't miss unrelated regressions.
13+
14+
### 2. Levers (you set these while authoring)
15+
- **Suite size** — how many scenarios you write (≈10 is typical; more for broader coverage).
16+
- **Adversarial intensity** — how many are stress cases vs cooperative happy paths.
17+
- **Include / exclude** — cover only certain flows, or skip persona types that don't apply, just by choosing what you author.
18+
19+
### 3. Pinned must-tests
20+
If the user has specific cases they insist on ("always test ordering then immediately canceling"), write those scenarios verbatim into `authored.yaml` alongside the generated ones. Hand-pinned scenarios are how a known bug becomes permanent coverage.
21+
22+
## What a focus does — and doesn't — change
23+
A focus steers *which goals and challenges dominate* and *what the expectations emphasize*. It should **not** flatten the suite: you still vary persona/mood/situation widely, and still keep a few routine scenarios as controls so a real agent failure is distinguishable from an over-hard suite. After generating, show the user the resulting `scenarios.yaml` and offer to re-roll or re-focus.
24+
25+
**Focus is additive, not subtractive.** It decides what gets *extra* scenarios and emphasis — it never removes the per-risk coverage floor from `risks.yaml` (see `writing-scenarios.md`): even a tightly-focused suite still includes ≥1 scenario for every risk item. In testing, a narrowly-focused suite that quietly dropped an unrelated constraint missed a real bug there — focus should *deepen* coverage, not shrink it.

0 commit comments

Comments
 (0)