Load Testing API
run_load_test runs a closed-loop voice load test: it holds a target number of
concurrent conversations against your voice agent for a set duration, so you can measure
how the agent behaves under continuous load, not just an initial burst that drains as
calls finish.
Purpose
A scenario-and-repeats run fires a batch of calls and drains as each one completes, so the
number of simultaneous calls falls over time. run_load_test instead sustains the
target concurrency: it dials a fresh conversation whenever one ends, keeping the live call
count at your target for the entire window. That steady plateau is the right shape for
answering "how does my agent hold up when N callers are on the line at once, for minutes?"
Use it to:
- Measure turn latency, success rate, and answer quality while a fixed number of calls run simultaneously over a sustained window.
- Surface degradation that only appears under continuous concurrency: queue buildup, backend timeouts, or drift that grows over the course of the run rather than at its start.
Each conversation is a full simulated call: a driver (the simulated caller) talks to your agent, and the checks you attach score every call.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | str | A label for the load-test run. |
target | Target | The voice agent under test. |
load_concurrent | int | The number of concurrent conversations to hold at the plateau. |
load_duration_s | float | How long, in seconds, to sustain that concurrency. |
seed_data | list[dict], optional | Conversation seed rows, sampled round-robin so the concurrent calls vary. Defaults to a single generic conversation. |
driver | Driver, optional | The simulated caller; its persona and prompt drive each conversation. Omit to use the default driver. |
checks | list[str], optional | Checks scored on every call's datapoint; your quality-under-load signal. |
per_call_max_duration_s | float, optional | Bound the wall-clock length of each individual call. When set, a call ends once it reaches the cap and is immediately replaced, so the target concurrency stays steady while no conversation runs longer than the cap ("call cycling"). Omit to let each call run for the full hold. |
calculate_metrics | bool | Compute aggregate metrics for the run. Defaults to True. |
project_id | str, optional | The project to record the run under. |
api_key / api_keys | str / dict, optional | Your API key, plus any per-component keys your target or driver require. |
Example
import os
from okareo import Okareo
from okareo.model_under_test import Driver, SipTarget, Target
okareo = Okareo(os.environ["OKAREO_API_KEY"])
run = okareo.run_load_test(
name="Support agent sustained load",
target=Target(
name="support-voice-agent",
target=SipTarget(sip_uri="sip:agent@your-domain.example.com"),
),
load_concurrent=25, # hold 25 concurrent conversations
load_duration_s=300, # for 5 minutes
per_call_max_duration_s=90, # optional: bound each call to 90s and recycle
driver=Driver(
name="support-caller",
prompt_template="You are a customer calling support with a routine question.",
),
checks=[
"result_completed",
"total_turn_count",
"time_to_first_audio",
"max_time_to_first_audio",
"target_silence_rate",
"avg_words_per_minute",
],
)
print(run.id)
How a run unfolds
- Ramp: Okareo dials up to
load_concurrentlive conversations. - Plateau: it holds that concurrency for
load_duration_s, starting a fresh conversation whenever one ends so the live count stays at target. - Wind-down: once the hold completes, in-flight calls end gracefully and the run finalizes.
Call cycling
Set per_call_max_duration_s to keep the plateau composed of short, bounded calls: each
conversation ends at the cap and is immediately replaced, so the target concurrency is held
steady while no single call runs longer than the cap. This models steady turnover, many
shorter calls flowing through your agent, rather than a fixed set of long-lived calls.
Leave it unset to let every conversation run for the full hold.
Reading results
Open the run to see aggregate latency (mean / p50 / p90) with per-conversation
distributions, per-check pass rates, and the full conversation table. Attach the standard
load-test check panel
(result_completed, total_turn_count, time_to_first_audio, max_time_to_first_audio,
target_silence_rate, avg_words_per_minute) to compare behavior under sustained load
against your single-call baseline and spot the concurrency at which quality starts to move.