Python bindings for model-language — a typed, safe template language for AI-agent prompts. Runs the exact same engine as the TypeScript package via a WebAssembly (WASI) module.
Project description
model-language (Python)
Python bindings for model-language —
a typed, safe template language for AI-agent prompts.
Powered by the production model-language engine compiled to a WebAssembly module:
templates render byte-for-byte identically in Python and JavaScript, a
guarantee enforced by a shared conformance/ suite run in CI.
Fast (parse once, render many), sandboxed, and it never crashes — template
problems degrade to empty output plus a warning.
▶ Live demo — try the language in a Tiptap editor (live validation, autocomplete, real-time render), powered by the same engine.
Filters format values — dates, numbers, text:
{{ user.created_at | date: "MMM D, YYYY" }} → Jul 5, 2026
{{ user.created_at | date: "h:mm A", "Europe/Kyiv" }} → 5:37 PM
{{ user.last_seen | time_ago }} → 3 days ago
Directives embed machine-readable constraints in a prompt. They are stripped from
the rendered text and returned in directives:
from model_language import render, validate, parse
src = (
"Help with billing.\n"
"{{verify_before: payments}}\n"
"{{identity: contact.email == payment.email}}\n"
'Greet {{contact.first_name | default: "there"}}.'
)
directives = [
{"name": "verify_before", "hasBody": False, "arg": {"kind": "scalar", "type": "enum", "values": ["payments", "calendar"]}},
{"name": "identity", "hasBody": False, "arg": {"kind": "comparison", "type": "field", "comparison": {"operators": ["=="], "operandType": "field"}}},
]
schema = [{"path": "contact.email", "type": "string"}, {"path": "contact.first_name", "type": "string"}]
out = render(
src,
data={"contact": {"first_name": "Vasyl"}},
schema=schema,
)
print(out["text"]) # -> "Help with billing.\n\nGreet Vasyl."
print([d["name"] for d in out["directives"]]) # -> ["verify_before", "identity"]
Usage
from model_language import render, validate, parse
out = render(
"Hi {{ user.name | default: 'there' }}!",
data={"user": {"name": "Vasyl"}},
)
print(out["text"]) # -> "Hi Vasyl!"
diags = validate(
"{{if user.plan == 'premium'}}x{{/if}}",
schema=[{"path": "user.plan", "type": "enum", "values": ["free", "pro"]}],
)
print([d["code"] for d in diags["diagnostics"]]) # -> ["ML202"]
render(template, data=None, schema=None, options=None)→{"text", "warnings", "resolvedBranches", "directives", "tokenEstimate"}. Passoptions={"now": <epoch_ms>}for datetime filters (the sandbox has no ambient clock; it defaults to0). Passoptions={"snippets": {...}}for{{include}}.validate(template, schema=None, options=None)→{"diagnostics", "maxTokenEstimate"}. Passoptions={"maxTokenEstimate": N}to raiseML213over a token budget.parse(template)→{"ast", "diagnostics"}.
Nothing raises for template problems — they degrade to empty output plus a
warnings/diagnostics entry.
Build (from source)
The bindings host model_language.wasm, built from the TypeScript engine:
# 1. Build the WASI module (from the repo root, needs Node + pnpm + the javy CLI)
pnpm install && pnpm wasm:build
# 2. Run the conformance parity tests
pip install wasmtime pytest
cd hosts/python && python -m pytest -q
The loader finds the module at ../wasm/dist/model_language.wasm by default;
set MODEL_LANGUAGE_WASM to point at a prebuilt one. Requires wasmtime>=25.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file model_language-1.1.0.tar.gz.
File metadata
- Download URL: model_language-1.1.0.tar.gz
- Upload date:
- Size: 600.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a538ad9d16e71c70ee84e069e82304be9318cfb7f6fa48eba0fc85a23833cae4
|
|
| MD5 |
dc604f2f7fc0222ff5fc38f20dc7b79e
|
|
| BLAKE2b-256 |
d0827b3a7a98bc343c33f8fd17a7d3c545afd34d23e27c71a0feef9c0a36a0fc
|
File details
Details for the file model_language-1.1.0-py3-none-any.whl.
File metadata
- Download URL: model_language-1.1.0-py3-none-any.whl
- Upload date:
- Size: 599.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa93602f5733e8e0cc1bf5d7e78436691b1b9ab2707b860161033e89639a52e9
|
|
| MD5 |
61abbe78d06cd23d344a4cdc4b6b8e1a
|
|
| BLAKE2b-256 |
c4f66f8ce7705e293582bb578f553584e56d8203b0c7ceab7cd3c0abfcdea102
|