A collection of Entities (1 or more, including other Aggregates) and potentially, Value Objects.
From Eric Evan’s blue book:
An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each AGGREGATE has a root and a boundary. The boundary defines what is inside the AGGREGATE. The root is a single, specific ENTITY contained in the AGGREGATE.
The root is the only member of the AGGREGATE that outside objects are allowed to hold references to[.]
From his “What I’ve learned about DDD since the book” talk:
Aggregates turned out to be one of the most difficult patterns to apply. There was an over-emphasis on access rules within aggregates (nobody can hold a reference to things within an aggregate apart from the aggregate root). A much more useful view at aggregates is to look at them as consistency boundaries for transactions, distributions and concurrency. […] Aggregates should be boundaries of consistency which you can trust.
Ideally, your repositories should only return Aggregates.
Objects with an unequivocal identity, holding data and business rules to validate them. Should only contain Value Objects or primitives, or else they become Aggregates.
https://codeopinion.com/aggregate-design-using-invariants-as-a-guide/