Qué significa cada campo
En la solicitud defines las preguntas y el formato esperado. La respuesta contiene un resultado por pregunta. Estos son los campos JSON del ejemplo.
Solicitud
model- El identificador del modelo. El ejemplo fija Jev 1.13 para dejar clara la versión.
state- El texto o los datos estructurados que se evalúan, como un mensaje de soporte.
questions- Un objeto cuyas claves son los nombres de las preguntas. Esas mismas claves aparecen después en answers.
<question_id>- Un nombre como action o urgency; la respuesta usa ese mismo nombre.
type- Formato de respuesta: choice selecciona una opción, score puntúa en una escala ordenada y noul evalúa una pregunta de sí o no.
instructions- La decisión concreta que debe tomar el modelo.
criteria- Las opciones permitidas en Choice, los niveles ordenados de Score o el significado de false y true en Noul.
Respuesta
answers- Un resultado por pregunta, con el mismo nombre.
choice- La opción elegida, la de mayor probabilidad.
probabilities- La probabilidad de cada opción; los valores suman 1.
confidence- Un nivel de confianza calculado a partir de la distribución de probabilidades, distinto de la probabilidad de la opción elegida.
score- Una posición ponderada por probabilidades en una escala ordenada; puede quedar entre dos niveles.
legend- La correspondencia entre las posiciones numéricas de Score y las descripciones de los niveles que definiste.
noul- Un valor entre 0 (no) y 1 (sí) para una pregunta binaria.
Un mismo contexto y tres preguntas independientes: Choice, Score y Probability. Cada ejecución consume un intento diario. Una respuesta con formato válido también puede equivocarse. Prueba casos representativos y define tus propios umbrales de enrutamiento.
LangChain · PythonIntegrar Jev en el harness de un agente de LangChain
El harness coordina las llamadas al modelo y a las herramientas. En cada punto de decisión, Jev lee un mensaje, una llamada a herramienta pendiente o el estado del agente y devuelve una respuesta tipada. Tu código decide cómo seguir; el modelo conversacional se ocupa de las tareas abiertas.
ModelRouterMiddlewarebefore_agent → wrap_model_callClasifica el último mensaje antes de iniciar la ejecución, elige un modelo y mantén esa elección durante el proceso. La opción, las probabilidades y la confianza quedan disponibles en el estado del agente.
AutoModeMiddlewarewrap_tool_callRevisa una llamada a herramienta antes de ejecutarla. Si Jev detecta riesgo o falta de autorización, el middleware la bloquea y devuelve un ToolMessage de error. No solicita aprobación humana.
TypeSafeClassifierChoice · Score · NoulPuedes añadir tus propios controles con middleware personalizado: pasa los mensajes o el estado del agente a TypeSafeClassifier y usa Choice, Score o Noul para decidir la siguiente acción o pedir revisión.
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 del servidor
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);