Part of the Kontiki suite — Python runtime, registry, terminal UI, and fleet monitoring for distributed services.
Full suite overview → https://kontiki-org.github.io/
Ops demo → kontiki-monitor Quickstart.
Overview
Kontiki is a Python runtime for distributed services on RabbitMQ. You write
@http, @rpc, @on_event, and @task. The decorators are the visible API;
most of the leverage sits one layer deeper — identity, routing, delivery, fleet
health, configuration, and testing. You express intentions in Kontiki terms,
not broker topology by hand.
This repository is the runtime. Together with the registry, KontikiTUI, and kontiki-monitor, every Python workload — API, worker, cron job, ops service — is the same operable, testable, and observable unit.
Most applications don't need the full depth of a specialized ops stack. Kontiki takes the commonly useful part and aims to integrate it into the same service model, instead of giving you another platform to assemble and tune.
Why conventions
Services should differ primarily because of what they do, not because each one introduces another way of being built and operated.
- An ops job fails months later: find the service in KontikiTUI instead of rediscovering its crontab, script, and log file.
- A request failed after crossing several services: follow its
flow_idtree in KontikiTUI instead of correlating timestamps across logs by hand. - Adding a new service — including a monitor: identity, configuration, lifecycle, logging, health, and failure reporting already follow the same conventions.
What Kontiki is not
Kontiki does not aim for maximum infrastructure choice. It is intentionally Python-first, RabbitMQ-based, and convention-driven. It does not abstract every broker, become a language-neutral platform, replace orchestration, or reproduce a tracing, long-term metrics, or IAM product. Those can coexist outside the common model; they are not the default for everyday needs.
Runtime
- One model from dev to production: merged YAML config,
cli.run, and the same entrypoint decorators in tests (kontiki.testingmocks on the bus) and in production. - Design interactions as messages: RPC for request/reply; events for async
work. On
@on_event, delivery is explicit — default (one instance per message, competing consumers),broadcast=True(every instance),in_session=True(one pinned instance via a session). - Route by
event_type: the event name is the routing contract; deployment identity (kontiki.service_name,kontiki.peers) and environment-specific names live in config, not in code. - Fleet registry: heartbeats, degraded state (
degraded_on), exception tracking, live instance ids (list_instances/GET /instances/{service_name}), and orchestrator live probes (GET /live/{service_name}). The bus runs without a registry; operating the fleet coherently assumes one. - Integrated operations: browse the fleet in KontikiTUI, alert from registry signals with kontiki-monitor.
For gotchas, controlled failures (rpc_error), and patterns beyond this
overview, see docs/advanced-features.md. For a feature-by-feature reference,
see docs/features.md.
Mental model (short)
| Need | Reach for |
|---|---|
| Sync API | @http / @rpc |
| Async reaction | @on_event |
| Time-driven work | @task |
| One instance handles an event | default @on_event (competing consumers) |
| Every instance handles it | @on_event(..., broadcast=True) |
| One pinned instance | @on_event(..., in_session=True) + open_session |
| RPC to one process | call(..., instance_id=) / RpcProxy(..., instance_id=) |
| Route an event | explicit event_type |
| Caller target from deploy config | RpcProxy(..., peer="…") / open_session(peer="…") → kontiki.peers |
| Fleet health | registry + degraded_on |
| Cross-service debug | flow_id → KontikiTUI Flows (tree, exception, export) |
| Tests on the bus | kontiki.testing |
| Gateway into Kontiki from FastAPI, etc. | standalone Messenger |
Kontiki suite
Kontiki is not only this runtime. The suite shares the same process model, registry, and terminal UI:
| Component | Role |
|---|---|
| Kontiki (this repo) | Service runtime — entrypoints, messaging, registry client, config, testing |
| kontiki-tui | Terminal UI over the registry and local logs — browse services, flows, and exceptions |
| kontiki-monitor | Fleet checks, registry signals, and host disk alerts |
When services register with the Kontiki registry, KontikiTUI gives a live picture of the fleet from the terminal:
Quickstart
Install Kontiki (via pip or Poetry):
pip install kontiki
Define a simple service. The service class wires entrypoints; a
delegate holds business logic (recommended pattern — see docs/features.md):
from kontiki.delegate import ServiceDelegate
from kontiki.messaging import Messenger, on_event, rpc
from kontiki.runner import cli
class MyDelegate(ServiceDelegate):
async def setup(self):
pass # optional: init from self.container.config
def process(self, payload):
return {"processed": payload}
class MyService:
name = "compute-api" # optional: overridden by kontiki.service_name in config
delegate = MyDelegate()
messenger = Messenger()
@rpc
async def compute(self, x):
return self.delegate.process(x)
@on_event("example.thing.happened")
async def on_thing(self, payload):
result = self.delegate.process(payload)
await self.messenger.publish("example.thing.processed", result)
def run():
cli.run(MyService, "Example Kontiki service.", version="0.1.0")
Expose it as a CLI command in pyproject.toml:
[tool.poetry.scripts]
my_service = "myapp.main:run"
Run your service:
my_service --config config.yaml
RPC plus a chained event — the shape most meshes grow from. In production,
peers resolve from config (kontiki.peers), delivery modes are set on handlers,
and the registry tracks the fleet. See examples/events/broadcast/,
examples/events/session/, and examples/registry/.
Testing a service in isolation
kontiki.testing lets you exercise one service on the bus without running
its peers. The usual form is a Gherkin feature: an executable spec of the
service boundary.
The feature shows the timeline — config and initial state, incoming events
or RPC, calls to peers and their controlled responses, published events,
return values, state changes. That sequence stays in the .feature, not in
Python fixtures.
From Boomerang's subscription-service: the service starts from its config, an RPC comes in, matching recipients come out.
Scenario: Return matching recipient for exact area and category
Given the subscription service is running with the following configuration
"""
kontiki:
amqp:
url: amqp://guest:guest@localhost/
http:
address: 127.0.0.1
port: 8000
logging:
directory: logs
handlers:
file:
class: logging.handlers.RotatingFileHandler
level: INFO
maxBytes: 10485760
backupCount: 5
root:
handlers: [file]
level: INFO
app:
subscriptions:
wind-fr69:
category: weather.wind
event_type: "*"
criteria:
- key: area.zone
operator: eq
value: FR-69
endpoints:
- email.email_primary
"""
When I call the RPC get_recipients_for_alert on the subscription service with the following arguments
"""
{
"alert": {
"schema_version": "1.0",
"alert_id": "wx_wind_fr69",
"source": "test",
"category": "weather.wind",
"event_type": "hail",
"severity": "moderate",
"occurred_at": "2026-01-15T12:00:00Z",
"title": "Wind warning",
"body": "Strong winds expected in FR-69.",
"areas": [
{"type": "zone", "value": "FR-69"}
],
"attributes": {}
}
}
"""
Then the RPC response is
"""
[
{
"channel": "email",
"endpoint_key": "email_primary"
}
]
"""
Mocks, controlled return values, and message capture live in
kontiki.testing; Behave steps drive them. The feature is the behavioural
source of truth. Steps execute it; they should not invent behaviour missing
from it.
See docs/features.md (Testing) and tests/integration/.
Documentation
- Features:
docs/features.md - Advanced features (patterns & gotchas):
docs/advanced-features.md - Configuration reference:
docs/configuration.md - Example configuration:
docs/kontiki-config.example.yaml - Contributing guidelines:
CONTRIBUTING.md - License:
LICENSE
Kontiki requires RabbitMQ ≥ 4.3 (for V2.0+ features like quorum queues). You do not declare exchanges or queues yourself — decorators and config declare the topology. To start a broker locally:
make run-amqp
Examples
Examples can be run via the Makefile (see targets such as run-rpc-service,
run-rpc-example, run-rpc-instance-example, run-simple-events-service,
run-task-service, etc.). Shared logging is examples/common.yaml: console
StreamHandler, default Kontiki formatter (omit formatters in YAML).
| Feature | Example path |
|---|---|
| Basic RPC | examples/rpc/ |
| Targeted RPC | examples/rpc/ |
| Simple events | examples/events/simple/ |
| Broadcast events | examples/events/broadcast/ |
| Event serialization | examples/events/serialization/ |
| Session-based events | examples/events/session/ |
| Periodic tasks (interval and cron) | examples/task/ |
| Service registry (admin + client) | examples/registry/ |
| Heartbeats & degraded mode | examples/heartbeat/ |
| HTTP entrypoints | examples/http/simple/ |
Misc
Kontiki did not come out of a naming workshop but from the album Kontiki by the band Cotton Mather. If you enjoy vintage 4-track indie pop as much as microservices, you should check it out.
Metadata
Release files for kontiki 2.3.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 | |
|---|---|---|---|
| kontiki-2.3.1.tar.gz | 52.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| kontiki-2.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 121.9 kB
Release files / kontiki-2.3.1.tar.gz
| Download URL | kontiki-2.3.1.tar.gz |
|---|---|
| Size | 52.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f05cad3b99f19b99e84bee56d5b0399aa2ad5a4ad7632d9acddb8bf443a0691e
|
|
BLAKE2b-256 checksum How to use checksums |
a30e65f24b3aabf343747ab26e47785f818f4eb4dbd83e39657cd29521f7ea9e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.13.7 Linux/6.8.0-142-generic
|
Release files / kontiki-2.3.1-py3-none-any.whl
| Download URL | kontiki-2.3.1-py3-none-any.whl |
|---|---|
| Size | 69.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
63f3f129280f69158fee2f5992b34d30753c8737b133a16a5be6ec00ab17a6e3
|
|
BLAKE2b-256 checksum How to use checksums |
b8ac975d6c26a6c0f86ed3d731ecd4b97e6535f5d725c0f26d3c0e719d0a4d47
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.13.7 Linux/6.8.0-142-generic
|