Skip to main content

Overview

Workflows enable you to automate treasury operations, reducing manual work and ensuring consistent execution of your treasury strategy. This guide will show you how to set up and manage automated workflows.

What are Workflows?

A workflow is an automation that executes transactions based on triggers you define. Each workflow:
  • Operates on a specific account
  • Contains one or more triggers
  • Creates transactions automatically when triggered
  • Can be paused or activated as needed

Workflow Components

1. Workflows

The top-level automation container:
{
  "id": "wf_123",
  "name": "Daily USDC Deposit",
  "description": "Automatically deposit idle USDC to Sky Protocol",
  "accountId": "acc_789",
  "status": "active"
}

2. Triggers

Conditions that cause a workflow to execute:

Schedule

Time-based execution (cron schedule)

Balance Above

When account balance exceeds threshold

Balance Below

When account balance falls below threshold

Manual

Execute on-demand via API or UI

3. Transaction Config

What happens when the trigger fires:
  • Type: deposit, withdraw, or transfer
  • Amount: How much to transact
  • Token: usdc, usdt, or usds
  • Strategy: Which DeFi protocol to use (for deposits/withdrawals)

Creating Your First Workflow

Step 1: Create the Workflow

const response = await fetch('/api/workflows', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  credentials: 'include',
  body: JSON.stringify({
    accountId: 'acc_789',
    name: 'Daily Yield Deposit',
    description: 'Deposit idle USDC to Sky Protocol every day at 9am',
    status: 'active'
  })
});

const { workflow } = await response.json();

Step 2: Add a Trigger

const response = await fetch('/api/triggers', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  credentials: 'include',
  body: JSON.stringify({
    workflowId: workflow.id,
    name: 'Daily at 9am',
    type: 'schedule',
    config: JSON.stringify({
      cron: '0 9 * * *'  // Every day at 9:00 AM
    }),
    transactionType: 'deposit',
    transactionConfig: JSON.stringify({
      amount: '1000',
      token: 'usdc',
      strategyId: 'sky-protocol'
    }),
    status: 'active'
  })
});

const { trigger } = await response.json();

Common Workflow Patterns

Pattern 1: Scheduled Deposits

Automatically deposit idle funds to earn yield:
1

Create Workflow

Link to your treasury account
2

Add Schedule Trigger

Set daily/weekly execution time
3

Configure Deposit

Define amount and target strategy
4

Monitor

Review created transactions
Example Cron Schedules:
  • 0 9 * * * - Every day at 9 AM
  • 0 9 * * 1 - Every Monday at 9 AM
  • 0 0 1 * * - First day of every month at midnight

Pattern 2: Balance-Based Sweeps

Automatically sweep excess funds to your treasury:
// Create workflow
const workflow = await createWorkflow({
  accountId: 'operational_wallet',
  name: 'Excess Fund Sweep',
  description: 'Move excess funds to main treasury'
});

// Add balance trigger
const trigger = await createTrigger({
  workflowId: workflow.id,
  name: 'When balance > $10k',
  type: 'balance_above',
  config: JSON.stringify({
    threshold: '10000'  // $10,000 USDC
  }),
  transactionType: 'transfer',
  transactionConfig: JSON.stringify({
    amount: 'excess',  // Transfer amount above threshold
    token: 'usdc',
    toAccountId: 'main_treasury'
  })
});

Pattern 3: Strategic Withdrawals

Withdraw funds when yield drops or you need liquidity:
const trigger = await createTrigger({
  workflowId: workflow.id,
  name: 'Low Balance Alert',
  type: 'balance_below',
  config: JSON.stringify({
    threshold: '5000'  // $5,000 USDC
  }),
  transactionType: 'withdraw',
  transactionConfig: JSON.stringify({
    amount: '10000',
    token: 'usdc',
    strategyId: 'sky-protocol'
  })
});

Pattern 4: Manual Execution

Create workflows that you trigger manually when needed:
// Create manual trigger
const trigger = await createTrigger({
  workflowId: workflow.id,
  name: 'Manual Emergency Withdrawal',
  type: 'manual',
  config: JSON.stringify({}),  // Empty config for manual triggers
  transactionType: 'withdraw',
  transactionConfig: JSON.stringify({
    amount: 'all',  // Withdraw everything
    token: 'usdc',
    strategyId: 'sky-protocol'
  })
});

// Execute when needed
const response = await fetch(`/api/workflows/${workflow.id}/run`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  credentials: 'include',
  body: JSON.stringify({
    triggerId: trigger.id
  })
});

Managing Workflows

Pause a Workflow

Temporarily stop a workflow from executing:
await fetch(`/api/workflows/${workflowId}`, {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/json' },
  credentials: 'include',
  body: JSON.stringify({ status: 'paused' })
});

Update a Trigger

Modify trigger conditions:
await fetch(`/api/triggers/${triggerId}`, {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/json' },
  credentials: 'include',
  body: JSON.stringify({
    config: JSON.stringify({
      cron: '0 12 * * *'  // Change to noon instead of 9am
    })
  })
});

Delete a Workflow

Remove a workflow and all its triggers:
await fetch(`/api/workflows/${workflowId}`, {
  method: 'DELETE',
  credentials: 'include'
});

Transaction Approval Flow

When a workflow creates a transaction, it follows the standard approval flow:
1

Trigger Fires

Workflow trigger condition is met
2

Transaction Created

Transaction created with status pending_approval
3

Team Reviews

Authorized users review the transaction
4

Approval

User approves: POST /api/transactions/{id}/approve
5

Execution

Execute on-chain: POST /api/transactions/{id}/execute
Workflow-generated transactions still require manual approval before execution, ensuring you always have control.

Best Practices

Test workflows with small amounts before deploying to production with large values.
Clear names help your team understand what each workflow does at a glance.
Review workflow-generated transactions to ensure they’re working as expected.
Configure notifications for workflow-generated transactions that need approval.
Use the description field to explain why each workflow exists and what it accomplishes.
Keep workflows focused on a single account for clearer tracking and management.

Advanced: Complex Workflows

Multi-Trigger Workflow

A single workflow can have multiple triggers:
// Create workflow once
const workflow = await createWorkflow({
  accountId: 'acc_789',
  name: 'Smart Treasury Management'
});

// Add multiple triggers
await createTrigger({
  workflowId: workflow.id,
  name: 'Daily Deposit',
  type: 'schedule',
  config: JSON.stringify({ cron: '0 9 * * *' }),
  transactionType: 'deposit',
  transactionConfig: JSON.stringify({ amount: '1000', token: 'usdc' })
});

await createTrigger({
  workflowId: workflow.id,
  name: 'Emergency Withdrawal',
  type: 'balance_below',
  config: JSON.stringify({ threshold: '1000' }),
  transactionType: 'withdraw',
  transactionConfig: JSON.stringify({ amount: '5000', token: 'usdc' })
});

await createTrigger({
  workflowId: workflow.id,
  name: 'Manual Override',
  type: 'manual',
  config: JSON.stringify({}),
  transactionType: 'transfer',
  transactionConfig: JSON.stringify({ amount: 'all', token: 'usdc' })
});

Troubleshooting

Check:
  • Workflow status is active
  • Trigger status is active
  • Trigger conditions are being met
  • Account has sufficient balance
Solution:
  • Review and approve pending transactions
  • Check if approval permissions are correctly set
  • Verify no team members are blocking approvals
Fix:
  • Update trigger’s transactionConfig
  • Ensure amount format is correct (string, not number)
  • Check if using excess or all keywords correctly

Next Steps