FlexTime-AI / openenv.yaml
HNS8273's picture
initial commit
510ab6f
Raw
History Blame Contribute Delete
5.41 kB
name: FlexTime
version: "1.0.0"
description: >
FlexTime is a real-world AI workforce scheduling environment where agents
learn to optimally assign employees to shifts while satisfying hard constraints
(skill matching, availability, max hours) and soft constraints (fairness,
preferences). Modeled after the genuine scheduling problem faced by operations
managers in retail, healthcare, and logistics every day.
author: FlexTime Team
license: MIT
tags:
- openenv
- scheduling
- workforce
- operations
- real-world
- optimization
entrypoint: "uvicorn app.main:app --host 0.0.0.0 --port 7860"
observation_space:
type: object
description: >
Current scheduling state: employees, shifts, assignments,
unmet demand, constraint violations, and computed metrics.
fields:
week_id: {type: string, description: "Episode identifier"}
task_id: {type: string, description: "Active task id"}
employees: {type: array, description: "Roster with skills, availability, hours"}
shifts: {type: array, description: "Shifts needing coverage"}
assignments: {type: array, description: "Active employee→shift assignments"}
unassigned_shifts: {type: array, description: "Shift IDs with no assignment yet"}
conflicts: {type: array, description: "Active constraint violations"}
metrics: {type: object, description: "Coverage, fairness, violations, demand"}
done: {type: boolean, description: "True when episode is complete"}
step_count: {type: integer, description: "Steps taken so far"}
max_steps: {type: integer, description: "Episode step limit"}
action_space:
type: object
description: >
A scheduling operation: assign one employee to one shift,
remove an assignment, swap two employees, or take no action.
fields:
action_type:
type: string
enum: [assign, remove, swap, noop]
description: "Operation to perform (required)"
employee_id:
type: string
description: "Employee ID — required for assign, remove, swap"
shift_id:
type: string
description: "Shift ID — required for assign, remove"
target_employee_id:
type: string
description: "Second employee ID — required for swap"
reward:
type: dense_shaped
range: [-1.0, 1.0]
description: >
Shaped reward at every step. Rewards partial progress.
Penalizes constraint violations and invalid actions.
components:
shift_covered: {value: "+0.15 × Δcoverage", description: "New shift filled"}
demand_signal: {value: "+0.05 × Δdemand", description: "Demand-weighted coverage gain"}
constraint_violated: {value: "-0.20 per violation", description: "New hard constraint broken"}
constraint_resolved: {value: "+0.10 per fix", description: "Hard violation removed"}
fairness: {value: "±0.03 × Δfairness", description: "Hour fairness change"}
conflict_resolved: {value: "+0.10 bonus", description: "Pre-seeded conflict cleared"}
invalid_action: {value: "-0.05", description: "Non-existent IDs etc."}
noop: {value: "0.0", description: "No-operation"}
tasks:
- id: task_easy
name: "Basic Shift Coverage"
difficulty: easy
description: >
Assign employees to all 5 open morning shifts for a single day.
All employees are available and skills match every shift.
Agent must fill all slots without creating overlaps.
max_steps: 20
target_score: 1.0
n_employees: 5
n_shifts: 5
- id: task_medium
name: "Weekly Schedule with Constraints"
difficulty: medium
description: >
Build a complete weekly schedule for 8 employees across 30 shifts.
Must respect skill requirements, availability windows, and the 40-hour
weekly maximum. Soft fairness constraint: max-min hours delta ≤ 4h.
Partial coverage scored proportionally.
max_steps: 60
target_score: 0.85
n_employees: 8
n_shifts: 30
- id: task_hard
name: "Fair Optimization Under Pressure"
difficulty: hard
description: >
12 employees, 50 shifts, 3 pre-seeded conflicts to resolve.
All sub-scores (coverage, fairness, constraint satisfaction, demand)
must simultaneously exceed 0.75 — missing any threshold triggers penalty.
Requires coordinated optimization across all constraint layers.
max_steps: 120
target_score: 0.75
n_employees: 12
n_shifts: 50
endpoints:
reset: {method: POST, path: /reset, description: "Initialize episode, returns Observation"}
step: {method: POST, path: /step, description: "Apply action, returns StepResult"}
state: {method: GET, path: /state, description: "Current Observation without state change"}
tasks: {method: GET, path: /tasks, description: "Task list + action schema"}
grader: {method: GET, path: /grader, description: "Episode score 0.0–1.0"}
baseline: {method: POST, path: /baseline, description: "Run baseline agent on all 3 tasks"}
health: {method: GET, path: /health, description: "Health check — returns 200"}
baseline:
agent: GreedyBaseline
seed: 42
scores:
task_easy: 0.95
task_medium: 0.72
task_hard: 0.48
mean: 0.72