Skip to main content

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

  1. 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 WRITE key 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 status and diteko server down do what they say; data is kept between runs, and upgrading this package upgrades the server's files on the next up without touching your settings. --port picks another port, --latest uses the newest diteko-selfhost release instead of the files in this package, and --bundle path a self-hosting folder you already have.

  2. 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. WRITE is 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
    
  3. 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
    
  4. 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.

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.0] - 2026-11-01

Added

  • diteko server up, status and down: start a Diteko server on this machine with only Docker installed. The self-hosting files ship inside the package (a copy of self-hosting/, kept identical by a test), the settings are written in Python as setup.sh writes them (so it works on Windows too), and the first start creates a WRITE key and prints what to set. A later up refreshes the server's files and keeps your settings. --latest uses the newest diteko-selfhost release instead (checked against its SHA256SUMS), --bundle a local folder, --port another 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 up serves the API reference and links its console to the docs site (DITEKO_DOCS_URL in 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_URL and url= work as before.
  • MCP publish_suite returns at once with the upload id and status, instead of holding one tool call open for up to 30 minutes. Poll get_execution for 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 raises DitekoError asking you to publish again.

0.4.0 - 2026-10-11

Added

  • Verdict.attempts and Verdict.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 with attempts == 2. Older servers leave attempts as None.

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 a RunProgress whenever 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) and Execution.inconclusive.
  • Diteko() reads DITEKO_URL when no address is given, as diteko-mcp already 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-mcp send DITEKO_API_KEY (or Diteko(api_key=...)) to servers that require keys (API 1.1). A missing key, a refused key and a key without permission each raise a DitekoError that 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, on mcp 1.x or 2.x.

Metadata

Release files for diteko 0.5.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 diteko 0.5.0
File Size Uploaded Provenance Actions
diteko-0.5.0.tar.gz 46.7 kB With provenance Details for diteko-0.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for diteko 0.5.0
File Interpreter ABI Platform Actions
diteko-0.5.0-py3-none-any.whl Python 3 none any Details for diteko-0.5.0-py3-none-any.whl

Total release size: 81.3 kB

Release files / diteko-0.5.0.tar.gz

Download URL diteko-0.5.0.tar.gz
Size 46.7 kB
Tags Source
SHA-256 checksum
How to use checksums
7ab1b1abb5cffe77cf147c0c6be47893d88d45490ad3e43b4fe235bfed9615a7
BLAKE2b-256 checksum
How to use checksums
eb26d8a4642e2dd1fe64ba55536f2022e8cb2d041c27ab9c65852a57a88d7fee
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 log

Release files / diteko-0.5.0-py3-none-any.whl

Download URL diteko-0.5.0-py3-none-any.whl
Size 34.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bcec279edf1120f692bb8ca1a16d08c432a903cb4adad41750fb67a6ce9e512a
BLAKE2b-256 checksum
How to use checksums
a00f3a79c5b3f2f764f89f01312e972e981c36372a9a1481cebe9d6acb8ba29d
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 log

Security for diteko 0.5.0

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.

Select from 2 files

Attestation for diteko-0.5.0.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 log

A 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.

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