All documentation

Tags and keywords

What a tag attaches to and where you can filter by one, and precisely what the keywords screen does today.

Tags settings screen showing the project's tags with add and remove controls

Tags

A tag is a short label you attach to a prompt, project-scoped and unique within it: the table carries a project id and a uniqueness constraint over the pair of that id and the name (alembic/versions/46d194c8c504_baseline_schema.py#upgrade), and the create endpoint refuses a name the project already has (api/routers/tags.py#create_tag). You create one from /settings/tags, by typing a name; there's no separate "create" step anywhere else, because typing an unrecognised name in the prompt editor creates it too, described below (api/routers/tags.py#create_tag). Nothing here can rename a tag once it exists; the tags router has no update endpoint, only create and delete.

A tag attaches to a prompt through the same relationship Prompts describes for the prompt record itself: creating or editing a prompt sends a list of tag ids, and the backend replaces the prompt's tags with the tags in that list that belong to the same project (api/routers/prompts.py#create_prompt, #update_prompt, #_attach_prompt_metadata). There is exactly one place in the app where you can filter by tag: the prompt list's tag dropdown, built from whatever tags the project actually has (frontend/src/routes/(app)/prompts/+page.svelte#tagFilter). Attaching one happens in the prompt create and edit form, which accepts free-typed tag names, matches each one to an existing tag case-insensitively, and creates a new tag on the spot for any name that doesn't match, through the shared resolveTagIds helper in frontend/src/lib/api/prompt-form.js (frontend/src/routes/(app)/prompts/+page.server.js#actions, frontend/src/routes/(app)/prompts/[id]/+page.server.js#actions).

Keywords

A keyword is the same shape as a tag at the data level: a short, project-scoped, unique label, created and deleted the same way, from /settings/keywords (alembic/versions/46d194c8c504_baseline_schema.py#upgrade, api/routers/keywords.py#create_keyword, #delete_keyword). It attaches to a prompt through the same field and the same code path a tag does: creating or editing a prompt sends a list of keyword ids, and the backend replaces the prompt's keywords with the ones in that list belonging to the same project (api/routers/prompts.py#create_prompt, #update_prompt, #_attach_prompt_metadata).

Attaching one happens in the prompt create and edit form, in its own picker beside the tag picker. It offers the keywords the project already has as buttons, takes a free-typed one, trims and lowercases it, and creates any name that does not exist yet, through a resolveKeywordIds helper written to mirror the tag one (frontend/src/lib/api/prompt-form.js#resolveKeywordIds, frontend/src/routes/(app)/prompts/+page.server.js#actions, frontend/src/routes/(app)/prompts/[id]/+page.server.js#actions).

Where a keyword then shows up is three places, and that is the whole list: as a chip on each row of the prompt list, as a chip in the header of a prompt's own page, and as a filter dropdown on the prompt list, which narrows alongside the status, tag and country dropdowns rather than instead of them (frontend/src/routes/(app)/prompts/+page.svelte#keywordFilter). The list can draw those chips because GET /projects/{id}/prompts returns each prompt's keywords next to its tags (api/routers/prompts.py#list_prompts, api/schemas/prompt.py#keywords). A prompt's own page reads them from the editable prompt record instead, since the read-only detail response it leads with carries tags but no keywords (frontend/src/routes/(app)/prompts/[id]/+page.svelte#promptKeywords).

Length and count caps

Each settings form now caps what you can type at exactly what the column behind it holds: 100 characters for a tag, 255 for a keyword (frontend/src/routes/(app)/settings/tags/+page.svelte#newTag, frontend/src/routes/(app)/settings/keywords/+page.svelte#newKeyword, alembic/versions/46d194c8c504_baseline_schema.py#upgrade). Neither create endpoint measures the name before inserting it (api/routers/tags.py#create_tag, api/routers/keywords.py#create_keyword), so those two form limits are the only thing standing in front of the database.

There is a second way in that carries no limit at all. The free-typed tag and keyword boxes in the prompt editor set no maximum length (frontend/src/lib/components/AddPromptModal.svelte#addCustomKeyword), so an over-long name typed there passes the form, passes the endpoint, and fails only when the database refuses the insert. Neither a tag nor a keyword has any cap on how many a project can have.

  • Prompts: the prompt record both tags and keywords attach to, and the create and edit form both of them reach through
  • Projects: the project scope every tag and keyword belongs to, alongside its team and its activity log
  • Team: who can create or delete a tag or a keyword, and who can only read them

Last verified 2026-08-11

Start monitoring your AI visibility.

See how AI search engines talk about your brand.

Free to start. No credit card required.