jevaas — SDK Python
SDK oficial do JEVaaS — decisão tipada com contrato versionado, rota por confiança e recibo auditável. Zero dependências (só stdlib).
pip install jevaas
import os
from jevaas import Jevaas, JevaasError, describe_route, is_actionable
jev = Jevaas(api_key=os.environ["JEVAAAS_API_KEY"]) # chave jev_sk_* do inquilino
# julga com o contrato publicado (versão vigente, ou fixe com contract_version=3)
r = jev.judge("ticket-router", {"ticket": {"messages": [{"author": "customer", "text": "..."}]}})
print(r["route"], r["selected"]["choice"], r["decisive_confidence"])
print(describe_route(r["route"], r["status"]))
# o JEVaaS NUNCA executa nada: `allow` é token opaco e quem o mapeia para
# permissão é o motor de política do consumidor.
if is_actionable(r):
rotear_para(r["allow"])
# sem contrato publicado, perguntas soltas (sem rotas, sem barra):
a = jev.fanout("texto do ticket", {"is_urgent": {"type": "noul", "instructions": "É urgente?"}})
print(a["answers"][0]["noul"])
# modo sombra: o julgamento vem, mas não autoriza agir. Devolva o desfecho real.
jev.receipt_outcome(r["receipt_id"], "aberto como incidente", action_taken=True)
jev.receipt_label(r["receipt_id"], "suporte")
Rotas de decisão
route |
O que o consumidor faz |
|---|---|
auto |
Age, dentro do allow — só com enforced: true |
collect_evidence |
Busca evidência nova e rejulga; não age |
human_review |
Enfileira para uma pessoa |
abstain |
Corrige o menu, não a pergunta |
is_actionable(r) responde a única pergunta que autoriza agir: route == "auto" e enforced is True. Em mode: shadow o julgamento é real e a autorização não existe — agir com ele é exatamente o que o modo sombra existe para impedir.
Robustez (produção)
- Retry/backoff exponencial com jitter em
429/502/503/504e falhas de rede (status 0); respeitaRetry-After. Configurável viamax_retries/timeout. - Destino (SSRF): o construtor recusa
base_urlque não sejahttp/httpse host público — loopback, faixas privadas, link-local, reservadas e multicast (IPv4 e IPv6, inclusive::ffff:127.0.0.1e CGNAT100.64/10) e os nomeslocalhost,*.localhost,*.local,*.internal. Nome DNS que não seja IP literal passa: resolver está fora do escopo do SDK. Para um servidor local,permitir_endpoint_privado=True— nunca em produção. - Erros tipados:
JevaasErrorexpõe.status,.message,.request_id(headerX-Request-Id— cite no suporte),.bodye.retryable. - Observabilidade:
on_requestrecebe{"method","path","status","request_id","attempt"}a cada requisição terminada, inclusive nas tentativas que falharam.
try:
r = jev.judge("ticket-router", state)
except JevaasError as e:
print(e.status, e.message, "request:", e.request_id, "retryable:", e.retryable)
endpoint_publico(url) aplica a mesma guarda sem levantar — útil para conferir a configuração antes de construir (e antes de subir):
from jevaas import endpoint_publico
if not endpoint_publico(url_do_painel):
raise SystemExit("destino não público: só http(s) de host público")
Ambiente
| Variável | Papel |
|---|---|
JEVAAAS_URL |
Base da API (padrão https://jev.api.br/v1) |
JEVAAAS_API_KEY |
Chave jev_sk_*; o texto claro aparece uma única vez, na emissão |
JEVAAAS_TIMEOUT_S |
Timeout em segundos (padrão 30) |
O SDK não lê o ambiente sozinho: passe os valores no construtor.
Superfície
judge · fanout · contracts · contract · contract_create · contract_update · contract_versions ·
contract_promote · contract_set_mode · receipts · receipt · receipt_label · receipt_outcome ·
calibration · run_eval · me · quota · usage · is_actionable · describe_route · endpoint_publico.
Especificação completa (OpenAPI 3.1): https://jev.api.br/v1/openapi.json · docs: https://jevaas.com.br/docs
Contrato de borda versionado: devkit/API-CONTRACT.md. Se o SDK divergir dele, o SDK está errado.
Mudanças na 0.2.0
judge()geradecision_idquando você não passa — uma vez por chamada, então o retry automático reenvia a mesma chave e o serviço devolve o recibo em vez de julgar e cobrar de novo. Continue passando o id de negócio (tkt_…) quando tiver: ele é preservado.fanout()aceitadecision_ide não repete mais em falha ambígua (rede/timeout, 504): o serviço não deduplica fanout. Trate status0/504como "pode ter sido cobrado".
Metadata
Release files for jevaas 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jevaas-0.3.2.tar.gz | 14.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jevaas-0.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.3 kB
Release files / jevaas-0.3.2.tar.gz
| Download URL | jevaas-0.3.2.tar.gz |
|---|---|
| Size | 14.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b75b1ceb635c2464fe955d44e03bbf389d84e3334cab5bb02ef35314d75354fd
|
|
BLAKE2b-256 checksum How to use checksums |
031688bb57aa83ef6e451f87ac65ac2dd88be0be61f1210568c5fc48afaf5b37
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|
Release files / jevaas-0.3.2-py3-none-any.whl
| Download URL | jevaas-0.3.2-py3-none-any.whl |
|---|---|
| Size | 10.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a403367b01ace58dea6f6a5052efc62769bec7d340dcf5868193a3b8ed049fe0
|
|
BLAKE2b-256 checksum How to use checksums |
c93f7d8094259895cb4ae14d84ffd4304b6a897584c9adb5fa157c52cc4a9bf1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|