chumak
A thin inference substrate for Python projects: user-authored profiles, LangChain as a handler, optional provenance/meta on every response.
Chumaks (Чумаки) were wandering Ukrainian salt-traders who traversed the steppe between distant places. They named the Milky Way after themselves — Чумацький Шлях, the Chumaks' Way — because they navigated by it.
What it is
A small library that abstracts away which LLM you're calling and how.
- Author profiles (TOML files) under the app's XDG config dir.
- Load a profile via
ProfileLoader(with inheritance + env-var overrides) - Call
infer(prompt=..., output_schema=..., profile=...)and get back a validated pydantic payload, normalised citations, and (optionally) a provenanceMetastamp.output_schemais optional: omit it for an untyped call whosepayloadis the model's plain response text (langchain handler only — see below).
Two built-in handlers:
langchain— useslangchain.chat_models.init_chat_model(profile.model)so a single identifier (anthropic:claude-opus-4-7,openai:gpt-5, …) routes to the right provider. Structured output, citations, and token usage all handled. With anoutput_schemathe call returns a validated instance; without one it returns the model's plain response text (a liveness/smoke probe or one-shot free-text question).subprocess— shells out to a CLI (claude --print,codex exec, etc.). Useful for prompt iteration via an existing, authorised tool. Schema is injected into the prompt as JSON Schema; stdout is parsed and validated. Requires anoutput_schema— untyped generation is a langchain-handler capability.
Profiles
Profiles are user-authored. chumak ships at most one generic example
(anthropic-claude-opus-4-7 via the LangChain handler). Everything else is yours.
Profiles live in consumer app directory, e.g. ~/.config/<your-app>/chumak/profiles/.
chumak does not impose a config dir; the app passes search_paths to ProfileLoader.
File shape
# ~/.config/galops-vision/chumak/profiles/claude.toml
handler = "langchain"
model = "anthropic:claude-opus-4-7"
temperature = 0.0
[model_kwargs]
max_tokens = 4096
Inheritance
# claude-account-b.toml
extends = "claude"
[model_kwargs]
# api_key sourced from env — see below
Env-var overlay
Every field on a profile is overridable from the environment. chumak does not provision special fields; the convention is uniform:
{APP_PREFIX}_PROFILE_{PROFILE_NAME}_{FIELD_PATH}
with __ as the nested-field delimiter (single _ stays inside field names):
# top-level field
export MYAPP_VISION_PROFILE_CLAUDE_MODEL=anthropic:claude-haiku-4-5
# nested into model_kwargs
export MYAPP_VISION_PROFILE_CLAUDE_ACCOUNT_B_MODEL_KWARGS__API_KEY=sk-ant-...
This means a profile file can be effectively empty on disk (just declaring the
profile's existence and maybe an extends), with all values supplied by the
environment. You decide which fields are sensitive and never touch disk.
Usage
from pathlib import Path
from chumak import ProfileLoader, infer
loader = ProfileLoader(
search_paths=[Path.home() / ".config/my-app/chumak/profiles"],
env_prefix="MYAPP",
)
loader.names() # -> ["claude", "claude-creative", ...]
profile = loader.load("claude")
from pydantic import BaseModel
class AnneSchema(BaseModel):
title: str
value: int
result = infer(
prompt="Extract title and value from this text: ...",
output_schema=AnneSchema,
profile=profile,
)
result.payload # -> MissionTitle(title=..., bounty=...)
result.citations # -> [Citation, ...] (if the model supplied any)
result.meta # -> Meta with cost, generated_at, model identity
With provenance
from chumak import Provenance
result = infer(
prompt="...",
output_schema=AnneSchema,
profile=profile,
provenance=Provenance(
artefact_type="model@v1",
artefact_id="artifact-type:2026-05-20T12:34:56Z",
),
)
result.meta.artefact_type # "mission_title@v1"
result.meta.derived_from # [...]
Design notes
- No domain knowledge: chumak carries no built-in prompts, no role concepts (tactical/narrator etc. — that's an app concern; just name your profile).
- LangChain is a handler, not the spine: subprocess CLIs are first-class.
- Provenance is opt-in: omit
provenance=andmeta.artefact_typeisNone. - The lib never reads env directly for its own settings. The env overlay for profiles is a deliberate, scoped exception, gated on the prefix the consumer passes in.
Tooling
uv, Python 3.12+, ruff, ty, pytest. See CONTRIBUTING.md for dev setup, the integration test, and quality-check commands.
Release files for chumak 0.2.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 | |
|---|---|---|---|
| chumak-0.2.1.tar.gz | 106.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| chumak-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 124.8 kB
Release files / chumak-0.2.1.tar.gz
| Download URL | chumak-0.2.1.tar.gz |
|---|---|
| Size | 106.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dae79390b283b51d47b58a41e14366e19b31d14a60cb47f543da30bb6c09268c
|
|
BLAKE2b-256 checksum How to use checksums |
27ca569ee2c620da90a2c6c9aeaba62c7382c304b10a833845cf612f53c9efeb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| 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":true}
|
Release files / chumak-0.2.1-py3-none-any.whl
| Download URL | chumak-0.2.1-py3-none-any.whl |
|---|---|
| Size | 18.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f9eb5158a5e6faa904ac319bc2510839c10c7cafab43675180c8d719302df972
|
|
BLAKE2b-256 checksum How to use checksums |
fed9f68650f338fea9dc75aed3f3b49e3de3ce07b9a48e8ed9d67e4c4290b4c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| 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":true}
|