Project Management
The VoiceRun CLI takes a project from scaffold to production: vr init creates the files, vr push uploads the handler, and vr release binds that code to an org-scoped environment with a snapshotted manifest. An entrypoint then routes incoming traffic to one or more releases.
Creating a Project#
Scaffold a new voice agent project with vr init:
vr init my-agent
Without arguments, vr init runs an interactive wizard that asks for a project name and (optionally) a remote template to start from. Pass --yes to skip the wizard.
The scaffold produces:
my-agent/
├── handler.py # Main agent code (entry point)
├── requirements.txt # Python dependencies
├── README.md # Project documentation
├── .gitignore
├── .vrignore # Files to exclude from vr push
├── .claude/CLAUDE.md # Instructions for Claude Code
├── AGENTS.md # Instructions for Codex / OpenClaw
└── .voicerun/
├── agent.yaml # Agent metadata (name, description)
├── values.yaml # Base deployment values
├── values.development.yaml # Development overrides
├── values.production.yaml # Production overrides
└── templates/ # Deployment, simulation, evaluator, and webhook resources
Options#
| Flag | Description |
|---|---|
--yes, -y | Skip prompts and use defaults |
--force, -f | Overwrite existing files |
--template, -t | Initialize from a remote template (name or ID) |
--var | Template variable as key=value (repeatable) |
Using Templates#
Initialize from a shared template:
vr init my-agent --template restaurant-booking vr init my-agent --template restaurant-booking --var language=spanish --var region=us
List available templates:
vr get templates
Project Configuration Templates#
VoiceRun projects include Helm-style configuration templates under .voicerun/. The CLI renders these templates during commands such as vr push, vr deploy, and vr render.
Template values come from .voicerun/values.yaml and can be overridden per environment with files such as .voicerun/values.development.yaml and .voicerun/values.production.yaml. Templates reference those values with .Values.*, and agent metadata from .voicerun/agent.yaml with .Agent.*.
For example, enable the optional session-end webhook by setting an HTTPS URL in the relevant values file:
webhook: url: https://example.com/voicerun/session-webhook
Leaving webhook.url as null skips the webhook resource during push/deploy, so new projects do not create a webhook unless you opt in.
You can comment out unused template examples with YAML comments (# ...) or Helm comment blocks ({{/* ... */}}). The CLI ignores template expressions inside those comments, so commented-out examples do not create placeholder values or affect rendering.
Validating a Project#
Check that your project structure, agent metadata, and (optionally) rendered templates are correct:
vr validate vr validate --environment production
Validation checks:
handler.pyexists and containsasync def handler(event, context)(skipped automatically when the renderedDeployment.spec.modeisrelay).voicerun/directory structure is correctagent.yamlis valid with required fields.voicerun/templates/*.yamlparse as YAML and have allowedkind+specfields- When
--environmentis given (or Helm templates are auto-detected), templates are rendered with Helm and the rendered output is validated
Use --quiet to only show errors.
Declarative Resources#
Anything under .voicerun/templates/ is rendered with Helm at release time and snapshotted onto the release manifest. Each YAML document declares one resource with apiVersion: voicerun/v1 and one of four kind: values:
| Kind | Purpose |
|---|---|
Deployment | Runtime config — mode, region, variables, stt, turnTaking, tts, relay, recording, redaction, tracing |
Simulation | Simulated caller config used by vr simulate |
Webhook | Session-end webhook delivery (URL + signing secret) |
Evaluator | Post-session scoring or extraction (judge / extraction) |
See the Declarative Resources reference for the full per-kind field list, types, and validation rules.
Values Files#
.voicerun/values.yaml is the base values file used by Helm. Per-environment overlays (e.g. prod.yaml, staging.yaml) live alongside it and are pulled in with --values prod.yaml on vr release, vr render, or vr simulate.
Secrets in rendered manifests are referenced with {{ Secrets.organization.NAME }}. The placeholder survives Helm rendering verbatim, lands in the manifest as-is, and is resolved against organization secrets at session start — secrets never round-trip through the release record.
Previewing the Render#
Preview what Helm will produce for the current project without creating a release:
vr render # default values.yaml vr render --values .voicerun/prod.yaml # overlay a values file vr render --set stt.model=nova-3 # override a single value vr render --output json # JSON instead of YAML
vr render also runs spec validation on the rendered output, so it doubles as a fast feedback loop while editing templates.
Pushing Code#
Upload your agent code to VoiceRun:
vr push
The first push creates a new agent and function on the server. Subsequent pushes update the existing function version until that version has been deployed. Once a function version is referenced by a deployment, VoiceRun treats it as immutable: a later vr push automatically creates a new child function version and writes the returned functionId back to .voicerun/agent.lock, so deployed environments keep serving the previously deployed code until you explicitly release or deploy the new version. Use --new when you want to force a new function version before deployment.
| Flag | Description |
|---|---|
--name | Name for the function version |
--new, -n | Create a new function version |
--yes, -y | Skip confirmation prompts |
After pushing, an agent.lock file is created in .voicerun/ to track the agent ID, function ID, and a checksum of the project files at push time. Other commands (release, debug, simulate, etc.) read agent.lock so they can default the agent automatically when run from inside a project.
.vrignore#
Control which files are excluded from the push with a .vrignore file (works like .gitignore):
# Exclude test files
tests/
*_test.py
# Exclude data directories
data/
*.csv
# Exclude build artifacts
__pycache__/
*.pyc
The following are always excluded: .venv, __pycache__, .git.
Pulling Code#
Download agent code from the server to your local machine:
vr pull # Inside a project (uses agent.lock) vr pull AGENT_ID # Outside a project vr pull AGENT_ID -o ./dir # Specify output directory
Releasing to an Environment#
A release binds an agent + function to an org-scoped environment at a point in time, with an immutable snapshot of the rendered manifest. The latest release for a given (agent, environment) pair is implicitly the active one — there's no separate "activate" step.
vr release <ENVIRONMENT> # Inside a project (agent from agent.lock) vr release my-agent production # Explicit agent vr release production --entrypoint support # Cut traffic over to the new release vr release production --entrypoint support --weight 25 # 25% canary rollout vr release production --values prod.yaml # Overlay an environment-specific values file vr release production --function FUNC_ID # Pin to a specific function version
Options#
| Flag | Description |
|---|---|
--function, -f | Function ID to release (defaults to agent.lock's functionId) |
--values, -v | Values file in .voicerun/ to overlay (e.g. prod.yaml). Without it, only .voicerun/values.yaml is loaded |
--entrypoint, -e | Entrypoint name or ID to point at the new release after creation |
--weight | Partial-rollout weight (1-100). Without it, the entrypoint's release list is replaced with the new release at weight 100. With it, the new release is appended at the given weight, leaving existing entries unchanged |
--yes, -y | Skip the unpushed-changes confirmation prompt |
Prerequisites#
- Run
vr pushfirst (or pass--functionexplicitly) so the release has a function to bind to. - The target environment must already exist — create one with
vr create environment <name>. - If
.voicerun/templates/exists, Helm must be installed.vr releaserenders the full manifest at release time so the runtime has an immutable snapshot.
Unpushed-changes check#
Before creating the release, the CLI compares the project's current checksum against the one stored in agent.lock at last vr push. On mismatch, it warns that the release will run the previously-pushed function (not what's on disk) and prompts to confirm. Pass --yes for CI use.
Routing traffic with entrypoints#
An entrypoint is the public endpoint that callers reach (a phone number, web widget, native SDK client). It carries a weighted list of releases, and the API picks one per call. See Entrypoints for the create/update commands.
Deploying (legacy)#
vr deploy <ENVIRONMENT> still exists for agents created before the release/entrypoint migration. It deploys a function version to a per-agent environment, not an org-scoped environment.
vr deploy development vr deploy production --yes
New projects should use vr release instead — vr deploy is preserved only to keep existing legacy agents working and may be removed in a future release.
During a legacy deploy, the API prewarms the sandbox module for the selected function before the CLI returns. First-time builds can take several seconds, so the CLI shows a Deploying and prewarming sandbox... spinner while it waits. If prewarm fails, the deploy still succeeds and the first live call falls back to the normal on-demand build path.
Opening the Dashboard#
Open your agent's page in the VoiceRun web dashboard:
vr open
Requires agent.lock (created after vr push).
