Nœuds d’action

La crate adk-action définit 14 types de nœuds d’action utilisés dans les workflows basés sur des graphes. Chaque type de nœud représente une opération discrète (appel de HTTP, transformation de données, branche conditionnelle, etc.) pouvant être composée en graphes orientés via le ActionNodeExecutor de adk-graph.

Vue d’ensemble

Les nœuds d’action sont les éléments constitutifs des graphes de workflows visuels et programmatiques. Ils fournissent :

  • Opérations typées — 14 types de nœuds couvrant les modèles de workflow courants
  • StandardProperties — Configuration partagée pour la gestion des erreurs, la traçabilité et le mappage des données
  • Interpolation des variables — Syntaxe {{variable}} pour les valeurs dynamiques
  • Intégration aux graphes — Exécutés par le ActionNodeExecutor de adk-graph

Installation

[dependencies]
adk-action = "2.1.0"

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

Types de nœuds (14)

NœudObjectifCatégorie
TriggerPoint d’entrée — démarre l’exécution du workflowContrôle
HTTPEffectue des requêtes HTTP (GET, POST, PUT, DELETE, PATCH)E/S
SetAttribuer des valeurs aux variables du workflowDonnées
TransformTransformer les données à l’aide d’expressions ou de codeDonnées
SwitchBranchement conditionnel basé sur des expressionsContrôle
LoopItérer sur des collections ou jusqu’à ce qu’une condition soit remplieContrôle
MergeRéunir plusieurs branchesContrôle
WaitSuspendre l’exécution pendant une durée ou jusqu’à un événementContrôle
CodeExécuter du code arbitraire (Rust ; JS/TS non implémenté)Calcul
DatabaseInterroger des bases de données — non implémentéE/S
EmailEnvoyer des e-mails via SMTP — non implémentéE/S
NotificationEnvoyer des notifications (Slack, webhook, push)E/S
RSSLire et analyser les flux RSS/AtomE/S
FileLire, écrire et transformer des fichiersE/S

La disponibilité est vérifiée lors de la construction du graphe

Certains types de nœuds acceptent et valident une configuration alors que leur backend n’existe pas.
Ils sont refusés par StateGraph::compile(), et non au milieu d’une exécution :

ConfigurationÉtat
Database (tout type)Rejetée — aucun pilote n’est intégré
Email (surveiller ou envoyer)Rejetée — IMAP et SMTP ne sont pas implémentés
Code avec language: javascript ou typescriptRejeté — aucun environnement d’exécution isolé ; utilisez rust
Http sans la fonctionnalité action-httpRejeté — activez la fonctionnalité

Un rejet indique le nœud et la raison, de sorte qu’un workflow qui ne peut pas s’exécuter échoue lors de son assemblage, plutôt qu’après que les nœuds précédents ont déjà produit des effets de bord.

Implémentez Node::validate sur un nœud personnalisé pour qu’il participe à la même vérification.

StandardProperties

Chaque nœud d’action possède StandardProperties — une configuration partagée qui contrôle le comportement de l’exécution :

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 Champs

ChampTypeDescription
on_errorErrorHandlingStop, ContinueOnFail ou RetryThenFail
retryOption<RetryConfig>Tentatives de nouvelle tentative et délai entre celles-ci
notesOption<String>Description lisible par l’humain pour le traçage
on_successOption<String>Nœud de rappel à exécuter en cas de succès
on_failureOption<String>Nœud de rappel à exécuter en cas d’échec
timeout_msOption<u64>Durée maximale d’exécution
continue_on_failboolIndique si les nœuds en aval s’exécutent après un échec
input_mappingOption<String>Expression permettant de transformer les données d’entrée
output_keyOption<String>Nom de la variable dans laquelle stocker la sortie

Interpolation des variables

Les nœuds d’action prennent en charge la syntaxe {{variable}} pour référencer l’état du workflow :

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();

Sources des variables

PréfixeSourceExemple
triggerCharge utile du nœud déclencheur{{trigger.body.email}}
envVariables d’environnement{{env.DATABASE_URL}}
nodesSortie des nœuds précédents{{nodes.fetch_user.json.name}}
workflowVariables au niveau du workflow{{workflow.run_id}}

L’accès imbriqué utilise la notation par points : {{nodes.http_1.json.data[0].id}}

Exemples de nœuds

Nœud 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();

Nœud de commutation

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();

Nœud de boucle

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();

Nœud de définition

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();

Intégration avec adk-graph

Les nœuds d’action sont exécutés par adk-graph via ActionNodeExecutor :

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?;

Définir des types de nœuds personnalisés

Implémentez le 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" }))
    }
}

Précédent : ← Réessayer et réfléchir | Suivant : Plugins →