Tool Workflow Recipes

SkillProductivity

Multi-tool recipes for common building energy modeling tasks. Use when chaining tools together for operations like adding windows, changing insulation, setting up HVAC, or running simulations.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Tool Workflow Recipes skill

What this skill tells your AI

The instructions your AI receives, as published by natlabrockies/openstudio-mcp in .claude/skills/tool-workflows/SKILL.md and read by ahel’s review.

Full workflows for simulation, results, HVAC setup, retrofit, geometry, and QA/QC are in dedicated skills. Call list_skills() to see them.

Add Windows to a Wall

list_surfaces()                           # find exterior wall names + azimuths
set_window_to_wall_ratio(surface_name="South Wall", ratio=0.4)

For different ratios per orientation, bin surfaces by azimuth:

  • South: 135-225 degrees
  • North: 315-360, 0-45 degrees
  • East: 45-135 degrees
  • West: 225-315 degrees

Change Wall/Roof Insulation

Add a layer to the EXISTING construction — do not rebuild the assembly from a hand-typed material list (that silently drops the original membrane/decking layers and can make the envelope worse):

create_standard_opaque_material(
    name="R20_Insulation", thickness_m=0.089,
    conductivity_w_m_k=0.04, density_kg_m3=30, specific_heat_j_kg_k=1000)
add_layer_to_construction(
    construction_name="ASHRAE 90.1 Ext Wall", material_name="R20_Insulation")
    # keeps all existing layers; verify assembly_r_si_after > assembly_r_si_before
assign_construction_to_surface(
    surface_name="South Wall", construction_name="ASHRAE 90.1 Ext Wall + R20_Insulation")

Repeat assign_construction_to_surface for each target surface, or use replace_window_constructions for bulk window replacement. Reserve create_construction(name=..., material_names=[...]) for building NEW assemblies from scratch, where you specify every layer deliberately.

Add Internal Loads to a Space

create_schedule_ruleset(name="Office_Occ", schedule_type="Fractional", default_value=0.5)
create_people_definition(
    name="Office People", space_name="Open Office",
    people_per_area=0.059, schedule_name="Office_Occ")
create_lights_definition(
    name="Office Lights", space_name="Open Office", watts_per_area=10.76)
create_electric_equipment(
    name="Office Plugs", space_name="Open Office", watts_per_area=1.076)

Set Up Weather

Weather files are SERVER-side (remote clients stage their own with request_upload). change_building_location sets weather, design days (from DDY), and climate zone in one call. The EPW must have companion .stat and .ddy files alongside it (same directory, same base filename).

list_weather_files()                      # find available weather files
change_building_location(weather_file="/inputs/Chicago.epw")

Fair HVAC System Sweep (decision-grade comparison)

Owned by the add-hvac skill — see its "Comparing Systems / Decision-Grade Results" section (get_skill("add-hvac")): per-candidate create_typical_building(system_type=..., hvac_only=True) swaps on the SAME configured model, then compare_runs. Do NOT use add_baseline_system/add_doas_system for comparative studies — generic wiring templates, no standards tuning.

Edit an Existing Air Loop's Supply Branch

Swap, add, or drop a coil or fan on an air loop that already exists (no measure):

get_air_loop_details(air_loop_name="PSZ-AC 1")        # exact names + supply order
replace_air_loop_supply_component(air_loop_name="PSZ-AC 1",
    component_name="PSZ-AC 1 DX Cooling Coil", new_component_type="CoilCoolingDXTwoSpeed")
set_component_properties(component_name="PSZ-AC 1 DX Cooling Coil",
    properties={"rated_high_speed_cop": 4.0})

add_air_loop_supply_component(..., insert_before=/insert_after=) places a new coil or fan relative to an existing one; remove_air_loop_supply_component drops one and moves the setpoint managers off the deleted node. Water coils need plant_loop_name.

Supply Air Temperature Reset

Swap a loop's outlet setpoint manager for an outdoor-air reset and tune it:

get_air_loop_details(air_loop_name="VAV 1")            # setpoint_managers on the outlet
add_setpoint_manager(spm_type="SetpointManagerOutdoorAirReset", name="VAV 1 SAT Reset",
    air_loop_name="VAV 1", replace_existing=True)
set_setpoint_manager_properties(setpoint_name="VAV 1 SAT Reset",
    properties={"setpoint_at_outdoor_low_temperature": 15.6, "outdoor_low_temperature": 10.0,
                "setpoint_at_outdoor_high_temperature": 12.8, "outdoor_high_temperature": 21.0})

Without replace_existing=True the call is refused when the node already has a Temperature setpoint manager (the SDK would delete it silently). remove_setpoint_manager(name=...) warns if a loop outlet is left with no Temperature control.

Tune Component Properties

list_model_objects(object_type="CoilHeatingGas")  # find component names
get_component_properties(component_name="Heating Coil 1")
set_component_properties(component_name="Heating Coil 1",
    properties={"efficiency": 0.95})

Economizer

set_economizer_properties(air_loop_name="VAV System",
    properties='{"economizer_control_type": "DifferentialEnthalpy"}')

Plant Loop Sizing

set_sizing_properties(loop_name="Chilled Water Loop",
    properties='{"design_loop_exit_temperature_c": 6.67, "loop_design_temperature_difference_c": 5.56}')

Apply External Measure

list_measure_arguments(measure_dir="/inputs/measures/my_measure")
apply_measure(measure_dir="/inputs/measures/my_measure",
    arguments={"param1": "value1", "param2": "42"})

Note: All measure arguments are strings. Booleans → "true" / "false". Numbers → "42".

Write and Apply a Custom Measure / ReportingMeasure

Owned by the measure-authoring skill (get_skill("measure-authoring")): the create_measure → test_measure → apply_measure chain, run_body patterns (Ruby + Python), ReportingMeasures against a completed run (test_measure(measure_dir=..., run_id=...) / apply_measure(measure_dir=..., run_id=...)), and the before/after comparison workflow. For HVAC measures, verify methods and wiring first:

search_api("CoilCoolingFourPipeBeam")             # check real setter/getter names
search_wiring_patterns("four pipe beam")           # get working Ruby wiring code

Object Cleanup

list_model_objects(object_type="Space")   # find objects
rename_object(object_name="Zone 1", new_name="North Office")
delete_object(object_name="Unused Space")
clean_unused_objects()                    # remove orphans

Inspect & Modify Any Object (Generic Access)

# Read all properties of any object
get_object_fields(object_type="BoilerHotWater", object_name="Boiler Hot Water 1")
# → returns property values + available setter methods

# Write a property using the discovered setter
set_object_property(object_type="BoilerHotWater", object_name="Boiler Hot Water 1",
    property_name="nominalThermalEfficiency", value=0.92)

# Works with any type — SizingSystem, CoilCoolingWater, etc.
get_object_fields(object_type="SizingSystem", object_name="VAV Sys 1 Sizing System")

Note: Always call get_object_fields first to discover property names and setter availability before using set_object_property.

Signals

GitHub stars
33
Forks
8
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
tool-workflows
Source
github.com/natlabrockies/openstudio-mcp