---
name: vr-debug-test
description: Debug and test VoiceRun voice agents using the Pipeline Debugger (GUI, headless, scripted) and the integrated test runner.
---

# Debug and Test a VoiceRun Agent

You are helping the user debug and test their voice agent. VoiceRun provides two complementary tools: the **Pipeline Debugger** for interactive and automated conversation testing, and the **test runner** for unit/integration tests. Follow these steps:

## Pipeline Debugger (`vr debug`)

### GUI Mode — Interactive testing

Launch the visual Pipeline Debugger for real-time agent testing:

```bash
vr debug
```

This automatically:
1. Pushes your local code to the server
2. Installs debugger dependencies (Node.js required)
3. Launches the Electron-based Pipeline Debugger connected to your agent

Use `--skip-push` if your code hasn't changed:

```bash
vr debug --skip-push
```

Target a specific environment:

```bash
vr debug -e staging
```

### Headless Mode — CI and coding agents

Run the debugger without a GUI, streaming events as JSONL to stdout:

```bash
vr debug --headless
```

In headless mode:
- JSONL events stream to **stdout** (one JSON object per line)
- Text input is read from **stdin** (one message per line)
- On exit, session JSON is exported to a file

Save the session output:

```bash
vr debug --headless --output session.json
```

### Scripted Mode — Repeatable test conversations

Run a predefined conversation from a JSON file:

```bash
vr debug --script test-messages.json
```

The script file is an array of strings, where each string is a user message sent one-per-turn:

```json
["Hello", "What's the weather in San Francisco?", "Thank you, goodbye"]
```

Combine with headless mode for automated testing in CI:

```bash
vr debug --headless --script test-messages.json --output results.json
```

### Outbound Call Mode — Real phone testing

Place an actual phone call to test the agent end-to-end. The project must be a VoiceRun project (`.voicerun/` directory must exist). `vr debug --outbound` automatically pushes your local code before placing the call.

Phone numbers must be in **E.164 format** — a `+` followed by country code and digits, no spaces or dashes (e.g. `+15551234567`).

```bash
vr debug --outbound --to-phone-number "+15551234567"
```

On success, a `telephonyCallId` is returned for tracking.

With optional caller ID and environment:

```bash
vr debug --outbound --to-phone-number "+15551234567" --from-phone-number "+15559876543" -e production
```

Skip pushing if code hasn't changed:

```bash
vr debug --outbound --to-phone-number "+15551234567" --skip-push
```

If targeting a non-debug environment, that environment must be deployed first with `vr deploy`.

### Debug options summary

| Option | Description |
|--------|-------------|
| `--skip-push`, `-s` | Skip pushing code, use existing deployment |
| `--environment`, `-e` | Target environment (default: `debug`) |
| `--headless` | Run without GUI, stream JSONL to stdout |
| `--output`, `-o` | Output file for headless session JSON |
| `--script` | Path to JSON file with scripted messages |
| `--outbound` | Place outbound phone call |
| `--to-phone-number` | Destination phone (E.164, required with `--outbound`) |
| `--from-phone-number` | Caller ID phone (E.164, optional) |

## Test Runner (`vr test`)

### Running tests

Run pytest-based tests for your agent:

```bash
vr test
```

This will:
1. Validate project structure
2. Install project dependencies (via uv)
3. Run pytest on the `tests/` directory

### Test options

| Option | Description |
|--------|-------------|
| `--verbose`, `-v` | Run pytest in verbose mode |
| `--coverage`, `-c` | Run with coverage reporting |
| `--environment`, `-e` | Fetch secrets from an environment (development, production) |
| `--skip-install` | Skip dependency installation |

```bash
# Verbose output
vr test -v

# With coverage
vr test -c

# Load development secrets for integration tests
vr test -e development

# Run specific test file
vr test tests/test_handler.py

# Pass extra pytest arguments
vr test -- -k "test_greeting" -x
```

### Writing tests

Create a `tests/` directory with test files. Tests should simulate events and verify the handler's responses:

```python
import pytest
from handler import handler
from primfunctions.events import StartEvent, TextEvent, TextToSpeechEvent
from primfunctions.context import Context


@pytest.fixture
def context():
    return Context()


async def collect_responses(handler_gen):
    responses = []
    async for response in handler_gen:
        responses.append(response)
    return responses


@pytest.mark.asyncio
async def test_greeting(context):
    """Agent greets user on session start."""
    event = StartEvent()
    responses = await collect_responses(handler(event, context))
    assert len(responses) > 0
    assert isinstance(responses[0], TextToSpeechEvent)
    assert responses[0].text  # Non-empty greeting


@pytest.mark.asyncio
async def test_user_input(context):
    """Agent responds to user text."""
    event = TextEvent(data={"text": "Hello there", "source": "speech"})
    responses = await collect_responses(handler(event, context))
    assert len(responses) > 0
    assert isinstance(responses[0], TextToSpeechEvent)
```

### Test patterns

1. **Event flow**: Simulate StartEvent → TextEvent → StopEvent sequences
2. **Edge cases**: Test empty input, long input, unexpected input
3. **Business logic**: Test each branch of your handler (tool calls, transfers, DTMF)
4. **Conversation state**: Verify context data persists across events
5. **Timeout behavior**: Test TimeoutEvent with different count values
6. **Error handling**: Verify graceful behavior when APIs fail

## Recommended Workflow

### Development loop

1. Edit `handler.py`
2. Run `vr test -v` to verify unit tests pass
3. Run `vr debug` to interactively test the conversation
4. Iterate until behavior is correct

### Pre-deployment verification

1. Run `vr test -v -c` for full test suite with coverage
2. Run `vr debug --headless --script test-scenarios.json` for automated conversation testing
3. Run `vr debug --outbound --to-phone-number "+1..."` for real phone testing
4. Deploy with `vr deploy production` once all tests pass

### CI/CD pipeline

```bash
# Validate structure
vr validate -q

# Run unit tests
vr test --skip-install -v

# Run automated conversation test
vr debug --headless --script tests/conversation.json --output test-results.json
```

## Troubleshooting

- **"Node.js not found"** — Install Node.js for the GUI debugger. Headless and outbound modes don't require Node.js.
- **"No tests found"** — Ensure test files are in a `tests/` directory and named `test_*.py`.
- **Debugger won't connect** — Check that `vr push` succeeded and the agent is deployed. Try `vr debug` without `--skip-push`.
- **Headless mode hangs** — Send text via stdin or use `--script` for automated input. Press Ctrl+C to exit and export the session.
- **Tests fail with import errors** — Run `vr test` without `--skip-install` to install dependencies first.
- **Secrets not available in tests** — Use `vr test -e development` to fetch environment secrets.
- **"Outbound mode requires a voicerun project"** — Run the command from a directory containing a `.voicerun/` folder, or run `vr init` to create a new project.
- **"No agent.lock found. Run 'vr push' first"** — Run `vr push` before using `--skip-push`.
- **"Invalid phone number format"** — Phone numbers must be in E.164 format: `+` followed by country code and digits (e.g. `+15551234567`).
- **"Failed to start outbound call"** — Verify the agent is deployed (`vr deploy`) and the environment exists. Check that outbound calling is enabled for your organization.
- **"--outbound cannot be combined with --headless, --output, or --script"** — Outbound mode is a standalone mode and cannot be used with debugger-specific options.

Guide the user through the appropriate testing approach based on their needs.
