Mitasu for Home — AI Operations Guide (spec for AI agents)

Version 2026-08-24 (kept in sync with the app; consistency is test-enforced). How to use: paste this entire document into an AI assistant that can reach the Shopify Admin API (Claude + the Shopify connector, Claude Code + a Shopify MCP, or a custom agent), then ask it to register or assign product information. 日本語版: https://mitasu.tech/ai/home-agent-guide.ja.md

All of this app’s data lives in Shopify metafields/metaobjects (no external database; every key is under the home_info namespace). Any AI agent with Admin GraphQL access can therefore create templates and assign them to products without going through the app’s admin UI.


⛔ Hard prohibition — never touch the store’s products themselves

This guide authorizes exactly two kinds of write:

  1. Creating and updating home_info metaobjects (templates)
  2. Writing home_info metafields on products (allowed keys only — see below)

Treat every other piece of store data as read-only. Do not create, change or delete it for any reason.

OperationAllowed?
Creating or duplicating products (productCreate / productDuplicate / productSet)Never
Changing a product (productUpdate — title, description, price, images, tags, status, category, SEO)Never
Creating, changing or deleting variants; changing inventory or pricesNever
Deleting or archiving products (productDelete)Never
Touching orders, customers, shipping, discounts, inventory, themes or app billingNever
Reading products (id / handle / title / variant structure)✅ Yes
metafieldsSet on home_info keys (allowed keys only)✅ Yes
metaobjectCreate / metaobjectUpdate on home_info_* types✅ Yes

Do not use productUpdate to write metafields. Always use metafieldsSet. productUpdate mutates the product resource itself and can silently change fields you did not intend to touch.

The app itself obeys this rule. The Mitasu for Home codebase contains no productCreate / productUpdate / productDelete calls at all — every write goes through metafieldsSet or the metaobject* mutations. An agent that goes beyond that does not just confuse the app: it damages data the merchant’s revenue depends on.

When in doubt, do nothing. “While I’m fixing the dimension sheet I’ll tidy the description”, “these products look like duplicates, I’ll delete them”, “I’ll reorder the images” — all of that is outside this guide, even if asked. Tell the store owner to do it in the Shopify admin or in the app.

The safest route is the CSV path in the next section. A CSV import is processed by the app, so it has no mechanism to alter a product resource at all.


Most important: the two safe paths

  1. [Safest — recommended] The CSV path — use the app’s CSV export → the AI fills in the columns → CSV import (Pro). Name-based references, validation and caps are all enforced by the app. Columns: title, handle, dimension_sheet, material_profile, sets, room_scenes, faq, assembly_template, delivery_template, cleaning_code, rub_count, comfort_hint (references go by template name; Q&A by question text; multiple values |-separated; empty columns are left unchanged. cleaning_code / rub_count are per-product overrides of the assigned materials profile, and comfort_hint is firm or soft — this product’s firmness guidance. All of them are validated and applied safely by the app).
  2. [Advanced] Direct GraphQL — follow this spec exactly. Only ever create templates (metaobjects) and assign references — never write any other key.

Absolute rules (violations break the storefront and/or the app admin)

  1. Store measurements in cm only (never store inch — the app converts at display time). Weights are kg.
  2. Write only template creations and ref assignments. Never write the per-product override/patch keys — dimension_override / clearance_note_text / material_override / room_scene_overrides / set_overrides / faq_overrides / assembly_info / delivery_note / delivery_note_text — nor the app-managed aggregates & internals: comfort_feedback / return_stats / returns_baseline / review_pending / insights_cache / installed_at / plan / plan_kind / plan_cancel_at / plan_period_end. Any *_override map is the merchant’s own per-product tweak — for those, tell the owner to use the app’s override UI. Where they live if you need to READ them (moved in 2026-08): comfort_feedback is in $app:votes; return_stats / returns_baseline / review_pending are in $app:internal; plan is an app-data metafield on the AppInstallation. None of them are under home_info any more. dimension_override holds one of two shapes. With rows it is a full snapshot of the sheet (that product no longer follows the sheet at all). With row_labels ([{from, to?}]) it is a row map: which of the sheet’s rows this product sells and what it calls them, with every number still coming from the sheet. Both are off limits to you, but if you are asked to “show only the sizes this product sells”, point the owner at “Sizes shown on this product” in the product editor, or the same setting on Bulk apply.
  3. Do not mirror Shopify’s standard attributes into the app namespace. Material, color, pattern etc. belong in Shopify’s standard category metafields (entered on the product page); the app displays them automatically in the Features tab. The app’s own materials & finish profile holds what those can’t express (per-part surfaces, care, firmness, capacity).
  4. Assignment caps: set_refs4 / room_scene_refs4 / faq_items10; products per set (items) ≤ 6.
  5. Search for an existing template by name before creating one (no duplicates). Delete templates only through the app UI (a raw delete skips the assignment/override cleanup).
  6. Before destructive changes (replacing existing refs, bulk updates), read the current values and confirm with the user.
  7. metafieldsSet accepts ≤ 25 entries per call. Always check userErrors.

Data model (template references + per-product overrides)

Templates = metaobjects (7 reusable types)

home_info_dimension_sheet (dimension sheet — the app’s hero feature)

keytypeallowed values / shape
nametextrequired. Display name (keep it unique — CSV references use it)
categorytextsofa / table / desk / chair / bed / mattress / bedding / pillow / shelf / rug / curtain / lighting / kitchen — decides which measurement columns render
rowsjsonOne row per size variant: [{ "size_label": "2-seater", "measurements": { "width_cm": 150, "depth_cm": 85, "height_cm": 80, "seat_height_cm": 42 } }]. Ranges: add <key>_max (e.g. "width_cm": 150, "width_cm_max": 170 → “150–170”). Omit unused keys (omitted columns don’t render)
packagedjsonShipping boxes, one entry per box: [{ "size_label"?, "w_cm", "d_cm", "h_cm", "weight_kg"? }]. Powers the doorway-fit check — the flagship feature. Packaged size ≠ product size; without boxes the storefront cannot judge “will it fit through my door”. Always fill this in when the merchant can supply it
clearance_notetextOptional delivery-path note (stairs, elevator, narrow hallway …)
figure_urltextURL of the merchant’s own figure image (a Shopify file). Shown instead of the bundled category drawing, and drops the A/B/C column letters (they point at lines on the bundled drawing). For a product photo that already has the measurements written on it, or a shape the bundled figure does not match, like an L-shaped sectional
standard_sizesbooleantrue only when rows are a published national size table (US mattresses, JP ready-made curtain sizes …); false for an ordinary size run. It silences the admin’s “Check your measurements” warning and is never read by the storefront. Real published tables do decrease (King 193 cm → California King 183 cm; Twin XL 203 cm → Full 191 cm), so without it correct data is reported as a typo

Measurement keys per category (only these render):

categorymeasurement keys
sofawidth_cm depth_cm height_cm seat_height_cm seat_depth_cm arm_height_cm
tablewidth_cm depth_cm height_cm clearance_cm top_thickness_cm (clearance = floor clearance = usable knee height)
chairwidth_cm depth_cm height_cm seat_height_cm seat_width_cm seat_depth_cm
bedwidth_cm length_cm height_cm clearance_cm (clearance = under-bed space)
shelfwidth_cm depth_cm height_cm inner_width_cm inner_depth_cm
rugwidth_cm length_cm pile_height_cm
lightingdiameter_cm height_cm cord_length_cm
beddingwidth_cm length_cm mattress_thickness_cm pocket_depth_cm (pocket depth decides whether a fitted sheet stays on)
mattresswidth_cm length_cm height_cm (height = thickness; mattress_thickness_cm belongs to bedding, not here)
deskwidth_cm depth_cm height_cm clearance_cm top_thickness_cm (clearance = floor clearance = usable knee height)
kitchenwidth_cm depth_cm height_cm diameter_cm length_cm — the union of two shapes, because kitchenware has no single one. Round items fill diameter + height + length (the handle); boards and containers fill width + depth + height. No bundled figure and no bundled templates (nothing common to draw or to size), so set figure_url to your own image or use the table alone
curtainwidth_cm length_cm (length = drop)
pillowwidth_cm length_cm height_cm (height = loft; a pillowcase leaves it empty)

home_info_material_profile (materials & finish)

keytypeallowed values / shape
nametextrequired
surfacesjsonPer-part list: [{ "part", "material", "finish"? }]. part: top / frame / legs / seat / back / cover / upholstery / shade / shelf / drawer. material (canonical English, exact spelling): Oak / Walnut / Pine / Beech / Ash / Teak / MDF / Plywood / Veneer / Steel / Stainless_steel / Aluminum / Brass / Rattan / Bamboo / Glass / Marble / Ceramic / Linen / Cotton / Polyester / Leather / Faux_leather / Boucle / Velvet / Concrete. finish: Oiled / Lacquered / Matte / Gloss / Powder-coated / Brushed / Natural / Stained / Painted / Waxed. Free text is allowed but presets are translated into every storefront language — prefer them
carejsonCare-icon codes as an array, e.g. ["wipe_damp","avoid_sunlight"] — see the care-code table below
firmnesstextSeating firmness 1 (soft) … 5 (firm); blank for non-seating
weight_capacity_kgtextMaximum load in kg; blank when not applicable
certificationsjsonCodes as an array: fsc / pefc / greenguard / greenguard_gold / oeko_tex / certipur / c2c / carb2 / jis / sg / bifma
cleaning_codetextUpholstery cleaning code as printed on the tag: w / s / ws / x / d (water-based only / solvent only / either / vacuum only / dry clean). Blank when not stated
rub_counttextAbrasion rating in double rubs (Martindale/Wyzenbeek), e.g. 30000. Blank when not tested
variation_notetextWhat differs between individual pieces (grain, knots, colour lots, marble veining) — sets expectations before the box is opened
notetextFree-text material story (~500 chars): how the material ages (oiled oak mellows to amber), plain-language durability guidance (50,000 double rubs = contract grade), texture stories. Rendered as a quiet paragraph under the profile

home_info_room_scene (room scene — Pro): name (required) / room_type (living / dining / bedroom / kids / office / outdoor …) / room_size_m2 / photo (photo URL string) / note

home_info_set (“complete the room” — Pro): name (required) / items (list.product_reference — product GIDs, ≤ 6) / note / image (file_reference — a Files GID; omit if unavailable)

home_info_faq (one Q&A pair): question (required) / answer (required)

home_info_assembly (assembly info)

keytypeallowed values / shape
nametextrequired
infojson{ "required"?, "minutes"?, "people"?, "tools"?, "manual_url"?, "manual_kind"? }. required: true = needs assembly, false = arrives fully assembled, omit = unstated. minutes/people positive-integer strings. tools: the codes hex_key / phillips / flathead / mallet / hammer / wrench / power_driver are translated into every storefront language; any other string prints as typed. manual_url links the instruction sheet (public URL); manual_kind (pdf / video) switches the storefront link wording

home_info_delivery (delivery info — DISPLAY ONLY; the app never touches orders, shipping rates or fulfillment)

keytypeallowed values / shape
nametextrequired
infojson{ "method"?, "setup"?, "stairs"?, "lead_min"?, "lead_max"?, "lead_unit"? }. method: parcel / courier_setup / freight. setup: doorstep / room_of_choice / unpack_setup. stairs: included / on_request / not_available. lead_unit: days (business days) or weeks; absent = weeks. Stock items are usually quoted in business days, made-to-order in weeks. The lead time is the merchant’s own promise, not a carrier quote
notetextDelivery note (≤600 chars). The merchant’s voice — never overwrite it with generated text. Kept as its own field so it is a plain-text edit rather than hand-editing info’s raw JSON; older records may still carry it at info.note (reads prefer note)

Product metafields (assignment — these 8 are the ONLY writable ones)

keytypecontent
dimension_sheet_refmetaobject_referencedimension-sheet GID (single)
material_profile_refmetaobject_referencematerials-profile GID (single)
room_scene_refslist.metaobject_referenceroom-scene GIDs (≤ 4, display order)
set_refslist.metaobject_referenceset GIDs (≤ 4, display order)
faq_itemslist.metaobject_referenceQ&A GIDs (≤ 10, display order)
assembly_refmetaobject_referenceassembly-template GID (single)
delivery_refmetaobject_referencedelivery-template GID (single)
comfort_hint_overridetextfirm / soft (empty = unset; real shopper votes win once they accumulate)

Variant metafields (writable)

dimension_sheet_ref / material_profile_ref only (e.g. a “Wide” variant with its own sheet, or a leather vs fabric variant with its own profile). Size variants normally live as ROWS of one sheet — prefer that.

Shop settings (SHOP-owned) — prefer pointing the owner to the app’s Settings

feature_flags (section on/off) / section_order / section_titles / default_unit (cm|inch, editor only) / week_start (mon|sun). Reading them is fine.

Care codes (for home_info_material_profile.care)

groupcodes
cleaningwipe_damp wipe_dry mild_detergent no_abrasive professional_clean
protectionoil_regularly waterproof_spray felt_pads tighten_bolts rotate_cushions
environmentavoid_sunlight avoid_heat avoid_humidity indoor_only
textilescover_washable shade_dry
  1. Read the products — classify the furniture category, size variants and materials from title/description/type/tags/standard category.
  2. Search existing templates firstmetaobjects(type: "...", first: 250) and check names. Reuse matches.
  3. Create only the missing templates — follow the schemas above exactly (especially cm-only and the packaged boxes: without them the doorway-fit check stays dark).
  4. AssignmetafieldsSet with the refs (list values are a JSON string like "[\"gid://...\"]"). Or generate a CSV and have the owner import it (the safest route).
  5. Verify — have the owner check the coverage marks on the app’s “Edit products” screen.

GraphQL examples

Create a dimension sheet (with packaged boxes)

mutation {
  metaobjectCreate(metaobject: {
    type: "home_info_dimension_sheet",
    fields: [
      { key: "name", value: "Fabric sofa 2/3-seater" },
      { key: "category", value: "sofa" },
      { key: "rows", value: "[{\"size_label\":\"2-seater\",\"measurements\":{\"width_cm\":150,\"depth_cm\":85,\"height_cm\":80,\"seat_height_cm\":42}},{\"size_label\":\"3-seater\",\"measurements\":{\"width_cm\":190,\"depth_cm\":85,\"height_cm\":80,\"seat_height_cm\":42}}]" },
      { key: "packaged", value: "[{\"size_label\":\"2-seater\",\"w_cm\":155,\"d_cm\":90,\"h_cm\":75,\"weight_kg\":38}]" },
      { key: "clearance_note", value: "Legs detach (-11 cm height) for narrow stairwells." }
    ]
  }) { metaobject { id } userErrors { field message } }
}

Assign to a product (sheet + materials + assembly + Q&A)

mutation {
  metafieldsSet(metafields: [
    { ownerId: "gid://shopify/Product/123", namespace: "home_info", key: "dimension_sheet_ref",
      type: "metaobject_reference", value: "gid://shopify/Metaobject/456" },
    { ownerId: "gid://shopify/Product/123", namespace: "home_info", key: "material_profile_ref",
      type: "metaobject_reference", value: "gid://shopify/Metaobject/789" },
    { ownerId: "gid://shopify/Product/123", namespace: "home_info", key: "assembly_ref",
      type: "metaobject_reference", value: "gid://shopify/Metaobject/321" },
    { ownerId: "gid://shopify/Product/123", namespace: "home_info", key: "faq_items",
      type: "list.metaobject_reference", value: "[\"gid://shopify/Metaobject/111\",\"gid://shopify/Metaobject/222\"]" }
  ]) { metafields { key } userErrors { field message } }
}

List existing templates (duplicate check / get GIDs for assignment)

{ metaobjects(type: "home_info_dimension_sheet", first: 250) {
    nodes { id field(key: "name") { value } }
    pageInfo { hasNextPage endCursor } } }

Troubleshooting

  • UNDEFINED_OBJECT_TYPE / definition errors → have the owner run the app’s “Settings → Re-check” (definitions self-heal).
  • Assigned but not visible on the storefront → check in order: ① is the feature Pro-only while the store is on Free (room scenes / sets / comfort votes / owner verdict are Pro)? ② is the section toggled off in Settings? ③ is the app block placed in the theme?
  • The doorway-fit check does not appear → the assigned sheet has no packaged boxes, or every box already passes the store’s doorway width (then a single reassuring line renders instead — that is by design). The width is a Settings choice: 70 cm by default, or 76 / 80 / 90.
  • Refs beyond the caps are not rendered — keep lists within the limits.