Named decisions
.pyjev.toml is a version-controlled decision specification, not a secret store.
Keep credentials in the environment, keyring, or user-level credential file.
Schema
Canonical files declare schema 1:
[pyjev]
schema = 1
A missing [pyjev] table remains accepted as legacy implicit schema 1. Unknown schema
fields, non-integer values, and unsupported schema numbers fail during local validation.
No migration machinery is implied by the marker.
Primitive declarations
[decision.ticket-route]
type = "choice"
question = "Which team should handle this?"
model = "jev-latest"
[decision.ticket-route.options]
billing = "Billing or refunds"
engineering = "Technical problem"
sales = "Purchasing question"
[decision.urgency]
type = "score"
question = "How urgent is this?"
levels = ["Can wait", "Normal", "Urgent", "Critical"]
Noul uses true and false criteria. Choice requires 2–255 options; Score requires
2–10 ordered levels. Unknown fields and invalid criteria are rejected before API access.
Bundles
A bundle asks several independent typed questions about one state in one SDK request:
[decision.ticket-triage]
type = "bundle"
[decision.ticket-triage.questions.refund]
type = "noul"
question = "Does the customer request a refund?"
[decision.ticket-triage.questions.route]
type = "choice"
question = "Which team should handle this?"
[decision.ticket-triage.questions.route.options]
billing = "Billing issue"
engineering = "Technical issue"
sales = "Purchase question"
Child keys become answer identifiers. Nested bundles and child model fields are not
allowed initially because one system_one() request uses one model. Model precedence is
explicit call model, then bundle model, then the client/SDK default.
Bundle results preserve every child result’s probabilities and confidence, plus shared
model, usage, raw response, and request ID. Bundles have no aggregate confidence policy;
--value and --min-confidence are rejected.
Compiled output contract
decision compile produces a credential-free JSON preview with this stable top-level shape:
{
"schema": 1,
"decision": {
"name": "ticket-route",
"type": "choice",
"config": ".pyjev.toml",
"fingerprint": "<sha256>"
},
"request": { "state": "...", "questions": {}, "model": null }
}
The schema marker is the compiled-output contract version. decision.name,
decision.type, decision.config, decision.fingerprint, and the request fields
are stable contract fields. The config identifier is relative to the current
project when possible and otherwise uses the config filename; it is never an
absolute machine path. Question and answer data retain the official SDK shape.
The SHA-256 fingerprint identifies the validated decision specification and
schema. It includes the decision name, type, criteria, model, and declaration
content. It excludes runtime state, credentials, and environment-specific
absolute paths, so the same declaration has the same fingerprint in different
checkouts. Compilation remains local: it does not construct a client, read a
credential, or contact the API.
Discovery and inspection
Configuration precedence is explicit config=/--config, then PYJEV_CONFIG, then the
nearest .pyjev.toml in the current directory or a parent. Use decision validate to
check all declarations without a network call and decision compile to inspect a
normalized request for a particular state.
When not to use named decisions
Do not put a decision in .pyjev.toml when its criteria are inherently dynamic at runtime.
For example, Connect Four legal actions depend on the current board; build those choices
in Python after deterministic filtering.