Skip to main content

TempоKat

Temporal.io integration for KatCity — async-first, config-driven, production-ready.

TempоKat wraps Temporal.io with the KatCity patterns you already know: Pydantic configuration, factory functions, a clean CLI, and first-class Sentry support. Drop it into any KatCity service and go from zero to running durable workflows in minutes.


Features

  • Config-driven workers — define every worker, queue, workflow, and activity in YAML
  • Factory pattern — get_worker(), get_client(), get_looper() mirror StashKat's API
  • Multi-worker Looper — run all workers in a single process with graceful shutdown
  • Schedule management — sync interval schedules declaratively from config
  • Pydantic data converter — serialize workflow inputs/outputs as Pydantic models automatically
  • Agnostic progress tracking — ProgressTracker mixin + canonical WorkflowProgress envelope + unified /status, /progress, /progress/stream endpoints
  • JWT token signing — multi-key keyring with kid-based rotation and Prometheus metrics
  • Sentry interceptor — one-line Sentry integration for workflows and activities
  • Full CLI — tempokat worker run, tempokat schedule sync, tempokat version
  • Async-first — built on asyncio, temporalio, and KatCity's async foundations

Installation

# Core (from monorepo)
uv sync --package tempokat

# With Sentry support
uv pip install "tempokat[sentry]"

# All extras
uv pip install "tempokat[all]"

Quick Start

1. Generate a config file

tempokat config default-config > config.yaml

2. Edit config.yaml

name: my-temporal-app

temporalio:
  host: localhost:7233
  namespace: default
  workers:
    - name: my-worker
      queue: my-task-queue
      workflows:
        - myapp.workflows:MyWorkflow
      activities:
        - myapp.activities:my_activity

3. Run the worker

tempokat worker run --config config.yaml

That's it. Your worker is connected to Temporal and processing tasks.


Configuration

TempоKat uses the standard KatCity YAML + environment variable configuration system.

name: my-app

temporalio:
  host: localhost:7233          # Temporal server address
  namespace: default            # Temporal namespace
  max_concurrent_activities: 100
  max_concurrent_workflow_tasks: 100
  enable_metrics: false         # Prometheus metrics
  metric_bind_address: "0.0.0.0:9000"

  workers:
    - name: main-worker
      queue: main-queue
      workflows:
        - myapp.workflows:OrderWorkflow
        - myapp.workflows:PaymentWorkflow
      activities:
        - myapp.activities:charge_card
        - myapp.activities:send_email
      # Per-worker overrides (inherits from parent if omitted)
      max_concurrent_activities: 50

schedules:
  daily-report:
    workflow_id: daily-report-wf
    workflow: myapp.workflows:DailyReportWorkflow
    task_queue: main-queue
    interval:
      every: 24h
      offset: 1h
    state: created   # created | paused | deleted
    payload:
      report_type: full

Environment variable overrides

All settings can be overridden with TEMPOKAT_ prefixed env vars:

TEMPOKAT_TEMPORALIO__HOST=prod-temporal:7233
TEMPOKAT_TEMPORALIO__NAMESPACE=production
TEMPOKAT_TEMPORALIO__ENABLE_METRICS=true

Programmatic API

Running workers

import asyncio
from tempokat import get_looper
from tempokat.config import config
from tempokat.init import init

async def main():
    conf = config("config.yaml")
    init(conf)
    looper = await get_looper(conf)
    await looper.run()

asyncio.run(main())

Creating a Temporal client

from tempokat import get_client
from tempokat.config import config

async def main():
    conf = config("config.yaml")
    client = await get_client(conf)

    handle = await client.start_workflow(
        MyWorkflow.run,
        "some-input",
        id="my-workflow-id",
        task_queue="my-task-queue",
    )
    result = await handle.result()
    print(result)

Syncing schedules

from tempokat import get_client
from tempokat.config import config
from tempokat.schedule import TemporalScheduler

async def sync():
    conf = config("config.yaml")
    client = await get_client(conf)
    scheduler = TemporalScheduler(client, conf.schedules)
    await scheduler.sync_schedules()

CLI Reference

tempokat --help

Commands:
  worker    Temporal worker operations
  schedule  Temporal schedule management
  version   Show version information
  config    Configuration utilities

Worker commands

# Run all workers from config
tempokat worker run --config config.yaml

# Override host and namespace at runtime
tempokat worker run --config config.yaml --host prod:7233 --namespace production

# Run a specific named worker
tempokat worker run --config config.yaml --worker payment-worker

# Ad-hoc worker (no config file needed)
tempokat worker run \
  --queue my-queue \
  --workflow myapp.workflows:MyWorkflow \
  --activity myapp.activities:my_fn

Schedule commands

# Sync all schedules defined in config
tempokat schedule sync --config config.yaml

# Override host
tempokat schedule sync --config config.yaml --host prod:7233

Pydantic Data Converter

TempоKat ships a Pydantic-aware data converter that serializes workflow inputs and outputs using model_dump_json() automatically.

Enable it globally via config:

temporalio:
  converter: tempokat.converters.pydantic:pydantic_data_converter

Sentry Integration

Install the extra:

uv pip install "tempokat[sentry]"

Add to config:

sentry:
  dsn: "https://your-dsn@sentry.io/123"
  traces_sample_rate: 0.1

Call init() at startup — TempоKat automatically registers SentryInterceptor on all workers:

from tempokat.init import init
from tempokat.config import config

conf = config("config.yaml")
init(conf)  # Sentry initialized + interceptor registered on all workers

Documentation


Package Structure

tempokat/
├── src/tempokat/
│   ├── __init__.py          # Public API: get_worker, get_client, get_looper, Looper, etc.
│   ├── main.py              # CLI entry point
│   ├── config.py            # ConfigSchema, TemporalConfigSchema, WorkerConfigSchema, etc.
│   ├── init.py              # init() — logging + Sentry setup
│   ├── factory.py           # get_client(), get_worker(), get_looper()
│   ├── worker.py            # WorkerFactory, Looper, Worker lifecycle
│   ├── schedule.py          # TemporalScheduler
│   ├── utils.py             # heartbeat_every, gather_with_concurrency, find_workflow
│   ├── version.py           # VERSION instance
│   ├── cli/
│   │   ├── worker.py        # `tempokat worker` commands
│   │   └── schedule.py      # `tempokat schedule` commands
│   ├── converters/
│   │   └── pydantic.py      # PydanticPayloadConverter, pydantic_data_converter
│   └── interceptors/
│       └── sentry.py        # SentryInterceptor
├── tests/
├── make/
└── pyproject.toml

Development

# Run tests
make test

# Run tests with coverage
make test-cov

# All checks (format + lint + types + tests)
make check

# Auto-fix issues
make fix

VelociKat Maintenance

This project was scaffolded by VelociKat. To check for template updates:

velocikat status
velocikat doctor

License

BSD 3-Clause License. See LICENSE for details.

Release files for tempokat 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tempokat 0.1.4
File Size Uploaded
tempokat-0.1.4.tar.gz 31.8 kB Details

Built distribution (wheel)

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

Total release size: 76.4 kB

Release files / tempokat-0.1.4.tar.gz

Download URL tempokat-0.1.4.tar.gz
Size 31.8 kB
Tags Source
SHA-256 checksum
How to use checksums
1ae81fada6c11b136d2c4e768e592e6e33b094587a73aa250f85092a4d725686
BLAKE2b-256 checksum
How to use checksums
e7dba9ff728dd8169d2bc1489955f25dc742ab4c7d5298fef0baa59488af9420
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / tempokat-0.1.4-py3-none-any.whl

Download URL tempokat-0.1.4-py3-none-any.whl
Size 44.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3d259451af3fc1abbb9f5ee7fac71a2785f3b195ca6301e305dc8af84993f3e1
BLAKE2b-256 checksum
How to use checksums
9507459394ea57c81cc4c926b85d3322ecc738f00f438ceb17edee78fc48095a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.0

2 release 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