Capability Selection
In the first guide, we used tags to apply behavior to data. In this guide, we take the next step: tags can also select which behavior applies.
This is where Tagex starts to look less like data cleanup and more like a semantic control mechanism.
The Problem: the Same Data, Different Meaning
In real systems, the same struct often needs to behave differently depending on context:
- Free vs paid users
- Development vs production
- Internal vs external consumers
- Different deployment tiers
This logic is usually implemented with conditionals scattered across the codebase.
Declaring Capabilities with Tags
With Tagex, you can encode capability-dependent semantics directly on fields.
type JobConfig struct {
MaxConcurrency int `cap:"limit, tier=premium"`
}
This tag does not say “this value must be valid”. It says:
Apply thelimitdirective using thepremiumtier.
Implementing a Capability-Aware Directive
A directive is free to consult external context: environment variables, configuration, licenses, or feature flags.
type LimitDirective struct {
Tier string `param:"tier"`
}
func (d *LimitDirective) Name() string {
return "limit"
}
func (d *LimitDirective) Mode() tagex.DirectiveMode {
return tagex.MutMode
}
func (d *LimitDirective) Handle(val int) (int, error) {
max := lookupLimitForTier(d.Tier)
if val > max {
return max, nil
}
return val, nil
}
This directive does not reject values. It adapts them to the declared capability.
Registering Capability Semantics
capTag := tagex.NewTag("cap")
tagex.RegisterDirective(&capTag, &LimitDirective{})
The same struct can now express different behavior without conditional logic in application code.
Context-Sensitive Processing
cfg := JobConfig{
MaxConcurrency: 32,
}
_, _ = capTag.ProcessStruct(&cfg)
Depending on the tier:
- Free users might be capped at 4
- Premium users might allow 16
- Enterprise users might allow 64
The struct itself declares which semantics apply.
Why This Is Not Validation
At no point did we ask: “Is this value allowed?”
Instead, we asked:
What does this value mean under this capability?
The same input can legitimately result in different outcomes depending on context.
What Capability Selection Buys You
- No scattered
if tier == ...logic - No duplicated policy enforcement
- Semantics live with the data they affect
- Behavior is explicit and inspectable
Tags become a declarative interface between data and policy.
Looking Ahead
So far, directives have:
- Normalized values
- Selected behavior based on capabilities
In the next guide, we will look at what happens after all semantics have succeeded, and why Tagex’s post-processing model is such a powerful abstraction.