Composition
Elements rarely stand alone — you compose them: an app references the elements it deploys, an automation routes data between steps, a wire connects one element’s output port to another’s input, a lab connects a brain/ears/mouth.
Composition is about how elements relate — the static structure that links one element to another. It is distinct from a run, which is what happens when you actually invoke an operation. You compose first; the composed elements run later.

How elements relate
Every circle’s elements live as a flat list in the circle’s private schema — there is no owning tree of folders. Relationships between those flat elements are expressed in a few distinct ways, and it matters which one you reach for.
Containment (parent_id). One element can own another. This is the owner link a board
has over its cards, or a lab over its brains. After the 2026-05-04 flat-element migration
most elements sit top-level with no parent; containment survives only for the cases below.
References (element_references). An explicit “uses” link with an alias and a
version_pin, stored in a per-circle table. Reach for this when element A must point at a
specific element B and you want that choice pinned.
Dispatch-by-lookup. The idiomatic “element A uses element B” at runtime: A looks up B
by element type (e.g. a sales-board finding the circle’s io/linkedin) and calls an
operation on it. No foreign key, no structural link — the connection is resolved when it’s
needed and re-resolved each time. If you find yourself asking “what’s the FK from this
element to that one?”, the answer is usually this: there isn’t one.
Compound elements nest their children
Two element families are genuinely compositional on disk — they parent their children, and those children only make sense inside the parent:
automationparentscondition,loop, andwait— the control-flow steps that make up an automation.labparentsbrain,ears, andmouth— the faculties of an intelligence lab.
These six are the only remaining parent_id consumers after the flat-element migration.
A nested child is addressed under its parent’s slug:
/api/{circle}/{parent_slug}/{child_slug}
Everything else is a flat element at /api/{circle}/{slug}, with category and element-type
as metadata for dispatch and filtering — never path segments.
Bonds (relational metadata)
Some relationships are neither containment nor a pinned reference but facts about an
element — “this pursuit card is about lead X, organization Y”. Those are bonds, stored
today as JSON in the element’s meta.bonds and resolved on read. Bonds are live for
sales-board pursuit state (a card’s lead_id / organization_id / contact_ids); for
everything else they remain intent rather than a queryable structure. A dedicated bonds
table is staged but not yet shipped, so do not assume bonds can be queried across elements
in SQL — parent_id is still authoritative for non-sales paths.
Authoring: on the canvas or in YAML
You compose elements two ways, both landing in the same place. On the canvas you create
elements and draw the connections between them — for example a wire joining one element’s
output port to another’s input — and the platform records each element and its
relationships as rows in the circle’s schema. The same structure can be declared as element
YAML and generated, which is how the built-in element types and their compositional rules
(what a compound element may contain) are defined. Canvas edits and YAML are two front-ends
onto one model: flat elements plus the relationship records that link them.