SynapsesOS
Guides

Architectural Rules

Synapses lets you define architectural rules that are checked against the code graph. Rules surface violations in context responses, preventing agents from introducing (or missing) structural problems.

Defining Rules in synapses.json

Add rules to the rules array in your project configuration:

{
"rules": [
{
"id": "no-direct-db-from-handlers",
"description": "HTTP handlers must not import database packages directly",
"type": "dependency",
"source": "internal/handlers/**",
"target": "internal/database/**",
"action": "deny"
},
{
"id": "service-layer-required",
"description": "Handlers must go through the service layer to access data",
"type": "path",
"source": "internal/handlers/**",
"target": "internal/database/**",
"via": "internal/service/**",
"action": "require"
}
]
}

Rule Types

Dependency Rules

Control which packages or files can import/call each other.

{
"type": "dependency",
"source": "internal/api/**",
"target": "internal/infra/**",
"action": "deny"
}

Actions:

  • deny — the source must NOT depend on the target
  • allow — explicitly permit (useful when a broader deny exists)

Edge Type Rules

Control specific relationship types between entities.

{
"type": "edge",
"edge_type": "CALLS",
"source": "internal/handlers/**",
"target": "internal/database/**",
"action": "deny"
}

Supported edge types: CALLS, IMPORTS, IMPLEMENTS, EMBEDS, RETURNS, DEPENDS_ON, TESTED_BY.

Path Pattern Rules (Multi-Hop)

Require or deny multi-hop paths through the graph.

{
"type": "path",
"source": "cmd/**",
"target": "internal/database/**",
"via": "internal/service/**",
"action": "require"
}

This rule says: any path from cmd/ to internal/database/ must pass through internal/service/. A direct dependency from cmd/ to internal/database/ is a violation.

Creating Rules Dynamically

Use rules(action="upsert") to create or update rules at runtime:

{
"tool": "rules",
"action": "upsert",
"arguments": {
"id": "no-circular-service-deps",
"description": "Services must not have circular dependencies",
"type": "dependency",
"source": "internal/service/users/**",
"target": "internal/service/billing/**",
"action": "deny",
"bidirectional": true
}
}

Rules created via rules(action="upsert") are persisted and take effect immediately.

File Pattern Matching

Source and target fields use glob patterns:

PatternMatches
internal/handlers/**All files recursively under handlers
internal/handlers/*.goGo files directly in handlers
**/test_*.pyTest files anywhere in the tree
cmd/api/main.goExact file match

Checking Violations

In get_context

When you call get_context or get_context(mode="intent"), any rule violations affecting the returned entities are included automatically:

// Response includes:
{
"violations": [
{
"rule_id": "no-direct-db-from-handlers",
"description": "HTTP handlers must not import database packages directly",
"source": "internal/handlers/user.go:HandleCreateUser",
"target": "internal/database/queries.go:InsertUser",
"edge_type": "CALLS"
}
]
}

With validate(action=“list”)

Query violations directly:

{
"tool": "validate",
"action": "list",
"arguments": {
"file": "internal/handlers/user.go"
}
}

Returns all rule violations involving the specified file. Omit file to get all violations in the project.

Rule Candidates from Failure Episodes

When agents record failure episodes (memory(action="save") with episode_type: "failure"), Synapses can suggest rules that would prevent recurrence.

{
"tool": "rules",
"arguments": {
"action": "candidates"
}
}

Returns suggested rules derived from patterns in failure episodes. For example, if multiple failures involve handlers directly calling database functions, Synapses suggests a dependency deny rule.

You can then promote a candidate to an active rule:

{
"tool": "rules",
"action": "upsert",
"arguments": {
"id": "candidate-001",
"description": "Auto-suggested: prevent handler-to-db coupling",
"type": "dependency",
"source": "internal/handlers/**",
"target": "internal/database/**",
"action": "deny"
}
}

Example: Layered Architecture

A full layered architecture rule set:

{
"rules": [
{
"id": "layer-handlers-no-db",
"description": "Handlers cannot access database directly",
"type": "dependency",
"source": "internal/handlers/**",
"target": "internal/database/**",
"action": "deny"
},
{
"id": "layer-handlers-use-service",
"description": "Handlers must use service layer",
"type": "dependency",
"source": "internal/handlers/**",
"target": "internal/service/**",
"action": "allow"
},
{
"id": "layer-service-no-handlers",
"description": "Services cannot depend on handlers",
"type": "dependency",
"source": "internal/service/**",
"target": "internal/handlers/**",
"action": "deny"
},
{
"id": "layer-no-cmd-to-db",
"description": "CLI commands must go through service layer",
"type": "path",
"source": "cmd/**",
"target": "internal/database/**",
"via": "internal/service/**",
"action": "require"
}
]
}