Nodos de acción

El crate adk-action define 14 tipos de nodos de acción utilizados en flujos de trabajo basados en grafos. Cada tipo de nodo representa una operación discreta (llamada a HTTP, transformación de datos, rama condicional, etc.) que puede componerse en grafos dirigidos mediante ActionNodeExecutor de adk-graph.

Descripción general

Los nodos de acción son los componentes básicos de los grafos de flujos de trabajo visuales y programáticos. Proporcionan:

  • Operaciones tipadas — 14 tipos de nodos que abarcan patrones comunes de flujos de trabajo
  • StandardProperties — Configuración compartida para el manejo de errores, el trazado y la asignación de datos
  • Interpolación de variables — Sintaxis de {{variable}} para valores dinámicos
  • Integración con grafos — Ejecutados por ActionNodeExecutor de adk-graph

Instalación

[dependencies]
adk-action = "2.1.0"

# Or specific action features via umbrella crate
adk-rust = { version = "2.1.0", features = ["action"] }

Tipos de nodos (14)

NodoPropósitoCategoría
TriggerPunto de entrada — inicia la ejecución del flujo de trabajoControl
HTTPRealiza solicitudes HTTP (GET, POST, PUT, DELETE, PATCH)E/S
SetAsignar valores a variables del flujo de trabajoDatos
TransformTransformar datos mediante expresiones o códigoDatos
SwitchRamificación condicional basada en expresionesControl
LoopIterar sobre colecciones o hasta que se cumpla una condiciónControl
MergeVolver a unir varias ramasControl
WaitPausar la ejecución durante un período o hasta que ocurra un eventoControl
CodeEjecutar código arbitrario (Rust; JS/TS no implementado)Cómputo
DatabaseConsultar bases de datos — no implementadoE/S
EmailEnviar correos electrónicos mediante SMTP — no implementadoE/S
NotificationEnviar notificaciones (Slack, webhook, push)E/S
RSSLeer y analizar feeds RSS/AtomE/S
FileLeer, escribir y transformar archivosE/S

La disponibilidad se comprueba al construir el grafo

Algunos tipos de nodos aceptan y validan una configuración aunque su backend no exista.
StateGraph::compile() los rechaza, no a mitad de una ejecución:

ConfiguraciónEstado
Database (cualquier tipo)Rechazado — no hay ningún controlador integrado
Email (monitorizar o enviar)Rechazado — IMAP y SMTP no están implementados
Code con language: javascript o typescriptRechazado — no hay un entorno de ejecución aislado; usa rust
Http sin la funcionalidad action-httpRechazado — habilita la funcionalidad

Un rechazo indica el nodo y el motivo, por lo que un flujo de trabajo que no puede ejecutarse falla mientras se está ensamblando, en lugar de hacerlo después de que los nodos anteriores ya hayan tenido efectos secundarios.

Implementa Node::validate en un nodo personalizado para participar en la misma comprobación.

StandardProperties

Cada nodo de acción incluye StandardProperties — una configuración compartida que controla el comportamiento de ejecución:

use adk_action::{StandardProperties, ErrorHandling, RetryConfig};

let props = StandardProperties::builder()
    // Error handling
    .on_error(ErrorHandling::ContinueOnFail)
    .retry(RetryConfig {
        max_attempts: 3,
        wait_between_ms: 1000,
    })

    // Tracing
    .notes("Fetch user profile from API")

    // Callbacks
    .on_success("notify_complete")
    .on_failure("alert_team")

    // Execution
    .timeout_ms(30_000)
    .continue_on_fail(true)

    // Input/output mapping
    .input_mapping("{{trigger.body.user_id}}")
    .output_key("user_profile")

    .build();

StandardProperties Campos

CampoTipoDescripción
on_errorErrorHandlingStop, ContinueOnFail o RetryThenFail
retryOption<RetryConfig>Intentos de reintento y retraso entre ellos
notesOption<String>Descripción legible para el seguimiento
on_successOption<String>Nodo de devolución de llamada que se ejecutará cuando se produzca un éxito
on_failureOption<String>Nodo de devolución de llamada que se ejecutará cuando se produzca un error
timeout_msOption<u64>Tiempo máximo de ejecución
continue_on_failboolSi los nodos posteriores se ejecutan después de un fallo
input_mappingOption<String>Expresión para transformar los datos de entrada
output_keyOption<String>Nombre de la variable donde se almacena la salida

Interpolación de variables

Los nodos de acción admiten la sintaxis {{variable}} para hacer referencia al estado del flujo de trabajo:

use adk_action::HttpNode;

let node = HttpNode::builder()
    .url("https://api.example.com/users/{{trigger.body.user_id}}")
    .method("GET")
    .headers(vec![
        ("Authorization".into(), "Bearer {{env.API_TOKEN}}".into()),
    ])
    .build();

Fuentes de variables

PrefijoFuenteEjemplo
triggerCarga útil del nodo de activación{{trigger.body.email}}
envVariables de entorno{{env.DATABASE_URL}}
nodesSalida de los nodos anteriores{{nodes.fetch_user.json.name}}
workflowVariables del flujo de trabajo{{workflow.run_id}}

El acceso anidado utiliza la notación de puntos: {{nodes.http_1.json.data[0].id}}

Ejemplos de nodos

Nodo HTTP

use adk_action::{HttpNode, HttpMethod};

let node = HttpNode::builder()
    .method(HttpMethod::Post)
    .url("https://api.example.com/orders")
    .headers(vec![
        ("Content-Type".into(), "application/json".into()),
    ])
    .body(r#"{"item": "{{trigger.body.item}}", "qty": {{trigger.body.quantity}}}"#)
    .properties(StandardProperties::builder()
        .timeout_ms(10_000)
        .on_error(ErrorHandling::RetryThenFail)
        .retry(RetryConfig { max_attempts: 3, wait_between_ms: 2000 })
        .output_key("order_response")
        .build())
    .build();

Nodo de conmutación

use adk_action::{SwitchNode, SwitchCase};

let node = SwitchNode::builder()
    .cases(vec![
        SwitchCase {
            condition: "{{nodes.classify.json.category}} == 'urgent'".into(),
            output: "urgent_path".into(),
        },
        SwitchCase {
            condition: "{{nodes.classify.json.category}} == 'normal'".into(),
            output: "normal_path".into(),
        },
    ])
    .fallback("default_path")
    .build();

Nodo de bucle

use adk_action::{LoopNode, LoopMode};

let node = LoopNode::builder()
    .mode(LoopMode::ForEach {
        items: "{{nodes.fetch_users.json.users}}".into(),
        item_var: "current_user".into(),
    })
    .body_nodes(vec!["process_user", "save_result"])
    .properties(StandardProperties::builder()
        .notes("Process each user in the list")
        .build())
    .build();

Nodo de asignación

use adk_action::SetNode;

let node = SetNode::builder()
    .assignments(vec![
        ("status".into(), "processing".into()),
        ("started_at".into(), "{{workflow.timestamp}}".into()),
        ("user_email".into(), "{{trigger.body.email}}".into()),
    ])
    .build();

Integración con adk-graph

Los nodos de acción son ejecutados por ActionNodeExecutor de adk-graph:

use adk_graph::{Graph, ActionNodeExecutor};
use adk_action::{TriggerNode, HttpNode, SetNode};

// Define nodes
let trigger = TriggerNode::webhook("order_received");
let fetch = HttpNode::get("https://api.example.com/inventory/{{trigger.body.sku}}");
let update = SetNode::new(vec![("available", "{{nodes.fetch.json.quantity}}")]);

// Build graph
let graph = Graph::builder()
    .node("trigger", trigger)
    .node("check_inventory", fetch)
    .node("update_status", update)
    .edge("trigger", "check_inventory")
    .edge("check_inventory", "update_status")
    .build()?;

// Execute
let executor = ActionNodeExecutor::new();
let result = executor.run(graph, initial_context).await?;

Definición de tipos de nodos personalizados

Implementa el trait ActionNode:

use adk_action::{ActionNode, ActionContext, ActionResult, StandardProperties};
use async_trait::async_trait;

struct CustomNode {
    config: MyConfig,
    properties: StandardProperties,
}

#[async_trait]
impl ActionNode for CustomNode {
    fn node_type(&self) -> &str { "custom" }
    fn properties(&self) -> &StandardProperties { &self.properties }

    async fn execute(&self, ctx: &ActionContext) -> ActionResult {
        let input = ctx.resolve("{{trigger.body.data}}")?;
        // Custom logic...
        Ok(serde_json::json!({ "result": "processed" }))
    }
}

Anterior: ← Reintentar y reflexionar | Siguiente: Complementos →