diteko (Python)
Generate, export and run tests for Amazon Connect contact flows, from Python. It is the testing counterpart to cxblueprint: build or export a flow, then let Diteko derive its grammar, evolve a test suite with Grammatical Evolution, export it, and run it on Connect's native testing.
This package is a client: it needs a Diteko server. It does nothing on its own. Point it at your team's Diteko, or start one on this machine with
diteko server up(it needs Docker; see https://github.com/Lehlohonolo-Sehako/diteko-selfhost).
The SDK talks to a running Diteko deployment over its REST API. If that deployment requires API
keys, set DITEKO_API_KEY (or pass api_key=); otherwise point the SDK only at a deployment
inside your network or behind your VPN.
pip install diteko # SDK
pip install "diteko[mcp]" # + MCP server for Claude Desktop / Cursor / VS Code
pip install "diteko[cxblueprint]"
Getting started
-
Find your Diteko. Diteko is self-hosted: you need the address of a running deployment. If you run your own (diteko-selfhost), that is
http://localhost:8080, which is also the SDK's default. To start one on this machine (with Docker installed):diteko server up # sets it up in ~/.diteko/server and starts it with Docker
It needs only Docker (Docker Desktop on macOS and Windows): the self-hosting files travel in this package, and the first start downloads the server image. The first time, it creates a
WRITEkey and prints the two settings to export (PowerShell syntax on Windows), plus the bootstrap ADMIN key for the console at the same address.diteko server statusandditeko server downdo what they say; data is kept between runs, and upgrading this package upgrades the server's files on the nextupwithout touching your settings.--portpicks another port,--latestuses the newest diteko-selfhost release instead of the files in this package, and--bundle patha self-hosting folder you already have. -
Get a key, if it asks for one. When a deployment requires API keys, whoever runs it creates one for you under Settings › API keys.
WRITEis enough for everything here except live runs on Connect. Put it in the environment:export DITEKO_URL=https://diteko.example.internal export DITEKO_API_KEY=dk_... # only if the deployment requires keys
-
Check the connection:
from diteko import Diteko dk = Diteko() # DITEKO_URL and DITEKO_API_KEY from the environment print(dk.version()) # {'api': '1.1', 'server': '…', 'auth': 'keys'} print(dk.whoami()) # the key in use, or None when keys are off
-
Run the example.
examples/cxblueprint_to_excel.py, also as a notebook, builds a flow with cxblueprint, evolves a suite and writes the Excel test script, in about a minute. Both ship in the source distribution:pip download --no-binary :all: --no-deps diteko, then unpack it.
Watching a run, and typed results
run = project.evolve(preset="standard").wait(progress=True) # one line on stderr, kept up to date
run = project.evolve(preset="standard").wait(progress=print) # or any callable, given a RunProgress
run.info.best_fitness, run.info.generation, run.info.generations
project.refresh().info # ProjectInfo: grammar, latest run, suite, last execution, typed
execution = suite.publish_to_connect(dry_run=True)
execution.results # [Verdict(test_id, status, message), ...]
execution.passed, execution.failed, execution.inconclusive # inconclusive: Connect could not start it, etc.
The pipeline
from diteko import Diteko
dk = Diteko("http://localhost:8080")
project = dk.projects.from_json("claims.json") # Connect export or cxblueprint output
project.grammar.generate() # derive, store and validate the grammar
run = project.evolve(preset="standard", focus="balanced").wait()
suite = run.suite(top=30, selection="coverage") # or selection="fitness"
for test in suite:
print(test.test_id, test.keys, test.fitness)
suite.export_xlsx("claims-tests.xlsx") # manual test script (ISO/IEC/IEEE 29119-3)
suite.export_native("claims-native.json") # Amazon Connect native test cases
result = suite.publish_to_connect(dry_run=True) # dry run unless you say otherwise
print(result.passed, result.failed, result.verdicts)
Straight from cxblueprint
from cxblueprint import Flow
from diteko import Diteko
flow = Flow.build("Burger Order")
menu = flow.get_input("Press 1 for Classic or 2 for Veggie", timeout=10)
# ... build the flow as usual ...
project = Diteko().projects.from_cxblueprint(flow) # compiles locally, uploads the JSON
Other ways in
dk.projects.import_from_connect("08e145dc-d959-4094-9021-6f10d8590be2") # from the instance
dk.projects.list() # every project and its next step
dk.projects.get(21601).suite(top=10).export_xlsx()
Grammars as BNF or JSON
The two forms are exact reflections of each other. Both are validated by the same parser, and both keep comments.
g = project.grammar.latest()
spec = g.to_json() # {"format": "diteko-grammar/v1", "start": ..., "rules": [...]}
g.replace(spec, format="json").save() # edit as JSON, store as canonical BNF
dk.convert_grammar(bnf_text, "bnf", "json")
Presets
preset |
calls × generations |
|---|---|
quick |
40 × 15 |
standard |
100 × 50 |
thorough |
200 × 120 |
focus |
favours |
|---|---|
balanced |
blocks and branches, plus happy paths and recoveries |
coverage |
visiting as much of the flow as possible |
errors |
timeouts and wrong keys that still end properly |
transfers |
calls that reach an agent queue |
Pass population=, generations=, weights={"state_coverage": 1.0} or seed= to go beyond them.
API keys
dk = Diteko("https://diteko.internal", api_key="dk_...") # or set DITEKO_API_KEY
dk.whoami() # {"name": "nightly CI", "prefix": "dk_...", "scope": "WRITE", ...}; None if keys are off
A key carries one scope: READ (see and export), WRITE (also create, run and dry-run),
PUBLISH_LIVE (also run on Connect for real, which is billed) or ADMIN (also manage keys).
Keys are created in the console under Settings, API keys.
MCP server
DITEKO_URL=http://localhost:8080 DITEKO_API_KEY=dk_... diteko-mcp # the key only if the server requires one
{ "mcpServers": { "diteko": { "command": "diteko-mcp", "env": { "DITEKO_URL": "http://localhost:8080", "DITEKO_API_KEY": "dk_..." } } } }
| Tool | Does |
|---|---|
list_projects |
every flow under test and its next step |
import_flow |
register a flow from JSON text, a file path, or a Connect flow id |
generate_grammar |
derive, store and validate a flow's grammar |
convert_grammar |
BNF ⇄ JSON |
start_evolution |
start a run (size, focus, seed) |
get_run |
a run's progress |
export_suite |
xlsx, json or native to a file |
publish_suite |
start a run on Connect and return at once; dry_run defaults to true, since a live run bills the AWS account |
get_execution |
a Connect run's status and verdicts; poll it until the status is no longer RUNNING |
Each tool carries MCP annotations: read-only tools say so, and publish_suite is marked as reaching an external system. Works with mcp 1.x and 2.x.
Support Diteko
Diteko is free to run for your own organisation. If it saves your team time, you can sponsor it on GitHub; the docs list other ways to help.
Versioning
The package follows Semantic Versioning. See the changelog for what each release changed.
The server reports an API version, MAJOR.MINOR, at GET /api/version. A minor bump only adds endpoints or fields. A major bump changes something an existing client relies on. Each SDK release speaks one API major version, currently 1. On its first call the SDK checks the server's version:
| Server | What happens |
|---|---|
| API 1.x | Works. |
| Another major | DitekoError, saying whether to upgrade the SDK or the server |
| Too old to report a version | A warning, then it carries on |
| Not a Diteko server | DitekoError: check DITEKO_URL |
| Nothing answering | DitekoError saying a server is needed and how to point at one; the next call checks again |
Diteko(url, check_version=False) skips the check, and dk.version() returns what the server reports.
Development
cd clients/python
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev,mcp]"
pytest # against an in-memory fake of the API
DITEKO_URL=http://localhost:8888 pytest # also runs the live and contract tests against a local stack
Changelog
All notable changes to the diteko Python package. The format follows
Keep a Changelog, and versions follow
Semantic Versioning as described under “Versioning” in the README.
[Unreleased]
[0.5.1] - 2026-11-01
Added
- A
Fundinglink on PyPI, and a "Support Diteko" section in this README.
[0.5.0] - 2026-11-01
Added
diteko server up,statusanddown: start a Diteko server on this machine with only Docker installed. The self-hosting files ship inside the package (a copy ofself-hosting/, kept identical by a test), the settings are written in Python assetup.shwrites them (so it works on Windows too), and the first start creates aWRITEkey and prints what to set. A lateruprefreshes the server's files and keeps your settings.--latestuses the newest diteko-selfhost release instead (checked against its SHA256SUMS),--bundlea local folder,--portanother port. When Docker is missing, stopped or may not pull the image, it says so.- The "no server answered" error mentions
diteko server up. - A server started with
diteko server upserves the API reference and links its console to the docs site (DITEKO_DOCS_URLin its.env; empty hides the links). - MCP tool
get_execution(upload_id): a Connect run's status, verdicts, inconclusive count and per-test results.Diteko.execution(upload_id)does the same from Python. [project.urls], so PyPI links to where you can run a server.
Changed
- The default server address is
http://localhost:8080, where a self-hosted Diteko listens, instead of:8888, which only Diteko's own development setup uses.DITEKO_URLandurl=work as before. - MCP
publish_suitereturns at once with the upload id and status, instead of holding one tool call open for up to 30 minutes. Pollget_executionfor the verdicts. - When no server answers, the error says the SDK needs a running Diteko server, how to point
at one (
DITEKO_URL) and where to get one. Connecting gives up after 10 seconds. - An address that is not a Diteko server (a 404 without a problem body on
/api/version, or a page that is not JSON) is reported as such, instead of a warning followed by a page of HTML. HTML in any error is reduced to its text and cut to 300 characters. - The version check runs again on the next call when the server could not be reached, instead of being skipped for the rest of the session.
evolve(preset="thorough")uses a per-bit mutation rate of 0.05 instead of 0.1, like the console's Thorough size: on the largest corpus flow it did better and was never worse elsewhere. Quick and standard runs are unchanged.
Fixed
Execution.wait()returned only on COMPLETED, so a run a server restart cut off (INTERRUPTED) blocked for the full 30-minute timeout. Every status but RUNNING now ends the wait, and INTERRUPTED raisesDitekoErrorasking you to publish again.
0.4.0 - 2026-10-11
Added
Verdict.attemptsandVerdict.passed_on_rerun. A server on API 1.2 re-runs a test that failed, once, because Connect's prompt recognition sometimes misses a prompt the flow played; a pass on the re-run is reported as a pass withattempts == 2. Older servers leaveattemptsasNone.
0.3.0 - 2026-10-11
Added
Run.wait(progress=True)keeps a line on stderr up to date while a run evolves; pass a callable instead to receive aRunProgresswhenever the generation or status changes.- Typed views alongside the raw responses:
Run.info(RunProgress),Project.info(ProjectInfo: grammar, latest run, suite, last execution),Execution.results(Verdicts with Connect's message) andExecution.inconclusive. Diteko()readsDITEKO_URLwhen no address is given, asditeko-mcpalready did.- A getting-started guide in this README, and
examples/cxblueprint_to_excel.py(and the same as a notebook): from a cxblueprint flow to an Excel test script.
Fixed
- A project's last execution no longer reads as RUNNING for a moment after the execution reported COMPLETED (fixed server-side).
0.2.0 - 2026-10-11
Added
- The first call checks that the server speaks this SDK's API major version
(
GET /api/version, API 1.x). A server on another major is refused with an error that says which side to upgrade; a server that predates version reporting gets a warning, not a failure.Diteko(..., check_version=False)skips the check. Diteko.version()returns the server's API version and build.- API keys: the SDK and
diteko-mcpsendDITEKO_API_KEY(orDiteko(api_key=...)) to servers that require keys (API 1.1). A missing key, a refused key and a key without permission each raise aDitekoErrorthat says which.Diteko.whoami()returns the key in use.
Fixed
- Moving a record to another parent with a partial update (for example a grammar to another flow) no longer fails on the server (fixed server-side, Diteko API 1.0).
0.1.0 - 2026-10-10
Added
- First release: projects from Connect exports, cxblueprint flows or a Connect instance; grammars as BNF or JSON; evolution with size and focus presets; suites exported as an Excel test script (ISO/IEC/IEEE 29119-3), JSON or Connect native tests; publishing to Connect, dry run by default.
diteko-mcp, an MCP server exposing the same pipeline as eight tools, onmcp1.x or 2.x.
Metadata
Release files for diteko 0.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| diteko-0.5.1.tar.gz | 47.2 kB | With provenance | Details for diteko-0.5.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| diteko-0.5.1-py3-none-any.whl | Python 3 | none | any | Details for diteko-0.5.1-py3-none-any.whl |
Total release size: 82.0 kB
Release files / diteko-0.5.1.tar.gz
| Download URL | diteko-0.5.1.tar.gz |
|---|---|
| Size | 47.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fe8d5f5e99f54097510652002a83fcd509d16fb48b087fcbd420c957004c5ad4
|
|
BLAKE2b-256 checksum How to use checksums |
9c7a5150b6ad48e03cec6967b4143bce355510e9aad456ba1ab23eab47bebb08
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 1, 2026.
Transparency logRelease files / diteko-0.5.1-py3-none-any.whl
| Download URL | diteko-0.5.1-py3-none-any.whl |
|---|---|
| Size | 34.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d8c4aa0699382a6322ecd8834f081f5de83b03125a657286b2c420796a35cf94
|
|
BLAKE2b-256 checksum How to use checksums |
306bd62688bae402b334c5f97b449c018e2213d4854b5ef235125ac803761b18
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 1, 2026.
Transparency logSecurity for diteko 0.5.1
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for diteko-0.5.1.tar.gz
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 Nov 1, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.