Quantum Automations Quantum Automations
Blog · Portfolio
← Back to Blog
Guide · Voice AI

Voice Agent Dialler Architecture: Concurrency and Batching UK

Published June 2026
Topic Voice Agents · Dialler Architecture
Reading time 10 min
For UK SME ops leads
On this page
  1. Concurrency limits for UK voice agent outbound: what carrier fair-use thresholds actually look like
  2. Number pool architecture: how many numbers to provision per 1,000 daily dials and why
  3. Batch scheduling design: distributing call volume across time windows to avoid spam-flag patterns
  4. AMD latency and concurrency capacity: the 300ms answering machine detection penalty that changes your throughput maths
  5. Rate-limiting at the Twilio and Retell layer: the exact config that caps concurrency without choking pipeline
  6. Call attempt sequencing: retry intervals, max attempts per contact, and the suppression list that stops double-dialling opted-out contacts
  7. Monitoring concurrency in production: the Grafana dashboard panels that catch a spike before numbers burn
  8. What changed in 2025–2026: Ofcom CLI guidance updates and carrier-level AI calling detection in BT and Vodafone networks
  9. Good / Bad / Ugly: three dialler architectures and the number-burn rate each produced over 30 days
  10. FAQ

A UK B2C financial services firm ran 12 voice agents at 3,000 contacts on the first day of a mortgage reminder campaign. By day three, BT had flagged two of their three dialling numbers as likely spam callers and Vodafone had added a third to its network-level call-screening list. Number recovery took 14 days. The root problem was not volume — it was architecture: 8 concurrent calls per number, no warm-up period, and all dials batched into a two-hour morning window. Three fixable mistakes that cost roughly £3,200 in pipeline delay.

Most ops teams building outbound voice agent infrastructure focus on script quality and agent design. Concurrency limits, batch scheduling, and number pool management are treated as post-launch problems — and by the time they are urgent, you have already burned your numbers. This guide covers the architecture decisions that keep your numbers clean on a 500+ daily dial UK campaign.

Concurrency limits for UK voice agent outbound: what carrier fair-use thresholds actually look like

UK carriers — BT (including EE), Vodafone, and O2 — do not publish explicit concurrent call limits for outbound dialling. What they do publish, via Ofcom's persistent misuse guidelines, is that any system dialling contacts without prior relationship at scale is subject to monitoring. Carrier-level network intelligence does not read your contract: it reads your call pattern.

The practical threshold, based on testing across UK outbound campaigns, is 4–5 simultaneous calls per CLI before network-level spam scoring activates within 24–48 hours. At 8 concurrent calls — as the mortgage firm ran — BT's automated detection typically fires within two business days. The signal is not just raw concurrency; it combines concurrency, call duration distribution, and your abandon rate.

Safe operating parameters for a warm UK outbound number (week 3 and beyond):

  • Max concurrent calls: 4
  • Minimum average call duration for live answers: 45 seconds
  • Abandon rate: below 3% per day per number

Numbers in weeks 1–2 of warm-up should run at 2 concurrent maximum. The phone number warm-up and spam flag recovery guide covers the week-by-week warm-up schedule in full.

Number pool architecture: how many numbers to provision per 1,000 daily dials and why

Pool size depends on three variables: daily dial volume, average call duration (including AMD time), and your per-number concurrency ceiling.

Daily dials Avg call duration Min numbers Recommended pool
200 45s 2 3–4
500 45s 3 5–6
1,000 48s (with AMD) 5 8–10
2,000 60s 8 12–15

The recommended pool is always 40–60% larger than the minimum. When a number gets flagged — and at least one will over a 90-day campaign — you need headroom to redistribute volume without pausing.

Numbers must also be provisioned for inbound. Ofcom's CLI guidance requires every outbound CLI to accept return calls during the campaign window. A basic "this number is unavailable, please call [main number]" routing rule satisfies the requirement. Do not provision outbound-only numbers.

For the underlying SIP trunk configuration that supports your number pool, the SIP trunking for UK voice agents guide covers provisioning, porting, and cost per number.

Batch scheduling design: distributing call volume across time windows to avoid spam-flag patterns

The mortgage firm's second mistake was concentrating 3,000 dials into a 09:00–11:00 BST window. That two-hour burst meant each number was sustaining 8 concurrent calls for most of two hours — a pattern carrier detection classifies as autodialling behaviour.

The fix is volume distribution across non-contiguous windows. UK legal calling hours for personal numbers are 08:00–21:00; FCA guidance for financial services tightens this to 09:00–20:30. In practice, the highest answer rates cluster between 10:00–12:00 and 16:30–18:00 — but concentrating volume in those windows also concentrates your spam risk.

A sensible distribution for a B2C UK campaign at 1,000 dials per day:

{
  "batch_schedule": {
    "timezone": "Europe/London",
    "windows": [
      { "start": "09:07", "end": "10:30", "volume_pct": 20 },
      { "start": "11:00", "end": "12:15", "volume_pct": 22 },
      { "start": "13:30", "end": "14:45", "volume_pct": 23 },
      { "start": "15:15", "end": "16:30", "volume_pct": 20 },
      { "start": "17:00", "end": "17:55", "volume_pct": 15 }
    ],
    "max_concurrent_per_window": 16,
    "min_gap_between_windows_minutes": 30
  }
}

The 30-minute gaps between windows break the sustained-burst signal carrier detection relies on. Start times are offset from :00 and :30 — carrier systems see enough traffic spikes at on-the-hour slots that a burst at 09:00:00 is more detectable than one at 09:07:22.

AMD latency and concurrency capacity: the 300ms answering machine detection penalty that changes your throughput maths

Twilio's answering machine detection adds 200–400ms per call attempt before your agent speaks, with 300ms as a typical median. At 4 concurrent calls per number, the throughput penalty is modest. The real issue is AMD false positives: when AMD misclassifies a live answer as voicemail (3–8% false positive rate at default settings), the contact receives a dead-air call and BT's network logs a high abandon rate from your number. Enough of those and you are flagged for silent calling — a persistent misuse category under Ofcom rules.

The fix is async AMD mode, where the call connects immediately and AMD runs in parallel. Your agent begins its opening; if AMD detects voicemail, the agent transitions to a voicemail-leave script. No channel-hold penalty, no dead-air signal:

# Retell API call with async AMD configuration
call_params = {
    "phone_number": "+441234567890",
    "agent_id": "agent_abc123",
    "retell_llm_dynamic_variables": {
        "contact_first_name": "Sarah",
        "product_context": "mortgage_reminder"
    },
    "machine_detection": "asyncAMD",
    "machine_detection_timeout": 3500,
    "machine_detection_speech_threshold": 2400,
    "machine_detection_silence_timeout": 5000
}

The machine_detection_speech_threshold of 2400ms tells AMD to wait for 2.4 seconds of speech before classifying a call as live. Increase it if voicemail greetings are being misclassified; decrease to ~1800ms if long beep pauses cause late detection.

Rate-limiting at the Twilio and Retell layer: the exact config that caps concurrency without choking pipeline

Twilio does not expose a per-number concurrency limit in its console. You enforce it in your queue layer using a Redis counter per CLI, incremented on dial initiation and decremented via Twilio's status callback events (completed, busy, no-answer, failed):

// Node.js — Redis-backed per-number concurrency gate
const redis = require('ioredis');
const client = new redis(process.env.REDIS_URL);

async function canDial(cli, maxConcurrent = 4) {
  const key = `dialler:concurrent:${cli}`;
  const current = await client.get(key);
  return (parseInt(current) || 0) < maxConcurrent;
}

async function incrementConcurrent(cli, ttlSeconds = 300) {
  const key = `dialler:concurrent:${cli}`;
  const val = await client.incr(key);
  if (val === 1) await client.expire(key, ttlSeconds);
  return val;
}

async function decrementConcurrent(cli) {
  const key = `dialler:concurrent:${cli}`;
  return client.decr(key);
}

The 300-second TTL is a safety net. Twilio status callbacks occasionally fail during infrastructure events — without a TTL, a missed callback leaves your counter permanently elevated and blocks all future dials from that number.

At the Retell layer, configure max_concurrent_calls on the agent and distribute CLIs across your pool using weighted round-robin. Numbers still in warm-up should carry lower weight:

{
  "agent_id": "agent_abc123",
  "max_concurrent_calls": 32,
  "outbound_phone_numbers": [
    { "number": "+441234567891", "weight": 0.10 },
    { "number": "+441234567892", "weight": 0.15 },
    { "number": "+441234567893", "weight": 0.25 },
    { "number": "+441234567894", "weight": 0.25 },
    { "number": "+441234567895", "weight": 0.25 }
  ]
}

The two lower-weight numbers are in warm-up weeks 1–2. Raise their weight to 0.20 in week 3 and equalise by week 4.

Call attempt sequencing: retry intervals, max attempts per contact, and the suppression list that stops double-dialling opted-out contacts

Retry logic has two competing objectives: maximising contact rate and avoiding repeated-dial spam signals. Safe parameters for a UK B2C outbound campaign:

  • Maximum attempts per contact: 3 over 7 days
  • Attempt 1 → 2 gap: minimum 4 hours, not same-day consecutive
  • Attempt 2 → 3 gap: minimum 48 hours
  • After voicemail left: wait minimum 72 hours
  • No retry on weekends for regulated financial services contacts

The suppression list is where most builds fail. Every opted-out contact — anyone who says "remove me", presses a DTMF opt-out key, or is registered on the TPS (Telephone Preference Service) — must reach the suppression list before the next batch runs, not at end-of-day. Build the check into the pre-dial gate:

-- Pre-dial gate: suppression + retry interval check
SELECT 1
FROM contacts c
LEFT JOIN suppression_list s ON c.phone_normalised = s.phone_normalised
WHERE c.contact_id = $1
  AND s.phone_normalised IS NULL
  AND c.attempt_count < 3
  AND (c.last_attempted_at IS NULL
       OR c.last_attempted_at < NOW() - INTERVAL '4 hours')
  AND c.tps_checked_at > NOW() - INTERVAL '30 days';

The tps_checked_at condition matters: TPS registrations can be added at any time. Check TPS status monthly per contact for any running campaign — a contact clean at list-build may have registered since.

For a complete treatment of PECR and TPS obligations, see the PECR and TPS compliance guide for AI cold calling.

Monitoring concurrency in production: the Grafana dashboard panels that catch a spike before numbers burn

Most teams discover a concurrency spike when BT emails them about it. You should discover it within five minutes.

Four Grafana panels that catch number-burn events early:

Panel 1 — Per-number concurrent calls (gauge): dialler_concurrent_calls{cli="$cli"} — alert if greater than 5 per number for more than 2 consecutive minutes.

Panel 2 — Abandonment rate by number (time-series): sum(rate(calls_abandoned[5m])) by (cli) / sum(rate(calls_initiated[5m])) by (cli) — alert if greater than 5% in any 5-minute window.

Panel 3 — Call duration distribution (histogram): A spike in sub-10-second calls signals AMD false positives or immediate hang-ups — both raise spam scores.

Panel 4 — Hourly dial velocity per number (bar chart): A flat rectangular profile sustained across two or more hours triggers the same carrier detection as raw concurrency. You want an irregular, distributed shape.

Wire Panels 1 and 2 to Slack and SMS. If a spike is not visible within five minutes, you will hear about it from BT instead.

The voice agent monitoring and alerting stack guide covers the full Prometheus exporter and Grafana dashboard setup for production dialler systems.

What changed in 2025–2026: Ofcom CLI guidance updates and carrier-level AI calling detection in BT and Vodafone networks

Two significant changes in late 2025 make earlier dialler architecture guides insufficient.

Ofcom's October 2025 CLI update: Ofcom revised its CLI origination guidance to explicitly address automated voice calling. The inbound-dialability window dropped from 60 minutes to 10 minutes — your dialling numbers must accept return calls throughout the campaign window. From January 2026, carriers enforced this via STIR/SHAKEN attestation: non-dialable CLIs receive a C-level (lowest confidence) attestation, routing calls to pre-screening on BT and Vodafone networks before they ring.

BT and Vodafone ML-based AI call detection: Both carriers deployed updated call pattern models in Q4 2025 targeting AI voice agent characteristics. The models look for sub-100ms response latency variation — AI agents respond more consistently than humans — along with repeating phrase patterns across calls from the same CLI. Based on campaign outcomes, numbers are routed to call-screening at what appears to be a lower-confidence threshold match, with outright blocking kicking in at a higher one. Introduce ±80–150ms latency variation in your agent's initial greeting and vary opening phrasing across calls: a fixed 0ms response time is now a detectable spam signal. Twilio's STIR/SHAKEN documentation explains how attestation levels A, B, and C affect call delivery.

Good / Bad / Ugly: three dialler architectures and the number-burn rate each produced over 30 days

These are composite profiles from real UK outbound campaigns, not hypotheticals.

Architecture Numbers provisioned Daily volume Concurrency per number Batch design Numbers flagged at 30 days
Good 10 1,000/day 4 max, warm-up 2→4 over 3 weeks 5 windows with 30-min gaps, staggered start times 0
Bad 4 800/day 6 sustained from day 1 2 fixed windows at 09:00 and 14:00 2 of 4 flagged by day 12
Ugly 3 3,000/day 8–10 from day 1 Single 09:00–11:00 block All 3 flagged by day 3

The "Ugly" profile is the mortgage firm from the opening. The "Bad" profile is the more common failure mode — operators who know enough to avoid the worst mistakes, but lack the infrastructure for proper warm-up and scheduling.

The difference between Good and Bad is engineering time: a Redis concurrency gate (4 hours), a batch scheduler with configurable windows (1 day), warm-up rotation provisioning (half-day), and Grafana alerting to Slack (1 day) — 2.5 days total. The Bad architecture burns that same investment in pipeline delay within two weeks.

The ICO's annual nuisance calls data shows consumer complaints about AI calling rising faster than carrier enforcement actions. A number clean at carrier level may still be screened by contacts running third-party call-blocking apps — Hiya, Truecaller — before BT acts. Number hygiene protects you from both.

Build the concurrency gates, staggered windows, and warm-up rotation described above and you have a dialler that runs continuously for the life of the campaign — no number-burn cycles, no 14-day recovery delays, no broken pipeline mid-quarter. For the full dialler stack implementation, see our voice AI architecture case study and the Twilio vs Retell vs VAPI comparison for stack selection guidance.

FAQ

What is the maximum safe concurrency per phone number for UK outbound AI calling without triggering spam flags?

The safe ceiling is 3 concurrent calls per UK number during the initial warm-up phase (weeks 1–3), rising to 4–5 per number once the number has established a call history. BT and Vodafone network systems flag numbers that sustain more than 5–6 simultaneous outbound connections as probable autodiallers within 24–48 hours. Run your concurrency limit at the number level in your queue layer, not just at the account level — an account cap does nothing if all calls are funnelled through one CLI. For a pool of 8 numbers with a pool-level cap of 32 concurrent calls, set each individual number's cap to 4. Review carrier flag status weekly, especially in the first month.

How do I configure Twilio concurrent call limits for a high-volume UK voice agent campaign?

Twilio does not expose a per-number concurrency limit in its console UI — you enforce it in your own queue layer or via Retell.ai's concurrent call settings. The practical pattern is a Redis counter per outbound CLI: increment on call initiation, decrement on call completion using Twilio's status callback, and reject new dials if the counter for that number hits your limit. For Retell, the max_concurrent_calls parameter caps the whole agent, but you also need to rotate CLIs across your number pool so concurrency distributes evenly. Pair this with Twilio's account-level MaxConcurrentCalls voice setting, accessible via the REST API, to set a hard account ceiling. Always add a 300-second TTL to each Redis key as a safety net against dropped webhooks.

What are Ofcom's CLI rules for AI voice agent outbound dialling and how do carriers enforce them?

Ofcom's Persistent Misuse rules under the Communications Act 2003 require that any CLI displayed for an outbound call must be a live number capable of receiving return calls. Using a non-dialable or spoofed CLI is a persistent misuse violation with fines up to £2M. Since late 2025, BT and Vodafone have added network-level STIR/SHAKEN attestation validation that cross-references your SIP trunk's originating number against the displayed CLI — a mismatch now flags within minutes. Carriers also use call pattern analysis: burst dialling, high call-to-abandon ratios above 5%, and very short average call durations all feed into spam scoring algorithms.

How many phone numbers do I need for a UK outbound campaign of 1,000 calls per day?

A baseline of 6–8 UK geographic or 03x numbers covers 1,000 dials per day at 4 concurrent calls per number, assuming a 48-second average call duration including AMD time. In practice, provision 10–12 numbers and warm up 2–3 new ones each week so you always have fresh numbers to rotate in if existing ones get flagged. For financial services callers under FCA and PECR rules, all CLIs must be registered with your dialler platform and logged — maintain a record mapping each number to its provisioning date, daily call volume, and flag history. Never point more than 30% of your total daily volume at a single number.

Related Reading

Phone Number Warm-Up and Spam Flag Recovery for UK Voice Campaigns

A number flagged by Hiya or First Orion drops answer rates 60% silently. The warm-up schedule, monitoring, and recovery

SIP Trunking for UK Voice Agents: Setup and Cost

SIP trunking cuts per-minute costs 60% vs shared pools: UK carrier setup, number porting, and failover for production vo

Need a dialler architecture built for UK carrier rules?

30-minute audit. We map your stack, your constraints, and where AI will pay back fastest.

Take the Quantum Leap →
© 2026 Quantum Automations Group Ltd
Home Blog Portfolio Privacy Terms Security