Workflows

Build visual AI workflows with drag-and-drop nodes, agent orchestration, conditional logic, and automated triggers.

Overview

Workflows enable you to create complex AI automation pipelines using a visual node-based editor. Features include:

  • Visual workflow builder with React Flow
  • Multiple trigger types (manual, webhook, cron, event)
  • Agent nodes for AI processing
  • Conditional branching and loops
  • Data transformation nodes
  • Integration with all Tenzro services

Quick Start

import { Tenzro } from '@tenzro/cloud';
const client = new Tenzro({ apiKey: 'your-api-key' });
// Create a simple workflow
const workflow = await client.workflows.create({
projectId: 'project-id',
workflowName: 'content-pipeline',
triggerType: 'webhook',
nodes: [
{
id: 'input',
type: 'trigger',
position: { x: 100, y: 100 },
data: { label: 'Webhook Trigger' },
},
{
id: 'agent',
type: 'agent',
position: { x: 300, y: 100 },
data: {
label: 'Content Agent',
agentId: 'your-agent-id',
},
},
{
id: 'output',
type: 'output',
position: { x: 500, y: 100 },
data: { label: 'Output' },
},
],
edges: [
{ id: 'e1', source: 'input', target: 'agent' },
{ id: 'e2', source: 'agent', target: 'output' },
],
});
// Publish the workflow
await client.workflows.publish(workflow.workflow_id);
// Execute manually
const execution = await client.workflows.execute(workflow.workflow_id, {
inputData: { topic: 'AI trends' },
});
console.log(execution.status); // 'COMPLETED'
console.log(execution.output_data); // Generated content

Node Types

Trigger Nodes

TypeDescription
manualManually triggered via API or console
webhookTriggered by HTTP POST to webhook URL
cronScheduled execution on cron schedule
eventTriggered by system events

Processing Nodes

NodeDescription
agentExecute an AI agent with input data
inferenceDirect LLM inference without agent
embedGenerate embeddings from text
transformTransform data with JavaScript
conditionalBranch based on conditions
loopIterate over arrays

Data Nodes

NodeDescription
vec-searchSearch vector database
vec-insertInsert into vector database
data-queryExecute SQL query
kev-getGet from key-value store
kev-setSet in key-value store
httpMake HTTP request

SDK Reference

Create Workflow

const workflow = await client.workflows.create({
projectId: string,
workflowName: string,
workflowDescription?: string,
nodes?: WorkflowNode[],
edges?: WorkflowEdge[],
viewport?: { x: number, y: number, zoom: number },
variables?: Record<string, any>,
triggerType?: 'manual' | 'webhook' | 'cron' | 'event',
triggerConfig?: Record<string, any>,
});

Lifecycle Management

// Publish workflow (makes it executable)
await client.workflows.publish(workflowId);
// Pause workflow (disable triggers)
await client.workflows.pause(workflowId);
// Update workflow nodes/edges
await client.workflows.update(workflowId, {
nodes: updatedNodes,
edges: updatedEdges,
});
// Delete workflow
await client.workflows.delete(workflowId);

Execution

// Execute workflow
const execution = await client.workflows.execute(workflowId, {
inputData?: Record<string, any>,
triggerType?: TriggerType,
triggerData?: Record<string, any>,
});
// Trigger via webhook-style endpoint
const result = await client.workflows.trigger(workflowId, data);
// Get execution details
const execution = await client.workflows.getExecution(workflowId, executionId);
// Get node-level execution details
const { nodeExecutions } = await client.workflows.getNodeExecutions(
workflowId,
executionId
);
// Cancel running execution
await client.workflows.cancelExecution(workflowId, executionId);

Templates

// Get available templates
const { data: templates } = await client.workflows.getTemplates('automation');
// Create workflow from template
const workflow = await client.workflows.createFromTemplate({
templateId: 'content-pipeline',
projectId: 'project-id',
workflowName: 'My Content Pipeline',
});

Statistics

const { stats } = await client.workflows.getStats(workflowId);
// Stats include:
interface WorkflowStats {
totalExecutions: number;
successfulExecutions: number;
failedExecutions: number;
successRate: string;
avgExecutionTimeMs: number;
totalCostMicrodollars: number;
totalCostDollars: string;
lastExecutedAt?: string;
nodeCount: number;
edgeCount: number;
}

Building Workflows

RAG Pipeline

const workflow = await client.workflows.create({
projectId: 'project-id',
workflowName: 'rag-pipeline',
triggerType: 'webhook',
nodes: [
{
id: 'trigger',
type: 'trigger',
position: { x: 100, y: 200 },
data: { label: 'User Query' },
},
{
id: 'embed',
type: 'embed',
position: { x: 300, y: 200 },
data: {
taskType: 'RETRIEVAL_QUERY',
dimensionality: 768,
},
},
{
id: 'search',
type: 'vec-search',
position: { x: 500, y: 200 },
data: {
vecDbId: 'your-vec-db-id',
topK: 5,
},
},
{
id: 'agent',
type: 'agent',
position: { x: 700, y: 200 },
data: {
agentId: 'your-agent-id',
inputMapping: {
query: '{{trigger.query}}',
context: '{{search.results}}',
},
},
},
{
id: 'output',
type: 'output',
position: { x: 900, y: 200 },
data: {},
},
],
edges: [
{ id: 'e1', source: 'trigger', target: 'embed' },
{ id: 'e2', source: 'embed', target: 'search' },
{ id: 'e3', source: 'search', target: 'agent' },
{ id: 'e4', source: 'agent', target: 'output' },
],
});

Conditional Branching

const nodes = [
{
id: 'classify',
type: 'agent',
position: { x: 300, y: 200 },
data: {
agentId: 'classifier-agent',
prompt: 'Classify this message as: support, sales, or other',
},
},
{
id: 'condition',
type: 'conditional',
position: { x: 500, y: 200 },
data: {
conditions: [
{ path: 'support', condition: "{{classify.result}} === 'support'" },
{ path: 'sales', condition: "{{classify.result}} === 'sales'" },
{ path: 'default', condition: 'true' },
],
},
},
{
id: 'support-agent',
type: 'agent',
position: { x: 700, y: 100 },
data: { agentId: 'support-agent' },
},
{
id: 'sales-agent',
type: 'agent',
position: { x: 700, y: 200 },
data: { agentId: 'sales-agent' },
},
{
id: 'general-agent',
type: 'agent',
position: { x: 700, y: 300 },
data: { agentId: 'general-agent' },
},
];
const edges = [
{ id: 'e1', source: 'trigger', target: 'classify' },
{ id: 'e2', source: 'classify', target: 'condition' },
{ id: 'e3', source: 'condition', target: 'support-agent', sourceHandle: 'support' },
{ id: 'e4', source: 'condition', target: 'sales-agent', sourceHandle: 'sales' },
{ id: 'e5', source: 'condition', target: 'general-agent', sourceHandle: 'default' },
];

Scheduled Workflow

const workflow = await client.workflows.create({
projectId: 'project-id',
workflowName: 'daily-report',
triggerType: 'cron',
triggerConfig: {
schedule: '0 9 * * *', // Every day at 9 AM UTC
timezone: 'America/New_York',
},
nodes: [
{
id: 'query',
type: 'data-query',
position: { x: 200, y: 200 },
data: {
dataDbId: 'analytics-db',
sql: `
SELECT date, SUM(revenue) as total
FROM orders
WHERE date = CURRENT_DATE - 1
GROUP BY date
`,
},
},
{
id: 'summarize',
type: 'agent',
position: { x: 400, y: 200 },
data: {
agentId: 'report-agent',
prompt: 'Generate a daily sales summary from this data: {{query.results}}',
},
},
{
id: 'email',
type: 'http',
position: { x: 600, y: 200 },
data: {
method: 'POST',
url: 'https://api.sendgrid.com/v3/mail/send',
headers: { Authorization: 'Bearer {{env.SENDGRID_KEY}}' },
body: {
to: 'team@company.com',
subject: 'Daily Sales Report',
content: '{{summarize.result}}',
},
},
},
],
});

Variables and Data Flow

Reference data between nodes using template syntax:

// Access trigger data
'{{trigger.field}}'
// Access previous node output
'{{nodeId.result}}'
'{{nodeId.data.field}}'
// Access workflow variables
'{{variables.apiKey}}'
// Access environment variables
'{{env.SECRET_KEY}}'
// Array access
'{{nodeId.results[0].text}}'
// Conditional expressions
'{{trigger.type === "urgent" ? "high" : "normal"}}'

Best Practices

  • Test in draft: Use manual execution to test before publishing
  • Use variables: Store configuration in workflow variables, not hardcoded
  • Handle errors: Add error handling nodes for critical paths
  • Monitor executions: Review failed executions and optimize
  • Version control: Workflows are versioned; track changes

Limits

ResourceLimit
Max nodes per workflow100
Max edges per workflow200
Execution timeout30 minutes
Max concurrent executions10
Cron minimum interval5 minutes