<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniel Castillo</title>
    <description>The latest articles on DEV Community by Daniel Castillo (@dcastillogi).</description>
    <link>https://dev.to/dcastillogi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1995492%2Fb3b2c6ea-96e2-44b2-9738-f35980150e05.png</url>
      <title>DEV Community: Daniel Castillo</title>
      <link>https://dev.to/dcastillogi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dcastillogi"/>
    <language>en</language>
    <item>
      <title>¿Cómo usar Jev?: Jev + LangChain + Vercel AI Gateway</title>
      <dc:creator>Daniel Castillo</dc:creator>
      <pubDate>Sun, 20 Sep 2026 20:19:51 +0000</pubDate>
      <link>https://dev.to/dcastillogi/jev-typesafe-ai-langchain-vercel-ai-gateway-427c</link>
      <guid>https://dev.to/dcastillogi/jev-typesafe-ai-langchain-vercel-ai-gateway-427c</guid>
      <description>&lt;p&gt;La mayoría de sistemas usan un LLM para decidir cosas como clasificar, priorizar o enrutar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;jev está diseñado específicamente para tomar esas decisiones.&lt;/strong&gt; En lugar de generar texto, evalúa un estado y devuelve una decisión tipada junto con las probabilidades de cada opción.&lt;/p&gt;

&lt;p&gt;En las evaluaciones publicadas por TypeSafe, jev alcanzó hasta &lt;strong&gt;193,6× mayor velocidad&lt;/strong&gt; y &lt;strong&gt;444,6× menor costo&lt;/strong&gt; que los modelos de referencia.&lt;/p&gt;

&lt;p&gt;En este artículo vas a ver cómo usar jev con LangChain a través de Vercel AI Gateway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dale esta skill a tu agente de código
&lt;/h2&gt;

&lt;p&gt;Si quieres que tu agente de código conozca esta integración, puedes instalar la skill &lt;code&gt;jev-ai-gateway-langchain&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;La skill incluye la configuración de AI Gateway y ejemplos de los primitives y middlewares utilizados en este artículo.&lt;/p&gt;

&lt;p&gt;En Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude plugin marketplace add dcastillogi/skills
claude plugin &lt;span class="nb"&gt;install &lt;/span&gt;jev-ai-gateway-langchain@dcastillogi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para otros agentes compatibles con &lt;code&gt;skills.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add dcastillogi/skills &lt;span class="nt"&gt;--skill&lt;/span&gt; jev-ai-gateway-langchain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Después de instalarla, puedes pedirle al agente que configure la conexión, cree classifiers con los primitives adecuados o incorpore los middlewares en tu aplicación de LangChain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 1: entender la entrada y la salida
&lt;/h2&gt;

&lt;p&gt;Una solicitud a jev tiene dos partes principales:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;State:&lt;/strong&gt; los datos que quieres evaluar. Puede ser un ticket, un documento, un registro o el historial de un agente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Questions:&lt;/strong&gt; las decisiones que jev debe tomar sobre esos datos.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;state + questions → jev → respuestas tipadas + probabilidades
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Puedes enviar varias preguntas sobre el mismo estado. Jev las evalúa en paralelo y devuelve cada respuesta bajo el identificador que definiste.&lt;/p&gt;

&lt;p&gt;Las preguntas de una misma solicitud son independientes. Si una decisión necesita el resultado de otra para formularse, debes hacer una segunda solicitud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 2: elegir el primitive adecuado
&lt;/h2&gt;

&lt;p&gt;Antes de construir tu classifier, define qué forma debe tener cada respuesta. TypeSafe ofrece tres primitives: &lt;code&gt;Noul&lt;/code&gt;, &lt;code&gt;Choice&lt;/code&gt; y &lt;code&gt;Score&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Primitive&lt;/th&gt;
&lt;th&gt;Tipo de decisión&lt;/th&gt;
&lt;th&gt;Resultado&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Noul&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Evaluar una condición binaria&lt;/td&gt;
&lt;td&gt;Probabilidad entre &lt;code&gt;0&lt;/code&gt; y &lt;code&gt;1&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Choice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Elegir una categoría&lt;/td&gt;
&lt;td&gt;Opción, distribución y confianza&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Score&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Medir una escala ordenada&lt;/td&gt;
&lt;td&gt;Puntaje, distribución, leyenda y confianza&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Noul: evaluar una condición
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Noul&lt;/code&gt; responde qué tan probable es que una condición sea verdadera. En un sistema de soporte puedes utilizarlo para representar la urgencia de un ticket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_typesafe&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Noul&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NoulCriteria&lt;/span&gt;

&lt;span class="n"&gt;urgent_question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Noul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;¿El ticket requiere atención inmediata?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;criteria&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;NoulCriteria&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;El cliente está bloqueado o existe una interrupción crítica.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;La solicitud puede esperar sin producir un impacto importante.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La respuesta contiene el campo &lt;code&gt;noul&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;probability&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nouls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;urgent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;noul&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Un valor cercano a &lt;code&gt;1&lt;/code&gt; favorece &lt;code&gt;true&lt;/code&gt;; uno cercano a &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;. Los valores próximos a &lt;code&gt;0.5&lt;/code&gt; no favorecen claramente ninguna respuesta.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Noul&lt;/code&gt; no incluye un campo &lt;code&gt;confidence&lt;/code&gt; separado.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NoulCriteria&lt;/code&gt; es opcional. Puedes utilizarlo cuando la condición necesita límites más precisos que una pregunta breve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choice: elegir una opción
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Choice&lt;/code&gt; clasifica el estado dentro de un conjunto definido por tu aplicación. Las claves son los valores que utilizará tu código y las descripciones explican cuándo corresponde cada opción.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_typesafe&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Choice&lt;/span&gt;

&lt;span class="n"&gt;department_question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;¿Qué equipo debe atender el ticket?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;criteria&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;billing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cobros, facturas y reembolsos.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;technical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Errores e interrupciones del servicio.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;account&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Acceso, permisos y datos de la cuenta.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;other&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ninguna de las categorías anteriores.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La respuesta contiene tres campos principales:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;department&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;
&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;probabilities&lt;/span&gt;
&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;confidence&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;choice&lt;/code&gt; es la opción seleccionada.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;probabilities&lt;/code&gt; contiene la distribución entre todas las opciones.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;confidence&lt;/code&gt; resume qué tan concentrada está esa distribución.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si tu lista no cubre todos los casos posibles, conviene incluir una opción como &lt;code&gt;other&lt;/code&gt; o &lt;code&gt;none_of_the_above&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Score: medir una escala
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Score&lt;/code&gt; se utiliza cuando las respuestas tienen un orden. Por ejemplo, puedes utilizarlo para medir la frustración de un cliente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_typesafe&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Score&lt;/span&gt;

&lt;span class="n"&gt;frustration_question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;¿Cuál es el nivel de frustración del cliente?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;criteria&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tono neutral.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Molestia expresada de forma moderada.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enojo explícito o lenguaje hostil.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La respuesta incluye:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;frustration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;
&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;probabilities&lt;/span&gt;
&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;legend&lt;/span&gt;
&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;confidence&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los niveles se numeran desde &lt;code&gt;0&lt;/code&gt;. &lt;code&gt;score&lt;/code&gt; es una media ponderada de sus probabilidades, por lo que puede ser fraccionario.&lt;/p&gt;

&lt;p&gt;En una escala de &lt;code&gt;0&lt;/code&gt; a &lt;code&gt;2&lt;/code&gt;, un resultado de &lt;code&gt;1.4&lt;/code&gt; representa una distribución entre los niveles existentes.&lt;/p&gt;

&lt;p&gt;Las descripciones deberían representar situaciones observables. Una escala como “sin impacto”, “función degradada” y “operación bloqueada” aporta más información que “bajo”, “medio” y “alto”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 3: conocer los cinco límites principales
&lt;/h2&gt;

&lt;p&gt;Estos son los límites relevantes que publica actualmente la documentación de TypeSafe:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Área&lt;/th&gt;
&lt;th&gt;Límite&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Opciones de &lt;code&gt;Choice&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Máximo de &lt;strong&gt;255&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Niveles de &lt;code&gt;Score&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Entre &lt;strong&gt;2 y 10&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Espacio de respuesta de &lt;code&gt;Noul&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Binario; devuelve &lt;code&gt;P(verdadero)&lt;/code&gt; entre &lt;code&gt;0&lt;/code&gt; y &lt;code&gt;1&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contexto total&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;64k tokens&lt;/strong&gt; por solicitud&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;state&lt;/code&gt; + pregunta más larga&lt;/td&gt;
&lt;td&gt;Máximo de &lt;strong&gt;32k tokens&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Un &lt;code&gt;Choice&lt;/code&gt; puede manejar taxonomías amplias. Si tienes más de 255 categorías, puedes dividir la clasificación en niveles o resolverla mediante una jerarquía.&lt;/p&gt;

&lt;p&gt;Un &lt;code&gt;Score&lt;/code&gt; debería incluir únicamente niveles que puedan distinguirse mediante sus descripciones. Agregar niveles similares puede distribuir la probabilidad entre alternativas poco claras.&lt;/p&gt;

&lt;p&gt;Los &lt;code&gt;64k&lt;/code&gt; tokens cubren el estado y todas las preguntas de la solicitud. Además, el estado combinado con la pregunta individual más larga debe permanecer dentro de &lt;code&gt;32k&lt;/code&gt; tokens.&lt;/p&gt;

&lt;p&gt;Estos valores pueden cambiar, así que si vas a diseñar cargas cercanas al límite, revisa la documentación antes de hacerlo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 4: instalar la integración de LangChain
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"langchain-typesafe[experimental]"&lt;/span&gt; python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;langchain-typesafe&lt;/code&gt; incluye &lt;code&gt;TypeSafeClassifier&lt;/code&gt;. El extra &lt;code&gt;experimental&lt;/code&gt; incorpora &lt;code&gt;ModelRouterMiddleware&lt;/code&gt; y &lt;code&gt;AutoModeMiddleware&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;La versión utilizada en este proyecto es alfa. El classifier está marcado como beta y los middlewares son experimentales.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 5: conectar LangChain con jev mediante AI Gateway
&lt;/h2&gt;

&lt;p&gt;Por defecto, &lt;code&gt;langchain-typesafe&lt;/code&gt; utiliza la API de TypeSafe y busca una credencial en &lt;code&gt;TYPESAFE_API_KEY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;En este proyecto queremos consumir jev mediante Vercel AI Gateway. Vercel expone una API compatible con el formato de TypeSafe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://ai-gateway.vercel.sh/typesafe/v1/systemone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solo necesitas indicarle al paquete dos datos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Utilizar la credencial de Vercel como &lt;code&gt;TYPESAFE_API_KEY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Utilizar &lt;code&gt;https://ai-gateway.vercel.sh/typesafe&lt;/code&gt; como &lt;code&gt;TYPESAFE_BASE_URL&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;El cliente añade &lt;code&gt;/v1/systemone&lt;/code&gt; a esa URL base. No necesitas transformar preguntas o respuestas ni intervenir el transporte HTTP.&lt;/p&gt;

&lt;p&gt;Creamos &lt;code&gt;gateway.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI_GATEWAY_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;VERCEL_OIDC_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No se encontró una credencial para Vercel AI Gateway.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TYPESAFE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TYPESAFE_BASE_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://ai-gateway.vercel.sh/typesafe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La credencial local se guarda en &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;AI_GATEWAY_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta capa de configuración también se aplica a los classifiers que los middlewares construyen internamente.&lt;/p&gt;

&lt;p&gt;Con esta configuración, &lt;code&gt;langchain-typesafe&lt;/code&gt; queda listo para enviar solicitudes a jev mediante AI Gateway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ejemplo: clasificar un ticket
&lt;/h2&gt;

&lt;p&gt;Ahora agrupamos los tres primitives definidos anteriormente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;  &lt;span class="c1"&gt;# Configura la API TypeSafe-compatible
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_typesafe&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypeSafeClassifier&lt;/span&gt;

&lt;span class="n"&gt;classifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TypeSafeClassifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;questions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;urgent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urgent_question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;department&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;department_question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;frustration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;frustration_question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luego enviamos el ticket como estado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ticket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;El sistema de pagos sigue fallando y no podemos completar ventas. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Necesitamos una solución hoy.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer_plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enterprise&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Las tres preguntas se envían en una sola solicitud. Puedes incorporar el resultado a una regla de negocio común:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;department&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;urgent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nouls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;urgent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;noul&lt;/span&gt;
&lt;span class="n"&gt;frustration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;frustration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;route_to_manual_triage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;urgent&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;frustration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;route_to_senior_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los umbrales son ilustrativos. Deberías evaluarlos con tickets representativos y definir qué hacer cuando el resultado sea incierto.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;TypeSafeClassifier&lt;/code&gt; implementa la interfaz &lt;code&gt;Runnable&lt;/code&gt;, por lo que también puedes utilizarlo con &lt;code&gt;ainvoke&lt;/code&gt;, &lt;code&gt;batch&lt;/code&gt; y dentro de otros flujos de LangChain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Más ejemplos con LangChain
&lt;/h2&gt;

&lt;p&gt;Además del classifier general, &lt;code&gt;langchain-typesafe&lt;/code&gt; incluye middlewares para decisiones frecuentes dentro de un agente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Seleccionar un modelo
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ModelRouterMiddleware&lt;/code&gt; utiliza un &lt;code&gt;Choice&lt;/code&gt; para seleccionar entre modelos ya configurados. Evalúa el último mensaje humano al inicio de la ejecución y guarda la respuesta en &lt;code&gt;model_route&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_typesafe.experimental.middleware&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ModelChoice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ModelRouterMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ModelRouterMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fast&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ModelChoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fast_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;criteria&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Consultas directas y cambios acotados.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;capable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ModelChoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;capable_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;criteria&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Arquitectura y decisiones de alto impacto.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Seleccione el modelo adecuado para completar la tarea.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fast_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Evaluar una herramienta
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;AutoModeMiddleware&lt;/code&gt; evalúa una llamada inmediatamente antes de ejecutar una herramienta.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_typesafe&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NoulCriteria&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_typesafe.experimental.middleware&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AutoModeMiddleware&lt;/span&gt;

&lt;span class="n"&gt;guardrail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AutoModeMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;¿La llamada propuesta es destructiva, irreversible o excede la &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;autorización concedida para este sistema?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;criteria&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;NoulCriteria&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Elimina datos, interrumpe servicios o produce un efecto no aprobado.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Consulta información o realiza un cambio reversible y autorizado.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La política debe indicar qué operaciones requieren aprobación. Esta evaluación complementa los controles de acceso y aislamiento de la aplicación.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supervisar el ciclo del agente
&lt;/h3&gt;

&lt;p&gt;También puedes ejecutar un classifier después de cada respuesta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.agents.middleware&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;after_model&lt;/span&gt;

&lt;span class="nd"&gt;@after_model&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;supervise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;supervisor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nouls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;escalate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;noul&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;record_handoff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La integración acepta mensajes de LangChain como &lt;code&gt;state&lt;/code&gt;, por lo que puedes evaluar el historial sin conversión manual.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.typesafe.ai/primitives" rel="noopener noreferrer"&gt;TypeSafe: Primitives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.typesafe.ai/primitives/choice" rel="noopener noreferrer"&gt;TypeSafe: Choice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.typesafe.ai/primitives/score" rel="noopener noreferrer"&gt;TypeSafe: Score&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.typesafe.ai/models" rel="noopener noreferrer"&gt;TypeSafe: Models and limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.typesafe.ai/api" rel="noopener noreferrer"&gt;TypeSafe API reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://typesafe.ai/blog/introducing-system-one-models-and-jev" rel="noopener noreferrer"&gt;TypeSafe: Introducing System One Models &amp;amp; Jev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/blog/building-a-harness-with-jev" rel="noopener noreferrer"&gt;LangChain: Building a Harness with Jev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vercel.com/docs/ai-gateway/sdks-and-apis/typesafe" rel="noopener noreferrer"&gt;Vercel: TypeSafe API with AI Gateway&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>jev</category>
      <category>typesafe</category>
      <category>langchain</category>
      <category>python</category>
    </item>
    <item>
      <title>Cómo solicitar aumentos de cuota para Amazon Bedrock (y que te los aprueben)</title>
      <dc:creator>Daniel Castillo</dc:creator>
      <pubDate>Thu, 19 Mar 2026 16:11:32 +0000</pubDate>
      <link>https://dev.to/dcastillogi/como-solicitar-aumentos-de-cuota-para-amazon-bedrock-y-que-te-los-aprueben-295o</link>
      <guid>https://dev.to/dcastillogi/como-solicitar-aumentos-de-cuota-para-amazon-bedrock-y-que-te-los-aprueben-295o</guid>
      <description>&lt;p&gt;Estás viendo errores como estos en tu app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ThrottlingException: Too many requests, please wait before trying again.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El problema son las cuotas de Bedrock: RPM (requests por minuto) o TPM (tokens por minuto).&lt;/p&gt;

&lt;p&gt;La solución es solicitar un aumento. En esta guía vas a encontrar el proceso completo: cómo revisar tus límites actuales, qué métricas sacar de CloudWatch, y una plantilla lista para pegar en el Support Center.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tiempos:&lt;/strong&gt; AWS Support tiene un SLA de 48 horas, pero abre el caso con al menos 72 horas de antelación. No improvises cuando ya estás en producción.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Idioma:&lt;/strong&gt; Escribe el caso en inglés. Se resuelve más rápido. La plantilla al final ya está en inglés.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Paso 1: Revisa tus cuotas actuales
&lt;/h2&gt;

&lt;p&gt;Ve a &lt;strong&gt;AWS Console → Service Quotas → AWS Services → Amazon Bedrock&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Busca tu modelo y revisa los valores de RPM y TPM aplicados. Si la cuota fue aumentada antes, verás el valor real, no el default de AWS.&lt;/p&gt;

&lt;p&gt;También puedes ver si ya tienes una solicitud en vuelo en la pestaña &lt;strong&gt;Pending quota requests&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 2: Extrae tu uso real desde CloudWatch
&lt;/h2&gt;

&lt;p&gt;Ve a &lt;strong&gt;CloudWatch → Metrics → All metrics → AWS/Bedrock&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Usa el &lt;strong&gt;inference profile ID&lt;/strong&gt; como dimensión &lt;code&gt;ModelId&lt;/code&gt;, no el ID del modelo base. Si usas inferencia global o cross-region, el profile ID puede parecer un string aleatorio.&lt;/p&gt;

&lt;p&gt;Las métricas que necesitas, con periodo de &lt;strong&gt;1 minuto&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Métrica&lt;/th&gt;
&lt;th&gt;Estadística&lt;/th&gt;
&lt;th&gt;Qué te dice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Invocations&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sum&lt;/td&gt;
&lt;td&gt;Llamadas por minuto (tu RPM real)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InputTokenCount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sum&lt;/td&gt;
&lt;td&gt;Tokens de entrada por minuto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;OutputTokenCount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sum&lt;/td&gt;
&lt;td&gt;Tokens de salida por minuto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InvocationThrottles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sum&lt;/td&gt;
&lt;td&gt;Requests rechazados por cuota&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EstimatedTPMQuotaUsage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Average / Max&lt;/td&gt;
&lt;td&gt;% de cuota TPM consumida&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxfo4cxzumprmta8niofn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxfo4cxzumprmta8niofn.png" alt="CloudWatch Metrics - AWS/Bedrock" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con esos datos calcula:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Steady State TPM/RPM&lt;/strong&gt; = promedio en horario normal&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Peak TPM/RPM&lt;/strong&gt; = máximo observado&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avg tokens per request&lt;/strong&gt; = total tokens / total invocaciones&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si &lt;code&gt;InvocationThrottles &amp;gt; 0&lt;/code&gt; o &lt;code&gt;EstimatedTPMQuotaUsage&lt;/code&gt; supera el 80% de forma sostenida, inclúyelo en el caso — es tu mejor argumento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 3: Redacta el caso
&lt;/h2&gt;

&lt;p&gt;Con los números del paso anterior, completa esta plantilla en texto plano. La vas a necesitar lista antes de abrir el ticket.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plantilla del caso (texto plano, en inglés)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWS Account Manager: (optional but recommended)
AWS Solutions Architect: (optional but recommended)

Business Context
[What your company does, its scale, and industry.]

Business Objective
[Specific goal: e.g., process N requests/minute for real-time inference.]

Architecture Overview
[How your system works and which AWS services are involved.]

Current Usage Baseline
[Your CloudWatch numbers here.]

Current usage:
  Input modalities:  Text / Image / Audio / Video
  Output modalities: Text / Image / Audio / Video
  Steady State TPM:  ...
  Peak TPM:          ...
  Steady State RPM:  ...
  Peak RPM:          ...
  Avg Input Tokens per Request:  ...
  Avg Output Tokens per Request: ...

Requested Quota
[Exact quota name from Service Quotas + value needed.]

Expected usage after quota increase:
  Input modalities:  Text / Image / Audio / Video
  Output modalities: Text / Image / Audio / Video
  Steady State TPM:  ...
  Peak TPM:          ...
  Steady State RPM:  ...
  Peak RPM:          ...
  Avg Input Tokens per Request:  ...
  Avg Output Tokens per Request: ...

Justification
[Tie your baseline to the business need. Lead with throttle data if you have it.]

Inference scope
[Global or region-only. If region-only, explain why.]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Paso 4: Abre el caso de soporte
&lt;/h2&gt;

&lt;p&gt;Ve al &lt;a href="https://support.console.aws.amazon.com/support/home#" rel="noopener noreferrer"&gt;AWS Support Center&lt;/a&gt; → &lt;strong&gt;Support interactions&lt;/strong&gt; → describe tu necesidad en el chat. Al fondo aparecerá el botón &lt;strong&gt;Create case&lt;/strong&gt;, dale clic y completa:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Case type: &lt;strong&gt;Service limit increase&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Service: &lt;strong&gt;Service Limit Increase&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Category: &lt;strong&gt;General&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bonus: automatiza esto con Kiro
&lt;/h2&gt;

&lt;p&gt;Todo este proceso, consultar cuotas, extraer métricas de CloudWatch, calcular los números y generar el borrador del caso, lo puedes hacer de forma asistida con el &lt;a href="https://github.com/dcastillogi/aws-quota-request-kiro-power" rel="noopener noreferrer"&gt;AWS Quota Request Power&lt;/a&gt; para &lt;a href="https://kiro.dev" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; que construí para esto. Incluye un steering file específico para Bedrock con toda la lógica de RPM, TPM y perfiles de inferencia.&lt;/p&gt;

&lt;p&gt;Si usas Kiro, vale la pena echarle un vistazo.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>bedrock</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
