In Lix, metadata refers to arbitrary, structured data that you can attach to entities or changes. It provides a flexible way to add context, annotations, flags, or any application-specific information to your Lix state, especially for data records whose primary schema you do not control.
The answer is simple: Use metadata when an entity is not owned by your application, but for interoperability reasons, you need to use that entity or its schema. In such cases, you can attach metadata to add your application's specific information without altering the original entity's schema.
Here are some examples:
lix_conversation_message). Your application might want to store additional context for these messages, such as the LLM_role (e.g., "user", "assistant") or the LLM_model used to generate a response. Since you don't own the lix_conversation_message schema, you use metadata to attach this information.review_status on a Markdown heading) without modifying the plugin's schema.file or commit, you can attach metadata to store application-specific details (e.g., imported_from_source for a file, or jira_ticket_id for a commit).Metadata is stored as a JSON object. You can attach it when creating or updating entities.
When inserting or updating records in Lix, you can include a metadata property, which should be a JSON object.
// Attaching metadata when inserting a new state record
await lix.db
.insertInto("state")
.values({
entity_id: "task-123", // The unique ID of this entity
schema_key: "my_app_entity", // The schema defining this entity
snapshot_content: {
// The actual data of the entity
id: "task-123",
name: "Review PR",
},
metadata: {
// The metadata for this state record
priority: "high",
assigned_to: "dev_team",
source: "jira_ticket_456",
},
})
.execute();To update specific properties within an existing metadata object, use SQL JSON functions like json_set. This allows you to modify metadata without overwriting the entire object.
// Update a specific metadata property for an entity
await lix.db
.updateTable("my_app_entity")
.set({
metadata: sql`json_set(metadata, '$.priority', 'urgent')`,
})
.where("id", "=", "task-123")
.execute();
// This preserves other metadata properties like 'assigned_to'You can query entities based on their metadata using SQL JSON functions like json_extract.
// Find entities with high priority
const highPriorityTasks = await lix.db
.selectFrom("my_app_entity")
.where(sql`json_extract(metadata, '$.priority')`, "=", "high")
.selectAll()
.execute();
// Find conversation messages from a specific LLM model
const gpt4Messages = await lix.db
.selectFrom("conversation_message")
.where(sql`json_extract(lixcol_metadata, '$.llm_model')`, "=", "gpt-4")
.selectAll()
.execute();Important Note on Columns:
When querying raw state tables (e.g., state), metadata is available in the metadata column. However, when querying entity views (e.g., conversation_message), metadata is surfaced through the operational column lixcol_metadata. Always use the correct column name for the view you are querying.
Follow these guidelines for effective metadata usage:
myapp_role, inlang_priority) to prevent collisions with other plugins or Lix's internal metadata.myapp_priority: "high" to a lix_conversation_message).const role = state.metadata?.myapp_role ?? "user";).snapshot_content: Avoid storing data in metadata that is already present in the entity's snapshot_content.