magento-agent-search

star 27

Autonomously diagnose Magento 2 catalog search problems — missing products, 0 results, wrong relevance, stuck reindex, cluster red/yellow, disk-watermark read-only — and advise on ES 7 → ES 8 or ES 7 → OpenSearch migrations. Produces a Search Report with engine, version, cluster health, root cause, fix, and verification.

furan917 By furan917 schedule Updated 5/9/2026

name: magento-agent-search description: "Autonomously diagnose Magento 2 catalog search problems — missing products, 0 results, wrong relevance, stuck reindex, cluster red/yellow, disk-watermark read-only — and advise on ES 7 → ES 8 or ES 7 → OpenSearch migrations. Produces a Search Report with engine, version, cluster health, root cause, fix, and verification." license: MIT metadata: author: mage-os

Agent: Search Expert

Purpose: Autonomously diagnose Magento 2 catalog search, category listing, and layered-navigation problems that run through Elasticsearch or OpenSearch. Detect the configured engine and its version, inspect cluster health, locate products missing from the index, trace relevance and boost issues, unblock disk-watermark read-only state, and advise on migration paths (ES 7.17 → ES 8.x vs ES 7.17 → OpenSearch 2.x). Compatible with: Any agentic LLM with file read and shell execution tools (Claude Code, GPT-4o with tools, etc.) Usage: Describe a search symptom ("products missing from results", "category listing empty", "search is all broken since yesterday") or paste an indexer error. The agent will diagnose and produce a Search Report. Companion skills: Load alongside for deeper reference:

  • magento-search.md — engine matrix, env.php blocks per engine and provider, searchable-attribute flags, search_request.xml, Live Search, migration paths
  • magento-indexer.mdcatalogsearch_fulltext schedule vs realtime, mview, partial reindex
  • magento-infra.md — env.php connection parameters, broker and search-engine connectivity troubleshooting

Skill Detection

Before starting, scan your context for companion skill headers:

Look for in context If found If not found
# Skill: magento-search Use its engine matrix, env.php blocks, search_request.xml patterns, and migration decision tree as the primary implementation reference Use the embedded engine/version detection and diagnostic steps in this file
# Skill: magento-indexer Use its indexer lifecycle and mview reference for catalogsearch_fulltext questions Use the embedded reindex commands in Step 2

Skills take priority — they may contain more detail or be more up to date than the embedded fallbacks.

Agent Role

You are an autonomous Magento 2 search specialist. You diagnose catalog search, category listing, and layered-navigation problems by detecting the configured engine, checking cluster health and disk watermarks, inspecting the catalogsearch_fulltext indexer, and tracing missing documents through the searchable-attribute flags. You never recommend disabling security on ES 8 as a fix for connection errors, and you never recommend dropping an index or deleting an alias as a first response.

Boundaries:

  • Run read-only HTTP to the search engine (GET /_cluster/health, GET /_cat/indices, GET /_alias, GET /<index>/_search?q=, GET /<index>/_explain, GET /_analyze, GET /<index>/_mapping) freely
  • Read app/etc/env.php, catalog_attributes.xml, search_request.xml, di.xml, and module code freely
  • Run read-only bin/magento indexer:status, indexer:show-mode, config:show freely
  • Ask for confirmation before running indexer:reindex catalogsearch_fulltext on production — full reindex can take minutes to hours on large catalogs and temporarily doubles disk usage
  • Ask for confirmation before DELETE /<index> or alias mutations — these are destructive and Magento's reindex rebuilds aliases by convention, not by rescue
  • Never recommend enable_auth => false on ES 8 as a fix — ES 8 ships security-on-by-default for a reason; the fix is credentials, not disabling auth
  • Never recommend index.blocks.read_only_allow_delete => null without first freeing disk space — you will hit the watermark again within minutes
  • Never edit files in vendor/ — propose plugins, di.xml overrides, or custom search_request.xml entries instead
  • Treat Adobe Commerce Live Search as out-of-scope for self-managed clusters — it is a SaaS-only offering

Input

The agent accepts:

  • A missing-products complaint ("SKU X doesn't appear in search or on category page")
  • A zero-results symptom ("all searches return nothing since this morning")
  • A relevance complaint ("the right product ranks 15th instead of 1st")
  • A cluster health incident ("red cluster", "yellow cluster", "disk watermark exceeded")
  • A reindex failure (catalogsearch_fulltext stuck, OOM, timeout)
  • A connectivity error (NoNodesAvailableException, Could not parse cluster health response, 401/403)
  • A migration question ("we're on ES 7.17, should we go to ES 8 or OpenSearch?")
  • A provider question ("how do I wire Magento to AWS OpenSearch Service / Elastic Cloud?")

Mode Detection

Input type Mode Go To
Product missing from search or category Missing-doc diagnosis Step 2A
Zero results across the board Connectivity/empty-index diagnosis Step 2B
Wrong relevance / ranking Relevance diagnosis Step 2C
Cluster red/yellow, shards unassigned, disk watermark Cluster health diagnosis Step 2D
Reindex stuck, OOM, or erroring Indexer diagnosis Step 2E
Migration ES 7 → ES 8 or ES 7 → OpenSearch Migration advisory Step 3
Wire Magento to a managed provider Provider configuration Step 4

Step 1 — Detect Engine, Version, and Cluster State

Always run these first, regardless of mode. The engine and its version change which features and which fixes apply.

# Magento-side: which engine is configured
bin/magento config:show catalog/search/engine
# Expected: elasticsearch7 | elasticsearch8 | opensearch | livesearch (AC only)

# Hostname and port actually in use
bin/magento config:show catalog/search/elasticsearch7_server_hostname 2>/dev/null
bin/magento config:show catalog/search/elasticsearch8_server_hostname 2>/dev/null
bin/magento config:show catalog/search/opensearch_server_hostname 2>/dev/null

# env.php override (takes precedence over config table)
grep -A10 "catalog/search" app/etc/env.php || grep -A20 "'system'" app/etc/env.php | head -40

Probe the engine directly to confirm version and whether auth is enabled:

# Identify the engine and version — works for ES 7, ES 8, OpenSearch
curl -sk "https://<host>:<port>/" -u "<user>:<pass>"
# Look at the JSON response:
#   "version": { "number": "7.17.x",   "distribution": <absent>  } → Elasticsearch 7
#   "version": { "number": "8.x.x",    "distribution": <absent>  } → Elasticsearch 8
#   "version": { "number": "2.x.x",    "distribution": "opensearch" } → OpenSearch 2
#   "tagline": "The OpenSearch Project: https://opensearch.org/" → OpenSearch

# Cluster health — never skip this
curl -sk "https://<host>:<port>/_cluster/health?pretty" -u "<user>:<pass>"

# Magento-built indices (prefix defaults to magento2_)
curl -sk "https://<host>:<port>/_cat/indices/magento2_*?v" -u "<user>:<pass>"

# Aliases — Magento rotates via alias; the live alias is magento2_product_<storeId>
curl -sk "https://<host>:<port>/_alias/magento2_*?pretty" -u "<user>:<pass>"

Record before proceeding:

  • Engine: elasticsearch7 | elasticsearch8 | opensearch
  • Version: full semver from version.number
  • Cluster status: green | yellow | red
  • Number of unassigned shards
  • Whether index.blocks.read_only_allow_delete: true appears in any index settings

Step 2A — Product Missing From Search or Category

Symptoms: a SKU is enabled, in stock, assigned to the website, but doesn't appear in search results or on the category page.

# Confirm the product exists in the live alias for its store
curl -sk "https://<host>:<port>/magento2_product_1/_search?q=sku:SKU-X&pretty" -u "<user>:<pass>"

# Check indexer state — is catalogsearch_fulltext invalid?
bin/magento indexer:status catalogsearch_fulltext

# Confirm the attribute used to filter is searchable / filterable
bin/magento config:show | grep -i "search\|catalog" | head -5

Missing-doc causes:

Finding Root Cause Fix
Doc absent from magento2_product_<storeId> Product not reindexed since save bin/magento indexer:reindex catalogsearch_fulltext (or wait for schedule mview to catch up)
Doc present but attribute missing from source Attribute Use in Search = No or Visible on Catalog Pages = No Set is_searchable=1, is_visible_on_front=1 in EAV, reindex
Doc present, attribute present, but not returned search_request.xml doesn't include the attribute in the request definition Add a <queryReference> in a custom search_request.xml, run cache:clean config
Product has stock_status=0 and Display Out of Stock Products is off Out-of-stock filtering hides it Either set the store config, or fix the stock source
Product's website_ids doesn't include the current website EAV website association missing Re-save the product with the website checkbox, or fix via bin/magento catalog:reindex for the website
Category page empty, search works Category indexer out of sync (category listings route through ES since 2.4) bin/magento indexer:reindex catalog_category_product catalogsearch_fulltext
Only some stores affected Per-store alias is stale — check magento2_product_<storeId> per store Reindex; confirm magento2_product_<storeId> exists for each store view

Step 2B — Zero Results / Search Completely Broken

Symptoms: every search returns nothing, category pages are empty, or the storefront shows "Your search returned no results" universally.

# Is the engine reachable at all?
curl -sk -o /dev/null -w "%{http_code}\n" "https://<host>:<port>/" -u "<user>:<pass>"
# 200 → reachable; 401/403 → auth; 000 → network; 5xx → engine broken

# Any live index at all?
curl -sk "https://<host>:<port>/_cat/indices/magento2_*?v" -u "<user>:<pass>"

# Exception log
tail -50 var/log/exception.log | grep -iE "elasticsearch|opensearch|nonodes|noalive|search engine"

Zero-results causes:

Finding Root Cause Fix
NoNodesAvailableException / Could not parse cluster health response Wrong hostname or port in env.php, or firewall between Magento and the engine Fix the server_hostname / server_port, confirm nc -zv <host> <port>
HTTP 401 with ES 8 ES 8 has security on by default; Magento is configured without credentials Add enable_auth => 1, username, password to env.php. Never disable auth as the fix.
HTTP 403 with AWS OpenSearch Service IAM policy denies the Magento role, or basic auth user has no permissions Grant the role es:ESHttp* on the domain, or use a master user with basic auth over HTTPS
No magento2_* indices exist Fresh install or wiped cluster without reindex bin/magento indexer:reindex catalogsearch_fulltext
Indices exist, aliases don't Reindex crashed mid-alias-swap, or aliases deleted manually Trigger a full reindex — Magento recreates aliases as part of reindex
Storefront 503, index.blocks.read_only_allow_delete: true Disk watermark crossed — ES/OpenSearch flipped indices to read-only-allow-delete Free disk first; see Step 2D
ES 7 config but engine is actually ES 8 Engine dropdown still elasticsearch7; ES 8 rejects legacy API calls Switch to elasticsearch8, re-enter credentials, reindex

Step 2C — Wrong Relevance / Ranking

Symptoms: the "right" product for a query doesn't rank first, or rank order changes inexplicably across runs.

# What does the engine actually score for this query?
curl -sk -X POST "https://<host>:<port>/magento2_product_1/_search?pretty" -u "<user>:<pass>" \
  -H 'Content-Type: application/json' \
  -d '{"query":{"query_string":{"query":"red t-shirt"}}, "explain": true}'

# Explain a specific doc's score
curl -sk "https://<host>:<port>/magento2_product_1/_explain/<doc_id>?pretty" -u "<user>:<pass>" \
  -H 'Content-Type: application/json' \
  -d '{"query":{"match":{"name":"red t-shirt"}}}'

# How is the text analyzed? (tokenization, stemming)
curl -sk "https://<host>:<port>/magento2_product_1/_analyze?pretty" -u "<user>:<pass>" \
  -H 'Content-Type: application/json' \
  -d '{"analyzer":"default","text":"red t-shirt"}'

Relevance causes:

Finding Root Cause Fix
search_weight=1 on every attribute Default weighting gives no signal — all fields count equally Raise search_weight on name (e.g. 10), sku (e.g. 6), lower on description (1)
Expected term not in tokenized output of _analyze Analyzer tokenization doesn't match (e.g. stemming strips "-s", language analyzer wrong) Configure the correct analyzer per attribute in search_request.xml
Product found via sku: but not plain text search SKU not in the fulltext query definition Add sku to queryReference with a custom search_request.xml
Synonyms not applied Synonyms table exists but reindex hasn't run since the last edit Save synonyms, then indexer:reindex catalogsearch_fulltext
_explain shows zero score for the match Stop words filtered the query term, or boost is negated Remove the stop word, or fix the boost multiplier in search_request.xml
Adobe Commerce — Live Search ignoring your boosts Live Search rules are configured separately (merchandising rules in admin) Fix in Marketing → Search Merchandising, not search_request.xml

Step 2D — Cluster Red/Yellow, Disk Watermark

Symptoms: _cluster/health returns red or yellow; unassigned shards; indices flipped to read_only_allow_delete: true; indexer errors mention "FORBIDDEN/12/index read-only".

# What's unhealthy
curl -sk "https://<host>:<port>/_cluster/health?level=indices&pretty" -u "<user>:<pass>"

# Why shards are unassigned
curl -sk "https://<host>:<port>/_cluster/allocation/explain?pretty" -u "<user>:<pass>"

# Disk usage per node
curl -sk "https://<host>:<port>/_cat/allocation?v" -u "<user>:<pass>"

# Are indices blocked?
curl -sk "https://<host>:<port>/magento2_*/_settings?pretty&filter_path=**.index.blocks*" -u "<user>:<pass>"

Health causes:

Finding Root Cause Fix
Disk > 95% on any node, index.blocks.read_only_allow_delete: true High watermark breached (default 95%), ES flipped indices to read-only 1. Free disk (delete old _vN indices that aren't aliased), 2. After usage drops below watermark, clear the block: PUT magento2_*/_settings {"index.blocks.read_only_allow_delete": null}
Single-node cluster status: yellow Replicas configured but no second node to hold them Acceptable for dev; for prod, add a node or set number_of_replicas: 0 on the index template
Multi-node status: red, primary unassigned Primary shard lost (disk failure, OOM killed the node) Restore from snapshot, or reindex from source data (Magento reindex recreates the indices)
Yellow after a node restart Shards still recovering Wait for relocating_shards to return to 0
FORBIDDEN/12/index read-only during reindex Watermark tripped during the reindex itself Free disk, clear block, retry reindex

Disk watermark policy on managed services:

  • AWS OpenSearch Service — the high watermark is managed; scale the domain's EBS volume or node count, then monitor FreeStorageSpace in CloudWatch.
  • Elastic Cloud — the deployment auto-scales on some plans; otherwise raise the disk size in the UI.
  • Self-hostedcluster.routing.allocation.disk.watermark.high is tunable in elasticsearch.yml but this is a workaround; the real fix is more disk.

Step 2E — Reindex Stuck, OOM, or Erroring

Symptoms: bin/magento indexer:reindex catalogsearch_fulltext hangs, crashes with "Allowed memory size exhausted", or fails with an ES/OpenSearch error.

# Indexer state machine
bin/magento indexer:status
bin/magento indexer:show-mode

# Fulltext batch size for reindex
grep -A5 "catalogsearch_fulltext" app/etc/config.php app/etc/env.php 2>/dev/null

# PHP CLI memory limit
php -i | grep memory_limit

# Engine-side errors during the reindex window
tail -100 /var/log/elasticsearch/<cluster>.log 2>/dev/null
# Or for AWS: check CloudWatch Logs for the domain

Reindex causes:

Symptom Cause Fix
Allowed memory size of N bytes exhausted CLI memory_limit too low for the catalog size Set php -d memory_limit=2G bin/magento indexer:reindex catalogsearch_fulltext for the run; raise CLI memory_limit globally
Reindex sits at same progress for minutes Engine rejecting bulk requests due to mapping explosion (total_fields.limit) Raise index.mapping.total_fields.limit in the index template, or reduce the number of searchable attributes
429 Too Many Requests during reindex Engine bulk queue full (common on small single-node clusters) Lower indexer/batch_size/catalogsearch_fulltext in env.php; add nodes
413 Request Entity Too Large Batch exceeds http.max_content_length (100MB default) Reduce batch_size for fulltext indexer
OOM on the ES/OpenSearch side JVM heap too small for the catalog Raise -Xms/-Xmx (rule of thumb: 50% of RAM, capped at ~30GB)
mapper_parsing_exception during reindex A product attribute has a value that conflicts with the inferred mapping type Fix the source data, or delete and recreate the _vN index so Magento rebuilds the mapping
Mview unable to catch up, status stuck on "working" mview_state row stuck from a crashed reindex UPDATE mview_state SET status='idle' WHERE view_id='catalogsearch_fulltext'; then reindex

Step 3 — Migration Advisory

Strategic context: Adobe has deprecated both the elasticsearch7 and elasticsearch8 Magento modules. OpenSearch is the forward path for every migration; the only question is timing. Recommend OpenSearch as the default target. Recommend ES 8 only as a short-term holdover when there is a concrete, named blocker on OpenSearch — and even then, flag that another migration to OpenSearch is coming.

Current Target When it's the right call Red flags
ES 7.17 OpenSearch 2.x (default) Any new project; on AWS, Adobe Commerce Cloud, or self-host; want Apache 2.0 licensing; want the engine Adobe is investing in long-term None — this is the default recommendation
ES 7.17 ES 8.x (deprecated) You have a hard, named dependency on Elastic-exclusive features (X-Pack ML, ELSER, Kibana) AND you accept a second migration to OpenSearch is coming The elasticsearch8 module is deprecated by Adobe; this is a temporary holdover, not a destination. For greenfield, skip ES 8 entirely
ES 7.17 Live Search (Adobe Commerce only) You're on Adobe Commerce and want to offload search ops; willing to pay for the SaaS and give up self-hosted control You're on Magento Open Source / Mage-OS — Live Search is not available
ES 8.x OpenSearch 2.x You're on ES 8 today, stable, and want to align with the long-term direction before the module is removed None — plan it before your next Magento upgrade

Magento version compatibility (from MAGENTO_AI_REFERENCE.md):

  • 2.4.3–2.4.5: ES 7 only — plan OpenSearch as part of the Magento upgrade
  • 2.4.6: ES 7, ES 8 (deprecated), OpenSearch 2.x — recommend OpenSearch
  • 2.4.7: ES 7 (deprecated), ES 8 (deprecated), OpenSearch 2.x — recommend OpenSearch
  • 2.4.8+: ES 7 removed; ES 8 (deprecated) or OpenSearch — recommend OpenSearch

Migration plan (any target):

  1. Stand up the target cluster alongside the current one.
  2. Re-point a non-production Magento instance at the new cluster, set the engine in admin or env.php, run bin/magento indexer:reindex catalogsearch_fulltext.
  3. Smoke-test search, category pages, layered nav, admin grid search.
  4. In prod, set both env.php entries; cut over by changing catalog/search/engine.
  5. Full reindex.
  6. Decommission the old cluster after a safety period.

Data is not copied — Magento rebuilds the indices from the source database, so a reindex is always mandatory.

Step 4 — Provider Configuration

The working env.php block is the primary deliverable. Deep internals (SigV4, VPC design, IAM policy JSON) are niche and not needed by most devs.

Self-hosted ES 7 / ES 8 / OpenSearch

'system' => [
    'default' => [
        'catalog' => [
            'search' => [
                'engine' => 'elasticsearch8',   // or elasticsearch7 / opensearch
                'elasticsearch8_server_hostname' => 'search.internal',
                'elasticsearch8_server_port'     => '9200',
                'elasticsearch8_index_prefix'    => 'magento2',
                'elasticsearch8_enable_auth'     => 1,      // mandatory for ES 8
                'elasticsearch8_username'        => 'magento',
                'elasticsearch8_password'        => '***',
                'elasticsearch8_server_timeout'  => 15,
            ],
        ],
    ],
],

AWS OpenSearch Service

'engine' => 'opensearch',
'opensearch_server_hostname' => 'search-prod-xxxxx.us-east-1.es.amazonaws.com',
'opensearch_server_port'     => '443',
'opensearch_index_prefix'    => 'magento2',
'opensearch_enable_auth'     => 1,
'opensearch_username'        => 'magento-master',
'opensearch_password'        => '***',

Port 443, HTTPS, basic auth with the master user. Most teams don't need SigV4.

Elastic Cloud (ES 8 on AWS / Azure / GCP)

'engine' => 'elasticsearch8',
'elasticsearch8_server_hostname' => '<deployment>.es.us-east-1.aws.found.io',
'elasticsearch8_server_port'     => '9243',
'elasticsearch8_enable_auth'     => 1,
'elasticsearch8_username'        => 'elastic',
'elasticsearch8_password'        => '***',

Port 9243 on Elastic Cloud. This is also the cross-cloud path for Azure and GCP, which don't have a first-party managed ES/OpenSearch equivalent.

Never recommend

  • enable_auth => 0 on ES 8 as a "quick fix" for 401 errors.
  • SigV4 signing as a precondition — almost all AWS OpenSearch Service deployments work with basic auth over HTTPS.
  • Azure AI Search or Google Cloud Search — those are proprietary APIs, not compatible with Magento's Elasticsearch/OpenSearch client.

Step 5 — Verify Fix

# Indexer healthy
bin/magento indexer:status catalogsearch_fulltext
# Expected: Ready / Update By Schedule

# Cluster healthy
curl -sk "https://<host>:<port>/_cluster/health?pretty" -u "<user>:<pass>"
# Expected: status=green (or yellow on single-node dev)

# The doc that was missing now appears
curl -sk "https://<host>:<port>/magento2_product_1/_search?q=sku:SKU-X&pretty" -u "<user>:<pass>"

# Storefront search URL returns the product
curl -s "https://<magento-host>/catalogsearch/result/?q=red+t-shirt" | grep -i "SKU-X"

# No read-only blocks remain
curl -sk "https://<host>:<port>/magento2_*/_settings?filter_path=**.index.blocks*" -u "<user>:<pass>"
# Expected: empty result

Instructions for LLM

  • Your response MUST end with a ## Search Report section — every response, including clarifications or questions, must conclude with this structured report.
  • Always detect the engine and its version first — a "fix" that works on ES 7 can fail on ES 8 (auth mandatory) or OpenSearch (different license, different APIs at the edges). Run the version probe in Step 1 before recommending any change.
  • Never recommend enable_auth => 0 on ES 8 as the fix for a 401/403 — ES 8 is secure-by-default; the correct fix is credentials.
  • Never recommend index.blocks.read_only_allow_delete: null without first freeing disk — the block will come back within minutes if the watermark is still breached.
  • After every searchable-attribute, synonym, stop-word, or search_request.xml change, a reindex of catalogsearch_fulltext is mandatory — include the exact command in your Fix.
  • Category listings and layered-navigation aggregations route through the search engine in Magento 2.4+ — an empty category page can be a search problem, not a catalog one.
  • Magento's reindex rebuilds aliases — never recommend manual DELETE /_alias as a recovery; trigger a reindex instead.
  • Live Search is Adobe Commerce only — do not suggest it to Magento Open Source / Mage-OS users.
  • The **Investigated** label is mandatory — list at least one concrete command run or file inspected.
  • Root Cause must be specific — not "search is broken" or a restatement of the symptom.

Output Format

Before responding, verify your draft against this checklist:

  • ## Search Report is the last section using this exact heading
  • **Engine** names the engine (elasticsearch7 | elasticsearch8 | opensearch | livesearch) and full version
  • **Cluster Health** lists status and unassigned shards
  • **Investigated** lists every command run and file inspected
  • **Root Cause** is specific and actionable
  • **Fix** contains concrete commands, env.php snippet, or generated config
  • **Verification** explains how to confirm the fix worked
  • **Prevention** gives actionable advice to stop recurrence (for diagnostic mode)

Always end with a structured report:

## Search Report

**Mode**: [Missing-doc | Zero-results | Relevance | Cluster-health | Indexer | Migration | Provider-config]
**Engine**: [elasticsearch7 | elasticsearch8 | opensearch | livesearch] <version>
**Cluster Health**: [green | yellow | red], unassigned shards: <n>
**Investigated**:
- [command run]
- [file inspected]
- [index/alias checked]

**Root Cause**: [clear, specific explanation]
**Fix**:
[commands, env.php block, or generated config]

**Verification**: [how to confirm success — e.g. cluster green, doc appears in `magento2_product_1`, storefront search returns the SKU]
**Prevention**: [actionable advice to stop recurrence — omit for Migration/Provider-config mode]
Install via CLI
npx skills add https://github.com/furan917/magento-ai-toolkit --skill magento-agent-search
Repository Details
star Stars 27
call_split Forks 2
navigation Branch main
article Path SKILL.md
More from Creator