Python SDK
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 # SDKpip install "diteko[mcp]" # + MCP server for Claude Desktop / Cursor / VS Codepip install "diteko[cxblueprint]"Getting started
Section titled “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):Terminal window diteko server up # sets it up in ~/.diteko/server and starts it with DockerIt 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:Terminal window export DITEKO_URL=https://diteko.example.internalexport DITEKO_API_KEY=dk_... # only if the deployment requires keys -
Check the connection:
from diteko import Ditekodk = Diteko() # DITEKO_URL and DITEKO_API_KEY from the environmentprint(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
Section titled “Watching a run, and typed results”run = project.evolve(preset="standard").wait(progress=True) # one line on stderr, kept up to daterun = project.evolve(preset="standard").wait(progress=print) # or any callable, given a RunProgressrun.info.best_fitness, run.info.generation, run.info.generations
project.refresh().info # ProjectInfo: grammar, latest run, suite, last execution, typedexecution = 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
Section titled “The pipeline”from diteko import Diteko
dk = Diteko("http://localhost:8080")
project = dk.projects.from_json("claims.json") # Connect export or cxblueprint outputproject.grammar.generate() # derive, store and validate the grammarrun = 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 casesresult = suite.publish_to_connect(dry_run=True) # dry run unless you say otherwiseprint(result.passed, result.failed, result.verdicts)Straight from cxblueprint
Section titled “Straight from cxblueprint”from cxblueprint import Flowfrom 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 JSONOther ways in
Section titled “Other ways in”dk.projects.import_from_connect("08e145dc-d959-4094-9021-6f10d8590be2") # from the instancedk.projects.list() # every project and its next stepdk.projects.get(21601).suite(top=10).export_xlsx()Grammars as BNF or JSON
Section titled “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 BNFdk.convert_grammar(bnf_text, "bnf", "json")Presets
Section titled “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
Section titled “API keys”dk = Diteko("https://diteko.internal", api_key="dk_...") # or set DITEKO_API_KEYdk.whoami() # {"name": "nightly CI", "prefix": "dk_...", "scope": "WRITE", ...}; None if keys are offA 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
Section titled “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
Section titled “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
Section titled “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
Section titled “Development”cd clients/pythonpython -m venv .venv && . .venv/bin/activatepip install -e ".[dev,mcp]"pytest # against an in-memory fake of the APIDITEKO_URL=http://localhost:8888 pytest # also runs the live and contract tests against a local stack