Entity connections
The two ways entities connect, structural links and semantic relations, and when to use each.
Records in your pod connect to each other in two ways. A structural link is a field on a record that points to another record, such as the contact on a deal. A semantic relation is a typed edge in the pod's graph, such as a note that references a decision. You read both together, in one list.
The two systems
| Structural links | Semantic relations | |
|---|---|---|
| Stored as | A field whose value is another record's id (valueType: "entity_id") | A relation with a type, between two records |
| Defined by | The kind's fields, set up with the space or its template | Any time, by a person, an agent or an automation |
| Direction | From the record that holds the field | Readable from either end |
| Good for | The core data model: "this deal's primary contact" | Knowledge found later: "this note references that decision" |
Structural links
A structural link is a field of type entity_id on a kind. Its value is the id of another record. For example, a
deal kind could have a contact field; every deal then shows it as a field people fill in.
Use a structural link when:
- the link is part of what the record is, and most records of that kind have it;
- you want it to appear as a field in forms;
- the link has a clear direction ("a deal has one primary contact");
- you are writing a template: model each relationship your kinds need as a field.
A field can also name a relation type. Writing that field then creates the matching relation in the graph, and clearing it removes the relation, so the link shows up in graph queries too.
Semantic relations
A semantic relation joins two records with a type, such as references, mentions or blocks. No field defines it:
a person, an agent or an automation creates one between any two records when it finds the connection.
{
"sourceEntityId": "<note-id>",
"targetEntityId": "<decision-id>",
"type": "references"
}Use a semantic relation when:
- the connection is found after the fact, not modelled up front;
- it joins records of any kinds, with no field behind it;
- you want to walk the graph, such as everything two hops from a record;
- it is many-to-many and does not fit a field;
- an agent is annotating what it found.
The type must be one the pod knows. Every pod has a set of default types, such as relates_to, references,
mentions, parent_of, depends_on, blocks, assigned_to, created_by and works_at, and a space or its
template can add its own. synap_list_profiles returns the relation types you may use.
When both could work
A deal could have a contact field, or a relates_to relation to the same person. The rule of thumb:
Use fields for what the kind's schema owns. Use relations for what you discover.
An assignee on a task is a field: it is part of the task. A references relation between two documents is a
relation: it came from reading them.
One list of connections
GET /api/hub/entities/{id}/connections (scope hub-protocol.read) returns every connection around a record, from
both systems and from the rest of the pod, in one list. Each item has a source:
source | What it is |
|---|---|
graph | A semantic relation, with its relationType and a direction of outgoing or incoming |
property | A structural link, with its propertySlug and propertyLabel |
thread | A conversation that used, created, updated or referenced the record |
context_channel | A conversation about the record |
focus_session | A session whose subject is the record |
The answer is { connections, counts }. limit caps the items read from each source (default 50, at most 200), and
workspaceId reads through one space. The typed client wraps it: client.getConnections(entityId) from
@synap-core/hub-rest-client.
GET /api/hub/relations reads only the graph, so a structural link whose field names no relation type is missing
there. Use /connections when you want every link without knowing where it is stored.
For agents
- Set a field when the link is a defined field (an assignee, the contact on a deal).
- Create a relation for a connection you discover:
synap_link_entitiesover MCP, orPOST /api/hub/relations. - Read the connections to see every link around a record:
GET /api/hub/entities/{id}/connections, orsynap_get_relationsover MCP for the graph edges alone.