jevlikedecisions
jevlikedecisions.decide(...) is one typed decision entrypoint over a family of provider adapters. Shared evidence is sent once, in full, and responses are checked against both the provider shape and the originating questions. Backend selection is mandatory: no call silently falls back to the deterministic mock_jevlike backend.
Installation and spend-gate setup
Python 3.11 or newer is required.
Install the package and its sole runtime dependency, llm-spendguard, with pip:
python -m pip install jevlikedecisions
Pending first release: The package is not yet published on PyPI. Until the first release is published, clone this repository, change into the clone, and run
python -m pip install .. Delete this note when publishing the first release.
Before making a model call, arm the spend gate in the virtual environment. This is required: jevlikedecisions deliberately refuses to call a model from an interpreter where spendguard is not enforcing. With the target virtual environment activated, run:
spendguard install-hook --venv "$VIRTUAL_ENV" --no-pkg
Temporary upstream workaround:
--no-pkgavoids aFileNotFoundErrorfor pip-installed, non-editablellm-spendguardenvironments whereinstall-hookotherwise looks for a repositorypyproject.toml. Remove this flag and note after that upstream defect is fixed.
Verify the activated interpreter:
spendguard doctor
The successful verdict line is ENFORCING HERE: 🟢 YES — calls from this interpreter are gated.
Temporary upstream workaround:
spendguard doctormay currently exit non-zero after printing that successful verdict, withValueError: Pricing returned no token cost. Read the verdict line rather than the exit code; remove this note after that upstream defect is fixed.
If gate setup is skipped, decide() refuses model calls through require_enforcing_spendguard.
Request and question schema
Every surface accepts the same JSON object:
{
"input_parts": ["complete evidence"],
"questions": [{"name": "safe", "type": "predicate", "description": "Is it safe?"}],
"backend": "mock_jevlike",
"intent": "documented-example",
"prompt_cache_key": null
}
intent and backend are required. Every decision result identifies backend, provider, model, route, via, ledger_id, usage, cost_complete, and known_input_cost_floor_usd. Inspect route to distinguish in-process and metered results. cost_complete says whether the cost is fully settled; when a provider omits output-token usage, a metered result has cost_complete: false, no ledger id, and only the known input-cost floor. In-process results are settled at zero cost. Every question has name, type, and description. type is predicate, choice, or score. A choice also has choices, whose entries contain value and description. A score also has levels, whose entries contain label and description. Library validation is authoritative for every surface.
Backend names and aliases come from the package configuration. An alias is accepted only at selection; estimates, approvals, receipts, audit evidence, and returned provenance always use the canonical backend name. Omitting backend never selects a default and produces a typed DecisionUnavailable refusal.
| Canonical backend | Accepted aliases | Provider | Model | Usability and precondition |
|---|---|---|---|---|
openai_decisions |
openai |
openai |
gpt-6-luna |
Usable only with OPENAI_API_KEY, an enforcing spendguard interpreter, and a matching estimate approval. The sole proven call is ledger 2bed00b5f31d4858: 319 input tokens costing $3.19e-05; its output side is unproven. |
typesafe_jev |
jev |
typesafe |
jev-1.14.0 |
Usable only with TYPESAFE_API_KEY, an enforcing spendguard interpreter, and a matching estimate approval. Input costs $0.042 per 1M tokens and output is free, as documented at docs.typesafe.ai/models; the wire schema is documented at docs.typesafe.ai/api/system-one. No live TypeSafe call has yet been proven. |
mock_jevlike |
none | mock |
deterministic |
Usable in-process and never selected implicitly. Predicate probability is exactly 0.5; choice selects the first option with probability/confidence 1.0 and all others 0.0; score selects the first level with score 0.0, probability/confidence 1.0, and all other levels 0.0; reported input/output tokens are both 0. |
Estimate, approve, then spend
The shipped configuration contains exactly three backends: metered typesafe_jev and openai_decisions, plus the in-process mock_jevlike test double. Their only transport kinds are http and in_process. A backend that declares the removed subscription transport is refused when configuration loads; subscription-lane LLM access belongs in llm-spendguard.
Choice questions may declare "calibrated_choice_distribution": "required" or "calibrated_choice_distribution": "omitted". Omitting the declaration preserves the current required contract: choice, probabilities for every declared choice in order, and confidence. Declaring omitted explicitly requests only name, type, and choice; returning either probabilities or confidence is a named nonconformance, even if null. Unknown or malformed declarations are refused with the permitted values from the packaged choice_distribution_contract configuration beside limits. Mixed declarations in one call are supported. The shared validator enforces the declared answer fields across Python, CLI, HTTP, and MCP. Score questions are unchanged.
Self-reported confidence is not calibrated. In the measured eight-question probe with twenty declared choices per question, gpt-6-luna returned top probability/confidence 1.0 on every item (entropy approximately zero; effective support 1.00), while glm-5.3 returned top probability/confidence 0.99 on every item (entropy 0.0629; effective support 1.06). Those degenerate vectors do not establish calibrated uncertainty. At the working shape of 32 questions × 29 choices, the measured output grew from 2,149 to 23,270 tokens. The declaration allows callers to omit that unvalidated distribution rather than pay for it. The field describes the requested distribution contract; it does not certify calibration when required.
Paid decisions fail closed. First call decide(..., estimate_only=True): it counts the complete provider request, prices it through spendguard.pricing, spends $0, and persists a matching approval. Only a later identical decide(...) may reach the gated metered transport. Provider usage remains authoritative for the real receipt. Configure approval storage with JEVLIKEDECISIONS_APPROVAL_DIR, approval signing with JEVLIKEDECISIONS_APPROVAL_INTEGRITY_KEY, receipt storage with JEVLIKEDECISIONS_RECEIPT_DIR, and an alternate package configuration with JEVLIKEDECISIONS_CONFIG. Credentials are read only from the environment variable named by the selected backend configuration.
Python, CLI, HTTP, and MCP
Python:
from jevlikedecisions import decide
estimate = decide(input_parts, questions, backend=backend, intent=intent, estimate_only=True)
result = decide(input_parts, questions, backend=backend, intent=intent)
CLI input comes from a JSON file or stdin. estimate prints the estimate and its approval_path; decide prints answers and receipt fields. The backend value accepts either a canonical name or an alias reported by backends.
jevlikedecisions backends
jevlikedecisions estimate --backend "$JEVLIKEDECISIONS_BACKEND" request.json
jevlikedecisions decide --backend "$JEVLIKEDECISIONS_BACKEND" request.json
The CLI flag fills a missing request backend; if both the flag and JSON field are present they must agree or the command fails. CLI exit codes follow sysexits: 0 (EX_OK) for success, 64 (EX_USAGE) for malformed input, 65 (EX_DATAERR) for a typed decision refusal, and 70 (EX_SOFTWARE) for an internal fault. The CLI reports every failure as TypeName: message on stderr; catching internal faults gives automation a stable code without hiding the fault.
The standard-library HTTP server exposes POST /backends, POST /estimate, and POST /decide; its backend field accepts the same config-derived canonical names and aliases. HTTP 400 identifies a malformed request, 422 identifies a typed decision refusal, 503 specifically identifies DecisionUnavailable, and 500 identifies an internal fault. Keeping unavailable decisions at 503 preserves the established retry signal, while the JSON error field retains the exact typed refusal. Set JEVLIKEDECISIONS_HTTP_PORT; optionally set JEVLIKEDECISIONS_HTTP_HOST. With no JEVLIKEDECISIONS_OPERATOR_TOKEN it binds only to loopback. When that token is set, callers must send it as an operator bearer token. A paid caller must successfully call /estimate before /decide with the identical request.
jevlikedecisions-http --host "$JEVLIKEDECISIONS_HTTP_HOST" --port "$JEVLIKEDECISIONS_HTTP_PORT"
The package's sole runtime dependency is llm-spendguard; its MCP surface is a standard-library JSON-RPC stdio server. The list_decision_backends, estimate_decision, and make_decision tools expose the same selection contract and send evidence whole. Enumeration is derived from configuration and reports canonical name, aliases, provider, model, usability, and every missing precondition; both decision tools accept exactly those canonical names and aliases. The approval from the estimate tool must exist before a paid call through the decision tool.
jevlikedecisions-mcp
Paid live-proof utility
scripts/run_paid_decision_live_proof.py preserves the reproducible paid-call proof harness in the repository. It takes a configuration path rather than embedding one; examples/paid_decision_live_proof.example.json shows the input shape. By default it estimates every configured backend, prints the per-backend and total token/USD estimates, and exits without making a paid call. After reviewing that complete estimate, rerun with the explicit --authorize-paid-calls flag to execute every configured proof. Its records include reported-output-token status, cost completeness, and the known input-cost floor alongside the ledger and receipt evidence.
PYTHONPATH=src python scripts/run_paid_decision_live_proof.py examples/paid_decision_live_proof.example.json
PYTHONPATH=src python scripts/run_paid_decision_live_proof.py examples/paid_decision_live_proof.example.json --authorize-paid-calls
assert_all_decisions_via_jevlikedecisions(...) cross-checks package-owned receipts against spendguard rows by ledger_id and fails closed when there are no auditable receipts. Spendguard's calls table has no endpoint, route, or via columns, so this proves receipt-backed package calls; it cannot prove that no outside caller contacted a Decisions endpoint.
Troubleshooting
A framework Python without a usable certificate bundle may need SSL_CERT_FILE set to the path of an installed CA bundle, such as the one supplied by certifi, before a real HTTPS call. Never put keys or secret values in configuration or examples.
anyjev remains a named v1 schema gap: its authoritative independent wire contract was unavailable, so no fields were invented. It can be added as another adapter without changing decide().
General LLM generation
This package wraps the jev and OpenAI Decisions APIs only. General text generation was removed; use llm-spendguard for general LLM calls.
Metadata
Release files for jevlikedecisions 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| jevlikedecisions-0.2.0.tar.gz | 3.2 MB | With provenance | Details for jevlikedecisions-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| jevlikedecisions-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for jevlikedecisions-0.2.0-py3-none-any.whl |
Total release size: 3.3 MB
Release files / jevlikedecisions-0.2.0.tar.gz
| Download URL | jevlikedecisions-0.2.0.tar.gz |
|---|---|
| Size | 3.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0ffa1ff772871138a66b56f62a5ed82828e75abc5359b9c586db1bed183e2fb1
|
|
BLAKE2b-256 checksum How to use checksums |
0aac5052dcb4fb4c983a93bc7fc39a35ba03e92c5555bbd915857f282f748d36
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.
Transparency logRelease files / jevlikedecisions-0.2.0-py3-none-any.whl
| Download URL | jevlikedecisions-0.2.0-py3-none-any.whl |
|---|---|
| Size | 75.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4febe8aeda01058c67a8cab11e34024872d5af9f71b1f8c0145aa16491ddc9fb
|
|
BLAKE2b-256 checksum How to use checksums |
b906702ff31d8bb53a5fe881810912d8e74b68923ff9ac4f7615cd0fcda45c7f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.
Transparency logSecurity for jevlikedecisions 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for jevlikedecisions-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.