Skip to main content

mod_turbotab

CLI-first TurboTable-style calculations for contact-center planning.

mod_turbotab keeps the historical name known by call-center planning and traffic analysts, while exposing turbotab as the primary interface for humans, scripts, and AI agents.

turbotab staffing required --sla 0.80 --service-time 20 --calls-per-interval 25 --aht 180 --json
{"calculation": "staffing.required", "inputs": {"aht": 180, "calls_per_interval": 25.0, "interval": 600.0, "service_time": 20, "sla": 0.8}, "result": {"name": "agents", "unit": "agents", "value": 11}, "schema_version": "1.0"}

Why

mod_turbotab answers operational questions that show up constantly in contact-center planning:

Question Command
How many agents do I need? turbotab staffing required ...
What SLA will this staffing achieve? turbotab sla achieved ...
How long will the queue wait be? turbotab queue wait ...
How many trunks are required? turbotab telecom trunks ...
What is the Erlang B/C/A result? turbotab erlang ...

It provides Erlang B, extended Erlang B, Engset B, Erlang C, Erlang A, queue metrics, staffing metrics, call capacity, and telephony trunk sizing with no third-party runtime dependencies.

Quick Start

Required staffing for 80% SLA in 20 seconds:

turbotab staffing required \
  --sla 0.80 \
  --service-time 20 \
  --calls-per-interval 25 \
  --aht 180 \
  --json

Achieved SLA for a fixed staffing level:

turbotab sla achieved \
  --agents 11 \
  --service-time 20 \
  --calls-per-interval 25 \
  --aht 180 \
  --json

Average queue wait:

turbotab queue wait \
  --agents 11 \
  --calls-per-interval 25 \
  --aht 180 \
  --json

Required trunks:

turbotab telecom trunks \
  --agents 11 \
  --calls-per-interval 25 \
  --aht 180 \
  --json

Every command group falls back to contextual help:

turbotab
turbotab sla
turbotab staffing required --help

CLI

Agent-facing commands are intent-first:

turbotab
├── staffing
│   ├── required
│   ├── asa
│   ├── capacity
│   ├── fractional-required
│   └── fractional-capacity
├── sla
│   ├── achieved
│   └── target-time
├── queue
│   ├── wait
│   ├── size
│   └── probability
└── telecom
    └── trunks

Detailed formula/module commands are also available:

turbotab agents ...
turbotab queues ...
turbotab erlang ...
turbotab traffic ...
turbotab trunks ...

Use --json when calling from agents or automation. Invalid inputs exit non-zero and print a concise error to stderr.

Agent usage

Agents should prefer the CLI with --json instead of parsing text output or importing Python internals.

turbotab staffing required --sla 0.80 --service-time 20 --calls-per-interval 25 --aht 180 --json

JSON output is the stable agent contract:

{
  "schema_version": "1.0",
  "calculation": "staffing.required",
  "inputs": {
    "aht": 180,
    "calls_per_interval": 25.0,
    "interval": 600.0,
    "service_time": 20,
    "sla": 0.8
  },
  "result": {
    "name": "agents",
    "unit": "agents",
    "value": 11
  }
}

The bundled skill lives at skills/mod-turbotab/SKILL.md. It includes command recipes, unit rules, and agent guardrails.

Units and assumptions

This project uses interval-based planning buckets.

Every function or CLI command that accepts call volume uses calls_per_interval, not calls per hour by default.

Parameter Meaning
calls_per_interval / --calls-per-interval Arrivals in the planning bucket
interval / --interval Planning bucket in seconds
Default interval 600 seconds, or 10 minutes
aht / --aht Average handle time in seconds
service_time / --service-time Target answer time in seconds
sla / --sla Ratio, for example 0.80 for 80%

For hourly semantics, pass --interval 3600:

turbotab staffing required --sla 0.80 --service-time 20 --calls-per-interval 150 --aht 180 --interval 3600 --json

Traffic intensity is computed as:

A = \frac{\lambda \cdot h}{I}

where A is offered traffic in erlangs, lambda is arrivals per interval, h is AHT in seconds, and I is interval length in seconds.

Worked example

With the default 10-minute bucket:

Input Value
Calls 25 per 10 minutes
AHT 180 seconds
Target SLA 0.80
Target answer time 20 seconds

CLI:

turbotab staffing required --sla 0.80 --service-time 20 --calls-per-interval 25 --aht 180 --json
turbotab sla achieved --agents 11 --service-time 20 --calls-per-interval 25 --aht 180 --json
turbotab queue wait --agents 11 --calls-per-interval 25 --aht 180 --json
turbotab telecom trunks --agents 11 --calls-per-interval 25 --aht 180 --json

Expected headline results:

Metric Result
Required agents 11
Achieved SLA 0.880836
Average queue wait 51 seconds
Required trunks 18

Python API equivalent:

from mod_turbotab.agents.capacity import agents_required

print(agents_required(0.80, 20, 25, 180))
Mathematical model

Notation:

Symbol Meaning
N Agents, servers, or trunks depending on context
lambda Arrival volume per configured interval
h Average handle time in seconds
I Planning interval in seconds
mu Service completions per interval per server
A Offered traffic in erlangs
rho Utilization
B(N, A) Erlang B blocking probability
C(N, A) Erlang C queueing probability

Core conversions:

\mu = \frac{I}{h}
A = \frac{\lambda}{\mu} = \frac{\lambda h}{I}
\rho = \frac{A}{N}

Erlang B recurrence:

B_0 = 1
B_n = \frac{A B_{n-1}}{n + A B_{n-1}}

Erlang C:

C(N, A) = \frac{B(N, A)}{\left(\frac{A}{N}\right) B(N, A) + \left(1 - \frac{A}{N}\right)}

Queue wait:

W_q = \frac{1}{N \mu (1 - \rho)}

SLA:

\mathrm{SLA}(t) = 1 - C(N, A)\exp\left(-\frac{N - A}{h}t\right)

ASA:

\mathrm{ASA} = \frac{C(N, A)}{N \mu (1 - \rho)}

Erlang A extends Erlang C with abandonment through average patience. When patience=None, pure Erlang C is used.

API reference

The CLI is the primary interface, but the Python API remains available.

Module Public functions
calculations.erlang erlang_b, erlang_b_ext, engset_b, erlang_c, erlang_a
calculations.traffic traffic, looping_traffic
agents.capacity agents_required, asa, agents_asa, nb_agents, call_capacity, fractional_agents, fractional_call_capacity
queues.queues queued, queue_size, queue_time, service_time, sla_metric
trunks.trunks number_trunks, trunks_required
utils min_max, int_ceiling, secs

Import example:

from mod_turbotab.agents.capacity import agents_required

agents = agents_required(
    sla=0.80,
    service_time=20,
    calls_per_interval=25,
    aht=180,
)
Exceptions

Project-specific exceptions live in exceptions.py:

Exception Meaning
InputValidationError Invalid argument values
CalculationError Calculation failed or search could not converge

Example:

from mod_turbotab.exceptions import CalculationError, InputValidationError

try:
    ...
except InputValidationError:
    ...
except CalculationError:
    ...

Limitations

  • number_trunks() uses a fixed blocking threshold of 0.001.
  • Some zero-value edge cases still return wrapped calculation errors instead of purpose-built validation messages.
  • Shrinkage, absenteeism, occupancy caps, and intraday simulation are tracked as future work in coming_soon/.

Metadata

Release files for mod-turbotab 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mod-turbotab 0.1.0
File Size Uploaded
mod_turbotab-0.1.0.tar.gz 56.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mod-turbotab 0.1.0
File Interpreter ABI Platform
mod_turbotab-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 99.4 kB

Release files / mod_turbotab-0.1.0.tar.gz

Download URL mod_turbotab-0.1.0.tar.gz
Size 56.0 kB
Tags Source
SHA-256 checksum
How to use checksums
372efcecc61b6895e726422df0be15b9e31ac2bc5a1db2334636cca03a1304be
BLAKE2b-256 checksum
How to use checksums
136ab08fb58dd9fcc8fba87887cdb39c0ed97ad16efb32a016845f703891bb7e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Release files / mod_turbotab-0.1.0-py3-none-any.whl

Download URL mod_turbotab-0.1.0-py3-none-any.whl
Size 43.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
af74e068f909ae563adf6921cc3fbe4bc1ff4913137f031e68d0ec5ad958f215
BLAKE2b-256 checksum
How to use checksums
e3cd07ff3d800b5fb256d281cd0dcd77bc4fde48ee7b3e14f3d503ea82f1180c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page