Specs → Attributes (🧪 Beta)
Beta Feature
client.attributes is currently in beta. The existing client.inventory.get_specs()
and client.inventory.add_specs() methods continue to work but are deprecated and will
be removed in SDK 2.0. Adopting the new Attributes API now is entirely opt-in — you can
migrate at your own pace.
What's changing
The legacy Specs system is being replaced by two new concepts:
- Attributes — globally-defined, reusable property templates (e.g. "Viscosity @ 25°C")
managed at the tenant level via
client.attributes. - Reference Values — the actual measured or assigned values for a given attribute on a
specific inventory item or lot, managed via
client.attributes.add_values()and related methods.
Previously, specs were defined and assigned to inventory items in a single step using
InventorySpec. The new API separates definition (what property is being tracked)
from value (what that property measures for this specific item).
Timeline:
| SDK version | What's available |
|---|---|
| 1.x (current) | Both client.inventory.get_specs() / add_specs() (deprecated) and client.attributes (beta) are available |
| 2.0 (planned) | get_specs(), add_specs(), InventorySpec, InventorySpecValue, InventorySpecList are removed |
Migrating now means your code is ready for 2.0 without further changes.
What's new
- Centralised attribute library — attributes are defined once at the tenant level and reused across any number of inventory items and lots. Specs were defined per-item with no sharing.
- Typed validation — each attribute declares a
datatype(number,string,enum) with optional range or operator constraints. - Lot-level values — reference values can be assigned to individual lots (
LOT…), not just inventory items. - Scoped reads —
get_values(scope=ALL)returns values for an inventory item and all its lots in one call. - Search —
client.attributes.search()provides full-text and field-level search across the attribute catalogue.
Side-by-side comparison
client.inventory (deprecated) |
client.attributes (new) |
|
|---|---|---|
| Define a property | Inline in InventorySpec |
client.attributes.create(attribute=...) |
| Assign a value to inventory | add_specs(inventory_id=..., specs=[...]) |
add_values(parent_id=..., values=[...]) |
| Read values for multiple inventory items | get_specs(ids=[...]) |
get_by_parent_ids(parent_ids=[...]) |
| Read values for inventory + lots | ❌ not supported | get_values(parent_id=..., scope=ALL) |
| Read values for lots only | ❌ not supported | get_values(parent_id=..., scope=LOT) |
| Remove a specific value | ❌ not supported | delete_values(parent_id=..., attribute_ids=[...]) |
| Remove all values | ❌ not supported | clear_values(parent_id=...) |
| Search attributes | ❌ not supported | client.attributes.search(text=...) |
| Shared attribute definitions | ❌ not supported | ✅ defined once, used everywhere |
| Return model | InventorySpecList |
AttributeValuesResponse |
Migrating
Step 1 — Create attribute definitions
In the old system, property definitions lived inside each InventorySpec. In the new system,
you define attributes once and reuse them.
from albert.resources.attributes import Attribute, AttributeCategory, ValidationItem
from albert.resources.parameter_groups import DataType, Operator
# Create a reusable "Viscosity" attribute
viscosity_attr = client.attributes.create(
attribute=Attribute(
datacolumn_id="DAC123", # the data column this property maps to
category=AttributeCategory.PROPERTY,
reference_name="Viscosity @ 25°C",
validation=[
ValidationItem(
datatype=DataType.NUMBER,
min=0.0,
max=500.0,
operator=Operator.BETWEEN,
)
],
)
)
print(viscosity_attr.id) # e.g. "ATR469"
Step 2 — Assign values to inventory items
from albert.resources.attributes import AttributeValue
# Before (deprecated)
from albert.resources.inventory import InventorySpec, InventorySpecValue
client.inventory.add_specs(
inventory_id="INVA123",
specs=[
InventorySpec(
name="Viscosity",
data_column_id="DAC123",
value=InventorySpecValue(reference="45.2"),
)
],
)
# After
client.attributes.add_values(
parent_id="INVA123",
values=[
AttributeValue(attributeId=viscosity_attr.id, referenceValue=45.2),
],
)
add_values is upsert — if a value already exists for an attribute it is updated, not
duplicated.
Step 3 — Read values back
# Before (deprecated)
spec_lists = client.inventory.get_specs(ids=["INVA123", "INVA456"])
for spec_list in spec_lists:
for spec in spec_list.specs:
print(spec.name, spec.value.reference)
# After — bulk read across multiple inventory items
responses = client.attributes.get_by_parent_ids(parent_ids=["INVA123", "INVA456"])
for response in responses:
for attr_value in response.attributes:
print(attr_value.attribute_definition.name, attr_value.reference_value)
# After — single item with lot-level scope
for response in client.attributes.get_values(
parent_id="INVA123",
scope=AttributeScope.ALL,
):
print(response.parent_id)
for attr_value in response.attributes:
print(attr_value.attribute_definition.name, attr_value.reference_value)
Removing values
The old InventorySpec API had no way to remove values. The new API supports both targeted
and full removal.
# Remove a specific attribute's value
client.attributes.delete_values(
parent_id="INVA123",
attribute_ids=["ATR469"],
)
# Remove all attribute values from an inventory item
client.attributes.clear_values(parent_id="INVA123")
# Remove all values from an inventory item and all its lots
client.attributes.clear_values(parent_id="INVA123", scope=AttributeScope.ALL)
Resource model changes
InventorySpec (deprecated) |
AttributeValue + AttributeValuesResponse (new) |
|
|---|---|---|
| Property identifier | data_column_id: str (inline) |
attribute_id: AttributeId (references a shared Attribute) |
| Value | InventorySpecValue.reference: str |
reference_value: str \| float \| None |
| Range | InventorySpecValue.min, .max |
AttributeValueRange.min, .max, .comparison_operator |
| Property metadata | Embedded in InventorySpec |
Separate AttributeDefinition (name, datacolumn, unit, validation, prmCount) |
| Lot-level support | ❌ | ✅ — any parent_id including LOT… IDs |
Deprecated symbols
The following are deprecated in 1.x and will be removed in 2.0:
| Symbol | Replacement |
|---|---|
client.inventory.get_specs() |
client.attributes.get_by_parent_ids() |
client.inventory.add_specs() |
client.attributes.add_values() |
InventorySpec |
Attribute + AttributeValue |
InventorySpecValue |
AttributeValueRange |
InventorySpecList |
AttributeValuesResponse |