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ón | Propietario actual | Contrato |
|---|---|---|
| Perfiles de proveedores y grafo de respaldo | Esquema y validación del proveedor zeroclaw-config | Un <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 proveedor | Funciones de fábrica de zeroclaw-providers | Materializa 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 sugerencias | RouterModelProvider | Resuelve 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. |
| Reintentos y conmutación por error | ReliableModelProvider | Clasifica 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 proveedor | Proveedores concretos y zeroclaw-providers/src/stream_guard.rs | Traduce 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 parcial | zeroclaw-runtime/src/agent/turn/provider_call.rs and stream_consume.rs | Reintenta 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 llamada | ProviderDispatch | Abre ámbitos de atribución alrededor de la llamada al proveedor seleccionada para cada intento. |
| Registro de recuperación exitosa | ReliableModelProvider | Expón un único registro local por tarea que compare lo solicitado con lo servido tras una recuperación correcta. Esto no es una contabilidad canónica por intento. |
| Avisos de recuperación para el usuario | Consumidores del tiempo de ejecución y de canales | Renderiza 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:
- La fábrica construye un
ReliableModelProviderpara el perfil del proveedor activo. El modelo principal efectivo procede de una anulación explícita de la construcción o delmodelconfigurado en el perfil. Cuando existe uno, este y elfallback_modelsdel perfil se convierten en entradas fijadas. Si no existe, el perfil aporta una entrada no fijada y susfallback_modelsno se materializan. Los perfilesfallbackreferenciados recursivamente se siguen recorriendo. Cada perfil referenciado conserva sus propias credenciales, endpoint, encabezados, modelo y anulaciones de capacidades. - 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 enRouterModelProvider. - 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 literalhint:<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[].modelde 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 losfallback_modelsde 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 omitamodel. - Los destinos de las rutas se deduplican por
model_provider. Si una ruta proporcionaapi_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.
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:
- El modelo principal efectivo del perfil o una entrada no fijada cuando no existe ningún modelo principal efectivo.
- Los
fallback_modelsde ese perfil, en orden, solo si existe un modelo principal efectivo. - 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:
ReliableModelProviderelige la primera entrada ordenada que admite las capacidades de transmisión solicitadas y no está en periodo de enfriamiento.- Abre ese flujo una vez. No cambia de entrada después de que se inicia el flujo.
- El analizador del proveedor específico traduce la semántica de finalización de su protocolo a
Finalo 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 unmessage_delta.stop_reasonno vacío indica una finalización, aunque no se haya observadomessage_stop; PR #9447 propone exigirmessage_stop, pero ese cambio aún no se ha integrado. - 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.
- 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. - 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 flujo que finaliza sin texto final ni llamadas a herramientas es una respuesta semánticamente vacía, no una respuesta correcta. Cuando el entorno de ejecución marca ese resultado como seguro para repetir y provider_retries es distinto de cero, Reliable permite una llamada de recuperación sin streaming al proveedor/modelo exacto que produjo el flujo vacío. Esa autorización se consume una sola vez; si la recuperación falla, se pasa a los candidatos configurados restantes con sus presupuestos normales de reintentos. Con cero reintentos, la entrada del flujo fallido sigue omitiéndose. El razonamiento que ya se haya mostrado sigue visible una vez, pero no cuenta como respuesta final. Esta excepción no autoriza repetir la ejecución después de 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 solo es una pista de recuperación de familia/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 notación de puntos. Por tanto, un fallback entre alias de la misma familia y el mismo modelo puede no distinguirse de la ruta solicitada. Las respuestas en tiempo de ejecución añaden un aviso de fallback de modelo/proveedor cuando el registro difiere. La entrega por canal añade un pie de página solo cuando hay un cambio entre familias; issue #7883 realiza el seguimiento de los avisos dentro de la misma familia.
Ese registro es un aviso de éxito, no un libro mayor canónico de todos los intentos. La incidencia n.º 9470 realiza un seguimiento del uso incorrecto y la atribución de costes entre los intentos rechazados y los avisos de reserva obsoletos tras la recuperación del flujo. Hasta que se resuelva esa incidencia, no infieras la exactitud del coste por intento a partir del aviso de reserva final ni de la identidad del proveedor solicitado.
El rechazo de contenido y el mecanismo de respaldo de salvaguardas también constituyen un contrato propuesto independiente de la fiabilidad del transporte. Tracker #9293 coordina ese trabajo en las superficies de proveedor, configuración, canal, puerta de enlace y web. El trabajo adyacente sobre la identidad de servicio propuesto en PR #8966 no cierra por sí solo la brecha de atribución de Reliable.
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 losfallback_modelsdel 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