Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Ciclo de vida de la configuración

La configuración es tanto una interfaz de operador como un contrato en tiempo de ejecución. Trátala como estado con un propietario claro, no como ajustes sueltos copiados en cualquier subsistema que los necesite.

La fuente canónica es zeroclaw_config::schema::Config, cargada desde config.toml. Las superficies de configuración visibles para el usuario, la referencia de configuración generada, el editor de configuración de la gateway, las sobrescrituras por variables de entorno, zeroclaw config set, zeroclaw config patch, Quickstart y los métodos RPC de configuración se enrutan todos a través de ese mismo esquema tipado.

Para el orden de compilación, las reglas de salida con seguimiento y las comprobaciones de deriva que convierten el esquema tipado en la referencia de configuración, consulta Canalización de documentación generada.

Qué posee qué

SuperficiePropietarioLímite de persistenciaAplicar límite en tiempo de ejecución
Esquema de configuracióncrates/zeroclaw-config/src/schema.rs más derivados ConfigurableCódigo, no documentación generadaNueva compilación binaria
Referencia generadacargo mdbook refs / markdown-schemadocs/book/src/reference/config.md en tiempo de compilaciónSolo documentación
Ubicación de arranqueZEROCLAW_CONFIG_DIR, ZEROCLAW_DATA_DIR, deprecated ZEROCLAW_WORKSPACESolo el entornoAntes de que exista Config
Anulaciones de schema-mirrorZEROCLAW_<lowercase_path> con __ para los puntosSolo en memoriaCada Config::load_or_init()
Escrituras de configuración de CLIzeroclaw config set, config patch, alias, helpers de modelosave_dirty() a config.tomlLa siguiente carga/recarga, a menos que el comando actual use el nuevo valor en memoria
Escrituras de configuración de RPC y TUIconfig/* métodos RPC usados por zerocodeConfirmación de configuración admitida: save_dirty() y luego publicarLas actualizaciones de pares publicadas se aplican de inmediato; los subsistemas gestionados por el demonio necesitan recargarse
Inicio rápido aplicarRuta de aplicación compartida para web, CLI y zerocodeAplicación por etapas completada como confirmación de configuración (superficies supervisadas)Web y RPC pueden señalar la recarga del daemon; la CLI independiente se aplica en la siguiente carga/recarga
Escrituras de configuración de GatewayManejadores de la API de configuración mediante persist_and_swap()Confirmación de configuración admitida: save_dirty() y luego publicarLas actualizaciones de pares publicadas se aplican inmediatamente; los subsistemas del daemon las aplican después de recargar
Recargar daemon/admin/reload, RPC config/reload o el canal de recarga en procesoVuelve a leer config.tomlRecrea los subsistemas del daemon en el mismo PID

No edites manualmente la referencia de configuración generada. Si un campo, enum, sección de alias, marcador secreto o descripción está mal allí, corrige el esquema o el generador y vuelve a generar la referencia.

Orden de carga

La carga de la configuración tiene varias fases distintas:

  1. Resuelve la raíz de instalación a partir de las variables de entorno de bootstrap. Esto ocurre antes de que exista cualquier Config, por lo que los nombres de bootstrap mantienen su forma en mayúsculas y no usan la gramática del espejo de esquema.
  2. Lee config.toml, ejecuta la migración del esquema en memoria, descifra los secretos configurados y registra cualquier sección crítica de seguridad mal formada como seguridad degradada.
  3. Aplica las anulaciones de schema-mirror a la configuración en memoria. En las variables de entorno, __ se asigna a ., así que ZEROCLAW_providers__models__openai__api_key apunta a providers.models.openai.api_key.
  4. Validar y advertir sin bloquear al operador fuera del editor de la puerta de enlace.

En una instalación nueva, los valores predeterminados se guardan antes de que se apliquen las sustituciones de entorno. Esto mantiene los secretos inyectados por el entorno y los valores locales de CI fuera del archivo nuevo.

Las anulaciones de entorno no se guardan

Las variables de entorno de schema-mirror son inyecciones en tiempo de ejecución. Se aplican al Config en memoria al cargarse y se registran en env_overridden_paths para que la CLI, el panel de control y quickstart puedan mostrar el indicador de anulación.

Al guardar, debe enmascarar estas rutas para devolverlas a su valor de disco anterior al reemplazo o a su valor predeterminado antes del cifrado. Esto es especialmente importante para los secretos: si un operador tiene una clave de API cifrada en el disco y arranca temporalmente con una anulación de entorno para la misma ruta, un guardado de configuración no relacionado no debe reemplazar la credencial real con el valor del entorno ni con una cadena de visualización enmascarada.

Revisa los cambios de configuración con esta invariante en mente:

  • ZEROCLAW_* los valores de schema-mirror afectan al proceso en ejecución después de la carga.
  • No se convierten en configuración duradera.
  • Las rutas guardadas deben preservar los secretos cifrados y las referencias externas a secretos, a menos que se haya editado intencionalmente la misma ruta.

Las entradas de credenciales permanecen tipadas

Los valores en tiempo de ejecución similares a credenciales siguen siendo valores de configuración. Las claves de API, los tokens de OAuth, las URL de los endpoints y otras credenciales de proveedores/canales deben pasar por el esquema de configuración tipado, la gestión de secretos de configuración o las sobrescrituras ZEROCLAW_* reflejadas por el esquema antes de que un constructor en tiempo de ejecución las reciba.

No agregue lecturas ad-hoc de std::env::var("PROVIDER_API_KEY") dentro de los constructores de provider, channel, tool, transcription, TTS, memory o gateway. Eso crea una segunda fuente de credenciales fuera de Config, omite la visibilidad de env-override y puede provocar que el comportamiento de CLI, gateway, RPC/TUI, quickstart y reload sea inconsistente.

Si ZeroClaw admite intencionadamente un puente nativo de variables de entorno para una familia de integraciones, documenta ese puente en el límite de integración y asígnalo al mismo valor de configuración tipado antes de la construcción. De lo contrario, los nombres de shell predeterminados del ecosistema, como ANTHROPIC_API_KEY, OPENROUTER_API_KEY o QDRANT_URL, deben transferirse mediante un puente a la variable ZEROCLAW_* correspondiente que refleja el esquema; consulta Variables de entorno.

Rutas sucias y escrituras incrementales

La mayoría de las superficies de edición usan Config::mark_dirty() más save_dirty(), no una reescritura completa. save_dirty() escribe solo las rutas punteadas cambiadas, conserva las entradas no marcadas como dirty y los comentarios cuando es posible, registra el schema_version actual y escribe mediante un reemplazo atómico de archivo temporal.

Esa ruta también es responsable de las secciones de clave de mapa. Crear un alias como un proveedor de modelos, un servidor MCP, un paquete de habilidades o un paquete de conocimientos debe modificar la sección correcta para que el alias sobreviva a un guardado y recarga. Una edición de configuración que solo actualiza el estado del panel en memoria no está completa.

Al revisar una escritura de configuración, verifica que:

  • la ruta editada se marca como sucia antes de la persistencia;
  • map-key crea, renombra y elimina ensucian la sección padre o la clave natural;
  • las rutas secretas y las rutas anuladas por env conservan su comportamiento de enmascaramiento al guardar;
  • schema_version permanece actual después de escrituras incrementales;
  • el valor cambiado persiste tras save_dirty() seguido de una recarga.

Las grabaciones completas necesitan procedencia de carga

Config::save() se niega a sobrescribir un config.toml existente a menos que el valor en memoria haya sido cargado desde ese mismo archivo (loaded_from, establecido por load_or_init tanto en su rama de archivo existente como en la de inicialización nueva, y por los cargadores que releen un archivo de configuración antes de modificarlo). Por lo tanto, un Config construido por defecto, construido programáticamente o reapuntado no puede reemplazar la configuración poblada de un operador con una copia casi vacía.

Crear un archivo que falta (primera ejecución) sigue teniendo éxito: un valor que nunca leyó un archivo obtiene exactamente una creación y luego debe recargarse o forzarse, y force_save() es la vía explícita para una sobrescritura intencional verificada. Al revisar una ruta de código que construye un Config nuevo y espera escribirlo sobre un archivo existente, cargue primero o justifique la llamada a force_save().

force_save() omite únicamente la comprobación de procedencia de la carga. Las comprobaciones de la ruta de destino siguen aplicándose. Para reemplazar un archivo existente, establece config_path en la ruta deseada con un directorio padre no vacío. Un nombre de archivo sin ruta, como config.toml, se rechaza si su destino resuelto en tiempo de ejecución ya existe, lo que mantiene la protección existente contra la sobrescritura de un archivo en un destino inferido.

Guardado vs aplicado

Un guardado exitoso significa que el archivo cambió. No siempre significa que todos los componentes en tiempo de ejecución hayan adoptado el cambio.

El daemon es el propietario del grafo del subsistema de larga duración: gateway, listeners de canal, scheduler, listener de MQTT, cableado de sesión, backend de memoria, fábricas de proveedores y cableado de costes. POST /admin/reload señala al bucle del daemon, que vuelve a leer config.toml y vuelve a instanciar esos subsistemas en el mismo proceso. El PID sigue siendo el mismo, pero los listeners se vuelven a vincular brevemente.

Las escrituras de configuración del Gateway llaman a persist_and_swap(): guardan en disco dentro de una confirmación de configuración admitida y serializada, luego publican la configuración guardada como el nuevo par publicado y establecen pending_reload. Esto hace que el editor de configuración refleje la escritura de inmediato, mientras que el banner de recarga indica al operador que los canales, proveedores, el planificador u otros componentes gestionados por el daemon podrían seguir ejecutándose desde la instancia de subsistema anterior.

zeroclaw gateway start independiente no tiene supervisor de daemon. Su punto final de recarga devuelve una respuesta que requiere reinicio porque no hay un bucle externo de daemon al que señalar.

Par publicado y serialización del redactor

El proceso supervisado mantiene un único par canónico publicado: el Config junto con su revisión, una época de autoridad opaca más una secuencia verificada. Los lectores reciben un manejador en vivo de solo lectura (zeroclaw_config::live::LiveConfigHandle) y observan la configuración y su revisión como una sola unidad; ese manejador ni expone mutación ni mantiene una segunda copia de la configuración.

Todo escritor participante de HTTP, RPC, TUI, Quickstart, emparejamiento e identidad de canal se admite a través de LiveConfigAuthority de la generación del daemon (begin_config_commit). La confirmación adquiere una sola vez el mutex de escritura de configuración de todo el proceso y, a continuación, retiene un lease de escritura de configuración de la generación hasta la publicación. Esperar al mutex no retiene un lease de escritura de configuración. Una reserva independiente de alias de agente, como la reserva de RPC Quickstart previa a la admisión, puede seguir contando para el drenaje de la generación. La fase irreversible (persistir y, después, publicar bajo una revisión asignada antes de cualquier E/S de disco) se ejecuta retenida, de modo que una solicitud cancelada no puede abandonar una confirmación despachada entre el reemplazo atómico del archivo y su publicación. Las confirmaciones fallan de forma segura (fail-closed) una vez que la generación se está cerrando; una recarga completa inicia una autoridad nueva con una época nueva (las secuencias solo se comparan dentro de una misma época).

La política de autorización aceptada derivada tiene su propio contador de publicación y de revisión, separado del par de configuración. Las escrituras de configuración HTTP publican esa política antes que el par de configuración; las escrituras de configuración RPC la publican después. Estos órdenes existentes no proporcionan un único límite de visibilidad atómico para ambas publicaciones, y el contador de la política no es una secuencia de ConfigRevision.

Otros límites que vale la pena mencionar:

  • Una publicación confirmada no se revierte cuando falla un efecto secundario posterior. Quickstart publica la configuración confirmada incluso cuando la instalación posterior de los archivos de personalidad falla. La CLI informa del alias guardado y dirige a la recuperación de los archivos del espacio de trabajo en lugar de volver a ejecutar Quickstart. Web y RPC siguen devolviendo el mismo resultado de error que se usa para los rechazos, sin un resultado de confirmación distinto, aunque señalan la recarga después de este éxito parcial.
  • El endpoint config migrate prepara un candidato completamente hidratado (secretos descifrados, sobrescrituras de entorno aplicadas, validación estricta) antes de reemplazar el archivo, por lo que un candidato que no puede hidratarse o validarse se rechaza y el archivo original queda intacto.
  • Las herramientas model_routing_config y proxy_config todavía guardan instantáneas de disco cargadas de forma independiente, sin admisión ni publicación de confirmación de configuración. model_routing_config upsert_agent usa persistencia de rutas modificadas (dirty-path) para que los valores no relacionados y los comentarios se conserven, pero sus otras acciones y proxy_config siguen escribiendo instantáneas tipadas completas. Estos escritores no participantes pueden perder ediciones concurrentes en la misma ruta o dejar a los lectores publicados desactualizados. Migrarlos al contrato de escritor participante sigue siendo un trabajo aparte.
  • La publicación no aplica por sí misma la configuración a los subsistemas en ejecución. El ledger de aplicación registra las confirmaciones de las actualizaciones existentes de proveedores de modelos mediante RPC; otros componentes gestionados por el daemon siguen requiriendo /admin/reload. Los nuevos overlays de seguridad y el comportamiento de traspaso de canal siguen condicionados por ADR-012.

Estado de la aplicación

GET /api/config/reload-status conserva pending_reload y añade una vista application de la autoridad de configuración activa. RPC config/status conserva la preparación de incorporación y añade la misma vista. La revisión publicada contiene una época y una secuencia opacas. Cada registro identifica la revisión realmente procesada, una ruta semántica como componentes de campo/clave, y la instancia de destino. Una clave de mapa con puntos sigue siendo un solo componente.

El destino del daemon informa queued_for_reload con daemon_reload_required. Solo una actualización RPC existente y seleccionada del proveedor de modelos puede informar applied_live para su incarnación de sesión capturada. Su registro está pending hasta que el consumidor propietario lo confirme, y una actualización de instancia rechazada queda como rejected. Los metadatos de aplicación del esquema identifican una posible capacidad de actualización existente, no evidencia de que una instancia en ejecución haya adoptado un valor. Las rutas desconocidas requieren recarga. Si la extracción de rutas modificadas no está disponible, una ruta vacía indica un requisito de recarga de toda la configuración con change_scope_unavailable.

La vista HTTP contiene únicamente registros del daemon. Los registros de sesión RPC requieren además concesiones vigentes de lectura de sesión, el selector de agente, la propiedad del principal autenticado, la propiedad de la conexión y la encarnación activa actual. Los administradores y el operador compartido conservan la omisión existente de propiedad del principal. Ninguno de los valores de configuración, credenciales, transcripciones ni texto de error del proveedor se incluye en estos registros. Al eliminar o reemplazar una sesión, su registro se retira en el límite protegido de lectura de estado; una devolución de llamada antigua no puede recrearlo ni confirmar a su sucesor.

El registro guarda el último cambio u intento observado para cada ruta y destino, no un historial de eventos duradero ni un inventario de cada subsistema. La retención está limitada por record_limit; truncated informa de la expulsión de registros. La ausencia de un registro no es evidencia de aplicación. Una edición no relacionada no reetiqueta los acuses de recibo anteriores con la última revisión. Una nueva autoridad tras una recarga completa inicia una nueva época sin acuses de recibo de cambios en vivo registrados. Limpiar pending_reload o devolver una respuesta correcta no puede cambiar los resultados de aplicación. Este fragmento no añade ninguna afirmación sobre la entrega del watcher ni sobre su estado de salud.

Recargar acceso

La recarga local está permitida desde loopback. La recarga remota requiere ambas cosas:

  1. gateway.allow_remote_admin = true
  2. emparejamiento habilitado y un token de portador emparejado válido

Optar por la administración remota mientras el emparejamiento está deshabilitado se rechaza en lugar de tratarse como acceso anónimo de recarga remota.

Las secciones de configuración mal formadas críticas para la seguridad solo pueden degradarse cuando el operador opta explícitamente por el servicio degradado. De lo contrario, el proceso se niega a servir porque la postura de seguridad restablecida a los valores predeterminados puede ser más débil de lo que pretendía el archivo.

Revertir y reparar

Las escrituras de configuración usan un reemplazo atómico mediante archivo temporal y permisos solo para el propietario. Al reemplazar un archivo existente, el escritor crea un config.toml.bak en el mismo directorio durante el reemplazo y lo elimina tras una escritura exitosa. Las escrituras del gateway también guardan una copia del archivo previo a la escritura y, con el mejor esfuerzo posible, la restauran si la persistencia falla antes de publicar el nuevo par.

No existe una reversión transaccional general para un cambio de configuración válido pero no deseado una vez que se ha guardado y aplicado. Restaura el config.toml anterior desde la copia de seguridad, vuelve a editar el campo mediante la CLI o el panel de control, y luego recarga o reinicia según el límite de tiempo de ejecución indicado arriba.

Config-visible no siempre es compatible en tiempo de ejecución

Un campo puede ser visible en el esquema antes de que cada ruta en tiempo de ejecución lo consuma. Eso solo es aceptable cuando la documentación y las notas de revisión lo indican claramente.

Por ejemplo, knowledge_bundles es visible en el esquema y aparece en las APIs de las secciones de configuración. Un PR que añade o modifica una superficie así debe ser preciso sobre si solo almacena configuración, conecta el comportamiento en tiempo de ejecución o completa ambas cosas.

Al revisar una PR que toca un campo visible en el esquema pero aún no consumido en tiempo de ejecución, exige que la descripción de la PR indique si el cableado en tiempo de ejecución está diferido, fuera de alcance o completado por el mismo cambio.

Lista de verificación para revisores

Para cambios en config-schema, env-var, default o reload, pregunta:

  • ¿Cuál es la fuente de verdad para el nuevo valor?
  • ¿Esto está creando estado duplicado o resolviéndolo desde Config en el momento de uso?
  • ¿La referencia generada proviene del código en lugar de prosa mantenida manualmente?
  • ¿Las anulaciones de entorno solo se cargan en tiempo de carga y se enmascaran durante los guardados?
  • ¿CLI, gateway, RPC/TUI y las superficies de inicio rápido coinciden en la ruta con puntos?
  • ¿Se resuelven las credenciales a través de configuración tipada o puentes documentados que reflejan el esquema, en lugar de lecturas de variables de entorno específicas del proveedor y ad-hoc?
  • ¿Una guardada persiste tras recargar el proceso, no solo en la renderización inmediata en memoria?
  • ¿El PR dice si los usuarios necesitan recarga, reinicio, migración o reversión manual?
  • Si el campo solo es visible en la configuración, ¿la PR evita afirmar compatibilidad en tiempo de ejecución?

Punteros de origen

  • Esquema de configuración y persistencia: crates/zeroclaw-config/src/schema.rs
  • Almacenamiento de pares publicados y manejador de solo lectura: crates/zeroclaw-config/src/live.rs
  • Autoridad de configuración en vivo, commits y ciclo de vida: crates/zeroclaw-runtime/src/live_config_authority.rs
  • Gramática de anulación de entorno: crates/zeroclaw-config/src/env_overrides.rs
  • Comandos de CLI de Config: src/main.rs
  • Métodos de configuración de RPC y TUI: crates/zeroclaw-runtime/src/rpc/dispatch.rs
  • Ruta de inicio rápido compartida de apply: crates/zeroclaw-runtime/src/quickstart/mod.rs
  • Señalización de recarga de Quickstart web: crates/zeroclaw-gateway/src/api_quickstart.rs
  • API de configuración de Gateway y banner de recarga: crates/zeroclaw-gateway/src/api_config.rs
  • Punto final de recarga y puerta de acceso: crates/zeroclaw-gateway/src/lib.rs
  • Ayudante de autenticación bearer de Gateway: crates/zeroclaw-gateway/src/api.rs
  • Pipeline de referencia generada: xtask/src/cmd/mdbook/refs.rs