Solve

Solve

Certified

Submit an optimization problem to the Timefold Platform

yaml
type: io.kestra.plugin.timefold.Solve
yaml
id: timefold_route
namespace: company.team

tasks:
  - id: solve
    type: io.kestra.plugin.timefold.Solve
    apiKey: "{{ secret('TIMEFOLD_API_KEY') }}"
    model: FIELD_SERVICE_ROUTING
    solveDuration: PT30S
    modelInput:
      vehicles:
        - id: Ann
          shifts:
            - id: Ann-2027-02-01
              startLocation: [33.68786, -84.18487]
              minStartTime: "2027-02-01T09:00:00Z"
      visits:
        - id: Visit A
          location: [33.77301, -84.43838]
          serviceDuration: PT1H30M
  - id: log_job_id
    type: io.kestra.plugin.core.log.Log
    message: "Submitted job: {{ outputs.solve.jobId }}"

yaml
id: timefold_schedule
namespace: company.team

# employees.csv  (name becomes the employee id):
#   name,skills
#   Alice,nursing|doctor
#   Bob,nursing
#
# shifts.csv  (required_skill becomes a requiredSkills object array):
#   id,start,end,required_skill
#   SHIFT-001,2027-02-01T08:00:00Z,2027-02-01T16:00:00Z,nursing
#   SHIFT-002,2027-02-01T16:00:00Z,2027-02-02T00:00:00Z,nursing

inputs:
  - id: employees_csv
    type: FILE
  - id: shifts_csv
    type: FILE

tasks:
  - id: build_dataset
    type: io.kestra.plugin.scripts.python.Script
    inputFiles:
      employees.csv: "{{ inputs.employees_csv }}"
      shifts.csv: "{{ inputs.shifts_csv }}"
    script: |
      import csv
      from kestra import Kestra

      employees = []
      with open("employees.csv") as f:
          for row in csv.DictReader(f):
              employees.append({
                  "id": row["name"],
                  "skills": [{"id": s} for s in row["skills"].split("|")],
              })

      shifts = []
      with open("shifts.csv") as f:
          for row in csv.DictReader(f):
              shifts.append({
                  "id": row["id"],
                  "start": row["start"],
                  "end": row["end"],
                  "requiredSkills": [row["required_skill"]],
              })

      Kestra.outputs({"modelInput": {"employees": employees, "shifts": shifts}})

  - id: solve
    type: io.kestra.plugin.timefold.Solve
    apiKey: "{{ secret('TIMEFOLD_API_KEY') }}"
    model: EMPLOYEE_SCHEDULING
    solveDuration: PT1M
    modelInput: "{{ outputs.build_dataset.vars.modelInput }}"

yaml
id: timefold_route_wait
namespace: company.team

tasks:
  - id: solve
    type: io.kestra.plugin.timefold.Solve
    apiKey: "{{ secret('TIMEFOLD_API_KEY') }}"
    model: FIELD_SERVICE_ROUTING
    solveDuration: PT30S
    wait: true
    modelInput:
      vehicles:
        - id: Ann
          shifts:
            - id: Ann-2027-02-01
              startLocation: [33.68786, -84.18487]
              minStartTime: "2027-02-01T09:00:00Z"
      visits:
        - id: Visit A
          location: [33.77301, -84.43838]
          serviceDuration: PT1H30M
  - id: log_result
    type: io.kestra.plugin.core.log.Log
    message: "Solved {{ outputs.solve.jobId }} — status: {{ outputs.solve.solverStatus }}, score: {{ outputs.solve.score }}"
Properties
Possible Values
FIELD_SERVICE_ROUTINGEMPLOYEE_SCHEDULINGPICKUP_DELIVERY_ROUTING
Defaulthttps://app.timefold.ai
DefaultSTORE
Possible Values
STOREFETCHFETCH_ONENONE
DefaultPT2S
DefaultPT10M
Defaultfalse
Formaturi