Purpose
Before an AI agent completes a purchase for a shopper it checks the store's policies — "Do they ship to me? What's the return window?" If shipping/returns policies are missing, empty, or buried in an image/PDF, the agent can't answer, loses confidence, and abandons or sends the shopper elsewhere. This skill audits the store's policies and ensures the key ones exist as clean, plain-text/HTML content an agent can read and quote. Fixes shipping-policy-readable and returns-policy-readable.
Prerequisites
- Authenticated Shopify CLI session (
shopify auth login --store <domain>) - Required API scopes:
read_legal_policies(orread_online_store_pages),write_legal_policies
Parameters
All skills accept these universal parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| store | string | yes | — | Store domain (e.g., mystore.myshopify.com) |
| format | string | no | human | Output format: human (default) or json |
| dry_run | bool | no | true | Preview proposed policy bodies without writing (defaults ON — edits live store policies) |
Skill-specific parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| policies | string | no | REFUND_POLICY,SHIPPING_POLICY | Comma list of policy types to ensure: REFUND_POLICY,SHIPPING_POLICY,PRIVACY_POLICY,TERMS_OF_SERVICE |
| mode | string | no | audit | audit (report gaps only) or apply (write supplied/drafted bodies) |
| bodies_dir | string | no | — | Directory of <POLICY_TYPE>.html files to use as the source of truth when mode: apply |
Safety
⚠️ Step 2 (
shopPolicyUpdate) replaces a LIVE legal policy's body — this is legally binding content. NEVER auto-generate legal text. Inmode: applythe skill only writes bodies you supply viabodies_dir; it will not invent policy language. Default ismode: audit+dry_run: true. Have legal/ops review every body beforemode: apply.
Workflow Steps
OPERATION:
shop— query Inputs: none; readshopPolicies { type body url }Expected output: Which target policies are present, empty, or image-only (heuristic: very short body or body that's just an<img>/link).COMPUTE (no API): classify each policy as OK / missing / thin / image-only. In
auditmode, stop here and report. Inapplymode, load the matching<TYPE>.htmlfrombodies_dirfor each gap and emit a before/after preview.OPERATION:
shopPolicyUpdate— mutation (only inmode: apply, notdry_run) Inputs:shopPolicy: { id: <policy id>, body: <supplied HTML> }per gap. Expected output: Updated policy; collectuserErrors.
GraphQL Operations
# shop:query — validated against api_version 2025-01
query PolicyAudit {
shop {
shopPolicies {
id
type
body
url
}
}
}
# shopPolicyUpdate:mutation — validated against api_version 2025-01
mutation PolicyUpdate($shopPolicy: ShopPolicyInput!) {
shopPolicyUpdate(shopPolicy: $shopPolicy) {
shopPolicy { id type url }
userErrors { field message }
}
}
Session Tracking
Claude MUST emit the following output at each stage. This is mandatory.
On start, emit:
╔══════════════════════════════════════════════╗
║ SKILL: <skill name> ║
║ Store: <store domain> ║
║ Started: <YYYY-MM-DD HH:MM UTC> ║
╚══════════════════════════════════════════════╝
After each step, emit:
[N/TOTAL] <QUERY|MUTATION> <OperationName>
→ Params: <brief summary of key inputs>
→ Result: <count or outcome>
If dry_run: true, prefix every mutation step with [DRY RUN] and do not execute it.
On completion, emit:
For format: human (default):
══════════════════════════════════════════════
OUTCOME SUMMARY
<Metric label>: <value>
Errors: 0
Output: <filename or "none">
══════════════════════════════════════════════
For format: json, emit:
{
"skill": "<skill-slug>",
"store": "<domain>",
"started_at": "<ISO8601>",
"completed_at": "<ISO8601>",
"dry_run": false,
"steps": [
{
"step": 1,
"operation": "<OperationName>",
"type": "query",
"params_summary": "<string>",
"result_summary": "<string>",
"skipped": false
}
],
"outcome": {
"metric_key": 0,
"errors": 0,
"output_file": null
}
}
Output Format
human: a policy table (type, status, length, readable?) + the audit verdict; in apply mode, the before/after for each written policy. json: { policies:[{ type, status, readable }], updated, errors, output_file }.
Error Handling
| Error | Cause | Recovery |
|---|---|---|
THROTTLED |
API rate limit | Wait 2s, retry up to 3 times |
ACCESS_DENIED |
Missing write_legal_policies |
Stay in audit mode; report gaps for manual fill |
bodies_dir missing a type |
No supplied body for a gap | Skip that policy, keep it in the gap report |
Best Practices
- Default to
mode: audit— this skill's main value is finding image-only or empty policies; writing legal text is a human decision. - Make policies concrete and parseable: state the return window in days, shipping timeframes, and regions in plain sentences — that's what agents quote.
- Avoid image/PDF-only policies entirely; agents (and many shoppers) can't read them.
- Keep the canonical policy text in
bodies_dirunder version control so re-applying after edits is auditable.