Comprendre chaque champ
La requête définit les questions et le format attendu. La réponse contient un résultat pour chacune. Voici les champs JSON utilisés dans l’exemple.
Requête
model- L’identifiant du modèle. L’exemple fixe Jev 1.13 pour préciser la version.
state- Le texte ou les données structurées à évaluer, comme un message de support.
questions- Un objet dont les clés sont les noms des questions. Vous retrouverez ces mêmes clés dans answers.
<question_id>- Un nom comme action ou urgency ; la réponse reprend ce même nom.
type- Le format de réponse : choice choisit une option, score situe une réponse sur une échelle ordonnée et noul évalue une question oui/non.
instructions- Le jugement précis demandé au modèle.
criteria- Les options de Choice, les niveaux ordonnés de Score ou le sens de false et true pour Noul.
Réponse
answers- Un résultat par question, sous le même nom.
choice- L’option sélectionnée, celle dont la probabilité est la plus élevée.
probabilities- La probabilité de chaque option ; leur somme vaut 1.
confidence- Un score de confiance calculé à partir de la distribution des probabilités, distinct de la probabilité de l’option retenue.
score- Une position pondérée par les probabilités sur une échelle ordonnée ; elle peut se situer entre deux niveaux.
legend- La correspondance entre les positions numériques du score et les niveaux que vous avez définis.
noul- Un nombre de 0 (non) à 1 (oui) pour une question binaire.
Un même contexte, trois questions indépendantes : Choice, Score et Probability. Chaque exécution compte pour une tentative quotidienne. Une réponse au bon format peut être erronée. Testez des cas représentatifs et définissez vos propres seuils de routage.
LangChain · PythonIntégrer Jev au harness d’un agent LangChain
Le harness orchestre les appels au modèle et aux outils. À un point de décision, Jev lit un message, un appel d’outil envisagé ou l’état de l’agent, puis renvoie une réponse typée. Votre code choisit la suite ; le modèle de chat garde les tâches ouvertes.
ModelRouterMiddlewarebefore_agent → wrap_model_callClasser le dernier message avant l’exécution pour choisir un modèle, puis conserver ce choix pendant le traitement. Le choix, les probabilités et le niveau de confiance restent accessibles dans l’état de l’agent.
AutoModeMiddlewarewrap_tool_callContrôler un appel d’outil avant son exécution. Si Jev détecte un risque ou une autorisation insuffisante, le middleware bloque l’appel et renvoie un ToolMessage d’erreur. Il ne demande pas de validation humaine.
TypeSafeClassifierChoice · Score · NoulAjoutez aussi vos propres points de contrôle : un middleware personnalisé transmet les messages ou l’état de l’agent à TypeSafeClassifier, puis votre code utilise Choice, Score ou Noul pour bifurquer ou demander une revue.
LangChain · Python · ModelRouterMiddleware
# pip install "langchain-typesafe[experimental]" langchain-openai
# Set TYPESAFE_API_KEY and OPENAI_API_KEY on your server.
from langchain.agents import create_agent
from langchain_typesafe.experimental.middleware import (
ModelChoice, ModelRouterMiddleware,
)
router = ModelRouterMiddleware(
choices={
"fast": ModelChoice(
model="openai:gpt-5.6-terra",
criteria="Simple lookups and extraction.",
),
"powerful": ModelChoice(
model="openai:gpt-6-astra",
criteria="Complex reasoning and high-stakes decisions.",
),
},
instructions="Choose the least costly model that can do the task safely.",
)
agent = create_agent("openai:gpt-5.6-terra", middleware=[router])
result = agent.invoke({"messages": [{"role": "user", "content": "Summarize this log."}]})
print(result["model_route"].choice)
TypeScript côté serveur
TypeScript · fetch// Run on your server. Keep the API key out of browser code.
const apiKey = process.env.OPENROUTER_API_KEY;
if (!apiKey) throw new Error("Set OPENROUTER_API_KEY");
const response = await fetch("https://openrouter.ai/api/alpha/decisions", {
method: "POST",
headers: {
Authorization: "Bearer " + apiKey,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "typesafe/jev-1.13",
state: {input: "A customer reports a duplicate charge."},
questions: {
team: {
type: "choice",
instructions: "Which team should handle this?",
criteria: {
billing: "Payments and refunds",
technical: "Bugs and integrations"
}
},
urgency: {
type: "score",
instructions: "How urgent is the issue?",
criteria: ["Can wait", "Needs attention today", "Immediate action"]
},
escalate: {
type: "noul",
instructions: "Should a human review this first?",
criteria: {false: "No review needed", true: "Review before acting"}
}
}
})
});
if (!response.ok) throw new Error("Decision request failed");
const {answers} = await response.json();
console.log(answers.team.choice, answers.urgency.score, answers.escalate.noul);