Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Ciclo de vida de la solicitud

Qué ocurre entre “el usuario envía un mensaje” y “el agente responde”: la ruta completa, con anotaciones sobre streaming, llamadas a herramientas y puertas de seguridad.

Entrante

flowchart LR
    A[External event] -->|webhook / push / poll / WS| B[Channel adapter]
    B -->|decode, dedup, pair-check| C[Inbound envelope]
    C -->|workspace binding| D[Runtime: process_message]

Un adaptador de canal (por ejemplo, discord.rs, telegram.rs, email_channel.rs) recibe eventos nativos de la plataforma y los convierte en un sobre de entrada uniforme. El adaptador maneja:

  • Decodificación: carga útil específica de la plataforma → formato de mensaje canónico
  • Deduplicación: evita reproducir el mismo mensaje dos veces (reinicios, reintentos)
  • Verificación de pares: aplica la política [channels.<name>.allowed_users] / IAM antes de que el evento llegue al runtime

Si el canal no está emparejado o el usuario no tiene permiso, el evento se descarta antes de que el tiempo de ejecución lo vea.

Bucle del agente

sequenceDiagram
    participant CH as Channel
    participant RT as Runtime
    participant SEC as Security
    participant MEM as Memory / history
    participant PR as Provider
    participant TL as Tool

    CH->>RT: process_message(envelope)
    Note over RT: resolve memory-inject policy from the turn's TurnOrigin
    RT->>MEM: recall(query, session scopes)
    MEM-->>RT: entries
    Note over RT: render [Memory context] preamble (engine-side)
    RT->>PR: chat(system, history, tools)
    loop Streaming
        PR-->>RT: StreamEvent::TextDelta
        RT-->>CH: draft update (if channel supports it)
    end
    PR-->>RT: StreamEvent::ToolCall(args)
    RT->>SEC: evaluate_tool_access(name, args, risk)
    alt Blocked
        SEC-->>RT: Err(reason)
        RT->>PR: chat(..., + tool_error)
    else Approval required
        SEC->>CH: ask_operator(prompt)
        CH-->>SEC: approved / denied
    else Allowed
        SEC-->>RT: Ok
    end
    RT->>TL: invoke(args)
    TL-->>RT: ToolResult
    RT->>MEM: append to turn/session history
    RT->>PR: chat(..., + tool_result)
    PR-->>RT: StreamEvent::TextDelta (final)
    RT-->>CH: reply(final)
    RT->>MEM: persist conversation/session history

Propiedades clave:

  • El streaming es de extremo a extremo. El proveedor transmite tokens. Si el adaptador de canal informa supports_draft_updates(), el runtime edita un mensaje enviado in situ a medida que llega el texto. Discord, Slack y Telegram admiten esta funcionalidad.
  • Las llamadas a herramientas están en curso. El modelo puede emitir una llamada a una herramienta mientras aún está generando texto. El entorno de ejecución lee el flujo hasta completarlo, muestra el texto visible a medida que llega, luego recupera las llamadas a herramientas, las valida, las invoca, proporciona el resultado y comienza un nuevo flujo para el siguiente turno.
  • La finalización de la transmisión sigue los eventos del protocolo. Los proveedores dan por finalizada una transmisión correcta cuando llega su evento SSE terminal, en lugar de esperar a que el servidor cierre la conexión. Los cuerpos de respuesta silenciosos producen un error una vez transcurrido el tiempo de espera del proveedor por inactividad de bytes, mientras que las generaciones activas pueden superar el tiempo de espera de las solicitudes sin transmisión.
  • La seguridad controla cada llamada a herramientas. evaluate_tool_access consulta el nivel de autonomía, las listas de permitidos/denegados y los límites de rutas. Las llamadas de riesgo medio bajo la autonomía Supervised pasan a la vía de aprobación del operador.
  • El contexto de memoria es inyectado por el motor. Antes de la primera llamada al proveedor, el motor del turno resuelve una política de inyección a partir de TurnOrigin del turno (quién inició el turno): los subturnos anidados nunca inyectan, los orígenes programados (cron, daemon) inyectan con las entradas de categoría de conversación excluidas, y los orígenes orientados al usuario inyectan (excluyendo las entradas de conversación cuando el turno no tiene ámbito de sesión). Un punto de creación puede suprimir la inyección para cualquier origen (por ejemplo, un trabajo cron con uses_memory = false), y los turnos que no llevan ningún backend de memoria la omiten por completo. Un único renderer aplica la degradación temporal, el filtrado por relevancia, un conjunto de omisión por prompt poisoning y límites de presupuesto de forma uniforme en todas las rutas; los backends de memoria solo responden a recall, no formatean el contexto.
  • El historial y la memoria son independientes. El historial de la sesión preserva la continuidad de la conversación, las llamadas a herramientas y los resultados de las herramientas. Las escrituras explícitas en memoria conservan entradas seleccionadas en el backend de memoria. Los recibos viajan en banda en el texto de la conversación en lugar de como un artefacto persistido separado. Para obtener detalles sobre la propiedad de los payloads, consulta Memory and payload lifecycle.

Recibos de la herramienta

Las ejecuciones exitosas de herramientas pueden recibir un recibo HMAC-SHA256 que se añade al texto del resultado de la herramienta y se devuelve al modelo en la conversación, demostrando que el resultado firmado provino del runtime. El HMAC se basa en una clave efímera en memoria y se calcula sobre tool_name || args || result || timestamp. Los recibos no se escriben en un registro separado en disco y no están encadenados; el modelo puede repetirlos, pero no puede falsificar uno nuevo válido sin la clave. Consulta Tool receipts.

Saliente

Los mensajes salientes vuelven a pasar por el mismo adaptador de canal. Los adaptadores con soporte para múltiples mensajes (Discord, Slack) pueden transmitir respuestas largas como una secuencia de mensajes; otros (correo electrónico, SMS) vacían el contenido al completar el flujo.

Dónde se encuentra en el código

  • Bucle del agente: crates/zeroclaw-runtime/src/agent/turn/ (run_tool_call_loop), con puntos de entrada en crates/zeroclaw-runtime/src/agent/loop_.rs (process_message, run)
  • Inyección de contexto de memoria: crates/zeroclaw-runtime/src/agent/memory_inject.rs (resolve_inject_policy, render_memory_context), indexada por TurnOrigin de los tipos de ingress de zeroclaw-api e invocada por el motor de turnos
  • Verificaciones de acceso a llamadas de herramientas: crates/zeroclaw-runtime/src/security/ (iam_policy.rs evaluate_tool_access)
  • Orquestación de canales: crates/zeroclaw-channels/src/orchestrator/
  • Streaming del proveedor: crates/zeroclaw-api/src/model_provider.rs (enum StreamEvent, reexportado desde zeroclaw-providers), compatible.rs (analizador SSE)

Desde #7415, cada transporte (channels, CLI, cron, gateway WebSocket, RPC/zerocode, ACP y la API integrada Agent) ejecuta el mismo motor de turnos: run_tool_call_loop en crates/zeroclaw-runtime/src/agent/turn/. Los puntos de entrada de streaming e integrados son envoltorios ligeros en agent.rs que configuran ajustes por llamante (dedup, comportamiento del límite de iteraciones, emisión de eventos) alrededor del bucle compartido. El módulo turn/ consta de un archivo por paso:

Archivo(s)Paso
mod.rsorquestador: control de iteración, ajustes, drenaje de dirección
history_window.rs · tool_specs.rs · vision_route.rsantes de la llamada: mantenimiento del historial, especificaciones de herramientas, enrutamiento de visión
provider_call.rs · stream_consume.rs · stream_guard.rsla llamada al LLM, el consumo del stream, la protección del protocolo a mitad del stream
parse_response.rs · protocol_detect.rs · context_recovery.rsinterpretación de respuestas, detección de problemas de análisis, recuperación de desbordamiento
approval_gate.rs · call_prep.rsaprobación y preparación de llamadas a herramientas (deduplicación, hooks, valores predeterminados de entrega)
post_exec.rs · results_collect.rs · history_append.rs · max_iter.rsregistro de resultados, detección de bucles, anexado al historial, límite de iteraciones
context.rs · events.rs · knobs.rs · steering.rs · outcome.rs · redact.rs · delivery_defaults.rstipos compartidos: contexto de turno, eventos, ajustes por llamador, dirección, resultados, depuración de credenciales