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
ActionNodeExecutordeadk-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)
| Nodo | Propósito | Categoría |
|---|---|---|
Trigger | Punto de entrada — inicia la ejecución del flujo de trabajo | Control |
HTTP | Realiza solicitudes HTTP (GET, POST, PUT, DELETE, PATCH) | E/S |
Set | Asignar valores a variables del flujo de trabajo | Datos |
Transform | Transformar datos mediante expresiones o código | Datos |
Switch | Ramificación condicional basada en expresiones | Control |
Loop | Iterar sobre colecciones o hasta que se cumpla una condición | Control |
Merge | Volver a unir varias ramas | Control |
Wait | Pausar la ejecución durante un período o hasta que ocurra un evento | Control |
Code | Ejecutar código arbitrario (Rust; JS/TS no implementado) | Cómputo |
Database | Consultar bases de datos — no implementado | E/S |
Email | Enviar correos electrónicos mediante SMTP — no implementado | E/S |
Notification | Enviar notificaciones (Slack, webhook, push) | E/S |
RSS | Leer y analizar feeds RSS/Atom | E/S |
File | Leer, escribir y transformar archivos | E/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ón | Estado |
|---|---|
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 typescript | Rechazado — no hay un entorno de ejecución aislado; usa rust |
Http sin la funcionalidad action-http | Rechazado — 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
| Campo | Tipo | Descripción |
|---|---|---|
on_error | ErrorHandling | Stop, ContinueOnFail o RetryThenFail |
retry | Option<RetryConfig> | Intentos de reintento y retraso entre ellos |
notes | Option<String> | Descripción legible para el seguimiento |
on_success | Option<String> | Nodo de devolución de llamada que se ejecutará cuando se produzca un éxito |
on_failure | Option<String> | Nodo de devolución de llamada que se ejecutará cuando se produzca un error |
timeout_ms | Option<u64> | Tiempo máximo de ejecución |
continue_on_fail | bool | Si los nodos posteriores se ejecutan después de un fallo |
input_mapping | Option<String> | Expresión para transformar los datos de entrada |
output_key | Option<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
| Prefijo | Fuente | Ejemplo |
|---|---|---|
trigger | Carga útil del nodo de activación | {{trigger.body.email}} |
env | Variables de entorno | {{env.DATABASE_URL}} |
nodes | Salida de los nodos anteriores | {{nodes.fetch_user.json.name}} |
workflow | Variables 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" }))
}
}
Relacionado
- Agentes de grafos — Orquestación de flujos de trabajo mediante grafos
- Nodos de acción de Studio — Editor visual de nodos en ADK Studio
- Disparadores — Tipos de disparadores de flujos de trabajo
Anterior: ← Reintentar y reflexionar | Siguiente: Complementos →