Skip to main content

Rules & Relations

Rules are declarative specifications that create relationships between entities across different systems in your graph. They run automatically on triggers or on demand, and are the primary way SixDegree connects data from separate tools.

Where relations come from

SixDegree creates relations from two distinct sources.

Intra-molecule relations are created automatically by molecules within their own domain. You don't configure these. They're intrinsic to the source system:

  • Salesforce molecule: SalesforceOpportunity --belongs_to--> SalesforceAccount
  • Zendesk molecule: ZendeskTicket --assigned_to--> ZendeskUser
  • PagerDuty molecule: PagerDutyIncident --on_escalation_policy--> PagerDutyEscalationPolicy

Inter-molecule relations are created by rules you configure. These cross system boundaries:

  • ZendeskTicket --escalated_to--> PagerDutyIncident
  • StripeSubscription --renews--> SalesforceAccount
  • ZendeskTicket --affects--> SalesforceAccount
  • PagerDutyIncident --affects--> KubernetesDeployment

This separation keeps molecules loosely coupled. A Stripe molecule doesn't need to understand Salesforce; you configure the cross-system relationship using a rule that matches your conventions.

tip

Molecules may suggest inter-molecule rules based on common patterns, but you decide which cross-system relationships are created.

Rule structure

Rules use a Kubernetes-style YAML format with five main sections: trigger, source, target, relation, and lifecycle.

apiVersion: sixdegree.ai/v1
kind: Rule
metadata:
name: ticket-affects-account
spec:
enabled: true
priority: 100
trigger:
on: discovery.completed
source:
kind: ZendeskTicket
match: all
target:
kind: SalesforceAccount
match: pattern
query: 'target.spec.name == source.labels["organization"]'
relation:
type: AFFECTS
attributes:
inferred: "true"
onDelete: keep

Triggers

Triggers define when a rule is evaluated.

TriggerWhen it fires
discovery.completedAfter a molecule finishes a discovery run
entity.createdWhen a new entity is added to the graph
entity.updatedWhen an entity's attributes change
entity.deletedWhen an entity is removed
relation.createdWhen a new relation is created
relation.deletedWhen a relation is removed
manualOnly when explicitly triggered via CLI

Event-based trigger

trigger:
on: entity.created
match:
kind: ZendeskTicket
labels:
status: open

Manual trigger

trigger:
on: manual
info

Most pattern-based rules should use discovery.completed. Use manual for explicit mappings that rarely change, such as an account managing a fixed set of subscriptions.

Source matching

The source section defines which entities the rule starts from.

ModeDescription
allEvery entity of the specified kind
patternEntities matching a CEL expression
specificAn explicitly listed set of entities

All entities of a kind

source:
kind: ZendeskTicket
match: all

Pattern matching

source:
kind: SalesforceAccount
match: pattern
query: 'source.labels["segment"] == "enterprise"'

Specific entities

source:
kind: SalesforceAccount
match: specific
entities:
- name: Acme Corp
- name: Globex

Target matching

The target section defines which entities to link to. It uses the same three match modes as source.

Pattern-based target

target:
kind: SalesforceAccount
match: pattern
query: 'target.spec.name == source.labels["organization"]'

Specific targets

target:
kind: StripeSubscription
match: specific
entities:
- name: sub_acme_platform
- name: sub_acme_support
- name: sub_acme_usage

Relations

The relation section defines what relationship to create between matched source and target entities.

Relation types

TypeMeaning
OWNSOwnership or management
BELONGS_TOMembership in a parent record
RENEWSA subscription renews an account
ESCALATED_TOA ticket escalates to an incident
AFFECTSOne record affects another
DEPENDS_ONDependency
RELATED_TOGeneral association

You can define custom relation types based on your domain conventions.

Static attributes

Relations can carry arbitrary attributes for context:

relation:
type: OWNS
attributes:
since: "2024-01-15"
priority: high
notes: "Primary account for the enterprise segment"

Every relation automatically gets created_at (timestamp) and created_by (one of rule:{name}, user:{id}, or molecule:{name}).

Computed attributes

Attribute values can be computed from source or target entity fields using CEL template expressions:

relation:
type: AFFECTS
attributes:
ticket_id: '{{ source.labels["id"] }}'
account_name: '{{ target.spec.name }}'

Lifecycle

onDelete behavior

When a rule is deleted, the onDelete field controls what happens to the relations it created.

ValueBehavior
keepRelations persist after rule deletion
cascadeRelations are deleted with the rule
onDelete: cascade
warning

Using cascade on a rule that matched thousands of entity pairs will delete all those relations when the rule is removed. Use keep for inferred relations you want to retain as permanent facts in the graph.

Idempotency

Rules are idempotent by default. Running a rule multiple times won't create duplicate relations.

RuleSets

A RuleSet groups related rules together. Use RuleSets when rules belong to the same integration, should be enabled or disabled together, or are versioned as a unit.

apiVersion: sixdegree.ai/v1
kind: RuleSet
metadata:
name: revenue-health-rules
labels:
source: molecule/salesforce
version: "1.2.0"
rules:
- name: ticket-affects-account
spec:
trigger:
on: discovery.completed
source:
kind: ZendeskTicket
match: all
target:
kind: SalesforceAccount
match: pattern
query: 'target.spec.name == source.labels["organization"]'
relation:
type: AFFECTS

- name: subscription-renews-account
spec:
trigger:
on: discovery.completed
source:
kind: StripeSubscription
match: all
target:
kind: SalesforceAccount
match: pattern
query: 'target.metadata.name == source.spec.account'
relation:
type: RENEWS

Molecule-provided rules

Molecules can ship default RuleSets that are installed when the molecule is configured. You can enable or disable the whole set, and they upgrade when the molecule updates. User-defined rules always take precedence.

CEL expressions

Rules use CEL (Common Expression Language) for pattern matching and computed attribute values.

Available variables

VariableAvailable inDescription
sourceSource queries, target queries, attributesThe source entity
targetTarget queries, attributesThe target entity
entityTrigger conditionsThe entity that fired the trigger

Entity field paths

// Metadata
entity.metadata.name
entity.metadata.createdAt

// Labels
entity.labels["key"]

// Spec (entity-specific fields)
entity.spec.title
entity.spec.url
entity.spec.status

String functions

// Substring check
target.spec.name.contains("Acme")

// Prefix / suffix
source.metadata.name.startsWith("enterprise-")
target.spec.plan.endsWith("-annual")

// Regex matching (RE2 syntax)
source.labels["id"].matches("^TICKET-[0-9]+$")
target.spec.name.matches(".*Corp$")

Comparison and logic

// Equality
source.labels["segment"] == "enterprise"

// Numeric comparison
entity.spec.priority > 5

// Boolean logic
source.spec.status == "open" && target.spec.renewed == false

Common patterns

Link tickets to accounts by organization name:

target.spec.name == source.labels["organization"]

Match records by naming convention:

target.metadata.name.startsWith(source.spec.prefix + "-")

Match by shared label:

target.labels["segment"] == source.labels["segment"]
tip

Test CEL expressions with sixdegree apply --dry-run before applying them. The dry-run output shows which entity pairs would be matched without writing any relations.

Full examples

Pattern-based: ticket to account

Link Zendesk tickets to Salesforce accounts where the account name matches the ticket's organization.

apiVersion: sixdegree.ai/v1
kind: Rule
metadata:
name: ticket-affects-account
spec:
enabled: true
trigger:
on: discovery.completed
source:
kind: ZendeskTicket
match: all
target:
kind: SalesforceAccount
match: pattern
query: 'target.spec.name == source.labels["organization"]'
relation:
type: AFFECTS
attributes:
inferred: "true"
onDelete: keep

Explicit: account owns subscriptions

An account explicitly owns a fixed set of subscriptions.

apiVersion: sixdegree.ai/v1
kind: Rule
metadata:
name: account-owns-subscriptions
spec:
trigger:
on: manual
source:
kind: SalesforceAccount
match: specific
entities:
- name: Acme Corp
target:
kind: StripeSubscription
match: specific
entities:
- name: sub_acme_platform
- name: sub_acme_support
- name: sub_acme_usage
relation:
type: OWNS
attributes:
notes: "Core enterprise subscriptions"
onDelete: cascade

A single service is owned by a specific account.

apiVersion: sixdegree.ai/v1
kind: Rule
metadata:
name: payments-service-owned-by-acme
spec:
trigger:
on: manual
source:
kind: KubernetesDeployment
match: specific
entities:
- name: payments-service
target:
kind: SalesforceAccount
match: specific
entities:
- name: Acme Corp
relation:
type: OWNED_BY
onDelete: cascade

CLI usage

# Apply rules from a file
sixdegree apply -f rules.yaml

# Preview what relations would be created without writing them
sixdegree apply --dry-run -f rules.yaml

# List all rules
sixdegree get rules

# Get a specific rule
sixdegree get rule ticket-affects-account

# Run a manual rule
sixdegree run rule account-owns-subscriptions

# Delete a rule
sixdegree delete rule ticket-affects-account

# List rulesets
sixdegree get rulesets

# Disable a ruleset
sixdegree disable ruleset revenue-health-rules

Best practices

  • Name rules descriptively. The name should explain what relationship the rule creates, not how it works.
  • Prefer pattern matching over explicit lists. Pattern-based rules scale automatically as new entities are discovered.
  • Group with RuleSets. Rules that belong to the same integration or should be toggled together should live in a RuleSet.
  • Match onDelete to intent. Use cascade for explicit mappings; use keep for inferred relations you want to survive rule changes.
  • Comment complex CEL. Add a YAML comment above any non-obvious query expression.

Next steps

  • Entities: understand the entity model that rules operate on
  • Molecules: see how molecules provide the intra-molecule relations that rules extend
  • Ontology: explore how entity kinds and relation types are defined
  • Graph: see how rules and relations build the connected graph
  • CLI reference: full command reference for sixdegree apply, get, run, and delete