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:
- Creating and updating
home_infometaobjects (templates) - Writing
home_infometafields 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.
| Operation | Allowed? |
|---|---|
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 prices | ❌ Never |
Deleting or archiving products (productDelete) | ❌ Never |
| Touching orders, customers, shipping, discounts, inventory, themes or app billing | ❌ Never |
| 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
- [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_countare per-product overrides of the assigned materials profile, andcomfort_hintisfirmorsoft— this product’s firmness guidance. All of them are validated and applied safely by the app). - [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)
- Store measurements in cm only (never store inch — the app converts at display time). Weights are kg.
- 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*_overridemap 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_feedbackis in$app:votes;return_stats/returns_baseline/review_pendingare in$app:internal;planis an app-data metafield on the AppInstallation. None of them are underhome_infoany more.dimension_overrideholds one of two shapes. Withrowsit is a full snapshot of the sheet (that product no longer follows the sheet at all). Withrow_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. - 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).
- Assignment caps:
set_refs≤ 4 /room_scene_refs≤ 4 /faq_items≤ 10; products per set (items) ≤ 6. - 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).
- Before destructive changes (replacing existing refs, bulk updates), read the current values and confirm with the user.
metafieldsSetaccepts ≤ 25 entries per call. Always checkuserErrors.
Data model (template references + per-product overrides)
Templates = metaobjects (7 reusable types)
home_info_dimension_sheet (dimension sheet — the app’s hero feature)
| key | type | allowed values / shape |
|---|---|---|
name | text | required. Display name (keep it unique — CSV references use it) |
category | text | sofa / table / desk / chair / bed / mattress / bedding / pillow / shelf / rug / curtain / lighting / kitchen — decides which measurement columns render |
rows | json | One 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) |
packaged | json | Shipping 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_note | text | Optional delivery-path note (stairs, elevator, narrow hallway …) |
figure_url | text | URL 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_sizes | boolean | true 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):
| category | measurement keys |
|---|---|
sofa | width_cm depth_cm height_cm seat_height_cm seat_depth_cm arm_height_cm |
table | width_cm depth_cm height_cm clearance_cm top_thickness_cm (clearance = floor clearance = usable knee height) |
chair | width_cm depth_cm height_cm seat_height_cm seat_width_cm seat_depth_cm |
bed | width_cm length_cm height_cm clearance_cm (clearance = under-bed space) |
shelf | width_cm depth_cm height_cm inner_width_cm inner_depth_cm |
rug | width_cm length_cm pile_height_cm |
lighting | diameter_cm height_cm cord_length_cm |
bedding | width_cm length_cm mattress_thickness_cm pocket_depth_cm (pocket depth decides whether a fitted sheet stays on) |
mattress | width_cm length_cm height_cm (height = thickness; mattress_thickness_cm belongs to bedding, not here) |
desk | width_cm depth_cm height_cm clearance_cm top_thickness_cm (clearance = floor clearance = usable knee height) |
kitchen | width_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 |
curtain | width_cm length_cm (length = drop) |
pillow | width_cm length_cm height_cm (height = loft; a pillowcase leaves it empty) |
home_info_material_profile (materials & finish)
| key | type | allowed values / shape |
|---|---|---|
name | text | required |
surfaces | json | Per-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 |
care | json | Care-icon codes as an array, e.g. ["wipe_damp","avoid_sunlight"] — see the care-code table below |
firmness | text | Seating firmness 1 (soft) … 5 (firm); blank for non-seating |
weight_capacity_kg | text | Maximum load in kg; blank when not applicable |
certifications | json | Codes as an array: fsc / pefc / greenguard / greenguard_gold / oeko_tex / certipur / c2c / carb2 / jis / sg / bifma |
cleaning_code | text | Upholstery 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_count | text | Abrasion rating in double rubs (Martindale/Wyzenbeek), e.g. 30000. Blank when not tested |
variation_note | text | What differs between individual pieces (grain, knots, colour lots, marble veining) — sets expectations before the box is opened |
note | text | Free-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)
| key | type | allowed values / shape |
|---|---|---|
name | text | required |
info | json | { "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)
| key | type | allowed values / shape |
|---|---|---|
name | text | required |
info | json | { "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 |
note | text | Delivery 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)
| key | type | content |
|---|---|---|
dimension_sheet_ref | metaobject_reference | dimension-sheet GID (single) |
material_profile_ref | metaobject_reference | materials-profile GID (single) |
room_scene_refs | list.metaobject_reference | room-scene GIDs (≤ 4, display order) |
set_refs | list.metaobject_reference | set GIDs (≤ 4, display order) |
faq_items | list.metaobject_reference | Q&A GIDs (≤ 10, display order) |
assembly_ref | metaobject_reference | assembly-template GID (single) |
delivery_ref | metaobject_reference | delivery-template GID (single) |
comfort_hint_override | text | firm / 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)
| group | codes |
|---|---|
| cleaning | wipe_damp wipe_dry mild_detergent no_abrasive professional_clean |
| protection | oil_regularly waterproof_spray felt_pads tighten_bolts rotate_cushions |
| environment | avoid_sunlight avoid_heat avoid_humidity indoor_only |
| textiles | cover_washable shade_dry |
Recommended workflow (analyze products → create templates → assign)
- Read the products — classify the furniture category, size variants and materials from title/description/type/tags/standard category.
- Search existing templates first —
metaobjects(type: "...", first: 250)and check names. Reuse matches. - Create only the missing templates — follow the schemas above exactly
(especially cm-only and the
packagedboxes: without them the doorway-fit check stays dark). - Assign —
metafieldsSetwith the refs (list values are a JSON string like"[\"gid://...\"]"). Or generate a CSV and have the owner import it (the safest route). - 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
packagedboxes, 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.