Getting started
This walkthrough introduces pyjev’s main idea: define a reusable decision contract, inspect it offline, then use the same contract from shell and Python.
Install
pip install pyjev
uv tool install pyjev
For a checkout, install contributor and documentation dependencies separately:
pip install -e '.[dev,docs]'
Create a decision contract
In a project directory, create .pyjev.toml:
[pyjev]
schema = 1
[decision.ticket-route]
type = "choice"
question = "Which team should handle this support request?"
[decision.ticket-route.options]
billing = "Billing, invoice, payment, or refund issue"
engineering = "Technical problem or product bug"
sales = "Purchasing, pricing, or procurement question"
This is a version-controlled specification. It is not a secret store and must not contain API keys.
Inspect before execution
Validation and compilation are local operations:
pyjev decision validate
pyjev decision show ticket-route
pyjev decision compile ticket-route --state "Stripe webhooks fail"
They do not read credentials, construct a client, or contact the Jev API. The compiled output is a normalized request preview with a stable schema marker and non-secret decision fingerprint.
Authenticate
For an interactive local setup, use hidden input:
pyjev auth set
pyjev auth status
pyjev auth test
For CI, prefer the environment:
export TYPESAFE_API_KEY='...'
pyjev auth test --json
auth test performs one minimal request through the official SDK and reports
safe metadata only. The explicit auth set --api-key option is retained for
compatibility but is unsafe because shell history and process listings may
expose the value. Do not put secrets in command output, decision files, or
logs.
Warning
The file fallback is plaintext. Restrictive permissions reduce exposure but do not encrypt the credential.
Execute from shell
echo "Stripe webhooks fail" | pyjev decide ticket-route --json
--json preserves result metadata. Use --value only when a scalar is safe to
consume, and use --min-confidence when the application requires a confidence
policy.
Execute from Python
from pyjev import Jev
with Jev() as jev:
result = jev.decide("ticket-route", state="Stripe webhooks fail")
print(result.value)
print(result.confidence)
print(result.probabilities)
For native asynchronous applications:
from pyjev import AsyncJev
async with AsyncJev() as jev:
result = await jev.decide("ticket-route", state="Stripe webhooks fail")
When to use a direct primitive
Use jev.choice(...), jev.noul(...), or jev.score(...) when criteria are
computed dynamically from deterministic application state. Keep deterministic
constraints in normal Python; use a named decision when the judgment contract
is stable and worth reviewing in source control.
Continue with Named decisions, Confidence, Authentication, and Python API.