@yottagraph-app/aether-instructions 1.1.22 → 1.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,27 @@
1
1
  # Elemental API Overview
2
2
 
3
- The Elemental API provides access to the Lovelace Knowledge Graph through the Query Server. This document explains core concepts and guides you to the right endpoint documentation.
3
+ The Elemental API provides access to the Lovelace Knowledge Graph through the
4
+ Query Server. This document explains core concepts and guides you to the right
5
+ documentation.
6
+
7
+ ## Access Paths
8
+
9
+ The knowledge graph is accessible via two interfaces:
10
+
11
+ - **MCP Tools** — Agent-friendly tools with built-in entity resolution, fuzzy
12
+ matching on all names, and automatic citation tracking. Ideal for interactive
13
+ exploration and Cursor agent workflows. See [mcp.md](mcp.md).
14
+ - **REST API** — Programmatic endpoints for building app features with
15
+ `useElementalClient()`. Requires manual PID lookups, NEID zero-padding, and
16
+ expression construction. See the endpoint files below.
17
+
18
+ Both access the same data. Choose based on your context: MCP when tools are
19
+ connected, REST when building application code.
20
+
21
+ **Recommended workflow when building features:**
22
+ 1. **MCP first** — explore the schema and test data access interactively
23
+ 2. **curl/CLI** — verify exact REST request/response shapes (especially for `/elemental/find` expressions)
24
+ 3. **Implement** — write application code with confidence in the API behavior
4
25
 
5
26
  ## Core Concepts
6
27
 
@@ -9,43 +30,57 @@ The Elemental API provides access to the Lovelace Knowledge Graph through the Qu
9
30
  Every entity has:
10
31
  - **NEID** — a unique Named Entity ID (stable identifier)
11
32
  - **Name** — human-readable label (may have aliases)
12
- - **Flavor** — the entity type (e.g. "organization", "person", "country", "vessel", "event")
33
+ - **Flavor** — the entity type (e.g. "organization", "person", "financial_instrument", "fund_account", "vessel", "event")
13
34
 
14
35
  #### Named Entity ID (NEID)
15
36
 
16
- Every entity in the system has a unique identifier called a NEID. Most API calls require a NEID, so your first step is usually looking up an entity by name to get its NEID.
37
+ Every entity in the system has a unique identifier called a NEID. REST API calls
38
+ require a NEID, so your first step is usually looking up an entity by name. MCP
39
+ tools accept names directly and resolve them automatically.
17
40
 
18
41
  **Format**: 20-character numeric string with zero-padding. Example: `00416400910670863867`
19
42
 
20
- When normalizing NEIDs, always pad with leading zeros to exactly 20 characters.
43
+ When normalizing NEIDs for the REST API, always pad with leading zeros to exactly
44
+ 20 characters. MCP tools handle this automatically.
21
45
 
22
46
  NEIDs are stable and can be persisted long-term, but may occasionally change if the database is rebuilt or the application switches databases. When an NEID becomes invalid (e.g., resolution returns no results), re-resolve the entity using its canonical name from the previous query result, then redo any downstream operations that depended on it. NEIDs should NEVER be hardcoded in source code.
23
47
 
24
- **Note**: The terms "eid" and "neid" are interchangeable throughout the API. Some endpoints use `neid` and others use `eid`, but they refer to the same entity identifier.
48
+ **Note**: The terms "eid", "neid", and "nindex" are interchangeable throughout
49
+ the system. Some endpoints use `neid`, others use `eid`, and internal tools may
50
+ use `nindex` — they all refer to the same entity identifier.
25
51
 
26
52
  ### Properties
27
53
 
28
- Key-value facts attached to entities, scoped by flavor.
54
+ Timestamped key-value facts attached to entities, scoped by flavor. Each property
55
+ value records **when** it was observed (`recorded_at`), so entities can have
56
+ multiple values for the same property over time — one per filing, extraction, or
57
+ data ingestion event.
29
58
 
30
- Examples: nationality, birth_date, industry, total_revenue, employee_count.
59
+ Examples: nationality, birth_date, industry, total_revenue, employee_count,
60
+ sources_of_funds, computation_date_valuation, internal_rate_of_return.
31
61
 
32
- Use the schema to discover which properties are available for
33
- a given entity type.
62
+ Use the schema to discover which properties are available for a given entity type.
63
+ Property names are fuzzy-matched in MCP tools (e.g. "revenue" matches
64
+ "total_revenue"); the REST API requires exact PIDs from the schema.
34
65
 
35
- ## Relationships
66
+ ### Relationships
36
67
 
37
68
  Directed, typed edges between two entities:
38
- - **Type** — e.g. "owns", "board_member_of", "subsidiary_of", "appears_in"
69
+ - **Type** — e.g. "owns", "board_member_of", "subsidiary_of", "trustee_of", "appears_in"
39
70
  - **Direction** — relationships go from source (subject) to target (object)
40
71
 
41
- ## Attributes
72
+ In the schema, relationships are properties with type `data_nindex` — the value is
73
+ another entity's identifier. See [relationships.md](relationships.md) for
74
+ traversal patterns using both MCP and REST.
75
+
76
+ ### Attributes
42
77
 
43
78
  Metadata attached to relationships. For example, the "participant" relationship
44
79
  connecting an entity to an event carries:
45
80
  - **role** — the entity's role in the event (e.g. "acquirer", "target", "plaintiff")
46
81
  - **sentiment** — an impact score for the entity's involvement
47
82
 
48
- ## Events
83
+ ### Events
49
84
 
50
85
  Structured occurrences extracted from source data, each with:
51
86
  - **Category** — e.g. "Bankruptcy", "IPO", "Layoffs", "Acquisition"
@@ -54,22 +89,40 @@ Structured occurrences extracted from source data, each with:
54
89
  - **Likelihood** — temporal status: confirmed, ongoing, likely, or speculative
55
90
  - **Participants** — entities involved, each with a role and sentiment score
56
91
 
57
- ## Endpoint Categories
92
+ ### Citations
93
+
94
+ Property values and relationships carry **citation markers** (e.g. `[1]`, `[2]`)
95
+ referencing the data sources that back each fact. Citations are tracked
96
+ automatically in MCP sessions. Retrieve the full bibliography (titles, URLs,
97
+ publication dates) with `elemental_get_bibliography` or by reading the
98
+ `session://elemental/bibliography` resource.
99
+
100
+ ## File Guide
58
101
 
59
102
  | File | Use When You Need To... |
60
103
  |------|------------------------|
61
- | [entities.md](entities.md) | Look up entities by name, get details and properties |
62
- | [find.md](find.md) | Search for entities by type, property values, or relationships using the expression language |
104
+ | [mcp.md](mcp.md) | Use MCP tools for interactive exploration (tools, resources, prompts) |
105
+ | [entities.md](entities.md) | Look up entities by name, get details and properties (REST) |
106
+ | [find.md](find.md) | Search for entities by type, property values, or relationships (REST expression language) |
63
107
  | [schema.md](schema.md) | Understand the data model: entity types (flavors), properties, and their metadata |
108
+ | [relationships.md](relationships.md) | Traverse entity relationships (both MCP and REST patterns) |
64
109
  | [graph.md](graph.md) | Generate visual network graphs |
65
110
  | [server.md](server.md) | Check server status and capabilities |
66
111
 
67
112
  ## Common Workflows
68
113
 
114
+ ### "What data is available for a bond / financial instrument?"
115
+ - **MCP**: `elemental_get_schema(flavor: "financial_instrument")` → see all properties and relationships
116
+ - **REST**: `GET /schema` → find the FID for "financial_instrument", then inspect its properties
117
+
69
118
  ### "Find all organizations in a specific sector"
70
- 1. `schema.md` Check available properties and flavors
71
- 2. `find.md` → Use the expression language to search by property values
119
+ - **MCP**: `elemental_get_related(entity: "sector name", related_flavor: "organization")`
120
+ - **REST**: `schema.md` → find PIDs; `find.md` search by property values
72
121
 
73
122
  ### "What companies are related to Apple?"
74
- 1. `entities.md` → Look up "Apple" to get NEID
75
- 2. `find.md` → Query linked entities to find related entities
123
+ - **MCP**: `elemental_get_related(entity: "Apple", related_flavor: "organization")`
124
+ - **REST**: `entities.md` → look up "Apple" to get NEID; `find.md` linked expression
125
+
126
+ ### "Who is the trustee of this bond?"
127
+ - **MCP**: `elemental_get_related(entity_id: {id_type: "neid", id: "08242646876499346416"}, related_flavor: "organization", relationship_types: ["trustee_of"], direction: "incoming")`
128
+ - **REST**: See [relationships.md](relationships.md) for the multi-step traversal pattern
@@ -0,0 +1,163 @@
1
+ # Relationships
2
+
3
+ Relationships are directed, typed edges between entities in the knowledge graph.
4
+ They connect a **source** (subject) entity to a **target** (object) entity via a
5
+ named relationship type.
6
+
7
+ ## When to Use
8
+
9
+ - You need to find entities connected to a given entity (e.g. "who owns this company?")
10
+ - You need to determine how two entities are connected
11
+ - You need to traverse the graph along specific relationship types
12
+
13
+ ## Key Concepts
14
+
15
+ ### Relationship Properties
16
+
17
+ In the schema, relationships are properties with type `data_nindex` — the value
18
+ is another entity's identifier rather than a scalar. Use `elemental_get_schema`
19
+ (MCP) or `GET /schema` (REST) to discover which relationships exist for a flavor:
20
+
21
+ - **domain_flavors** — which entity types can be the source of this relationship
22
+ - **target_flavors** — which entity types can be the target
23
+
24
+ For example, `trustee_of` might have domain `["organization"]` and target
25
+ `["financial_instrument"]`, meaning organizations can be trustees of financial
26
+ instruments.
27
+
28
+ ### Direction
29
+
30
+ Relationships are directional. When querying, direction controls which side of
31
+ the edge you're searching from:
32
+
33
+ | Direction | Meaning | Example |
34
+ |-----------|---------|---------|
35
+ | `outgoing` | Center entity is the **subject** | "What does Apple own?" (Apple → owns → target) |
36
+ | `incoming` | Center entity is the **object** | "Who owns Apple?" (source → owns → Apple) |
37
+ | `both` | Union of outgoing and incoming | "All ownership relationships involving Apple" |
38
+
39
+ ### Common Relationship Types
40
+
41
+ Relationship types vary by dataset. Use schema discovery to find what's available.
42
+ Common examples:
43
+
44
+ - `owns`, `owns_stake_in` — ownership
45
+ - `board_member_of`, `is_director`, `is_officer` — corporate governance
46
+ - `subsidiary_of` — corporate structure
47
+ - `trustee_of` — fiduciary relationships
48
+ - `appears_in` — entity appears in an article
49
+ - `participant` — entity participates in an event
50
+
51
+ ## Traversal via MCP Tools
52
+
53
+ MCP tools handle PID resolution, NEID formatting, and entity name lookup automatically.
54
+
55
+ ### Find connected entities
56
+
57
+ Use `elemental_get_related` to find entities connected to a center entity:
58
+
59
+ ```
60
+ elemental_get_related(
61
+ entity: "Apple",
62
+ related_flavor: "person",
63
+ relationship_types: ["is_officer"],
64
+ direction: "incoming",
65
+ related_properties: ["nationality"]
66
+ )
67
+ ```
68
+
69
+ This finds people who are officers of Apple, with their nationality.
70
+
71
+ ### Get relationship counts between two entities
72
+
73
+ Use `elemental_get_relationships` to see how two specific entities are connected:
74
+
75
+ ```
76
+ elemental_get_relationships(
77
+ source: {entity: "Bank of New York Mellon"},
78
+ target: {entity_id: {id_type: "neid", id: "08242646876499346416"}}
79
+ )
80
+ ```
81
+
82
+ Returns relationship types (e.g. `trustee_of`) with temporal counts showing
83
+ when the relationship was observed.
84
+
85
+ ### Discover available relationships
86
+
87
+ Use `elemental_get_schema` to find what relationship types exist for a flavor:
88
+
89
+ ```
90
+ elemental_get_schema(flavor: "organization")
91
+ → relationships: [{name: "owns", target_flavors: ["organization"]}, ...]
92
+
93
+ elemental_get_schema(flavor: "organization", query: "trustee")
94
+ → relationships: [{name: "trustee_of", target_flavors: ["financial_instrument"]}, ...]
95
+ ```
96
+
97
+ ## Traversal via REST API
98
+
99
+ The REST API requires manual PID lookups, NEID zero-padding, and expression
100
+ construction. See find.md for the full expression language and entities.md for
101
+ property value retrieval.
102
+
103
+ ### Graph-layer traversal (linked expression)
104
+
105
+ For entity types that are first-class graph nodes (person, organization, location),
106
+ use `POST /elemental/find` with a `linked` expression:
107
+
108
+ ```
109
+ POST /elemental/find
110
+ Content-Type: application/x-www-form-urlencoded
111
+
112
+ expression={"type":"linked","linked":{"to_entity":"00416400910670863867","distance":1,"pids":[42],"direction":"incoming"}}&limit=50
113
+ ```
114
+
115
+ The `pids` array specifies which relationship types to follow (e.g. PID 42 for
116
+ `is_officer`). Look up PIDs via `GET /schema`.
117
+
118
+ Combine with `is_type` to filter results by flavor:
119
+
120
+ ```json
121
+ {
122
+ "type": "and",
123
+ "and": [
124
+ {"type": "linked", "linked": {"to_entity": "00416400910670863867", "distance": 1, "direction": "incoming"}},
125
+ {"type": "is_type", "is_type": {"fid": 9}}
126
+ ]
127
+ }
128
+ ```
129
+
130
+ ### Property-layer traversal (getPropertyValues)
131
+
132
+ For entity types that are attached as property values (documents, filings,
133
+ financial instruments), use `POST /elemental/entities/properties` with the
134
+ relationship PID:
135
+
136
+ ```
137
+ POST /elemental/entities/properties
138
+ Content-Type: application/x-www-form-urlencoded
139
+
140
+ eids=["00416400910670863867"]&pids=[203]
141
+ ```
142
+
143
+ Relationship property values (`data_nindex` type) are raw entity identifiers.
144
+ **You must zero-pad them to 20 characters** to form valid NEIDs for subsequent
145
+ API calls:
146
+
147
+ ```typescript
148
+ const rawValue = "4926132345040704022"; // 19 chars
149
+ const neid = rawValue.padStart(20, '0'); // "04926132345040704022"
150
+ ```
151
+
152
+ MCP tools handle this padding automatically — this is only needed with the REST API.
153
+
154
+ ## Tips
155
+
156
+ - Always discover relationship types from the schema first — don't hardcode
157
+ relationship names or PIDs.
158
+ - Use `direction` deliberately. "Who owns X?" is `incoming`; "What does X own?"
159
+ is `outgoing`. The default `both` is convenient but may return noisy results.
160
+ - Relationship property values from the REST API need NEID zero-padding.
161
+ MCP tools handle this automatically.
162
+ - When combining relationship traversal with type filtering, wrap the `linked`
163
+ expression in an `and` with `is_type` (see find.md for the expression language).
@@ -19,15 +19,16 @@ The schema defines the data model: what **entity types** (flavors) exist and wha
19
19
  - A name (e.g., "name", "length", "mailing_address", "acquires")
20
20
  - A data type (e.g., "data_cat" for text, "data_float" for numbers)
21
21
  - Domain flavors — which entity types can have this property
22
+ - **Attribute Types** = Metadata that can be attached to property values (e.g., sentiment scores, URLs, snippets). When `getPropertyValues` returns `include_attributes=true`, the attribute keys are numeric strings representing Attribute IDs (AIDs). **AIDs are a separate namespace from PIDs** — for example, PID 15 is "industry" but AID 15 is "sentiment". Use the schema `attributes` array to resolve these.
22
23
 
23
24
  ## Choosing a Schema Endpoint
24
25
 
25
26
  There are two schema endpoints with different levels of detail:
26
27
 
27
- | Endpoint | Flavors include | Properties include |
28
- |----------|-----------------|-------------------|
29
- | `GET /schema` | findex, name, singular/plural display names | pid, name, display_name, unit, value_type, domain_findexes, target_findexes |
30
- | `GET /elemental/metadata/schema` | fid, name only | pid, name, type only |
28
+ | Endpoint | Flavors include | Properties include | Attributes include |
29
+ |----------|-----------------|-------------------|--------------------|
30
+ | `GET /schema` | findex, name, singular/plural display names | pid, name, display_name, unit, value_type, domain_findexes, target_findexes | aid, name, atype, applicable_properties, description |
31
+ | `GET /elemental/metadata/schema` | fid, name only | pid, name, type only | aid, name, atype, applicable_properties, description |
31
32
 
32
33
  **Use `/schema`** (recommended) when you need:
33
34
  - Human-readable display names (e.g., "Organization" vs "organization")
@@ -39,9 +40,30 @@ There are two schema endpoints with different levels of detail:
39
40
  ## Tips
40
41
 
41
42
  - Many API responses return only FIDs and PIDs (not names) — use the schema to translate these to human-readable names
43
+ - When `getPropertyValues` returns attributes with numeric keys (e.g., `"15": -0.3`), look up the key in the schema `attributes` array by `aid` to find the name (e.g., `aid: 15` → "sentiment")
42
44
  - Cache schema results; the data model changes infrequently
43
45
  - Use `/elemental/metadata/properties/{pid}/summary` to understand value distributions before filtering
44
46
 
47
+ ### Flavor ID field names: `findex` vs `fid`
48
+
49
+ The flavor identifier field has **different names** depending on the endpoint:
50
+
51
+ | Endpoint | Field name | Example |
52
+ |----------|-----------|---------|
53
+ | `GET /schema` | `findex` | `{"findex": 12, "name": "article"}` |
54
+ | `GET /elemental/metadata/schema` | `fid` | `{"fid": 12, "name": "article"}` |
55
+
56
+ These contain the same value — just different keys. When writing code that
57
+ consumes schema responses, always handle both:
58
+
59
+ ```typescript
60
+ const articleFlavor = flavors.find(f => f.name === 'article');
61
+ const articleFid = articleFlavor?.fid ?? articleFlavor?.findex ?? null;
62
+ ```
63
+
64
+ The `is_type` expression in `find.md` always uses `fid` regardless of which
65
+ schema endpoint you used to discover the value.
66
+
45
67
  ## Common Workflow
46
68
 
47
69
  1. **Get the schema** → `GET /schema` to learn available flavors and properties
@@ -56,11 +78,11 @@ There are two schema endpoints with different levels of detail:
56
78
 
57
79
  `GET /schema`
58
80
 
59
- Returns detailed schema information including entity types (flavors) with display names and properties with display names, units, and domain/target relationships. This endpoint provides more detail than /elemental/metadata/schema.
81
+ Returns detailed schema information including entity types (flavors) with display names, properties with display names, units, and domain/target relationships, and quad attribute types. This endpoint provides more detail than /elemental/metadata/schema.
60
82
 
61
83
  #### Guidance
62
84
 
63
- This endpoint returns richer metadata than /elemental/metadata/schema, including display names, units, and relationship domains. Use this when you need human-readable names or property metadata.
85
+ This endpoint returns richer metadata than /elemental/metadata/schema, including display names, units, relationship domains, and attribute type definitions. Use this when you need human-readable names or property metadata. The attributes array maps numeric attribute IDs (AIDs) to names — use it to resolve the numeric keys returned by getPropertyValues with include_attributes=true.
64
86
 
65
87
  #### Responses
66
88
 
@@ -80,7 +102,7 @@ GET /schema
80
102
  **Response:**
81
103
 
82
104
  ```json
83
- {"flavors": [{"findex": 9, "name": "person", "singular_display_name": "Person", "plural_display_name": "People"}, {"findex": 10, "name": "organization", "singular_display_name": "Organization", "plural_display_name": "Organizations"}], "properties": [{"pid": 8, "name": "name", "display_name": "Name", "value_type": "data_cat"}, {"pid": 15, "name": "industry", "display_name": "Industry", "value_type": "data_cat"}]}
105
+ {"flavors": [{"findex": 9, "name": "person", "singular_display_name": "Person", "plural_display_name": "People"}, {"findex": 10, "name": "organization", "singular_display_name": "Organization", "plural_display_name": "Organizations"}], "properties": [{"pid": 8, "name": "name", "display_name": "Name", "value_type": "data_cat"}, {"pid": 15, "name": "industry", "display_name": "Industry", "value_type": "data_cat"}], "attributes": [{"aid": 15, "name": "sentiment", "atype": "float", "applicable_properties": ["appears_in", "participant", "sentiment"], "description": "A sentiment score in [-1, +1]."}]}
84
106
  ```
85
107
 
86
108
  ---
@@ -251,6 +273,18 @@ GET /elemental/metadata/properties/8/summary
251
273
 
252
274
  ## Types
253
275
 
276
+ ### SchemaAttribute
277
+
278
+ Quad attribute type used as keys in property value attributes
279
+
280
+ | Field | Type | Description |
281
+ |-------|------|-------------|
282
+ | aid | integer | Unique attribute type identifier. Appears as a string key (e.g., "15") in property value attributes. |
283
+ | applicable_properties | string[] | Property names that commonly carry this attribute (e.g., ["appears_in", "participant"]) |
284
+ | atype | string | Attribute data type: "float", "int", "bool", or "blob" (string values) |
285
+ | description | string | Semantic description of what this attribute represents |
286
+ | name | string | Attribute name (e.g., "sentiment", "url", "snippet") |
287
+
254
288
  ### SchemaFlavor
255
289
 
256
290
  Entity type (flavor) with human-readable display names
@@ -280,10 +314,11 @@ Property with display name, unit, and domain information
280
314
 
281
315
  ### SchemaResponse
282
316
 
283
- Detailed schema response with entity types (flavors) and properties including display names, units, and domains
317
+ Detailed schema response with entity types (flavors), properties, and quad attribute types
284
318
 
285
319
  | Field | Type | Description |
286
320
  |-------|------|-------------|
321
+ | attributes | `SchemaAttribute`[] | Array of quad attribute types that appear as keys in property value attributes (when include_attributes=true). These use a separate ID namespace (AID) from property PIDs. |
287
322
  | flavors | `SchemaFlavor`[] | Array of entity types (flavors) with display names |
288
323
  | properties | `SchemaProperty`[] | Array of properties with display names, units, and domain information |
289
324
 
@@ -328,6 +363,17 @@ Detailed schema response with entity types (flavors) and properties including di
328
363
  |-------|------|-------------|
329
364
  | **flavors** | `Flavor`[] | Array of entity types (flavors) available in the system |
330
365
  | **properties** | `Property`[] | Array of properties available in the system |
366
+ | attributes | `Attribute`[] | Array of quad attribute types. These map the numeric keys in property value attributes (from include_attributes=true) to human-readable names. AIDs are a separate namespace from property PIDs. |
367
+
368
+ ### Attribute
369
+
370
+ | Field | Type | Description |
371
+ |-------|------|-------------|
372
+ | **aid** | integer | Unique attribute type identifier. Appears as a string key (e.g., "15") in property value attributes. |
373
+ | **name** | string | Attribute name |
374
+ | **atype** | string | Attribute data type. Values: `float`, `int`, `bool`, `blob` |
375
+ | applicable_properties | string[] | Property names that commonly carry this attribute |
376
+ | description | string | Semantic description of what this attribute represents |
331
377
 
332
378
  ### Flavor
333
379