Skip to main content

crystalia-tower

An ATC-style triage tower for agent and human callsigns.

Work performed by an agent session is invisible until a human relays it, which makes the human the transport wire between concurrently-running sessions. crystalia-tower replaces that wire: every participant -- agent or human -- is a node with a callsign, an inbox, and presence. Messages are addressed, typed from a fixed eight-verb vocabulary, and carry refs rather than bulk.

The thing it is for: an agent queues "need your ruling", the human answers, the agent unblocks -- with no live coordinator session and no copy-paste.

Install

pip install crystalia-tower

Python 3.13 or newer. Installs three console scripts: ctower, ctower-cab and ctower-launch.

Quickstart

A tower is a directory. init is the only verb that will not guess where it is; the rest read CRYSTALIA_TOWER_HOME, or take --tower.

ctower init --tower ~/towers/demo
export CRYSTALIA_TOWER_HOME=~/towers/demo
export CRYSTALIA_TOWER_CALLSIGN=vlad

# hand work to an agent callsign that need not exist yet
ctower send ASSIGN gatto-1 unit=DEMO note='look at the failing test'

# the agent's side: what is waiting, and what it owes a readback
ctower check --callsign gatto-1
ctower ack <msg-id> --callsign gatto-1

# the tower, both axes, every strip
ctower status
ctower roll

check --wait 300 blocks until traffic lands instead of polling, and exits 0 with interrupted: true in the envelope if a signal cuts the wait short -- a killed wait found nothing out, and that is not the same as a quiet tower.

The eight verbs

ASSIGN REPORT WILCO ROGER STANDBY UNABLE SAY-AGAIN MAYDAY

The set is closed. A ninth token is a validation failure, not an extension point. A message carries unit=, status=, reason=, ref= and note=; note= bytes are stored byte-identically, never parsed, never interpolated into a shell, and never sent anywhere off the machine.

The three commands

Command What it is
ctower the CLI: send, inbox, check, ack, status, init, roll
ctower-cab a terminal UI over your own inbox and the strip tower
ctower-launch start an agent process with its queued traffic handed over as its brief

Machine-readable output

Every verb takes --json and emits a versioned envelope. The seven schemas that pin it ship in the source distribution under docs/json-schema/v1/, one per verb, identified as urn:crystalia-tower:json-schema:v1:<verb>. The envelope is a public API: it is pinned by test, not described by prose.

Exit codes are frozen: 0 success, 2 usage, 3 validation, 4 unknown callsign, 5 unknown msg-id, 6 permission, 7 tower unavailable, 8 launch collision. ctower-launch adds 1 for a failure to start the child -- the tower committed its work and what failed was the exec -- and otherwise exits with the child's own code, reporting a signalled child as 128+N. Three non-happy outcomes are exit 0 by design: a --wait deadline expiring, a message to a callsign never seen before, and a launch over an empty queue.

What is built, and what is not

Single-host works. A tower is a directory on one machine, and every participant reaches it through the filesystem.

Multi-host is NOT built. There is no server, no network listener, no signing and no authentication in this release: --tower takes a path, not a URL. Remote towers are Phase 2 of the TOWER-01 multi-host implementation plan, which lives in the development workspace and is not shipped with this distribution. Nothing in this package should be read as promising it yet.

Traffic is pull-only. No notifier, no cron, no hook, no watcher, no daemon sits on the message path -- you learn you have mail by asking. The single narrow exception is crash telemetry, which is on by default and switched off with CRYSTALIA_TOWER_SENTRY_DISABLED=1. It never carries note= bytes.

Working on the source

The source distribution carries the tests and the schemas. The TOWER-01 design documents are not shipped; they live in the development workspace.

uv sync --extra dev
uv run pytest
uv run ruff check src tests
uv run mypy src/crystalia_tower

Always use uv run; never source .venv/bin/activate.

Two invariants are easy to break and are enforced by lint rather than by review: sqlite3 may be imported only under src/crystalia_tower/store/sqlite/, and subprocess only by src/crystalia_tower/launch.py. Nothing is swallowed either -- a caught exception is re-raised, translated to a named error type, or surfaced. There is no fourth option.

Licence

MIT. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

crystalia_tower-0.0.6.tar.gz (393.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

crystalia_tower-0.0.6-py3-none-any.whl (131.7 kB view details)

Uploaded Python 3

File details

Details for the file crystalia_tower-0.0.6.tar.gz.

File metadata

  • Download URL: crystalia_tower-0.0.6.tar.gz
  • Upload date:
  • Size: 393.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.7

File hashes

Hashes for crystalia_tower-0.0.6.tar.gz
Algorithm Hash digest
SHA256 f0228481641e5bb8fd8232462c9a1e5bbd9738feff2b3098dd3acaa4f0b39ec4
MD5 79993cd971542927eb7386138b622dc9
BLAKE2b-256 f5ac38fc371b776a4ea3a53a8e31048f903307d3e2eab53b6b3096b435b20b1f

See more details on using hashes here.

File details

Details for the file crystalia_tower-0.0.6-py3-none-any.whl.

File metadata

File hashes

Hashes for crystalia_tower-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 5e6b8677a54e05504e036f789bffee34247fc6fcca5625d10c1c5a8a0969f2b3
MD5 c2ec448a22b6935967580863416b118d
BLAKE2b-256 1b58d427f7b64385cb884df67990ac1bd6bd561fd0799e6dd1e26c5279d7b48c

See more details on using hashes here.

Release history Release notifications | RSS feed

0.0.8

2 files

0.0.7

2 files

This release

0.0.6 This release

2 files

0.0.5

2 files

0.0.4

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 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