Skip to content

A guide for AI agents

This page is part of the Moket skill: it is written for AI agents, which read it as Markdown. Values in angle brackets in the examples stand for ids an agent gets from Moket.

Leather ​

The Leather Workbench is Moket's own plugin for leather goods: wallets, card holders, straps and cases. Its features work like any feature of a part: you add them with feature.create in a plan and read them with describe_commands first. A leather part is flat pieces stacked on each other, stitch lines through them, and folds that close it.

Read Parts first. inspect_document lists the user's plugins under plugins with their feature types; Leather is there unless the user turned it off in Settings > Plugins.

Features ​

FeatureWhat it does
io.moket.leather.pieceA flat piece from one closed region of a sketch, thickness thick, with its leather, finish, grain, name and count.
io.moket.leather.stitchPathA stitch line: holes along edges of a piece's face, margin in from them, at a pitch, spread by arc length.
io.moket.leather.stitchHolesPunches a stitch line's holes through every piece in bodies, the same holes in each layer: chisel slits or round.
io.moket.leather.seamAllowanceMoves a piece's cut line out from chosen edges for the pattern; the piece itself does not change.
io.moket.leather.foldFolds pieces along a sketch line by an angle with an inside radius; stacked layers fold together.
  • A piece grows from its sketch along the sketch's normal; "flip": true grows it the other way. Its faces are named like an extrude's: f(<piece>:start) on the sketch, f(<piece>:end) on top, f(<piece>:side:<line>) round it.
  • Stack a piece on another by sketching it on the lower one's top face ("plane":{"kind":"face","ref":{"kind":"face","name":"f($outer:end)"}}). On a face that faces up, the sketch's x and y are the part's X and Y.
  • Leathers are veg-tan (outers, 1.2 to 2 mm), chrome-tan (pockets, 0.6 to 1 mm) and lining (0.4 to 0.8 mm); finishes natural, tan, brown, dark-brown, black, burgundy, navy, green. Use the user's leather and thickness.
  • The usual pitch is 3.85 mm (a 4 mm iron), 3 mm for small goods; the margin 3 to 4 mm. corners hole puts a hole at every corner and evens the pitch between corners.

Stitching through layers ​

One stitch line and one Stitch holes through every layer it holds give every layer the same holes. Draw the stitch line on the top layer's face and list the pieces it goes through in bodies, bottom to top: a hole goes only where a piece is, so a pocket that covers part of the outer gets the holes over it.

Edges of a stitch line follow each other end to end. Name them from the piece and the lines of its sketch: in the same plan, a template's lines are $outline.lines.bottom (a rectangle's bottom, right, top, left; a profile's $pocket.lines.0 from its first corner on).

json
{
  "summary": "Card holder 100 x 65 with a front pocket, stitched round",
  "steps": [
    {
      "label": "Name and parameters",
      "commands": [
        { "type": "document.rename", "name": "Card holder" },
        {
          "type": "parameter.create",
          "id": "$width",
          "name": "width",
          "expression": "100 mm"
        },
        {
          "type": "parameter.create",
          "id": "$height",
          "name": "height",
          "expression": "65 mm"
        },
        {
          "type": "parameter.create",
          "id": "$pocketHeight",
          "name": "pocketHeight",
          "expression": "45 mm"
        }
      ]
    },
    {
      "label": "Outer, 1.4 mm veg-tan",
      "commands": [
        {
          "type": "sketch.template",
          "id": "$outline",
          "name": "Outer",
          "template": {
            "kind": "rectangle",
            "width": "width",
            "depth": "height"
          }
        },
        {
          "type": "feature.create",
          "id": "$outer",
          "featureType": "io.moket.leather.piece",
          "name": "Outer",
          "params": {
            "profile": { "sketch": "$outline" },
            "body": "$outerBody",
            "thickness": "1.4 mm",
            "leather": "veg-tan",
            "finish": "brown"
          }
        }
      ]
    },
    {
      "label": "Pocket on the outer, 0.8 mm chrome-tan",
      "commands": [
        {
          "type": "sketch.template",
          "id": "$pocketOutline",
          "name": "Pocket",
          "template": {
            "kind": "profile",
            "corners": [
              { "x": "-width / 2", "y": "-height / 2" },
              { "x": "width / 2", "y": "-height / 2" },
              { "x": "width / 2", "y": "pocketHeight - height / 2" },
              { "x": "-width / 2", "y": "pocketHeight - height / 2" }
            ],
            "plane": {
              "kind": "face",
              "ref": { "kind": "face", "name": "f($outer:end)" }
            }
          }
        },
        {
          "type": "feature.create",
          "id": "$pocket",
          "featureType": "io.moket.leather.piece",
          "name": "Pocket",
          "params": {
            "profile": { "sketch": "$pocketOutline" },
            "body": "$pocketBody",
            "thickness": "0.8 mm",
            "leather": "chrome-tan",
            "finish": "brown"
          }
        }
      ]
    },
    {
      "label": "Stitch round the outer, through the pocket",
      "commands": [
        {
          "type": "feature.create",
          "id": "$stitch",
          "featureType": "io.moket.leather.stitchPath",
          "name": "Edge stitch",
          "params": {
            "edges": [
              {
                "kind": "edge",
                "name": "e(f($outer:end)|f($outer:side:$outline.lines.bottom))"
              },
              {
                "kind": "edge",
                "name": "e(f($outer:end)|f($outer:side:$outline.lines.right))"
              },
              {
                "kind": "edge",
                "name": "e(f($outer:end)|f($outer:side:$outline.lines.top))"
              },
              {
                "kind": "edge",
                "name": "e(f($outer:end)|f($outer:side:$outline.lines.left))"
              }
            ],
            "margin": "4 mm",
            "pitch": "3.85 mm"
          }
        },
        {
          "type": "feature.create",
          "id": "$holes",
          "featureType": "io.moket.leather.stitchHoles",
          "name": "Edge holes",
          "params": {
            "line": "$stitch",
            "bodies": ["$outerBody", "$pocketBody"],
            "shape": "chisel"
          }
        }
      ]
    }
  ]
}

Checking stitch counts ​

A stitch line and Stitch holes report what they made: the preview's reports ("78 holes, pitch 3.8 to 3.83 mm, 298 mm of stitching"), the feature's report in inspect_document and its reports in get_feature, with the count in details (holes). Two edges sewn to each other (the sides of a gusset and the panel it joins, a fold's two halves stitched closed) need the same number of holes: compare the reports, and change the pitch or the gaps (startGap, endGap on an open line) of one until they match. Tell the user the counts.

Folds ​

A fold turns the pieces in bodies about a line of a sketch on them (line: {"sketch":<sketch>,"curves":[<line>]}), by angle (180 deg folds them shut) with an inside radius. The side to the left of the line, seen from the side the sketch faces and walking from its start to its end, moves; otherSide moves the other one, and under folds away from the side the sketch faces. Every layer folds with its own radius, the stitches and the pieces lying wholly on the moving side ride along.

json
{
  "summary": "Key fob strap 120 x 25, folded in half",
  "steps": [
    {
      "label": "Strap and crease",
      "commands": [
        { "type": "document.rename", "name": "Key fob" },
        {
          "type": "sketch.template",
          "id": "$outline",
          "name": "Strap",
          "template": {
            "kind": "rectangle",
            "width": "120 mm",
            "depth": "25 mm"
          }
        },
        {
          "type": "feature.create",
          "id": "$strap",
          "featureType": "io.moket.leather.piece",
          "name": "Strap",
          "params": {
            "profile": { "sketch": "$outline" },
            "body": "$strapBody",
            "thickness": "1.4 mm"
          }
        },
        {
          "type": "feature.create",
          "id": "$crease",
          "featureType": "core.sketch",
          "name": "Crease",
          "params": {
            "plane": {
              "kind": "face",
              "ref": { "kind": "face", "name": "f($strap:end)" }
            },
            "entities": [
              { "id": "$a", "kind": "point", "x": 0, "y": -20, "fixed": true },
              { "id": "$b", "kind": "point", "x": 0, "y": 20, "fixed": true },
              {
                "id": "$creaseLine",
                "kind": "line",
                "start": "$a",
                "end": "$b"
              }
            ],
            "constraints": []
          }
        }
      ]
    },
    {
      "label": "Fold the left half over",
      "commands": [
        {
          "type": "feature.create",
          "id": "$fold",
          "featureType": "io.moket.leather.fold",
          "name": "Fold",
          "params": {
            "line": { "sketch": "$crease", "curves": ["$creaseLine"] },
            "bodies": ["$strapBody"],
            "angle": "180 deg",
            "radius": "1 mm"
          }
        }
      ]
    }
  ]
}

Draw the crease as a core.sketch on the top layer's face with two fixed points and a line between them; placeholders work as entity ids. The line here runs up the middle, so the left half folds over onto the right. Fold last, after every stitch, hole and allowance: the pattern shows each piece flat as cut. A fold whose pieces need more room warns The pieces inside the fold need an inside radius of at least ... mm: raise the radius to it, never leave the warning. Folds are geometric: the leather does not stretch or thin.

A wallet ​

A bifold wallet is an outer, a liner stacked on it, and pockets stacked on the liner on each side of the fold:

  1. Parameters for the closed size, thicknesses, margin and pitch; the outer and the liner the open size (twice the closed width).
  2. Pockets on the liner, each stack on the one under it, each pocket a little lower than the one it covers so the cards show.
  3. A stitch line round each pocket stack, through the stack and the liner and outer under it; a stitch line round the liner through the liner and the outer. Compare the counts of seams that must match.
  4. The fold on the liner's top face at the middle, through every piece, 180 deg, with the radius it asks for.

The pattern and plugins of the user ​

  • The user exports the pattern (the Leather workbench's Export pattern: tiled PDF, PDF, SVG and DXF at 1:1). You cannot; name the pieces (name) and their count so the pattern reads well.
  • A user's own plugin runs only in a browser tab: on Moket's server its features are described, and adding or changing one answers PLUGIN_NEEDS_TAB. Ask the user to open Moket in a tab, then call again.
  • A plugin the user does not have on shows missing in inspect_document: its features keep their last result, frozen, and cannot be changed.

Moket Help