Aller au contenu

Docs · Référence

API publique

Le contrat TypeSafe, à l'identique, plus des extensions préfixées x_. Toutes sont optionnelles : un client TypeSafe qui les ignore fonctionne.

Base URL : https://<domaine> en externe, http://gateway:8080 depuis le réseau Docker. Routes publiques sous /v1/*, administration sous /admin/v1/*, santé sous /health et /health/ready.

Authentification

Chaque appel porte Authorization: Bearer jaas_<prefix>_<secret>. Le préfixe fait 8 caractères [a-z0-9], le secret 32 caractères base62. La gateway vérifie un hash argon2id du secret (poivré côté serveur), l'expiration et la révocation. Chaque réponse porte l'en-tête x-typesafe-request-id.

POST /v1/systemone

POST/v1/systemone

Évalue un state contre des questions typées. Coût quota : 1 + nombre de questions.

Requête

corps de la requête
{
  "state": "string | object | array",
  "model": "kev-0.8b",
  "questions": {
    "department": { "type": "choice", "instructions": "…", "criteria": { "billing": "…", "shipping": null } },
    "urgent":     { "type": "noul",   "instructions": "…", "criteria": { "true": "…", "false": "…" } },
    "tone":       { "type": "score",  "instructions": "…", "criteria": ["calm", "annoyed", "angry"] }
  },
  "x_template": { "id": "ticket-triage", "version": 3, "variables": { "subject": "…", "body": "…" } },
  "x_schema":   { "id": "triage", "version": 2 }
}
ChampTypeRôle
statestring | object | arrayLe contexte à évaluer. Ignoré (peut être omis) si x_template est présent.
modelstringAccepté et renvoyé tel quel. Le backend est choisi par le schéma. Un model inconnu (jev-latest, kev-latest…) n'est pas une erreur.
questionsmap nom → questionFormat TypeSafe : type, instructions, criteria. Ignoré si x_schema est présent, obligatoire sinon.
x_template{ id, version?, variables }Slug du template ; version par défaut : dernière publiée. La gateway rend le state à partir des variables.
x_schema{ id, version? }Slug du schéma ; version par défaut : dernière publiée.

Types de question

typecriteriaLimites
choicemap option → description (ou null)1 à 255 options, 20 au plus recommandé
scoretableau ordonné de niveaux2 à 10 niveaux
noul{ true, false } optionnelquestion oui/non
  • Nombre de questions ≤ JEVIS_MAX_QUESTIONS (32 par défaut). State ≤ JEVIS_MAX_STATE_CHARS (32 000 caractères par défaut).
  • Sans x_schema, l'empreinte structurelle des questions inline doit correspondre à une version publiée d'un schéma autorisé pour l'application. Voir l'empreinte.

Réponse

200 OK
{
  "model": "kev-0.8b",
  "answers": {
    "department": { "type": "choice", "choice": "billing", "probabilities": { "billing": 0.81, "shipping": 0.19 }, "confidence": 0.81 },
    "urgent":     { "type": "noul", "noul": 0.93 },
    "tone":       { "type": "score", "score": 1.2, "legend": { "0": "calm", "1": "annoyed", "2": "angry" },
                    "probabilities": { "0": 0.1, "1": 0.6, "2": 0.3 }, "confidence": 0.6, "x_abstain": true }
  },
  "usage": { "input_tokens": 101, "output_tokens": 12 },
  "x_decision_id": "019a1b2c-…",
  "x_backend": "kev-0.8b-cpu",
  "x_schema": { "id": "triage", "version": 2 },
  "x_schema_version": 2,
  "x_template": { "id": "ticket-triage", "version": 3 },
  "x_latency_ms": { "gateway": 212, "backend": 187 }
}
ChampRôle
answers.*.confidencemax(probabilities) après température. Pour noul : max(noul, 1 − noul), implicite.
answers.*.x_abstaintrue quand la confiance est sous abstain_threshold de la version de schéma. La réponse est conservée.
usageRelayé du backend s'il le fournit, sinon omis.
x_decision_idUUIDv7 de la décision enregistrée. Sert pour l'outcome.
x_backendNom du backend qui a répondu.
x_schema{ id, version } du schéma utilisé.
x_schema_versionLa version en entier, toujours présente (utilisée par la console et les logs).
x_template{ id, version } si un template a été rendu.
x_latency_ms{ gateway, backend } en millisecondes.

Erreurs

Un format unique, pour l'API publique comme pour l'admin :

{ "error": { "code": "schema_not_granted", "message": "…", "details": {} } }
HTTPcodeQuand
401invalid_api_keyClé absente, invalide, expirée ou révoquée.
403schema_not_grantedLe schéma résolu n'est pas autorisé pour l'application.
404not_foundDécision inconnue ou appartenant à une autre application.
409conflictOutcome déjà enregistré avec une autre valeur.
422validation_errorCorps invalide (types, bornes, question inconnue…).
422invalid_schemaSchéma ou questions invalides.
422template_render_errorVariables manquantes ou mal typées, rendu Jinja en échec.
429rate_limitedRate limit par minute dépassé. En-tête Retry-After.
429quota_exceededQuota journalier dépassé. En-tête Retry-After.
503backend_unavailableAucun réplica du backend ne répond.

POST /v1/decisions/{id}/outcome

POST/v1/decisions/{decision_id}/outcome

La valeur réellement observée, par question.

requête
{ "answers": { "department": "billing", "urgent": true, "tone": 2 }, "source": "agent-ui" }
200 OK
{ "decision_id": "019a1b2c-…", "recorded": ["department", "urgent", "tone"] }
  • Valeur par question : clé d'option (choice), booléen (noul), index de niveau entier (score).
  • Idempotent : même valeur déjà enregistrée → 200 ; valeur différente → 409 conflict. Question inconnue → 422.
  • L'application appelante doit être propriétaire de la décision, sinon 404.

GET /v1/decisions/{id}

GET/v1/decisions/{decision_id}

Renvoie la décision avec ses réponses et ses outcomes, pour l'application propriétaire. Le state n'est inclus que si l'application a log_state activé.

GET /v1/models

GET/v1/models

Compatible TypeSafe et kev. Un modèle par backend activé. Authentification requise.

{ "models": [ { "name": "kev-0.8b", "description": "…", "release_date": "…" } ] }

Santé

Sans authentification : GET /health{ "status": "ok" }, et GET /health/ready { "status": "ok", "database": true, "redis": true } ou 503.

L'API d'administration (/admin/v1/*) est décrite dans le contrat complet du dépôt : doc/api-contract.md.