작업 노드
adk-action 크레이트는 그래프 기반 워크플로에서 사용되는 14가지 작업 노드 유형을 정의합니다. 각 노드 유형은 개별 작업(HTTP 호출, 데이터 변환, 조건부 분기 등)을 나타내며, adk-graph의 ActionNodeExecutor을 통해 방향성 그래프로 구성할 수 있습니다.
개요
작업 노드는 시각적 및 프로그래밍 방식의 워크플로 그래프를 구성하는 기본 요소입니다. 다음을 제공합니다.
- 타입이 지정된 작업 — 일반적인 워크플로 패턴을 다루는 14가지 노드 유형
- StandardProperties — 오류 처리, 추적 및 데이터 매핑을 위한 공유 구성
- 변수 보간 — 동적 값을 위한
{{variable}}구문 - 그래프 통합 —
adk-graph의ActionNodeExecutor에서 실행
설치
[dependencies]
adk-action = "2.1.0"
# Or specific action features via umbrella crate
adk-rust = { version = "2.1.0", features = ["action"] }
노드 유형 (14가지)
| 노드 | 목적 | 범주 |
|---|---|---|
Trigger | 진입점 — 워크플로 실행 시작 | 제어 |
HTTP | HTTP 요청(GET, POST, PUT, DELETE, PATCH) 생성 | 입출력 |
Set | 워크플로 변수에 값 할당 | 데이터 |
Transform | 표현식 또는 코드를 사용하여 데이터 변환 | 데이터 |
Switch | 표현식에 따른 조건부 분기 | 제어 |
Loop | 컬렉션을 반복하거나 조건이 충족될 때까지 반복 | 제어 |
Merge | 여러 분기를 다시 하나로 결합 | 제어 |
Wait | 일정 시간 동안 또는 이벤트가 발생할 때까지 실행 일시 중지 | 제어 |
Code | 임의의 코드 실행 (Rust; JS/TS는 구현되지 않음) | 계산 |
Database | 데이터베이스 쿼리 — 구현되지 않음 | 입출력 |
Email | SMTP을 통해 이메일 전송 — 구현되지 않음 | 입출력 |
Notification | 알림 전송(Slack, 웹훅, 푸시) | 입출력 |
RSS | RSS/Atom 피드 읽기 및 구문 분석 | 입출력 |
File | 파일 읽기, 쓰기 및 변환 | 입출력 |
그래프가 빌드될 때 가용성이 확인됩니다
일부 노드 유형은 구성을 허용하고 검증하지만 해당 백엔드는 존재하지 않습니다.
이러한 노드는 실행 도중이 아니라 StateGraph::compile()에 의해 거부됩니다:
| 구성 | 상태 |
|---|---|
Database (모든 유형) | 거부됨 — 통합된 드라이버가 없음 |
Email (모니터링 또는 전송) | 거부됨 — IMAP 및 SMTP가 구현되지 않음 |
Code과 language: javascript 또는 typescript | 거부됨 — 샌드박스 처리된 런타임이 없습니다. rust를 사용하세요 |
action-http 기능이 없는 Http | 거부됨 — 기능을 활성화하세요 |
거부 결과에는 노드와 이유가 명시되므로, 실행할 수 없는 워크플로는 이전 노드에서 이미 부작용이 발생한 후가 아니라 조립되는 동안 실패합니다.
사용자 지정 노드에 Node::validate을 구현하면 동일한 검사에 참여할 수 있습니다.
StandardProperties
모든 작업 노드에는 StandardProperties이 포함되어 있습니다. 이는 실행 동작을 제어하는 공유 구성입니다.
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 필드
| 필드 | 유형 | 설명 |
|---|---|---|
on_error | ErrorHandling | Stop, ContinueOnFail, or RetryThenFail |
retry | Option<RetryConfig> | 재시도 횟수 및 재시도 간 지연 시간 |
notes | Option<String> | 추적을 위한 사람이 읽을 수 있는 설명 |
on_success | Option<String> | 성공 시 실행할 콜백 노드 |
on_failure | Option<String> | 실패 시 실행할 콜백 노드 |
timeout_ms | Option<u64> | 최대 실행 시간 |
continue_on_fail | bool | 실패 후 다운스트림 노드가 실행되는지 여부 |
input_mapping | Option<String> | 입력 데이터를 변환하는 표현식 |
output_key | Option<String> | 출력을 저장할 변수 이름 |
변수 보간
Action 노드는 워크플로 상태를 참조하기 위한 {{variable}} 구문을 지원합니다.
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();
변수 소스
| 접두사 | 출처 | 예시 |
|---|---|---|
trigger | 트리거 노드 페이로드 | {{trigger.body.email}} |
env | 환경 변수 | {{env.DATABASE_URL}} |
nodes | 이전 노드의 출력 | {{nodes.fetch_user.json.name}} |
workflow | 워크플로 수준 변수 | {{workflow.run_id}} |
중첩된 액세스에는 점 표기법을 사용합니다: {{nodes.http_1.json.data[0].id}}
노드 예제
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();
스위치 노드
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();
루프 노드
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();
설정 노드
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();
adk-graph와의 통합
액션 노드는 adk-graph의 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?;
사용자 지정 노드 유형 정의
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" }))
}
}
관련 항목
- 그래프 에이전트 — 그래프 워크플로 오케스트레이션
- Studio 액션 노드 — ADK Studio의 시각적 노드 편집기
- 트리거 — 워크플로 트리거 유형
이전: ← 재시도 및 성찰 | 다음: 플러그인 →