Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Ciclo de vida del enrutamiento del proveedor

El enrutamiento de proveedores comienza después de que ZeroClaw ha seleccionado el agente que gestiona un turno. Incluye la selección de perfiles de proveedor y modelos, los reintentos y las alternativas de respaldo, la recuperación de transmisiones y la atribución que explica qué backend atendió la solicitud. El despacho de canal a agente sigue un ciclo de vida independiente; consulta Ciclo de vida del tiempo de ejecución del canal.

Consulta esta página cuando un cambio afecte a model_routes, a la selección del modelo para la sesión o durante el turno, al mecanismo de reserva del proveedor, a la clasificación de reintentos, a los períodos de enfriamiento por límite de solicitudes, a la finalización de la transmisión, a la reproducción tras un fallo de la transmisión o a la atribución del proveedor solicitado frente al proveedor que atendió la solicitud.

Mapa de propiedad

PreocupaciónPropietario actualContrato
Perfiles de proveedores y grafo de respaldoEsquema y validación del proveedor zeroclaw-configUn <family>.<alias> separado por puntos identifica el endpoint, las credenciales, el modelo principal opcional, las capacidades y las declaraciones de respaldo ordenadas de un perfil.
Construcción del proveedorFunciones de fábrica de zeroclaw-providersMaterializa cada perfil con su propia configuración, aplana las entradas de respaldo configuradas en orden y diseña el enrutamiento en torno a la fiabilidad.
Selección basada en sugerenciasRouterModelProviderResuelve hint:<name> en un destino de proveedor configurado y un modelo de enrutamiento. El destino principal está fijado al modelo activo/predeterminado. Un destino no principal se fija cuando su perfil configura un modelo; de lo contrario, su entrada fiable permanece sin fijar y recibe el modelo de enrutamiento.
Selección basada en esfuerzoPerfil de ejecución resuelto más puntos de entrada de turnos de agente/canalClasificar de forma determinista un turno con opt-in, seleccionar una de las dos pistas de ruta existentes, preservar las opciones explícitas de modelo y restringir los intentos de proveedor elegibles para el turno.
Reintentos y conmutación por errorReliableModelProviderClasifica los fallos, reintenta con una espera progresiva limitada, respeta los periodos de enfriamiento de los límites de frecuencia y avanza por las entradas materializadas.
Terminación del flujo del proveedorProveedores concretos y zeroclaw-providers/src/stream_guard.rsTraduce la semántica de finalización de cada protocolo de proveedor a StreamEvent::Final o a un error de truncamiento.
Reproducción del flujo y confirmación de la salida parcialzeroclaw-runtime/src/agent/turn/provider_call.rs and stream_consume.rsReintenta un flujo fallido sin streaming solo antes de confirmar la salida de eventos inmutables. Nunca repitas una respuesta cancelada o parcialmente visible.
Atribución por llamadaProviderDispatchAbre ámbitos de atribución alrededor de la llamada al proveedor seleccionada para cada intento.
Registro de recuperación exitosaReliableModelProviderExponer un único registro local a la tarea de solicitado frente a servido tras una recuperación exitosa. En las rutas de turno instrumentadas con eventos, el libro mayor usage_by_provider registra los intentos facturables mediante TurnEvent::Usage, con la identidad del proveedor que sirvió la solicitud y un indicador accepted.
Avisos de recuperación para el usuarioConsumidores del tiempo de ejecución y de canalesRenderiza el registro de recuperación correcta en su propia superficie de salida. Ten en cuenta que las reglas no son uniformes entre los consumidores.

Construcción y selección

El entorno de ejecución comienza con una referencia de proveedor y un modelo activos, obtenidos del agente seleccionado, de una anulación de sesión o de un model_switch durante el turno. A continuación, la construcción del proveedor compone dos envoltorios:

  1. La fábrica construye un ReliableModelProvider para el perfil del proveedor activo. El modelo principal efectivo procede de una anulación explícita de la construcción o del model configurado en el perfil. Cuando existe uno, este y el fallback_models del perfil se convierten en entradas fijadas. Si no existe, el perfil aporta una entrada no fijada y sus fallback_models no se materializan. Los perfiles fallback referenciados recursivamente se siguen recorriendo. Cada perfil referenciado conserva sus propias credenciales, endpoint, encabezados, modelo y anulaciones de capacidades.
  2. Cuando se configuran model_routes, la fábrica crea un proveedor fiable independiente para la ruta principal y cada destino de ruta único, y después los envuelve en RouterModelProvider.
  3. Un hint:<name> reconocido selecciona su destino configurado antes de que la llamada entre en la política de fiabilidad de ese destino. Un valor de modelo normal usa la ruta predeterminada. Un hint desconocido registra una advertencia, permanece en el dominio de fiabilidad predeterminado y conserva el literal hint:<name> como modelo solicitado. Una entrada predeterminada con un valor fijado sigue sirviendo ese valor; una entrada predeterminada sin un valor fijado reenvía el valor literal y el proveedor puede rechazarlo antes de que continúe la gestión normal de alternativas o errores.

Hay dos restricciones actuales de construcción:

  • La fijación de rutas es condicional. El destino principal se fija al modelo activo/predeterminado que se pasa al construir el proveedor, incluso cuando una sugerencia reconocida vuelve a apuntar al perfil principal activo; el valor model_routes[].model de esa sugerencia no anula la fijación principal. Un destino no principal con un modelo de perfil configurado se fija a ese modelo, por lo que el modelo de su ruta tampoco anula el modelo del perfil. Un destino no principal sin un modelo configurado es válido y permanece sin fijar; el modelo de la ruta llega a ese proveedor, y los fallback_models de ese perfil no se materializan aunque sus perfiles de respaldo referenciados se sigan recorriendo. Mantén cada modelo de ruta alineado con la fijación del destino cuando exista, y ten en cuenta el comportamiento sin fijación cuando el perfil de destino omita model.
  • Los destinos de las rutas se deduplican por model_provider. Si una ruta proporciona api_key, la primera credencial de ruta coincidente tiene prioridad al construir el destino compartido. Da preferencia a las credenciales del perfil del proveedor cuando varias sugerencias comparten un destino.

Este orden importa: el enrutamiento elige un dominio de fiabilidad; no evita la fiabilidad. Un servicio de enrutamiento externo como OpenRouter aún puede realizar una selección del lado del servidor detrás de un único perfil de ZeroClaw, pero es opcional y no sustituye los contratos propios de enrutamiento y respaldo de ZeroClaw.

Cuando un perfil de ejecución resuelto tiene effort_routing, el punto de entrada del turno ejecuta el estimador determinista de complejidad antes de la ejecución del proveedor. Los turnos simples y estándar seleccionan la sugerencia local configurada. Un turno complejo selecciona la sugerencia en la nube solo bajo la política de escalado explícita auto. No se realiza ninguna llamada al modelo para la clasificación, y la telemetría de decisiones excluye el texto del prompt. Las selecciones explícitas del operador en la CLI, la sesión y el canal desactivan este paso automático en su ámbito correspondiente; /model auto en el canal lo restablece. Un model_switch emitido por el modelo cambia el proveedor/modelo activo sin cambiar si la ruta es automática o está controlada por el operador, por lo que el enrutamiento automático por esfuerzo permanece activo tras un model_switch emitido por el modelo, salvo que una anulación del operador ya lo haya desactivado.

El límite del proveedor aplica la decisión, además de seleccionar un modelo. Las rutas estructuradas de agente y canal instalan una lista de permitidos local a la tarea que comprueba cada bucle de candidatos de Reliable, incluidas las rutas sin streaming, con streaming y de recuperación de stream. Los puntos de entrada directos de CLI y daemon construyen su router de turno solo a partir de los destinos de ruta permitidos. Por lo tanto, una decisión local no puede pasar al proveedor de nube configurado mediante el fallback por disponibilidad. Una decisión de nube sí puede usar las referencias configuradas de proveedores locales y de nube.

El esquema y los ejemplos dirigidos al operador se encuentran en Configuración del proveedor y Enrutamiento. Mantén allí la sintaxis de los campos en lugar de duplicarla en los documentos de arquitectura.

Orden de los intentos sin streaming

Para un alias de producción, la fábrica aplana el grafo configurado mediante un recorrido en profundidad. El orden efectivo es:

  1. El modelo principal efectivo del perfil o una entrada no fijada cuando no existe ningún modelo principal efectivo.
  2. Los fallback_models de ese perfil, en orden, solo si existe un modelo principal efectivo.
  3. Cada perfil de fallback, en orden, incluidos la entrada principal o sin fijar de ese perfil, los modelos de respaldo aptos y los perfiles de respaldo anidados.

Para cada entrada materializada, ReliableModelProvider intenta realizar la solicitud hasta provider_retries + 1 veces. Un error reintentable normalmente mantiene la entrada actual y aplica un retroceso acotado. Una limitación de tasa reintentable coloca ese perfil de proveedor en un periodo de enfriamiento en memoria y avanza cuando existe otra entrada. La mayoría de los errores no reintentables avanzan inmediatamente; los errores de ventana de contexto tienen un manejo específico del método y pueden devolver el control antes para la recuperación en tiempo de ejecución. Una respuesta correcta finaliza el recorrido; si todas las entradas fallan, el envoltorio devuelve un error agregado con los fallos de los intentos.

El orden de materialización y el orden de ejecución efectivo pueden diferir después de un límite de solicitudes. Las entradas principal y fallback_models de un perfil comparten una única clave de enfriamiento, por lo que un 429 en la principal puede hacer que se omitan los modelos restantes del mismo perfil mientras el enfriamiento esté activo.

El grupo global reliability.api_keys no es actualmente un mecanismo de conmutación por error operativo. El wrapper selecciona y registra una clave alternativa después de un límite de tasa que permite reintentos, pero el trait ModelProvider no puede aplicar esa clave al proveedor construido, por lo que el reintento sigue utilizando la credencial original. Incidencia #9190 realiza el seguimiento de la corrección. Utiliza perfiles de respaldo distintos o un servicio de enrutamiento externo cuando se requiera una conmutación por error a nivel de credenciales.

Las respuestas vacías reciben el mismo tratamiento de reintentos limitados, en lugar de convertirse inmediatamente en un turno vacío del asistente.

Las declaraciones de reserva no válidas tienen dos límites distintos. Las referencias colgantes, los ciclos, las aristas con profundidad excesiva, los identificadores de modelo vacíos y los modelos principales duplicados se notifican y se podan como se describe en Configuración del proveedor. Un perfil de reserva que se resuelve, pero no puede proporcionar la credencial requerida o no se puede construir, provoca un fallo en la inicialización del proveedor en lugar de cambiar la ruta silenciosamente.

Límite de streaming y reproducción

El streaming tiene deliberadamente un contrato de reintentos más limitado que las llamadas sin streaming:

  1. ReliableModelProvider elige la primera entrada ordenada que admite las capacidades de transmisión solicitadas y no está en periodo de enfriamiento.
  2. Abre ese flujo una vez. No cambia de entrada después de que se inicia el flujo.
  3. El analizador del proveedor específico traduce la semántica de finalización de su protocolo a Final o a un error. La mayoría de los analizadores SSE con validación requieren su señal de finalización configurada. Anthropic actualmente también considera que un EOF posterior a un message_delta.stop_reason no vacío indica una finalización, aunque no se haya observado message_stop; PR #9447 propone exigir message_stop, pero ese cambio aún no se ha integrado.
  4. El entorno de ejecución consume y sanitiza los eventos del flujo. Si el flujo falla antes de que la salida de eventos inmutables sea visible, el entorno de ejecución reintenta la llamada completa mediante la ruta sin transmisión, que vuelve a entrar en todo el recorrido de fiabilidad.
  5. Si el texto, el razonamiento o los eventos de herramientas preejecutados ya han llegado a un sumidero de eventos inmutable, la interrupción se convierte en StreamInterruptedAfterOutput. El entorno de ejecución no reproduce la solicitud. Solo el texto ya reenviado al consumidor se convierte en texto parcial persistido del asistente.
  6. La cancelación nunca se convierte en un reintento automático del proveedor. La cancelación antes de que se reenvíe texto aborta el turno. La cancelación después de que se reenvíe texto conserva ese texto parcial del asistente; la salida que solo contiene razonamiento o la salida de una herramienta preejecutada no se convierte por sí sola en texto parcial persistido del asistente al cancelar.

Los sumideros de actualización de borradores son mutables. Un mecanismo de respaldo previo a la confirmación puede reemplazar un borrador sin duplicar la salida inmutable, mientras que los sumideros de eventos definen el límite de no repetición.

Un stream que finaliza sin texto final ni llamadas a herramientas es una respuesta semánticamente vacía, no una respuesta correcta. Cuando el runtime marca ese resultado como seguro para reintentar y provider_retries es distinto de cero, Reliable permite una única llamada de recuperación sin streaming al proveedor/modelo exacto que produjo el stream vacío. Esta concesión se consume una sola vez; si la recuperación falla, se avanza a los candidatos configurados restantes con su presupuesto de reintentos normal. Con cero reintentos, la entrada de stream fallida permanece omitida, salvo que sea el único candidato; en ese caso se permite un único intento de recuperación sin streaming de la misma entrada (recuperación, no reproducción). Esta concesión de candidato único también se consume una sola vez; cuando ambas concesiones se aplican a la misma entrada, se fusionan en un único intento. El razonamiento ya mostrado sigue visible una vez, pero no cuenta como respuesta final. Esta excepción no autoriza a reproducir tras una cancelación, una salida visible interrumpida ni trabajo de herramientas ejecutado por el proveedor.

Esta división mantiene la recuperación del transporte en el entorno de ejecución, el entramado específico del proveedor en el adaptador y la política de reintento y reserva en la capa de fiabilidad. Una implementación del proveedor no debería inventar una segunda política de repetición a nivel de turno.

Atribución y carencias conocidas

ProviderDispatch establece la atribución en torno a cada llamada al proveedor. ReliableModelProvider registra la alternativa de respaldo solicitada y la servida solo después de que una llamada sin transmisión se completa correctamente o de que una transmisión de respaldo se completa sin errores. El código del entorno de ejecución y del canal puede consultar ese registro local a la tarea para informar a un usuario de que se produjo una recuperación.

El registro es solo una pista de recuperación de familia o modelo. Las entradas de producción usan la familia del proveedor como display_name, por lo que el registro puede perder el alias de perfil con puntos. Un fallback entre alias de la misma familia y del mismo modelo puede, por tanto, ser indistinguible de la ruta solicitada. Las respuestas en tiempo de ejecución añaden un aviso de fallback de modelo o proveedor cuando el registro difiere. La entrega por canales conserva el pie de aviso de cambio de familia y usa channels.model_fallback_notice para el fallback ordinario dentro de la misma familia a un modelo distinto. Los modos globales son off por defecto, redacted sin identificadores de enrutamiento y detailed con los identificadores de proveedor y modelo solicitados y servidos. Consulta Avisos de respaldo de modelo para la configuración y las compensaciones de privacidad por audiencia.

El orquestador de canales resuelve esta política a partir del Config activo en ese momento durante la entrega saliente, en lugar de capturarla en una instantánea dentro de un identificador de canal de larga duración. Las rutas existentes de publicación y recarga de configuración aplican los cambios a un daemon en ejecución. El aviso decora el contenido saliente después de que la respuesta del asistente entra en el historial, por lo que no pasa a formar parte del historial de prompts ni modifica el registro del intento de servicio. Los avisos de seguridad conservan su comportamiento independiente.

En las rutas de turno instrumentadas con eventos, la contabilidad por intento reside en el registro usage_by_provider, no en ese registro. Cada intento facturable en esas rutas, aceptado o rechazado, emite TurnEvent::Usage con su provider_ref/model de servicio y un indicador accepted; el frame done de la gateway deriva cost_usd como la suma del registro. Las consultas independientes de una sola vez sin un sink de eventos, incluida la reflexión de skills, pueden registrar costos sin entrar en este registro. Esto resuelve issue #9470 (atribución incorrecta de uso y costo en intentos rechazados y avisos de fallback obsoletos tras la recuperación del stream). No inferir la precisión del costo por intento únicamente a partir del aviso de fallback final o de la identidad del proveedor solicitado; consultar el registro.

La contingencia por rechazo de contenido y salvaguardas es un contrato propuesto aparte de la fiabilidad del transporte. Tracker #9293 coordina ese trabajo entre las superficies de proveedor, configuración, canal, gateway y web. El trabajo de identidad de servicio y registro por intento en PR #8966 cierra la brecha de atribución de costes en Reliable; la contingencia por rechazo de contenido sigue rastreándose por separado.

Lista de verificación de cambios

Para los cambios en el enrutamiento de proveedores, responde estas preguntas antes de la aprobación del revisor:

  • ¿Afecta el cambio al envío de agentes, la selección de sugerencias, el mecanismo de respaldo de fiabilidad o a un enrutador externo? Indique exactamente un responsable para cada decisión.
  • Si una indicación apunta a cualquier perfil de proveedor, ¿su gestión del modelo coincide con la construcción del destino? Compara el destino principal con el valor fijado activo/predeterminado. Para un destino no principal con un modelo configurado, compara el modelo de la ruta con ese valor fijado. Si el perfil omite model, confirma que el modelo de la ruta debe propagarse y que los fallback_models del perfil no se materializarán.
  • ¿Cada perfil de reserva conserva su propio punto de conexión, credenciales, modelo, encabezados y anulaciones de capacidades?
  • ¿Qué se puede reintentar, qué avanza inmediatamente y qué error se devuelve después de agotar los reintentos?
  • ¿Se puede volver a reproducir una solicitud después de cualquier salida que un usuario o un consumidor inmutable ya haya observado?
  • ¿Qué señal exacta acepta cada analizador sintáctico del proveedor como finalización? ¿Se considera truncado un EOF antes de esa señal?
  • ¿Se conservan por separado las identidades de proveedor/modelo solicitadas y las servidas?
  • ¿El uso, el coste, los registros y las notificaciones al usuario se derivan del mismo intento de servicio, o se realiza un seguimiento explícito de la limitación?
  • ¿Las pruebas de streaming y sin streaming cubren el mismo límite de fallo en el que se espera que el comportamiento coincida?

Punteros de origen

  • Trait del proveedor y eventos de streaming: crates/zeroclaw-api/src/model_provider.rs
  • Selección de rutas: crates/zeroclaw-providers/src/router.rs
  • Fijación del modelo del perfil: crates/zeroclaw-providers/src/model_pin.rs
  • Reintentos, tiempo de espera, mecanismo de respaldo y avisos de respaldo: crates/zeroclaw-providers/src/reliable.rs
  • Construcción de proveedores y materialización del grafo de respaldo: crates/zeroclaw-providers/src/lib.rs, crates/zeroclaw-providers/src/factory.rs
  • Protección de finalización del flujo del proveedor: crates/zeroclaw-providers/src/stream_guard.rs
  • Reproducción del flujo en tiempo de ejecución y gestión de salidas parciales: crates/zeroclaw-runtime/src/agent/turn/provider_call.rs, crates/zeroclaw-runtime/src/agent/turn/stream_consume.rs
  • Guías del operador: Configuración del proveedor, Enrutamiento, Streaming