name: labor-forecast
description: Generate labor forecast reports with crew assignments, gap analysis, and utilization tracking
user-invocable: true
metadata:
{ "openclaw": { "emoji": "👷", "category": "construction", "requires": { "bins": ["python3"], "pip": [] } } }
When to use
Use this skill when the user needs labor planning and forecasting for construction projects. Common scenarios:
- Weekly labor planning: allocate crews across active projects for the upcoming week
- Monthly forecasting: project labor needs 4-8 weeks out to identify hiring or subcontracting needs
- Gap analysis: identify periods where demand exceeds available workforce
- Utilization reporting: track crew utilization rates and identify under/over-allocation
- Multi-project coordination: balance labor across several concurrent projects
- Union hall dispatch planning: plan upcoming labor requests based on projected needs
Steps
Gather labor data from the user: project schedules, crew sizes, availability, and any known constraints (vacations, weather days, etc.).
Build a JSON config object with this structure:
{
"output_path": "/absolute/path/to/labor_forecast.md",
"forecast": {
"company": "TCG Construction",
"prepared_by": "Dave Richardson",
"report_date": "2026-02-07",
"period_start": "2026-02-10",
"period_end": "2026-03-07",
"view": "weekly"
},
"projects": [
{
"name": "Highway 94 Bridge",
"number": "PRJ-2026-0042",
"priority": 1,
"phase": "Foundation",
"weeks": [
{
"week_of": "2026-02-10",
"crews": [
{ "trade": "Iron Workers", "count": 12, "hours_per_day": 10 },
{ "trade": "Concrete Crew", "count": 8, "hours_per_day": 10 },
{ "trade": "Laborers", "count": 6, "hours_per_day": 8 }
]
},
{
"week_of": "2026-02-17",
"crews": [
{ "trade": "Iron Workers", "count": 14, "hours_per_day": 10 },
{ "trade": "Concrete Crew", "count": 10, "hours_per_day": 10 },
{ "trade": "Laborers", "count": 8, "hours_per_day": 8 }
]
}
]
},
{
"name": "TCG Warehouse Addition",
"number": "PRJ-2026-0051",
"priority": 2,
"phase": "Steel Erection",
"weeks": [
{
"week_of": "2026-02-10",
"crews": [
{ "trade": "Iron Workers", "count": 6, "hours_per_day": 8 },
{ "trade": "Equipment Operators", "count": 2, "hours_per_day": 8 }
]
},
{
"week_of": "2026-02-17",
"crews": [
{ "trade": "Iron Workers", "count": 8, "hours_per_day": 8 },
{ "trade": "Equipment Operators", "count": 3, "hours_per_day": 8 }
]
}
]
}
],
"available_workforce": [
{ "trade": "Iron Workers", "available": 20 },
{ "trade": "Concrete Crew", "available": 12 },
{ "trade": "Laborers", "available": 15 },
{ "trade": "Equipment Operators", "available": 6 },
{ "trade": "Electricians", "available": 8 }
],
"constraints": [
"Iron Workers Local 25 contract limits OT to 10 hrs/week without premium",
"Two laborers on PTO week of Feb 17"
]
}
- Write the JSON config to a temporary file:
cat > /tmp/labor_forecast_config.json << 'JSONEOF'
{ ... your config ... }
JSONEOF
- Run the generator script:
python3 {baseDir}/labor_forecast.py /tmp/labor_forecast_config.json
Report the output path printed by the script to the user.
Clean up the temporary JSON file.
JSON Config Reference
| Field |
Type |
Required |
Description |
output_path |
string |
no |
Absolute path for output markdown (defaults to /tmp/) |
forecast |
object |
yes |
Report metadata |
projects |
array |
yes |
Project labor requirements |
available_workforce |
array |
yes |
Available labor by trade |
constraints |
array |
no |
Known scheduling constraints |
Forecast Object
| Field |
Type |
Required |
Description |
company |
string |
no |
Company name |
prepared_by |
string |
no |
Report author |
report_date |
string |
yes |
Report generation date (YYYY-MM-DD) |
period_start |
string |
yes |
Forecast period start (YYYY-MM-DD) |
period_end |
string |
yes |
Forecast period end (YYYY-MM-DD) |
view |
string |
no |
One of: weekly, monthly (default: weekly) |
Project Object
| Field |
Type |
Required |
Description |
name |
string |
yes |
Project name |
number |
string |
no |
Project number |
priority |
number |
no |
Priority ranking (1 = highest) |
phase |
string |
no |
Current project phase |
weeks |
array |
yes |
Weekly labor requirements |
Week Object
| Field |
Type |
Required |
Description |
week_of |
string |
yes |
Week start date (YYYY-MM-DD, should be a Monday) |
crews |
array |
yes |
Crew requirements for this week |
Crew Object
| Field |
Type |
Required |
Description |
trade |
string |
yes |
Trade/craft name |
count |
number |
yes |
Number of workers needed |
hours_per_day |
number |
no |
Hours per day (default: 8) |
Available Workforce Object
| Field |
Type |
Required |
Description |
trade |
string |
yes |
Trade/craft name (must match project crew trade names) |
available |
number |
yes |
Total workers available across all projects |
Examples
Two-Week Forecast
{
"forecast": {
"company": "TCG Construction",
"report_date": "2026-02-07",
"period_start": "2026-02-10",
"period_end": "2026-02-21"
},
"projects": [
{
"name": "Highway 94 Bridge",
"priority": 1,
"phase": "Foundation",
"weeks": [
{
"week_of": "2026-02-10",
"crews": [
{ "trade": "Concrete Crew", "count": 10, "hours_per_day": 10 },
{ "trade": "Laborers", "count": 6, "hours_per_day": 8 }
]
}
]
}
],
"available_workforce": [
{ "trade": "Concrete Crew", "available": 12 },
{ "trade": "Laborers", "available": 15 }
]
}
Constraints
- Output format is markdown only
- Dates must be in YYYY-MM-DD format
- Trade names must match exactly between project crews and available_workforce (case-sensitive)
- The script calculates total demand per trade per week by summing across projects
- Gap analysis flags any week where total demand exceeds available workforce
- Utilization is calculated as (total assigned / total available) per trade
- The script requires only Python 3 standard library (no additional pip packages)
- The output directory must already exist if specifying an output_path
- Currency is not applicable to this report type