Tags
One label vocabulary across every primitive: declare and annotate tags, attach them on each owning surface, filter by them, and rename, merge, or delete them everywhere at once.
Tags are the campaign handle — there is no separate campaign object. Put the same label on a sequence, its lead table, the workflow feeding it, the conversations it produces, and its learnings wiki page, and tags get returns the whole footprint in one read.
A tag exists once it is declared (a registry row carrying a description, colour, and pinned flag) or carried (some item's tags array holds it). Either alone is enough, and drift is permanent in both directions: a declared tag nobody uses stays declared with a count of 0, and a carried tag nobody declared is fully real — it indexes, renames, merges, and deletes like any other.
Labels are lowercased, trimmed, and deduplicated, up to 50 per item. They are not slugified: "Q3 Outbound" becomes q3 outbound, spaces intact. Chip colour derives from the label unless someone sets an override, so the same tag looks the same everywhere by default.
Browse
oxygen tags list # every tag with per-primitive counts, most-used first
oxygen tags get q3-outbound # everything carrying the tag, deep-linked/tags is the same read plus editing: search across labels and descriptions, All / Pinned / Unused facets, New tag, per-row Edit… / Rename… / Pin / Delete…, and a selection bar with Merge into… / Pin / Unpin / Delete. Each tag's own page groups its items by kind. Tag chips filter the sequencer, publishing queue, and unibox lists; ?tag= deep-links into a pre-filtered view.
Declare and annotate
oxygen tags create q3-outbound --description "Q3 founder-led launch" --color blue --pinned
oxygen tags update q3-outbound --clear-color --unpinnedcreate is idempotent and never touches carriers — running it on a tag forty items already carry just annotates it. Colours are the named set (gray, red, orange, amber, yellow, green, teal, blue, indigo, purple, pink); omit --color to keep deriving it from the label. update changes only the flags you pass; --clear-description and --clear-color remove a value. To change the label itself use tags rename.
Attach
Tags are attached on each primitive's own surface:
oxygen sequences create ... --tags q3-outbound,saas-founders
oxygen sequences update <sequence> --tags q3-outbound # replaces the set; "" clears
oxygen tables tag <table> --tags q3-outbound
oxygen workflows tag <workflow> --tags q3-outbound # org metadata; no new revision
oxygen knowledge page upsert --slug <slug> --tags q3-outbound ...
oxygen publishing tags set <post> --add q3-outbound # add/remove deltas
oxygen inbox tag <conversation> --add q3-outbound # add/remove deltas; --channel linkedin/whatsapp for DMs
oxygen crm tag companies <record> --add tier-1 # add/remove deltas (run `oxygen crm setup` once to add the attribute)
oxygen mailboxes tag <mailbox> --tags q3-pool # pool sending identities under a campaign
oxygen senders tag <sender> --tags q3-pool
oxygen blueprints tag <blueprint> --tags q3-outbound # a saved blueprint; no re-export needed
oxygen domains tag acme.com --tags q3-pool # sending domains (survives `domains sync`)
oxygen projects tag outbound --tags q3-outbound # table projects
oxygen senders profiles tag <id> --tags q3-pool # a whole sending identity in one edit
oxygen voice numbers tag +14155550142 --tags q3-pool # dialing numbersFeeds carry no tags of their own: a live table's capture is part of the table, so oxygen tables tag is where a feed joins a campaign.
Most list commands accept --tag to filter — sequences list, publishing posts list, tables list, workflows list, messages query, blueprints list — each taking one tag.
Every sending-identity list — mailboxes, domains, senders, senders profiles, voice numbers — takes --tag as a comma-separated set instead, matching any of them:
oxygen mailboxes list --tag q3-pool,q4-pooloxygen inbox list --tag is the exception: it filters on the tags of the conversation's campaign (its sequence), not the conversation's own tags. DMs have no campaign link, so a tag filter there returns email only.
An archived sequence is otherwise immutable but still accepts a tags-only update, so finished campaigns can still be filed into a learnings tag.
In the web app
Anywhere tags appear there is an editing affordance: Add tags beside a tag glyph on an item with none yet, collapsing to a + once it has some (tight call sites show the + in both states). It opens a picker listing the tags your workspace already uses, pinned first, each with its carrier count; type to filter. Pick any number of them; if what you type doesn't exist yet, choose Create "…" and it's added on save. On list rows, clicking an existing tag chip filters the list instead; the add affordance is what edits.
Your changes save when you close the picker. If someone (or the AI Inbox Tagger) adds a tag while you have it open, that tag is kept — the picker only applies what you actually changed.
Filtering the sending pool
On Sequencer → Accounts, every tab (Senders, LinkedIn, Email, WhatsApp, Phone numbers) has a Tags dropdown next to its search box. Pick one or more tags to narrow the list to anything carrying any of them; clicking a tag chip on a row does the same thing, and clicking it again removes it.
The Email tab lists inboxes under their domains, and both can be tagged. Tagging the domain is the shortcut: filter to that tag and the domain shows up with all of its inboxes, so you don't have to tag twenty inboxes one at a time. Combine the tag filter with another filter (say Provider) and it narrows to inboxes proper — a tagged domain with no matching inbox drops out.
Auto-tagging inbound conversations
The AI Inbox Tagger (a workspace agent at /agents/inbox-auto-tagger; the /agents nav entry is beta-gated) classifies every new inbound conversation against a tag allowlist you configure and applies the matches automatically — riding the same analysis call that already categorizes replies, so it adds no model cost. It only ever adds tags, and it never re-adds a tag you removed from a conversation.
oxygen inbox auto-tagger get
oxygen inbox auto-tagger set --enabled --tags "pricing-question,partnership,support-request"
oxygen inbox auto-tagger set --channels email,linkedin # default is all three
oxygen agent get inbox-auto-tagger # state + recent tag applications--tags replaces the whole allowlist (max 50). --tags "" clears it, which pauses tagging while leaving the agent enabled.
Reshape the vocabulary
oxygen tags rename q3-outbound q3-founder-launch # preview: per-kind counts, no writes
oxygen tags rename q3-outbound q3-founder-launch --apply
oxygen tags merge q3-outbound q3-old --into q3-founder-launch --apply
oxygen tags delete q3-old q3-scratch --apply # IRREVERSIBLEAll three are preview-first: without --apply they print per-kind (and per-tag) would-change counts and mutate nothing. All three are unfiltered by liveness — archived and finished items are rewritten too, so an un-archive never resurfaces the old name. That is why a preview count can legitimately exceed what tags list shows, which hides archived carriers. All three are safe to re-run after a partial failure.
Rename onto an existing tag behaves exactly like merging into it. When a tag absorbs another, the surviving tag wins per field, but a field it left empty is filled from the first source that has one; pinned ORs. delete strips the tag from every carrier and removes its declaration.
Semantics worth knowing
- Whole-set vs delta is per-surface, and the flag names it:
--tagsreplaces every tag on the item (--tags ""clears them) with no preview step, so read the current tags first when you mean to edit rather than overwrite. Exactly three surfaces take--add/--removedeltas instead — publishing posts, inbox conversations, and CRM records — so the auto-tagger and your edits merge instead of clobbering each other. Every other surface is whole-set, projects, sending domains, sender profiles and phone numbers included. - The tag index hides finished work: archived tables, wiki pages, blueprints, domains, projects, sender profiles and conversations drop out, as do canceled posts, disabled mailboxes, disconnected senders, and released phone numbers. Archived sequences stay in.
- The unibox's warmup/DMARC/bounced markers are system badges — derived state, not tags.
- Tags carry no approvals and spend no credits — they are workspace metadata.