Traits (L0–L3)
23 traits across 4 levels. What each is, how you get it, what the kernel does with it.
Traits are computed from what a component declares. You don’t label them — the kernel figures out what they are from what they do.
Summary
| Trait | Level | Triggered by | Description |
|---|---|---|---|
| identifiable | L0 | @component(name) |
Has a name, factory, version |
| lifecycle | L0 | @lifecycle.* |
Has activate/deactivate callbacks |
| dependable | L0 | @requires |
Declares dependencies |
| registrable | L0 | @provides/@requires |
Can provide/require services |
| inspectable | L0 | @lifecycle.health |
Has a health check |
| factoryable | L0 | @component |
Can be instantiated N times |
| observable | L1 | @requires(logger=ILogger) |
Has logging/tracing |
| configurable | L1 | @requires(config=IConfig) |
Has config |
| secured | L1 | @requires(auth=IAuth) |
Has auth/credentials |
| storable | L1 | @requires(storage=IStorage) |
Has storage |
| communicable | L1 | has @runnable or @subscribe |
Uses the bus |
| runnable | L2 | @runnable |
Has callable functions |
| subscribable | L2 | @subscribe |
Reacts to events |
| kinded | L2 | @kind |
Defines data schemas |
| skillful | L2 | @skill |
Provides AI knowledge |
| routable | L2 | @api |
Has API surface declarations |
| reactive | L2 | @computed or @effect |
Has reactive properties/effects |
| adaptable | L2 | (aspirational) | Wraps external tools |
| targeted | L3 | has @prop declarations |
Parameterized with properties |
| scoped | L3 | @requires(creds=ICredentials) or @requires(storage=IStorage) |
Uses structurally-scoped services |
| versioned | L3 | version != "0.0.0" |
Has a version |
How Traits Are Computed
The kernel reads ComponentMeta at discovery time and auto-infers traits:
# This component...
@component("search", version="1.0")
@requires(config=IConfig, logger=ILogger)
@api("rest", prefix="/search")
class SearchApp:
@computed
def url(self): return self.rt.config.get("url")
@runnable("search", params=P, description="Search")
async def search(self, params): ...…automatically gets these traits:
- L0: identifiable, lifecycle, dependable, registrable, factoryable
- L1: configurable, observable, communicable
- L2: runnable, routable, reactive
- L3: versioned
Query at runtime:
status = kernel.status()
for comp in status["components"]:
print(f"{comp['name']}: {comp['traits']}")