Swirls

SWIRLS_

  • How it works
  • Pricing

56 matches

OverviewDeliver client operations10Win and grow accounts8Resolve customer issues6Create and distribute content9Run people and operations5Review money and agreements3Monitor systems and data9Compose dependable work6

56 matches

OverviewDeliver client operations10Win and grow accounts8Resolve customer issues6Create and distribute content9Run people and operations5Review money and agreements3Monitor systems and data9Compose dependable work6
← Finance & LegalFormView on GitHub

Document Approval Workflow

Multi-stage document approval with human review gates and revision requests.

aiswitchemail

Source

/**
 * Multi-stage document approval workflow with human review gates.
 */

form document_submission {
  label: "Submit Document"
  schema: @json {
    {
      "type": "object",
      "required": ["title", "content", "author", "author_email", "doc_type"],
      "properties": {
        "title": { "type": "string", "title": "Document Title" },
        "content": { "type": "string", "title": "Document Content" },
        "author": { "type": "string", "title": "Author" },
        "author_email": { "type": "string", "format": "email", "title": "Author Email" },
        "doc_type": {
          "type": "string",
          "title": "Document Type",
          "enum": ["policy", "procedure", "contract", "proposal"]
        }
      }
    }
  }
}

workflow approve_document {
  label: "Document Approval"

  root {
    type: code
    label: "Extract document"
    code: @ts { return context.nodes.root.input }
    outputSchema: @json {
      {
        "type": "object",
        "properties": {
          "title": { "type": "string" },
          "content": { "type": "string" },
          "author": { "type": "string" },
          "author_email": { "type": "string" },
          "doc_type": {
            "type": "string",
            "enum": ["policy", "procedure", "contract", "proposal"]
          }
        }
      }
    }
  }

  node quality_check {
    type: ai
    label: "Quality check"
    kind: object
    model: "google/gemini-2.5-flash"
    prompt: @ts {
      const doc = context.nodes.root.output
      return "Review this " + doc.doc_type + " document for quality. Check grammar, clarity, completeness, and formatting.\n\nTitle: " + doc.title + "\n\n" + doc.content
    }
    schema: @json {
      {
        "type": "object",
        "required": ["quality_score", "issues"],
        "properties": {
          "quality_score": { "type": "number", "minimum": 0, "maximum": 100 },
          "issues": { "type": "array", "items": { "type": "string" } },
          "suggestions": { "type": "array", "items": { "type": "string" } }
        }
      }
    }
  }

  node manager_review {
    type: code
    label: "Manager review"
    code: @ts { return {} }
    review: {
      enabled: true
      title: "Manager Approval Required"
      description: "Review this document and approve or request revisions. See the quality_check node output for the AI quality report. Reject fails the run; Request Revisions emails the author."
      schema: @json {
        {
          "type": "object",
          "required": ["decision"],
          "properties": {
            "decision": { "type": "string", "enum": ["approve", "revise"], "title": "Decision" },
            "comments": { "type": "string", "title": "Comments" }
          }
        }
      }
      actions: [
        { id: "submit", label: "Submit Decision", outcome: "approve" },
        { id: "reject", label: "Reject", outcome: "reject" }
      ]
    }
  }

  node route_decision {
    type: switch
    label: "Route decision"
    cases: ["approved", "needs_work"]
    router: @ts {
      const review = context.reviews.manager_review
      if (review.decision === "approve") return "approved"
      return "needs_work"
    }
  }

  node publish {
    type: code
    label: "Mark as published"
    code: @ts {
      return {
        status: "published",
        title: context.nodes.root.output.title,
        author: context.nodes.root.output.author,
        published_at: new Date().toISOString()
      }
    }
  }

  node request_revisions {
    type: email
    label: "Request revisions"
    from: @ts { return "[email protected]" }
    to: @ts { return context.nodes.root.output.author_email }
    subject: @ts { return "Revisions requested: " + context.nodes.root.output.title }
    text: @ts {
      const review = context.reviews.manager_review
      return "Your document requires revisions.\n\nDecision: " + review.decision + "\nComments: " + (review.comments || "No additional comments.")
    }
  }

  flow {
    root -> quality_check
    quality_check -> manager_review
    manager_review -> route_decision
    route_decision -["approved"]-> publish
    route_decision -["needs_work"]-> request_revisions
  }
}

trigger on_doc_submit {
  form:document_submission -> approve_document
  enabled: true
}

Flow

Trigger to workflow

document_submissionform
approve_document
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

Workflow nodes

CODE
Code Node
Extract document
AI
AI Node
Quality check
CODE
Code Node
Manager review
SWITCH
Switch Node
Route decision
CODE
Code Node
Mark as published
EMAIL
Email Node
Request revisions
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.