TurfAI Task Types Reference
Synced from the source repositories. Do not edit by hand.
Complete reference for all available task types in TurfAI workflows.
Overview
Task types are the building blocks of TurfAI workflows. Each task type performs a specific operation and can be connected to form complex automation pipelines.
API Endpoint: GET /api/workflows/task-types
Categories
| Category | Description | Task Types |
|---|---|---|
| AI Operations | ML-powered document processing | classification, extraction, llm, summarization, classify_and_extract, rag_enable, rag_query |
| Google Integrations | Google Drive/Gmail operations | google_drive_fetch |
| External Integrations | HTTP API calls | rest_api |
| Communication | Email/notifications | email_send |
| Workflow Control | Flow control primitives | decision, wait |
Core Integration Tasks
These are the most commonly used task types for workflow integrations.
google_drive_fetch_task
Fetch files from Google Drive and import to GCS.
Processor: google_drive_fetch
Use Cases:
- Fetch job descriptions from shared folders
- Download resumes submitted via forms
- Import policy documents for RAG indexing
Configuration
{
"task_type": "google_drive_fetch_task",
"config": {
"file_id": "1ABC123xyz"
}
}Config Options:
| Field | Type | Required | Description |
|---|---|---|---|
file_id | string | One of | Direct Google Drive file ID |
folder_id | string | One of | Folder ID for search mode |
file_name | string | With folder_id | File name to search for |
Modes:
- Direct: Provide
file_idto fetch specific file - Search: Provide
folder_id+file_nameto find file in folder
Output
{
"file_url": "gs://turfdms/documents/123/file.pdf",
"file_id": "1ABC123xyz",
"file_name": "Resume_JohnDoe.pdf",
"mime_type": "application/pdf",
"size": 245789,
"document_id": 123
}Example Node
{
"id": "fetch-resume",
"type": "google_drive_fetch_task",
"data": {
"label": "Fetch Resume from Drive",
"task_type": "google_drive_fetch_task",
"config": {
"file_id": "{{resume_file_id}}"
}
}
}rest_api_task
Make HTTP requests to external APIs with template variable support.
Processor: rest_api
Use Cases:
- Fetch configuration from external services
- Post results to external systems
- Integrate with third-party APIs
- Call internal TurfAI endpoints
Configuration
{
"task_type": "rest_api_task",
"config": {
"url": "http://localhost:9005/roles/{{role_id}}",
"method": "GET",
"timeout": 30,
"output_mapping": {
"jd_file_id": "$.data.jd_file_id",
"hiring_manager_email": "$.data.hiring_manager_email"
}
}
}Config Options:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
url | string | Yes | - | API URL (supports {{variable}} templates) |
method | string | No | GET | HTTP method |
headers | object | No | {} | Request headers (supports templates) |
body | object | No | - | Request body for POST/PUT/PATCH |
timeout | number | No | 30 | Timeout in seconds |
output_mapping | object | No | - | JSONPath mappings for response extraction |
Template Variables
URLs, headers, and body values support {{variable}} syntax:
{
"url": "https://api.example.com/users/{{user_id}}/documents",
"headers": {
"Authorization": "Bearer {{api_token}}"
},
"body": {
"name": "{{candidate_name}}",
"email": "{{email}}"
}
}Output Mapping (JSONPath)
Extract specific fields from the response:
{
"output_mapping": {
"extracted_name": "$.data.user.name",
"first_item": "$.items[0].id",
"nested_value": "$.response.metadata.count"
}
}Output
{
"data": {
"jd_file_id": "1ABC123xyz",
"hiring_manager_email": "manager@company.com"
},
"status_code": 200,
"_raw_response": { ... }
}Example: Fetch Role Configuration
{
"id": "fetch-role-config",
"type": "rest_api_task",
"data": {
"label": "Fetch Role Configuration",
"task_type": "rest_api_task",
"config": {
"url": "http://localhost:9005/roles/{{role_id}}",
"method": "GET",
"output_mapping": {
"jd_file_id": "$.data.jd_file_id",
"hiring_manager_email": "$.data.hiring_manager_email",
"hr_email": "$.data.hr_email"
}
}
}
}email_send_task
Send emails with HTML support and template variables.
Processor: email_send
Use Cases:
- Send job match notifications
- Deliver workflow results
- Send policy update confirmations
- Notify stakeholders
Configuration
{
"task_type": "email_send_task",
"config": {
"to": ["{{hiring_manager_email}}", "hr@company.com"],
"cc": ["{{recruiter_email}}"],
"subject": "New Application: {{candidate_name}} for {{position}}",
"body": "<h2>Application Received</h2><p>Candidate: {{candidate_name}}</p><p>Match Score: {{match_score}}%</p>",
"html": true
}
}Config Options:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
from | string | No | System default | Sender email |
to | array | Yes | - | Recipient emails (supports templates) |
cc | array | No | [] | CC recipients |
bcc | array | No | [] | BCC recipients |
subject | string | Yes | - | Email subject (supports templates) |
body | string | Yes | - | Email body (supports templates) |
html | boolean | No | true | Send as HTML |
Output
{
"sent": true,
"recipients": ["manager@company.com", "hr@company.com"],
"timestamp": "2024-11-24T10:30:00.000Z"
}Example: Notification Email
{
"id": "send-notification",
"type": "email_send_task",
"data": {
"label": "Send Match Notification",
"task_type": "email_send_task",
"config": {
"to": ["{{hiring_manager_email}}"],
"subject": "New Application Match: {{candidate_name}}",
"body": "<h2>New Job Application</h2><p><strong>Candidate:</strong> {{candidate_name}}</p><p><strong>Position:</strong> {{position}}</p><p><strong>Match Score:</strong> {{match_score}}%</p><h3>Summary</h3><p>{{ai_summary}}</p>",
"html": true
}
}
}wait_task
Poll an endpoint until a condition is met. Generic async wait primitive.
Processor: wait
Use Cases:
- Wait for RAG indexing to complete
- Poll external job status
- Wait for approval workflows
- Monitor async processing
Configuration
{
"task_type": "wait_task",
"config": {
"endpoint": "/api/internal/documents/{{document_id}}/rag-status",
"method": "GET",
"watch_field": "rag_processing_status",
"success_value": "completed",
"failure_values": ["failed", "error"],
"poll_interval": 3,
"timeout": 120
}
}Config Options:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
endpoint | string | Yes | - | URL to poll (supports templates) |
method | string | No | GET | HTTP method |
watch_field | string | Yes | - | Field to monitor (dot notation supported) |
success_value | string | No | "completed" | Value indicating success |
failure_values | array | No | ["failed", "error"] | Values indicating failure |
poll_interval | number | No | 3 | Seconds between polls |
timeout | number | No | 120 | Maximum wait time in seconds |
Output
{
"status": "success",
"final_value": "completed",
"response": { ... },
"elapsed_seconds": 45
}Example: Wait for RAG Indexing
{
"id": "wait-for-rag",
"type": "wait_task",
"data": {
"label": "Wait for RAG Completion",
"task_type": "wait_task",
"config": {
"endpoint": "/api/internal/documents/{{document_id}}/rag-status",
"watch_field": "rag_processing_status",
"success_value": "completed",
"failure_values": ["failed"],
"poll_interval": 5,
"timeout": 300
}
}
}AI Operations Tasks
classification_task
Classify documents into categories using AI.
Processor: classification
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
classification_type | string | "document_type" | Type: document_type, sentiment, topic |
include_confidence | boolean | true | Include confidence scores |
return_multiple | boolean | false | Return multiple classifications |
Input
| Field | Type | Required | Description |
|---|---|---|---|
file_url | string | Yes | GCS URL of document |
metadata | object | No | Additional context |
Output
{
"prompt_title": "Resume Classification",
"section": "HR Documents",
"confidence": 0.95,
"classification": {
"type": "resume",
"subtype": "technical"
}
}extraction_task
Extract structured data from documents.
Processor: document_extraction
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
prompt_id | string | - | Prompt ID to use |
model_type | string | "vertex" | LLM: vertex, openai, anthropic |
output_format | string | "json" | Output: json, text |
use_classification_prompt | boolean | false | Use prompt from classification |
Input
| Field | Type | Required | Description |
|---|---|---|---|
file_url | string | Yes | GCS URL of document |
prompt_data | object | No | Prompt override |
Output
{
"extraction_result": {
"name": "John Doe",
"email": "john@example.com",
"skills": ["Python", "Machine Learning"],
"experience_years": 5
},
"confidence": 0.92,
"tokens_used": 1250
}llm_task
Generic LLM-powered text processing.
Processor: llm_task
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
prompt_id | string | - | Use predefined prompt |
prompt_text | string | - | Custom prompt text |
model_type | string | "vertex" | LLM provider |
process_combined_inputs | boolean | true | Combine all inputs |
output_format | string | "json" | Output format |
Input
| Field | Type | Required | Description |
|---|---|---|---|
file_url | string | No | Document URL |
prompt_data | object | No | Prompt variables |
text_input | string | No | Direct text input |
Output
{
"result": { ... },
"tokens_used": 850
}summarization_task
Generate document summaries.
Processor: summarization
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
summary_type | string | "brief" | Type: brief, detailed, bullet_points |
max_length | number | 500 | Max words |
Output
{
"summary": "This resume belongs to a senior software engineer with 5 years of experience in Python and machine learning...",
"word_count": 150
}classify_and_extract
Combined classification and extraction in one step.
Processor: classify_and_extract
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
classification_type | string | "document_type" | Classification type |
extract_after_classify | boolean | true | Run extraction after |
Output
{
"classification": {
"type": "resume",
"confidence": 0.95
},
"extraction_result": {
"name": "John Doe",
"skills": ["Python", "ML"]
}
}rag_enable_task
Enable RAG indexing for a document.
Processor: rest_api (calls internal endpoint)
Configuration
Default configuration calls /api/internal/rag/enable:
{
"url": "http://localhost:1338/api/internal/rag/enable",
"method": "POST",
"body": {
"document_id": "{{document_id}}",
"user_id": "{{user_id}}",
"force_reprocess": false
}
}Input
| Field | Type | Required | Description |
|---|---|---|---|
document_id | number | Yes | From previous node (e.g., drive fetch) |
user_id | number | Yes | From workflow context |
Output
{
"rag_status": "queued",
"rag_job_id": "rag-embed-123-1700000000"
}rag_query_task
Query the RAG knowledge base.
Processor: rest_api (calls internal endpoint)
Configuration
Default configuration calls /api/internal/rag/query:
{
"url": "http://localhost:1338/api/internal/rag/query",
"method": "POST",
"body": {
"query": "{{query}}",
"user_id": "{{user_id}}",
"top_k": 5
}
}Input
| Field | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query |
user_id | number | Yes | From workflow context |
Output
{
"answer": "According to the Remote Work Policy document, employees can work remotely up to 3 days per week...",
"sources": [
{
"document_id": 45,
"document_name": "Remote Work Policy.pdf",
"snippet": "...employees may work from home up to three days...",
"score": 0.92
}
],
"session_id": "sess-abc123"
}Workflow Examples
F1: Job Application Notification
{
"nodes": [
{
"id": "1",
"type": "rest_api_task",
"data": {
"label": "Fetch Role Config",
"config": {
"url": "http://localhost:9005/roles/{{role_id}}",
"output_mapping": {
"jd_file_id": "$.data.jd_file_id",
"hiring_manager_email": "$.data.hiring_manager_email"
}
}
}
},
{
"id": "2",
"type": "google_drive_fetch_task",
"data": {
"label": "Fetch JD",
"config": { "file_id": "{{jd_file_id}}" }
}
},
{
"id": "3",
"type": "google_drive_fetch_task",
"data": {
"label": "Fetch Resume",
"config": { "file_id": "{{resume_file_id}}" }
}
},
{
"id": "4",
"type": "extraction_task",
"data": {
"label": "Extract Resume",
"config": { "output_format": "json" }
}
},
{
"id": "5",
"type": "llm_task",
"data": {
"label": "Calculate Match",
"config": {
"prompt_text": "Compare this resume to the job description and provide a match score..."
}
}
},
{
"id": "6",
"type": "email_send_task",
"data": {
"label": "Notify Hiring Manager",
"config": {
"to": ["{{hiring_manager_email}}"],
"subject": "New Application: {{candidate_name}}",
"body": "<h2>Match Score: {{match_score}}%</h2>..."
}
}
}
]
}F4-A: HR Policy Ingestion
{
"nodes": [
{
"id": "1",
"type": "google_drive_fetch_task",
"data": {
"label": "Fetch Policy Doc",
"config": { "file_id": "{{policy_file_id}}" }
}
},
{
"id": "2",
"type": "rag_enable_task",
"data": {
"label": "Enable RAG"
}
},
{
"id": "3",
"type": "wait_task",
"data": {
"label": "Wait for Indexing",
"config": {
"endpoint": "/api/internal/documents/{{document_id}}/rag-status",
"watch_field": "rag_processing_status",
"success_value": "completed",
"timeout": 300
}
}
},
{
"id": "4",
"type": "email_send_task",
"data": {
"label": "Send Confirmation",
"config": {
"to": ["{{notification_email}}"],
"subject": "Policy Indexed: {{policy_name}}",
"body": "The policy document has been indexed and is now searchable."
}
}
}
]
}F4-B: Employee Q&A
{
"nodes": [
{
"id": "1",
"type": "rag_query_task",
"data": {
"label": "Query Knowledge Base",
"config": {
"body": {
"query": "{{question}}",
"user_id": "{{user_id}}",
"top_k": 5
}
}
}
},
{
"id": "2",
"type": "email_send_task",
"data": {
"label": "Send Answer",
"config": {
"to": ["{{employee_email}}"],
"subject": "Answer to your question",
"body": "<p>{{answer}}</p><h3>Sources</h3>{{sources}}"
}
}
}
]
}Template Variables
All task types support {{variable}} template syntax for dynamic values.
Sources of Variables
- Webhook Payload: Data sent to trigger endpoint
- Previous Node Outputs: Results from upstream nodes
- Workflow Context:
user_id,execution_id, etc.
Example Flow
Webhook payload: { "candidate_name": "John", "role_id": "engineer" }
↓
Node 1 (rest_api_task): Uses {{role_id}} → outputs { "jd_file_id": "ABC123" }
↓
Node 2 (google_drive_fetch_task): Uses {{jd_file_id}} → outputs { "file_url": "gs://..." }
↓
Node 3 (email_send_task): Uses {{candidate_name}}, {{file_url}}Error Handling
Task Failure
When a task fails, the workflow execution status becomes failed:
{
"status": "failed",
"error": "REST API call failed: 404 Not Found",
"failed_node": "fetch-role-config",
"task_states": {
"fetch-role-config": {
"status": "failed",
"error": "404 Not Found"
}
}
}Timeout Handling
The wait_task returns failure status on timeout:
{
"status": "failure",
"final_value": "processing",
"elapsed_seconds": 120,
"error": "Timeout waiting for completion"
}Control Flow Tasks
decision
NEW in v1.1 - Conditional branching based on runtime evaluation.
Evaluates a condition and directs workflow execution down one of two paths (true or false). Enables dynamic workflow behavior based on previous task outputs.
Processor: decision (alias: decision_task)
Use Cases:
- Route documents based on classification results
- Handle different document types with separate processing paths
- Conditional approval workflows
- Dynamic email routing based on content analysis
- Skip processing steps based on validation results
Configuration
{
"task_type": "decision",
"config": {
"operator": "==",
"left_operand": "$.classification.type",
"right_operand": "Invoice",
"true_label": "true",
"false_label": "false"
}
}Config Options:
| Field | Type | Required | Description |
|---|---|---|---|
operator | string | Yes | Comparison operator: ==, !=, >, <, >=, <=, in, contains, matches |
left_operand | string | Yes | JSONPath expression (e.g., $.classification.type) or literal value |
right_operand | string/number/boolean | Yes | Value to compare against (can be literal or JSONPath) |
true_label | string | No | Label for true path (default: "true") |
false_label | string | No | Label for false path (default: "false") |
Supported Operators:
| Operator | Description | Example |
|---|---|---|
== | Equals | $.type == "Invoice" |
!= | Not equals | $.status != "processed" |
> | Greater than | $.amount > 1000 |
< | Less than | $.confidence < 0.8 |
>= | Greater or equal | $.score >= 90 |
<= | Less or equal | $.priority <= 5 |
in | Left in right (array/string) | "pdf" in $.allowed_types |
contains | Right in left (array/string) | $.tags contains "urgent" |
matches | Regex match | $.email matches ".*@company.com" |
JSONPath Support
Use JSONPath expressions to reference outputs from previous tasks:
$.task_name.field_nameExamples:
$.classification.type- Access classification result$.extraction.invoice_amount- Access extracted field$.email.to- Access email configuration- Literal values:
"Invoice",1000,true
Output
{
"result": true,
"branch": "true",
"decision": "true",
"active_path": "true",
"condition": {
"operator": "==",
"left_operand": "$.classification.type",
"right_operand": "Invoice",
"left_value": "Invoice",
"right_value": "Invoice"
}
}Output Fields:
| Field | Type | Description |
|---|---|---|
result | boolean | Condition evaluation result |
branch | string | Selected branch label |
decision | string | "true" or "false" |
active_path | string | Path taken by execution |
condition | object | Details about evaluated condition |
Edge Configuration
Decision nodes MUST have exactly 2 outgoing edges:
- True Edge: Label =
"true"(or customtrue_label) - False Edge: Label =
"false"(or customfalse_label)
Frontend: When connecting edges from a decision node:
- Click the edge to select it
- Set the edge
labelproperty to"true"or"false" - The workflow executor uses this label to activate/deactivate paths
Example: Document Type Routing
{
"nodes": [
{
"id": "classify",
"type": "classification_task",
"data": {
"label": "Classify Document",
"task_type": "classification_task",
"config": {
"category": "document_type"
}
}
},
{
"id": "decision",
"type": "decision",
"data": {
"label": "Is Invoice?",
"task_type": "decision",
"config": {
"operator": "==",
"left_operand": "$.classify.type",
"right_operand": "Invoice"
}
}
},
{
"id": "process-invoice",
"type": "extraction_task",
"data": {
"label": "Extract Invoice Data",
"task_type": "extraction_task",
"config": {
"prompt_id": 42
}
}
},
{
"id": "process-other",
"type": "summarization_task",
"data": {
"label": "Summarize Document",
"task_type": "summarization_task",
"config": {
"type": "brief"
}
}
}
],
"edges": [
{ "source": "classify", "target": "decision" },
{
"source": "decision",
"target": "process-invoice",
"sourceHandle": "true",
"label": "true"
},
{
"source": "decision",
"target": "process-other",
"sourceHandle": "false",
"label": "false"
}
]
}Workflow Execution Behavior
- Decision node executes - Evaluates condition
- Edge activation - Marks one edge as active based on result
- Path execution - Only nodes on active path execute
- Skipped nodes - Nodes on inactive path get
status: "skipped" - Convergence - Paths can merge back together downstream
Important: The workflow remains a DAG (Directed Acyclic Graph). Decision nodes create diverging paths, not loops.
Advanced Examples
Numeric Comparison:
{
"operator": ">",
"left_operand": "$.extraction.invoice_amount",
"right_operand": "10000"
}Array Contains:
{
"operator": "contains",
"left_operand": "$.classification.tags",
"right_operand": "urgent"
}Regex Match:
{
"operator": "matches",
"left_operand": "$.extraction.email",
"right_operand": ".*@approved-domain\\.com$"
}Nested Field Access:
{
"operator": "==",
"left_operand": "$.rest_api.response.data.status",
"right_operand": "approved"
}Validation Rules
Backend validation (workflow-validation.js) enforces:
- Decision nodes must have exactly 2 outgoing edges
- Both edges must have labels
- One edge must be labeled "true", one "false"
- Config must include:
operator,left_operand,right_operand
Validation errors will prevent workflow execution.
Frontend Component
- Node Type: Diamond-shaped with orange gradient
- Handles:
- Top: Target (incoming)
- Left: Source (true path, green)
- Right: Source (false path, red)
- Config Panel: Dropdown operators, JSONPath hints, condition preview
Limitations (Phase 1)
- ⚠️ No loops: Workflow must remain acyclic (no cycles allowed)
- ⚠️ Binary branches: Only true/false (multi-way branching not supported)
- ⚠️ Simple conditions: No AND/OR/NOT logic (single comparison only)
Workaround for complex conditions: Chain multiple decision nodes
See Also
- Webhook Integration Guide - Trigger workflows externally
- PLAN_2024_11_24.md - Implementation details