Tags: roar and GLaaS
On this page
What tags are
Tags are governed, hereditary metadata. A tag records a compliance-relevant fact about an artifact — its license, whether it contains PII, its data-residency jurisdiction — and then flows downstream on its own. Tag a raw dataset contains_pii=present, and every model, checkpoint, and export derived from it inherits that tag through the lineage graph, without you re-stating it at each step.
That inheritance is the whole point. Labels are freeform metadata you attach and maintain. Tags are a small, governed vocabulary that roar propagates for you — so a compliance fact established once at the source can't quietly fall off the record three transforms later.
Tags live under the reserved tag.* namespace inside the same versioned label document, but they are not freeform: they carry per-value provenance (who set each value, and which job it came from) and a bind ledger that controls how far they travel. You interact with them through the dedicated roar tag verb, never through roar label.
Availability. Tags are a
roar0.4.0 feature.
Quick use
roar tag add contains_pii=present raw.csv # tag an artifact by path or hash
roar tag add license=Apache-2.0 @2 # tag the output(s) of job step 2
roar tag show model.pkl # show current tags
roar tag history model.pkl # every revision, append-only
roar tag why contains_pii model.pkl # explain how it got this tag
roar tag rm license=Apache-2.0 @2 # remove one value
roar tag rm license @2 # remove the whole kind
roar tag bind model.pkl # promote its tags across sessions
roar tag unbind model.pkl # revoke that promotion
Targets are the same everywhere: @N is job step N in the active session; a path or hash prefix is an artifact.
Canonical kinds
Tags are restricted to a small canonical vocabulary, because a typo'd kind (licence, pii_present) is a compliance fact that silently doesn't propagate and doesn't match a search. The built-in kinds are:
| Kind | Meaning |
|---|---|
license | Distribution license of the artifact |
contains_pii | Whether the artifact contains personal data |
jurisdiction | Data-residency / legal jurisdiction |
classification | Sensitivity classification |
special_category | GDPR Art. 9 / special-category data |
roar tag add rejects an unknown kind by default and tells you exactly how to allow it. If your organization has its own vocabulary, opt in per-project with a .roarconfig:
[tags]
custom_kinds = ["export_control", "retention_class"]
Custom kinds are additive — they extend the canonical set rather than replace it, and the append-aware error message spells out the two lines to add so you don't have to guess the format.
Heredity: how tags propagate
Within a session, tags propagate automatically from a job's inputs to its outputs. Run a training job whose input dataset is tagged contains_pii=present, and the model it produces is tagged contains_pii=present too — marked as inherited (origin=system) and stamped with the producing job, so the record shows the value wasn't a fresh human assertion but a consequence of the lineage.
Each value therefore carries where it came from:
origin=user— a human act: a bareroar tag add, orroar run --add-tag.origin=system— inherited via propagation at job-record time, annotated with the job that carried it.
Propagation is deliberately over-approximate within a session (a false positive is cheap and safe; a false negative is a compliance miss). It is a union: an artifact accumulates every value it inherits, and roar tag rm never rewrites history — it just stops a value from propagating forward.
Crossing sessions: bind
Automatic propagation stops at the session boundary. Crossing it requires an explicit bind — a human act naming the concrete artifact whose tags are of record. This is what stops a stray 0-byte or scratch artifact from one project infecting everyone else's work: tags don't leak across sessions, users, or organizations unless someone deliberately promotes them.
roar tag addon a named artifact is born bound — naming a concrete, inspectable artifact is itself the human act, so it writes an implicit bind covering exactly the value you added.roar run --add-tagstays session-scoped until you bind the artifact — it stamps the output within the run but doesn't promise anything cross-session.roar tag bind <artifact>promotes an artifact's current tag set to cross-session scope;roar tag unbindrevokes it.roar register --bind/--no-bindcontrols whether registering to GLaaS promotes the artifact's tags.
The bind ledger is append-only: bind and unbind write events, they never delete. One unbind heals the whole downstream cone — everything that inherited through a revoked bind becomes mechanically identifiable as superseded. roar tag bind echoes what it promotes (path, size, and the tag set) so binding junk means reading past a line telling you the artifact is empty.
Explaining a tag: roar tag why
Compliance is about accountability, so every inherited tag can be traced back to the human act that originated it:
roar tag why contains_pii model.pkl
# Why does model.pkl have contains_pii?
# model.pkl contains_pii=present (inherited from job train.py)
# └─ raw.csv contains_pii=present (tag add — user)
roar tag why walks the inheritance path back to the originating tag add / run --add-tag, annotating any cross-session hop with the explicit bind that authorized it. It explains an artifact's tag; point it at an artifact (by path or hash), not a job step.
Barriers on roar run
Sometimes inheritance shouldn't happen — a step genuinely strips PII, or produces a differently-licensed output. Two run modifiers shape what a job records:
roar run --block-tag contains_pii -- python anonymize.py # stop a kind from inheriting
roar run --block-tag license=GPL-3.0 -- python build.py # stop one value
roar run --add-tag contains_pii=absent -- python anonymize.py # assert a value on the outputs
--block-tag KIND blocks a whole kind from propagating into this job's outputs; --block-tag KIND=VALUE blocks a single value; --add-tag KIND=VALUE stamps a value.
These modifiers are recorded on the job and replayed by roar reproduce. A barrier is a property of the job, not a flag you have to remember — so reproducing a pipeline reproduces the tag layer faithfully, instead of silently re-inheriting a tag you had deliberately blocked.
Seeing tags
Both roar show and roar tag show render tags the same way — a clean Tags section listing kind: value1, value2, with the internal bind ledger hidden. Jobs additionally show a Barriers section when they carried --block-tag modifiers. roar tag history shows every version of the tag document, append-only.
Visibility
Tags follow the scope of the artifact they're attached to, exactly like labels:
| Scope of the artifact | Tag readable to … |
|---|---|
anonymous | public |
public | public |
private | you only |
<owner>/<project> | project members only |
A tag on a private artifact is invisible outside that scope — GLaaS never returns a tag to someone who can't already read the artifact it's on. There is no way to make an artifact private but its tags public; the tag inherits the artifact's visibility.
Tags on glaas.ai
When you roar register a tagged artifact, its tags travel with it. On glaas.ai the artifact's record carries its tags — following the scope rules above — so the license and PII status you established at the source are visible on the registered artifact for anyone entitled to see it. This is what turns a private, per-repo convention into an organization-wide compliance record, and feeds the audit / AI-BOM view of what a model is actually built from.
Where to look next
- Labels — freeform metadata; tags are the governed, hereditary subset under
tag.*. - Scopes — how tag visibility, and the bind boundary, follow scope.
- Audit (AI-BOM) — tags as part of the bill of materials for a model.
- roar Guide — the full
roar tagcommand reference.