Declarative objects have a simple protocol: you can use classes in lieu of instances and they are equivalent, and any keyword arguments you give to the constructor will override those instance variables. (So if a class is received, we'll simply instantiate an instance with no arguments).
You can provide a class variable __unpackargs__ (a list of strings), and if the constructor is called with non-keyword arguments they will be interpreted as the given keyword arguments.
If __unpackargs__ is ('*', name), then all the arguments will be put in a variable by that name.
You can define a __classinit__(cls, new_attrs) method, which will be called when the class is created (including subclasses). Note: you can't use super() in __classinit__ because the class isn't bound to a name. As an analog to __classinit__, Declarative adds __instanceinit__ which is called with the same argument (new_attrs). This is like __init__, but applied after __unpackargs__ and other factors have been taken into account.
If __mutableattributes__ is defined as a sequence of strings, these attributes will not be shared between superclasses and their subclasses. E.g., if you have a class variable that contains a list and you append to that list, changes to subclasses will effect superclasses unless you add the attribute here. So any variables listed there will be copied (shallowly).
See the source for more information.