Every skill in my creative library reads an artifact somebody produced. The attribute skill reads a listing. The review audit reads reviews. The main image lab reads a 52-tactic library I wrote by hand. Even when the skill has to go and fetch the evidence itself, the evidence is a thing โ a page, a record, a file with a URL.
This one reads a dropdown.
amazon-autocomplete-keyword-expander lives in ~/.codex/skills/, it is 771 words across 96 lines plus a four-line agent manifest, and its entire job is to type into the Amazon search box and read the suggestions that appear underneath it. There is no export button. There is no API. There is no report. The surface it reads exists for about four seconds and then it's gone, and if you didn't write it down it never happened.
That turns out to change the engineering in ways I didn't anticipate, and it introduced one guardrail class that none of my other skills have needed.
The problem, and what it costs to do by hand
Keyword research on Amazon is a solved problem in one direction and completely unsolved in the other.
If you want volume, you have tools. Helium 10, Jungle Scout, SmartScout, Brand Analytics โ they'll all give you a normalized search term with an estimated number next to it, and that number is what you bid against. Fine. That job is covered.
If you want phrasing, you have almost nothing. And phrasing is what I actually need, because I don't write bids. I write the copy that goes on an image, the first sixty characters of a 75-character title, and the Item Highlights line that now renders as its own row under the product name in desktop search. For all three of those, the question is not how many people search this โ it's what exact string does a person in this category type, and in what order do they type the modifiers.
Autocomplete is the only free source of that. It's Amazon telling you, in Amazon's own words, what it expects a shopper to be in the middle of typing.
Done properly by hand it's tedious in a specific way: you type the seed, read the panel, write the suggestions down, clear the field, type a narrower phrase, read again, write again, and repeat across four or five seeds. Call it thirty to forty-five minutes per product to do it thoroughly, most of which is transcription rather than thinking. Which is exactly why it's the step that gets skipped โ a keyword tool with a volume column feels more rigorous than a person squinting at a search box, so brands run the tool, get their normalized terms, and never once look at the literal strings.
The build
No scraping service. No proxy pool. No API key. The Codex in-app browser, already open, already on a logged-in Amazon session, plus a skill file telling it what to do and โ more importantly โ what not to.
The workflow itself is six steps and it's boring on purpose:
- Open the in-app browser and navigate to
https://www.amazon.com/. - Focus the search field labeled
Search Amazon. - Type the seed phrase.
- Read the suggestion rows.
- Replace the field text with one refined phrase.
- Read the second-layer suggestions.
The demonstration this was built from used mens belt, then mens nylon belt. What came back included mens belts stretchable, mens nylon belts 1.25 inch wide, and mens nylon belt with plastic buckle.
Look at those last two for a second, because they're the whole argument for the skill. 1.25 inch wide is a slot-two frame. with plastic buckle is a compatibility answer and possibly a return driver. A volume tool would normalize both of those into "mens nylon belt" and hand you a number. Autocomplete handed me the specification the shopper is actually holding in their head while they type.
The output is a CSV with columns root_seed, expanded_seed, suggestion, suggestion_type, modifier_type, notes, captured_at โ and I'll come back to that suggestion_type column, because it's the interesting one.
The constraint that isn't about safety
Here's the line in the file I'd point at if you only read one:
Do not submit the search unless the user explicitly asks for results-page validation.
An agent handed a search box submits the search. That is the single most obvious thing to do with a search box, it's what the affordance is for, and every model I've handed a browser to wants to press enter. So the file forbids it.
I initially wrote that rule for a boring reason โ submitting navigates you away from the panel you're trying to read, and you have to come back. Then I thought about it for another minute and realised it's load-bearing for a completely different reason.
Submitting a search writes to your search history. Your search history feeds your autocomplete.
So if the agent submits forty exploratory searches while mining a category, it has just taught Amazon a great deal about what this account is interested in โ and the next time anyone runs this skill on that machine, some portion of what comes back is the account's own past behaviour reflected back at it, dressed as market demand.
The act of measuring changes the thing being measured. Read-only isn't just the safe posture here, it's the methodologically correct one, and I didn't know that when I wrote the sentence. It's the first constraint in my library that turned out to be protecting the integrity of the data rather than the integrity of the account.
The new guardrail class: the surface is a mirror
Every prior skill I've written had to solve some version of don't make things up. This one has a problem I'd never had before: the page is personalized to the reader.
A logged-in Amazon session's autocomplete is not a clean market signal. Part of it is general demand and part of it is you โ your recent searches, your orders, your browsing. Amazon frequently labels these visually, and a human glancing at the panel knows to ignore the row that's obviously their own history. A model reading the visible text does not, unless you tell it to.
So the file tells it to:
If Amazon shows account-specific or shopping-history suggestions, label them as personalized and separate them from general keyword suggestions.
And the CSV carries suggestion_type values of keyword, question, or shopping-history/personalized, so the distinction survives into the artifact rather than living in whoever ran it.
The failure this prevents is worth naming precisely, because it's not a hallucination and it wouldn't look wrong. The bad version is a clean, well-formatted keyword map in which four of the twenty rows are things this account searched last month โ and then somebody briefs a shot list off it, or writes a title around a modifier that nobody outside the building has ever typed. Nothing errored. The report looks great. You've merchandised against a mirror.
There's a second rule in the same section that's purely about not being creepy, and I'd keep it even if the first one didn't exist:
If the page is in a signed-in state, avoid including private account, address, order, or browsing-history details in the user-facing output.
If this skill ever runs on a client's machine during a screen share, that sentence is the difference between a keyword report and an incident.
What broke: coordinates, branching, and a keyword that lies
The coordinates. This skill started life as a Record & Replay capture โ I demonstrated the flow once in the browser and Codex wrote down what I did. That gets you the sequence for free, which is genuinely useful. It also gets you a pile of pixel coordinates, which are a promise Amazon can break on a Tuesday. So the file explicitly throws them away:
Do not rely on coordinates from the recording. Use the accessible search field and visible suggestion text.
Record the sequence, discard the positions. A recording is a good way to learn a workflow and a terrible way to store one.
The branching. First real run, I asked for expansion on a five-seed category and got back something enormous. Every suggestion had been treated as a new seed, every one of those had produced six more, and the model was very pleased with itself. A model handed a tree structure will fill the tree โ the same failure as a model handed a quota filling the quota. The fix is one clause:
Avoid infinite branching; default to one expansion layer unless the user asks for a larger tree.
The keyword that lies. This is the one that matters commercially, and it's the reason a keyword skill written by a creative person looks different from one written by a PPC person. Autocomplete returns modifiers, and some of those modifiers are claims. waterproof. heavy duty. hypoallergenic. for hiking. Every one of them is a legitimate research finding about what shoppers type, and some of them are a suppression risk or a return driver if you put them in organic copy on a product that doesn't do that thing. So:
When using suggestions for Amazon listing work, separate fact-safe listing language from PPC-only or research-only terms. Do not recommend organic copy that misdescribes the product.
A keyword tool that hands you "waterproof" for a water-resistant product has not given you a keyword. It has given you a return, a one-star review about the product not being what the page said, and a contribution to a return rate that follows you around.
The honest limitation, said out loud
Autocomplete has no volume. It is a ranked list with no magnitudes attached, and anybody who tells you the top suggestion is the highest-volume one is guessing.
What a suggestion is is evidence that a phrase gets typed often enough that Amazon decided to put it in a dropdown. That's a floor, not a number. Which makes this a phrasing instrument and not a demand instrument, and the correct use is to pair it with something that actually reports volume rather than to replace it.
I'd rather write that sentence than let a nice CSV imply a precision it doesn't have.
Cost, and what I won't claim
The workflow was an evening. The constraints took longer than the workflow, which is now the fourth time in a row I've written that sentence in one of these posts and I've stopped treating it as a coincidence.
Running it costs a few dollars per session. There's no cron, no daemon, no unattended write path โ a human invokes it, a human reads the output, and a human decides what goes on a listing.
I'm not going to publish an hours-saved-per-month figure across a nine-person team. I don't have run logs that would support one and a made-up efficiency number is exactly the thing I'd call out in somebody else's post. The narrow true version: getting from a seed term to a labelled, deduplicated map of how shoppers phrase things in a category goes from thirty-odd minutes of transcription to a few minutes of reading. The judgment about which of those phrasings is fact-safe, which one earns the first sixty characters of a title, and which one deserves a frame โ unchanged, and that's the part I'm paid for.
The number on the other side of the ledger is the one that justifies it: one product title built around a modifier that turned out to be the account's own browsing history costs more than every minute this skill will ever save.
Six things worth stealing
- Ask whether the surface you're reading has an export. If it doesn't, the capture step is the product, and the schema you write down is the only version of that data that will ever exist. Put
captured_atin it. - Check whether reading the thing changes the thing. In a lot of live systems it does. Submitting, clicking, dismissing, and "let me just clean this up" all write state. My forbidden-actions list explicitly includes delete search history for that reason โ an agent tidying up after itself is an agent destroying your data.
- Record the sequence, throw away the coordinates. Record & Replay is a great way to author a workflow and a terrible way to store one.
- Cap the branching before you run it. Any recursive structure handed to a model will be filled to whatever depth you didn't forbid.
- Label personalized data as personalized, in the schema. If the surface is tailored to the reader, an agent reading it will hand you your own behaviour back as market evidence, and it will look exactly like a finding.
- Separate the research vocabulary from the publishable vocabulary. Not every true keyword is a safe claim, and the file is a better place to enforce that than your memory at 11pm.
The pattern across all of these build logs is starting to be embarrassingly consistent: the workflow is the cheap part, the constraint sentences are the product, and the expensive failures are always the ones that came back beautifully formatted and confidently wrong about something nobody thought to check.