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
← HR & OperationsFormView on GitHub

Job Application Screener

AI evaluates job applications for fit, routes top candidates to human review, and sends rejections.

aiswitchemail

Source

/**
 * Screens job applications. AI evaluates fit, human reviews top candidates.
 */

form job_application {
  label: "Job Application"
  visibility: public
  schema: @json {
    {
      "type": "object",
      "required": ["name", "email", "role", "resume_text"],
      "properties": {
        "name": { "type": "string", "title": "Full Name" },
        "email": { "type": "string", "format": "email", "title": "Email" },
        "role": { "type": "string", "title": "Role Applied For" },
        "resume_text": { "type": "string", "title": "Resume (paste text)" },
        "linkedin_url": { "type": "string", "title": "LinkedIn URL" }
      }
    }
  }
}

workflow screen_application {
  label: "Screen Application"

  root {
    type: code
    label: "Extract application"
    code: @ts { return context.nodes.root.input }
    outputSchema: @json {
      {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "email": { "type": "string" },
          "role": { "type": "string" },
          "resume_text": { "type": "string" },
          "linkedin_url": { "type": "string" }
        }
      }
    }
  }

  node evaluate {
    type: ai
    label: "Evaluate candidate"
    kind: object
    model: "google/gemini-2.5-flash"
    prompt: @ts {
      const app = context.nodes.root.output
      return "Evaluate this candidate for the " + app.role + " role. Score their fit.\n\nName: " + app.name + "\n\nResume:\n" + app.resume_text
    }
    schema: @json {
      {
        "type": "object",
        "required": ["score", "strengths", "concerns", "recommendation"],
        "properties": {
          "score": { "type": "number", "minimum": 0, "maximum": 100 },
          "strengths": { "type": "array", "items": { "type": "string" } },
          "concerns": { "type": "array", "items": { "type": "string" } },
          "recommendation": { "type": "string", "enum": ["advance", "maybe", "pass"] }
        }
      }
    }
  }

  node route {
    type: switch
    label: "Route by recommendation"
    cases: ["advance", "maybe", "pass"]
    router: @ts {
      return context.nodes.evaluate.output.recommendation
    }
  }

  node prepare_review {
    type: code
    label: "Human review"
    code: @ts { return {} }
    review: {
      enabled: true
      title: "Review candidate"
      description: "Decide whether to advance this candidate to interview. See the evaluate node output for the AI screening summary. Submit your decision; rejected candidates are notified automatically."
      schema: @json {
        {
          "type": "object",
          "required": ["decision"],
          "properties": {
            "decision": { "type": "string", "enum": ["interview", "reject"], "title": "Decision" },
            "notes": { "type": "string", "title": "Notes" }
          }
        }
      }
      actions: [
        { id: "submit", label: "Submit Decision", outcome: "approve" }
      ]
    }
  }

  node review_decision {
    type: switch
    label: "Route on review decision"
    cases: ["interview", "reject"]
    router: @ts {
      const review = context.reviews.prepare_review || {}
      return review.decision === "interview" ? "interview" : "reject"
    }
  }

  node schedule_interview {
    type: code
    label: "Schedule interview"
    code: @ts {
      const review = context.reviews.prepare_review || {}
      return {
        status: "interview",
        name: context.nodes.root.output.name,
        email: context.nodes.root.output.email,
        role: context.nodes.root.output.role,
        score: context.nodes.evaluate.output.score,
        reviewer_notes: review.notes || ""
      }
    }
  }

  node review_rejection {
    type: email
    label: "Send rejection after review"
    from: @ts { return "[email protected]" }
    to: @ts { return context.nodes.root.output.email }
    subject: @ts { return "Update on your application for " + context.nodes.root.output.role }
    text: @ts {
      return "Hi " + context.nodes.root.output.name + ",\n\nThank you for applying. After careful review, we have decided to move forward with other candidates. We appreciate your interest and wish you the best."
    }
  }

  node send_rejection {
    type: email
    label: "Send rejection"
    from: @ts { return "[email protected]" }
    to: @ts { return context.nodes.root.output.email }
    subject: @ts { return "Update on your application for " + context.nodes.root.output.role }
    text: @ts {
      return "Hi " + context.nodes.root.output.name + ",\n\nThank you for applying. After careful review, we have decided to move forward with other candidates. We appreciate your interest and wish you the best."
    }
  }

  node maybe_pool {
    type: code
    label: "Add to maybe pool"
    code: @ts {
      return {
        status: "maybe_pool",
        name: context.nodes.root.output.name,
        email: context.nodes.root.output.email,
        role: context.nodes.root.output.role,
        score: context.nodes.evaluate.output.score
      }
    }
  }

  flow {
    root -> evaluate
    evaluate -> route
    route -["advance"]-> prepare_review
    route -["pass"]-> send_rejection
    route -["maybe"]-> maybe_pool
    prepare_review -> review_decision
    review_decision -["interview"]-> schedule_interview
    review_decision -["reject"]-> review_rejection
  }
}

trigger on_application {
  form:job_application -> screen_application
  enabled: true
}

Flow

Trigger to workflow

job_applicationform
screen_application
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 application
AI
AI Node
Evaluate candidate
SWITCH
Switch Node
Route by recommendation
CODE
Code Node
Human review
SWITCH
Switch Node
Route on review decision
CODE
Code Node
Schedule interview
EMAIL
Email Node
Send rejection after review
EMAIL
Email Node
Send rejection
CODE
Code Node
Add to maybe pool
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.