S3D Agent Skill

Open Source Skills

These skills are open source โ€” clone, improve, or contribute at github.com/skyciv/skyciv-ai-skills

You are an agent that builds, analyses, and queries SkyCiv Structural 3D (S3D) structural models via the SkyCiv API. This skill covers the full s3d_model JSON schema and every function in the S3D.model, S3D.results, S3D.file, and S3D.SB namespaces.

Prerequisite: Always begin a session with S3D.session.start as the first function. See the skyciv-core skill for auth, options, and the request/response envelope.


The s3d_model Object#

The s3d_model is the JSON representation of a structural model. It is passed to S3D.model.set.

{
"settings": { ... },
"nodes": { ... },
"members": { ... },
"plates": { ... },
"meshed_plates": { ... },
"sections": { ... },
"materials": { ... },
"supports": { ... },
"settlements": { ... },
"point_loads": { ... },
"moments": { ... },
"distributed_loads": { ... },
"pressures": { ... },
"area_loads": { ... },
"self_weight": { ... },
"load_combinations": { ... },
"groups": { ... },
"gridlines_and_elevations": [ ... ]
}

All objects use integer-keyed dictionaries (e.g. "1": { ... }, "2": { ... }), except gridlines_and_elevations, which is a plain array.

Tip: To inspect a model as JSON, open it in SkyCiv S3D and use File โ†’ Export โ†’ SkyCiv File (JSON for API). To test JSON, use File โ†’ Import โ†’ SkyCiv File (JSON for API).


settings#

KeyTypeAcceptsDefault
unitsstring or object"imperial", "metric", or detailed objectvaries
vertical_axisstring"Y", "Z""Y"
precisionstring"fixed", "exponential""fixed"
precision_valuesinteger1โ€“15โ€”
evaluation_pointsinteger3โ€“50โ€”
solver_timeoutintegersecondsโ€”
non_linear_tolerancestringe.g. "1" (= 1%)โ€”
non_linear_theorystring"small", "finite""small"
auto_stabilize_modelbooleanโ€”false
member_offsets_axisstring"global", "local""local"
dynamic_modesintegerpositive integer5

Detailed units object:

{
"units": {
"length": "m",
"section_length": "mm",
"material_strength": "mpa",
"density": "kg/m3",
"force": "kn",
"moment": "kn-m",
"pressure": "kpa",
"mass": "kg",
"translation": "mm",
"stress": "mpa"
}
}

Imperial defaults: ft, in, ksi, lb/ft3, kip, kip-ft, ksf, kip, in, ksi.


nodes#

{
"nodes": {
"1": { "x": 0, "y": 0, "z": 0 },
"2": { "x": 5, "y": 0, "z": 0 }
}
}

members#

KeyTypeDescription
typestring"normal" (default), "normal_continuous", "cable", "tension", "compression", "rigid" โ€” see below
node_AintegerStart node ID
node_BintegerEnd node ID
section_idintegerSection ID. null when type = "rigid".
rotation_anglefloatRotation about member axis in degrees (โˆ’180 to 180). Ignored for "cable"/"rigid".
fixity_A / fixity_Bstring6-character restraint code. Ignored (forced "FFFRRR") for "cable"; still applies for "rigid" and controls which forces/moments transfer through the link.
offset_Ax/Ay/AzfloatLocal offsets at node A. Ignored for "cable"/"rigid".
offset_Bx/By/BzfloatLocal offsets at node B. Ignored for "cable"/"rigid".
local_axis_y[float]Global vector [X,Y,Z] for local y-axis
local_axis_z[float]Global vector [X,Y,Z] for local z-axis
mirrorstring (optional)"no" (default), "y", "z", "y_and_z" โ€” mirrors the member's section about its local axes without needing a separate mirrored section
disable_non_linear_effectsstring (optional)"yes", "no" (default) โ€” excludes this member from non-linear/P-delta effects

type values:

  • cable โ€” tension-only, no bending stiffness, true catenary sag. Triggers a non-linear analysis. Forces rotation_angleโ†’0, fixity_A/fixity_Bโ†’FFFRRR, offsetsโ†’0.
  • tension / compression โ€” linear, single-direction-only axial member (no sag). fixity/offset/rotation_angle behave as normal. Prefer this over cable unless true sag matters โ€” it's simpler and doesn't force a non-linear solve.
  • rigid โ€” infinitely stiff link, section_id: null, offsets/rotation_angle ignored, fixity_A/fixity_B still control force/moment transfer.
{
"members": {
"1": {
"node_A": 1,
"node_B": 2,
"section_id": 1,
"rotation_angle": 0,
"fixity_A": "FFFFFF",
"fixity_B": "FFFFFF",
"offset_Ax": "0", "offset_Ay": "0", "offset_Az": "0",
"offset_Bx": "0", "offset_By": "0", "offset_Bz": "0"
},
"2": {
"type": "tension",
"node_A": 3,
"node_B": 4,
"section_id": 2,
"fixity_A": "FFFRRR",
"fixity_B": "FFFRRR"
},
"3": {
"type": "rigid",
"node_A": 5,
"node_B": 6,
"section_id": null,
"fixity_A": "FFFFFF",
"fixity_B": "FFFRRR"
}
}
}

plates#

KeyTypeDescription
nodes[integer]Node IDs forming the plate (min 3, sequential order)
thicknessfloatPlate thickness (section_length units)
material_idintegerMaterial ID
rotZfloatRotation about local Z in degrees (default 0)
typestring"auto" โ€” considers shear deformation automatically
diaphragmstring"no" or "rigid"
statestring"stress" or "strain"

meshed_plates#

Manually defined mesh elements (usually auto-generated by S3D.model.mesh).

KeyDescription
node_A/B/C/DCorner node IDs. node_D: null for triangular elements
parent_plateID of the parent plate

sections#

Sections can be defined four ways:

1. Library section (recommended for standard shapes):

{
"sections": {
"1": {
"load_section": ["American", "AISC", "W shapes", "W14x22"],
"material_id": 1
}
}
}

2. Custom section from My Sections:

{ "1": { "load_custom": ["Folder1", "my-section-name"] } }

3. Numeric properties only (no design/stress support):

{
"1": {
"name": "MySection",
"area": 6500,
"Iy": 16000000,
"Iz": 50000000,
"J": 250000,
"material_id": 1,
"shear_area_z": 500,
"shear_area_y": 800
}
}

4. Template shape:

{
"1": {
"material_id": 1,
"info": {
"shape": "ibeam",
"dimensions": { "h": 200, "b": 100, "tf": 10, "tw": 6 }
}
}
}

Available template shapes: rectangle, hollow rectangle, circle, hollow circle, ibeam/i, tbeam/tee/t, lbeam/angle/l, channel/c, lipped channel, zshape/z, lipped zshape, lipped angle, lipped channel box.


materials#

KeyTypeDescription
namestringMaterial name
densityfloatDensity
elasticity_modulusfloatYoung's modulus
poissons_ratiofloatPoisson's ratio
yield_strengthfloatYield strength
ultimate_strengthfloatUltimate strength
classstring"steel", "aluminium", "concrete", "wood", "masonry", "other"

supports#

KeyDescription
nodeNode ID
restraint_code6-char restraint code
tx/ty/tz/rx/ry/rzSpring stiffness values (used when restraint char = S)

point_loads#

KeyDescription
type"n" (nodal) or "m" (member)
nodeNode ID (when type = "n")
memberMember ID (when type = "m")
positionPosition along member as % (0โ€“100, when type = "m")
x_mag/y_mag/z_magLoad magnitudes
load_groupLoad group name (string)

moments#

Same structure as point_loads โ€” x_mag/y_mag/z_mag represent moment magnitudes about each axis.


distributed_loads#

KeyDescription
memberMember ID
x/y/z_mag_ALoad magnitude at start (position A)
x/y/z_mag_BLoad magnitude at end (position B)
position_A/BStart/end positions as percentage (0โ€“100)
load_groupLoad group name
axes"global", "global_projected", or "local"

pressures#

Applied to plates.

KeyDescription
plate_idPlate ID
x/y/z_magPressure magnitude
axes"global", "global_projected", "local"
load_groupLoad group name

area_loads#

KeyDescription
type"one_way", "two_way", "general_one_way", "column_wind_load", "open_structure", "non_rectangular"
nodesNode IDs defining the area (3 or 4). Array of integers, except for general_one_way which uses a comma-separated string.
magLoad magnitude. Not used for general_one_way โ€” use mags instead.
magsComma-separated magnitude(s). Required for column_wind_load (paired with elevations) and general_one_way (a single value for uniform, or n values paired with n + 1 values in intervals for a stepped/tapered load)
column_directionSpan direction as "nodeA,nodeB". Relevant for one_way, column_wind_load, general_one_way
loaded_members_axis"all" or "major". Relevant for open_structure and general_one_way
intervalsgeneral_one_way only โ€” comma-separated step-interval distances, n + 1 values matching n values in mags. Blank = uniform load
excluded_member_idsgeneral_one_way only โ€” comma-separated member IDs to exclude from carrying the load
exclude_internal_membersgeneral_one_way only โ€” "off", "angled", or "all": auto-excludes internal members not aligned to the span
cantilever_extensionsgeneral_one_way only โ€” "left,right" offsets extending the load polygon along the span to pick up cantilevered members
direction"X", "Y", "Z", or projected variants
LGLoad group

Prefer general_one_way over plain one_way โ€” it's the most robust one-way option: non-rectangular spans, stepped/tapered magnitudes, and finer control over which members carry the load.


self_weight#

{
"self_weight": {
"enabled": true,
"x": 0,
"y": -1,
"z": 0
}
}

load_combinations#

{
"load_combinations": {
"1": {
"name": "1.2D + 1.6L",
"criteria": "strength",
"Dead": 1.2,
"Live": 1.6,
"SW1": 1.2
}
}
}

criteria is optional: "strength", "serviceability", or "other". Load group names used as keys (e.g. "Dead", "SW1") โ€” values are load factors.


load_cases#

Maps load groups to standard load type categories for a named design code. This tells the solver how to classify each load group when auto-generating code-based load combinations.

{
"load_cases": {
"DESIGN-CODE-NAME": {
"LOAD_GROUP_NAME": "LOAD_TYPE"
}
}
}

The key is the design code identifier. Each nested key is a load group name from your model; the value is the code-defined load type for that group.

ASCE 7-22 (LRFD):

{
"load_cases": {
"ASCE-7-2022-LRFD": {
"D1": "D",
"SW1": "D",
"L1": "L",
"S1": "S",
"W1": "W"
}
}
}

AS 1170.0-2002:

{
"load_cases": {
"AS-1170.0-2002": {
"SDL": "G",
"SW1": "G",
"Q": "Qdd",
"W_East": "Wu",
"W_North": "Wu",
"W_South": "Wu",
"W_West": "Wu"
}
}
}

EN 1990-2002:

{
"load_cases": {
"EN-1990-2002": {
"G1": "G",
"SW1": "G",
"Qa1": "Qa",
"S1": "Sl",
"Wx-": "W",
"Wx+": "W",
"Wy-": "W",
"Wy+": "W"
}
}
}

Multiple load groups can map to the same load type (e.g. several wind direction groups all mapped to "W"). Multiple design codes can coexist in the same load_cases object.


groups#

{
"groups": {
"1": {
"name": "Columns",
"ids": [1, 2, 3],
"type": "elements"
}
}
}

type accepts: "elements", "nodes", "supports", "plates", "groups".


gridlines_and_elevations#

Optional, purely visual/organisational โ€” doesn't affect analysis, but enables per-level platform features (e.g. isolating a floor). An array (not an integer-keyed dictionary) of elevation/story objects:

{
"gridlines_and_elevations": [
{
"name": "Base",
"elevation": 0,
"axis": "y",
"is_draw": true,
"beams": [],
"columns": [
{ "section_id": 1, "x": 0, "z": -10, "s3d_id": 1 }
],
"plates": [],
"points": [],
"gridlines": [
{
"grid_id": "1",
"start_x": 0, "start_z": -10,
"end_x": 0, "end_z": 10,
"vector_x": 0, "vector_z": 1,
"grid_label": "start",
"startpt": [0, -12],
"endpt": [0, 12]
}
]
}
]
}
  • axis should match settings.vertical_axis.
  • columns[].s3d_id is the ID of the matching column in members/nodes; columns[].section_id is the ID in sections.
  • beams, plates, points are reserved (mirror columns structurally) โ€” not yet documented, leave as [].
  • gridlines[].grid_id is the label text printed on the gridline; grid_label ("start" or "end") controls which end it's printed at.
  • startpt/endpt extend slightly past start_x/start_z/end_x/end_z to leave room for the label โ€” not the structural extents.

Restraint Codes#

A 6-character string. First 3 = translational DOF (local X, Y, Z). Last 3 = rotational DOF (local X, Y, Z).

CharacterMeaning
FFixed
RReleased (free)
SSpring

Examples:

  • "FFFFFF" โ€” fully fixed (pin/fixed support)
  • "FFFRRR" โ€” pinned (fixed translation, free rotation)
  • "FFFFFR" โ€” fixed except rotation about local Z

S3D.model Functions#

S3D.model.set#

Sets the structural model for the session.

{
"function": "S3D.model.set",
"arguments": { "s3d_model": { /* model object */ } }
}

S3D.model.get#

Returns the current s3d_model object. Requires S3D.model.set earlier in session.

{ "function": "S3D.model.get" }

S3D.model.repair#

Fixes common model issues before solving. Requires S3D.model.set.

CheckDescription
unused_nodesRemove floating/disconnected nodes
large_structureDetect unit-system issues (extreme slenderness)
merge_nodesMerge near-coincident nodes
zero_membersRemove zero-length members
continuous_to_normal_membersSplit members with intermediate nodes
intersect_membersConnect crossing members
default_sectionAdd a default section to members with none
force_plate_meshAllow analysis without pre-meshed plates
{
"function": "S3D.model.repair",
"arguments": {
"checks": ["unused_nodes", "merge_nodes", "intersect_members"]
}
}

Omit checks to run all repairs.

S3D.model.solve#

Runs structural analysis. Requires S3D.model.set.

KeyTypeDefaultDescription
analysis_typestring"linear""linear", "nonlinear", "buckling", "dynamic", "response_spectrum"
repair_modelbooleanfalseRun repair before solving
return_databooleantrueInclude solve data in response
formatstring"json""json", "csv", "summary", "s3d"
lc_filter[string]all"envelope", "envelope_abs_max", "load_case", "load_group", "load_combo", or specific LC names like "LC1"
result_filter[string]all"reactions", "member_forces", "member_stresses", "member_peak_results", "member_discontinuities", "member_displacements", "plate_forces", "plate_stresses", "plate_element_forces", "plate_element_stresses", "plate_peak_results", "buckling", "dynamic_frequency"
include_nodal_displacementsbooleanfalseInclude nodal displacements per load combo
{
"function": "S3D.model.solve",
"arguments": {
"analysis_type": "linear",
"repair_model": true,
"lc_filter": ["envelope_abs_max"],
"result_filter": ["member_peak_results", "reactions"]
}
}

Tip: Always use result_filter and lc_filter to minimise response size.

Results are returned as a dictionary keyed by load combination index.

S3D.model.mesh#

Meshes plates. Requires S3D.model.set.

KeyTypeDefaultDescription
methodstring"frontal_quads""frontal_quads", "frontal", "adapt", "packing_parallelograms", "delaunay"
granularityinteger11 (coarse) to 5 (fine)
plate_ids[integer]all platesSpecific plates to mesh

S3D.model.takeScreenshot#

Returns base64 PNG screenshots.

KeyTypeDescription
views[string]"iso", "front", "side", "top", "custom"
is_rendererbooleanUse 3D renderer (true) or wireframe (false)
wireframe_settingsobjectshow_nodes, show_loads, show_plates, projection
zoom_factorfloatโˆ’50 to 50
scalefloat0 to 5

S3D.model.surfaceSpringSupports#

Simulates surface spring supports on a plate.

{
"function": "S3D.model.surfaceSpringSupports",
"arguments": {
"subgrade_modulus": 3,
"spring_type": "linear",
"plate_ids": [1]
}
}

spring_type: "linear", "compression", "tension".

S3D.model.script#

Run custom JavaScript against the S3D model. Useful for complex topology operations.

{
"function": "S3D.model.script",
"arguments": {
"script": "var id = S3D.structure.nodes.add({x:10, y:0, z:0}); API_RETURN_DATA = {new_node: id};"
}
}

Write to API_RETURN_DATA to return data. Available S3D functions include S3D.structure.nodes.add, S3D.structure.members.add, S3D.structure.supports.add, S3D.structure.members.intersect, S3D.UI.update.

S3D.model.getLocalAxisVectors#

Returns local axis vectors {x, y, z} for each member.


S3D.results Functions#

S3D.results.get#

Fetches analysis results after solving. Same filter options as S3D.model.solve.

{
"function": "S3D.results.get",
"arguments": {
"result_filter": ["member_peak_results"],
"lc_filter": ["envelope_abs_max"]
}
}

S3D.results.set#

Set results from an external source for further processing.

{
"function": "S3D.results.set",
"arguments": { "analysis_results": { /* results object */ } }
}

S3D.results.fetchMemberResult#

Get detailed results for a specific member.

KeyTypeDescription
member_idintegerMember ID (null = all members)
LC[integer]Load combination IDs (empty = all)
res_keystring"bmd_z", "bmd_y", "axial", "sfd_y", "sfd_z", "top_bending_stress_z", "displacement", "displacement_x/y/z"
typestring"array", "x,y" (with x positions), "image" (base64 plot)
{
"function": "S3D.results.fetchMemberResult",
"arguments": {
"member_id": 1,
"LC": [1],
"res_key": "bmd_z",
"type": "x,y"
}
}

S3D.results.getAnalysisReport#

Generate a PDF or TXT analysis report. Requires S3D.model.set and S3D.model.solve.

{
"function": "S3D.results.getAnalysisReport",
"arguments": {
"job_name": "My Project",
"file_type": "pdf",
"load_combinations": [1, 2, "Envelope Absolute Max"],
"sections": {
"title_page": true,
"nodal_reactions": true,
"member_forces": true,
"member_displacements": true
}
}
}

Returns view_link and download_link URLs.

S3D.results.getDynamicFreq#

Returns dynamic/frequency analysis results.

{
"function": "S3D.results.getDynamicFreq",
"arguments": {
"result_filter": ["modes", "mass_participation_percentage"]
}
}

S3D.file Functions#

S3D.file.save#

Save the current model to cloud storage. Requires S3D.model.set.

{
"function": "S3D.file.save",
"arguments": {
"name": "my-model",
"path": "projects/analysis/",
"public_share": true
}
}

Returns a URL to open the file in S3D, and optionally a public_link.

S3D.file.open#

Load a model from cloud storage (sets it for the session).

{
"function": "S3D.file.open",
"arguments": {
"name": "my-model",
"path": "projects/analysis/",
"load_results": false
}
}

Use uid instead of name/path if the file UID is known.

S3D.file.share#

Share a model file with other SkyCiv users.

{
"function": "S3D.file.share",
"arguments": {
"name": "my-model",
"path": "projects/",
"share_with": ["[email protected]"]
}
}

S3D.file.getFileDirectory#

List files/folders in cloud storage.

{
"function": "S3D.file.getFileDirectory",
"arguments": {
"path": "projects/",
"full_list_flat": true
}
}

S3D.file.restoreVersion#

Roll back to a prior version.

{
"function": "S3D.file.restoreVersion",
"arguments": { "rollback_versions": 1 }
}

S3D.SB (Section Builder) Functions#

S3D.SB.getLibraryTree#

List available sections in the section library.

{
"function": "S3D.SB.getLibraryTree",
"arguments": {
"section_map": ["American", "AISC", "W shapes"]
}
}

S3D.SB.loadLibraryShape#

Load a specific section from the library into the session.

S3D.SB.buildCustomShape#

Build a custom section from points or a line-with-thickness.

{
"function": "S3D.SB.buildCustomShape",
"arguments": {
"units": "mm",
"type": "points",
"points": [
[0, 0, 0], [100, 0, 0], [100, 200, 0], [0, 200, 0]
],
"run_solve": true,
"material_id": 1
}
}

type: "line" takes an open polyline + thickness to create thin-walled sections.

S3D.SB.solve#

Calculate section properties for the currently loaded section.

{ "function": "S3D.SB.solve" }

S3D.SB.submit#

Submit the current section into the structural model.

{
"function": "S3D.SB.submit",
"arguments": { "section_id": 1 }
}

S3D.SB.runGSD#

General Section Designer โ€” FEA-based RC section capacity check.

KeyDescription
design_code"ACI", "AS 3600", "BS", "CSA", "EN", "IS 456", "NSCP 2015"
concrete_classe.g. "C5000" (ACI) or "N32" (AS)
steel_gradee.g. "Grade 60" (ACI)
reinforcementArray of {z, y, diam}
loadsArray of {N, M_z, M_y}

Full Workflow Example#

{
"auth": { "username": "[email protected]", "key": "YOUR_KEY" },
"options": { "validate_input": true },
"functions": [
{ "function": "S3D.session.start", "arguments": { "keep_open": false } },
{
"function": "S3D.model.set",
"arguments": {
"s3d_model": {
"settings": { "units": "metric", "vertical_axis": "Y" },
"nodes": {
"1": { "x": 0, "y": 0, "z": 0 },
"2": { "x": 5, "y": 0, "z": 0 }
},
"members": {
"1": {
"node_A": 1, "node_B": 2, "section_id": 1,
"rotation_angle": 0,
"fixity_A": "FFFFFF", "fixity_B": "FFFFFF",
"offset_Ax": 0, "offset_Ay": 0, "offset_Az": 0,
"offset_Bx": 0, "offset_By": 0, "offset_Bz": 0
}
},
"sections": {
"1": { "load_section": ["Australian", "Steel (300 Grade)", "Universal beams", "310 UB 32.0"], "material_id": 1 }
},
"materials": {
"1": { "name": "Steel", "density": 7850, "elasticity_modulus": 200000, "poissons_ratio": 0.27, "yield_strength": 350, "ultimate_strength": 470, "class": "steel" }
},
"supports": {
"1": { "node": 1, "restraint_code": "FFFFFF", "tx": 0, "ty": 0, "tz": 0, "rx": 0, "ry": 0, "rz": 0 },
"2": { "node": 2, "restraint_code": "FFFFRR", "tx": 0, "ty": 0, "tz": 0, "rx": 0, "ry": 0, "rz": 0 }
},
"distributed_loads": {
"1": { "member": 1, "y_mag_A": -10, "y_mag_B": -10, "x_mag_A": 0, "z_mag_A": 0, "x_mag_B": 0, "z_mag_B": 0, "position_A": 0, "position_B": 100, "load_group": "LL", "axes": "global" }
},
"load_combinations": {
"1": { "name": "LC1", "LL": 1.5 }
},
"plates": {}, "meshed_plates": {}, "settlements": {},
"point_loads": {}, "moments": {}, "pressures": {},
"area_loads": {}, "self_weight": {}, "groups": {}
}
}
},
{
"function": "S3D.model.solve",
"arguments": {
"analysis_type": "linear",
"repair_model": true,
"result_filter": ["member_peak_results", "reactions"]
}
}
]
}