Protocols & Heat

Behavioral rules, heat system, domain scoping, writing your own.

Behavioral rules in .soma/protocols/ as markdown with YAML frontmatter. Loaded by heat: hot (≥8) = full body, warm (≥3) = breadcrumb, cold = name only. Heat rises on use (+1 auto-detect), decays per session if unused. Domain scoping via applies-to field. Write your own: add name, heat-default, breadcrumb, applies-to frontmatter. Configure thresholds in settings.json.

Protocols are behavioral rules that guide Soma’s actions. They live in .soma/protocols/ as markdown files with YAML frontmatter.

Built-in Protocols

ProtocolDefault HeatApplies ToWhat It Does
breath-cyclehotalwaysSessions have phases: inhale, hold, exhale. Never skip exhale.
frontmatter-standardwarmalwaysAll .md files get YAML frontmatter with type, status, dates.
git-identitywarmgitCommits use the correct name/email for the repo context.
heat-trackinghotalwaysProtocols and muscles have temperature that rises on use and decays.

Heat System

Every protocol has a temperature that determines how it loads:

TemperatureHeat RangeWhat Loads
🔥 Hot8+Full protocol body in system prompt
🟡 Warm3–7Breadcrumb only (1–2 sentence reminder)
❄️ Cold0–2Name listed, content not loaded

How Heat Changes

EventHeat Change
Protocol referenced explicitly+2
Protocol applied in action (auto-detected)+1
/pin <name>Set to hot + pinned (no decay)
/kill <name>Set to 0 + unpinned
Session end (unused protocol)-1 (decay)
Session end (used protocol)No change
Session end (pinned protocol)No change

Heat state is stored in .soma/.protocol-state.json and persists across sessions.

Thresholds

Default thresholds can be overridden in settings.json:

{
  "protocols": {
    "warmThreshold": 3,
    "hotThreshold": 8,
    "maxHeat": 15,
    "decayRate": 1,
    "maxBreadcrumbsInPrompt": 10,
    "maxFullProtocolsInPrompt": 3
  }
}

Domain Scoping (applies-to)

Protocols declare which projects they’re relevant to via the applies-to frontmatter field. At boot, Soma detects project signals by scanning for marker files:

SignalDetected By
alwaysAlways matches (meta-protocols)
git.git/ directory exists
typescripttsconfig.json or tsconfig.base.json
javascriptpackage.json (also set by typescript)
pythonpyproject.toml, requirements.txt, setup.py, Pipfile
rustCargo.toml
gogo.mod
frontendFramework configs (next.config.*, vite.config.*, etc.) or src/components/
docsdocs/ directory
multi-repo2+ child directories with .git/

A protocol with applies-to: [git, typescript] loads only in projects that have at least one of those signals. A protocol with no applies-to field (or applies-to: [always]) loads everywhere.

Writing Your Own Protocol

1. Create the file

cp .soma/protocols/_template.md .soma/protocols/my-protocol.md

2. Edit the frontmatter

---
type: protocol
name: my-protocol
status: active
updated: 2026-03-09
heat-default: warm
applies-to: [typescript]
breadcrumb: "One sentence that captures what this protocol enforces. This is ALL the agent sees when warm."
---

Required frontmatter fields:

FieldPurpose
nameProtocol identifier (used in heat state, /pin, /kill)
heat-defaultStarting temperature: cold, warm, or hot
breadcrumbOne sentence shown when protocol is warm

Optional fields:

FieldDefaultPurpose
applies-to[always]Domain signals this protocol applies to
scopelocallocal = project only, shared = eligible for parent chain
tierfreefree or enterprise

3. Write the body

# My Protocol

## TL;DR
- Dense bullet points
- What the agent MUST do
- 3-7 bullets max

## Rule

The detailed behavioral rules go here. This is loaded when the protocol is hot.

## When to Apply

Contexts where this activates.

## When NOT to Apply

Explicit exclusions.

4. The three loading tiers

TierWhat the Agent SeesWhen
Breadcrumbbreadcrumb: frontmatter valueProtocol is warm
TL;DR## TL;DR sectionAgent reads deeper on demand
Full bodyEntire file (minus frontmatter)Protocol is hot

Write the breadcrumb to be self-contained — it’s the only thing loaded at warm temperature.

Protocol Resolution Chain

Protocols resolve from project → parent → global, with project protocols shadowing same-named parent/global ones:

CWD/.soma/protocols/       ← project (highest priority)

../.soma/protocols/         ← parent (if exists)

~/.soma/protocols/          ← global (lowest priority)

If both project and global define git-identity.md, the project version wins.

Files to Know

FilePurpose
.soma/protocols/*.mdProtocol definitions
.soma/protocols/_template.mdTemplate for new protocols
.soma/.protocol-state.jsonHeat state (auto-managed, don’t edit)
.soma/settings.jsonOverride heat thresholds