Skip to content

Body Architecture

Structured identity with templates, variables, lazy loading, and the soma chain.

Body Architecture

The body is Soma’s structured identity system. Files in .soma/body/ become template variables (soul.md{{soul}}). Templates (_mind.md, _memory.md) use these variables to compile the system prompt and preload. Lazy files load on demand. The soma chain (project → parent → global) merges content with child-wins priority.

How It Works

_ prefix = template. Contains {{variables}}, defines structure. No prefix = content. Loaded as-is into a {{filename}} variable.

body/
├── soul.md           → {{soul}}      Who you are
├── voice.md          → {{voice}}     How you communicate
├── body.md           → {{body}}      Project context
├── journal.md        → {{journal}}   Observations across sessions
├── pulse.md          → {{pulse}}     Heartbeat tasks
├── DNA.md            → {{dna}}       Body reference (lazy)

├── _mind.md          ← template      System prompt structure
├── _memory.md        ← template      Preload format
├── _boot.md          ← template      Boot message
└── _first-breath.md  ← template      First-ever session greeting

All variables work in all templates — no scoping. Use {{scripts_table}} in _memory.md, use {{journal|tldr}} in _mind.md.

Content Files

soul.md — Who You Are

Variable: {{soul}}

Identity, values, posture. Written in first person. When this exists, SOMA.md and identity.md are ignored. Keep it under 30 lines — the soul should be light.

voice.md — How You Communicate

Variable: {{voice}}

Communication style: delivery, tone, rhythm. Write instincts, not rules.

body.md — Working Context

Variable: {{body}}

Project-specific context: stack, conventions, deploy targets, current focus. Update this at each exhale if the project changed.

journal.md — What You Notice

Variable: {{journal}}

Quiet observations — not the work log (that’s memory/sessions/). What you noticed about the user, patterns, what surprised you.

ecosystem.md — Cross-Project Map

Variable: {{ecosystem}}

Shared context across projects in a workspace. Describes what exists, how projects connect, who owns what. Useful for multi-project setups where multiple .soma/ directories share a parent.

Inherited via the soma chain. If your project doesn’t have ecosystem.md, the agent walks up to the parent or global .soma/body/ and uses theirs. Create your own to override.

Adding Your Own Files

Any .md without a _ prefix becomes a variable. Dashes become underscores:

You createVariable
ecosystem.md{{ecosystem}}
my-rules.md{{my_rules}}
project-context.md{{project_context}}

Templates

_mind.md — System Prompt

Controls the system prompt layout. Compiled by compileFullSystemPrompt() on the first turn, cached for subsequent turns.

# Who I Am
{{soul}}

{{voice}}

{{#body}}
# Where I Am
{{body}}
{{/body}}

# Tools & Context
<tool_guidance>
{{tools_section}}
</tool_guidance>

{{guard_section}}
{{docs_section}}
{{skills_block}}

<rules>
{{core_rules}}
</rules>

No _mind.md? The agent uses a built-in default. Every variable is optional — missing variables produce empty sections that disappear.

Why no {{protocol_summaries}} / {{muscle_digests}} / {{scripts_table}}? They were removed from the shipped template in fcd32bd (SX-600, 2026-04-23 — cache economics). The compiler already prepends protocol summaries + muscle digests as a static block via compileFrontalCortex() (in core/prompt.ts) BEFORE the template renders. Interpolating them again in _mind.md causes double injection — same content twice, wasted tokens, and the volatile slot ends up in a cache position that invalidates ~80% of the prefix below it on every edit. The variables are still populated for backwards compatibility, but the canonical pattern is to rely on the prepend and let the template render only what’s specific to your project.

_memory.md — Preload Format

Controls what the agent writes at /exhale. Shapes the continuation prompt for the next session.

_boot.md — Boot Message

What the agent sees on session start. Carries novel per-session content — the system prompt already has identity, protocols, muscles. The boot message adds git context, preload, and greeting.

Note: On resume (soma -c), _boot.md is NOT rendered — a minimal delta message is sent instead.

_first-breath.md — First Session

Used on the very first soma run in a new project. Has conditional blocks:

{{#has_code}}
This project has code. Read the structure first.
{{/has_code}}

{{#is_blank}}
Blank project. Ask what we're building.
{{/is_blank}}

Modifiers

Slice content with pipe modifiers: {{variable|modifier}}

ModifierExampleWhat
tldr{{journal|tldr}}First meaningful paragraph
section:Name{{body|section:Current Focus}}Content under a heading
lines:N{{soul|lines:10}}First N lines
last:N{{journal|last:5}}Last N lines

Lazy vs Eager

By default, body files load every session (eager). Add lazy: true to frontmatter for on-demand loading:

---
lazy: true
---
  • Eager: soul, voice, body, pulse — always in the system prompt
  • Lazy: DNA, journal (if long), STATE, references — available as skills, zero boot cost

Variable Reference

Content Variables (from body files)

VariableSource
{{soul}}body/soul.md (or SOMA.md fallback)
{{body}}body/body.md
{{voice}}body/voice.md
{{journal}}body/journal.md
{{pulse}}body/pulse.md
{{<filename>}}Any body/<filename>.md

System Variables (generated at boot)

VariableWhat
{{core_rules}}Behavioral framework
{{protocol_summaries}}Active protocols (heat-sorted)
{{muscle_digests}}Learned patterns (hot=full, warm=digest)
{{scripts_table}}Discovered scripts with usage counts
{{inbox_summary}}Unread messages from .soma/inbox/
{{tools_section}}Available tools
{{guard_section}}File protection rules
{{docs_section}}Documentation references
{{skills_block}}Available skills
{{context_awareness}}CLAUDE.md/AGENTS.md awareness
{{git_context}}Recent git changes
{{date_time_cwd}}Current date, time, directory

Session Variables

VariableWhat
{{preload}}Continuation prompt from last session
{{session_id}}Session identifier: s01-abc123
{{greeting}}Contextual greeting (narrative only)
{{session_files}}Session log + preload file paths
{{today}}ISO date
{{project_name}}Project name
{{soma_path}}Absolute path to .soma/
{{version}}Agent version

Exhale Variables (available in _memory.md)

VariableWhat
{{logVerb}}Write or Append to
{{preloadVerb}}Write or Update
{{logPath}}Session log file path
{{target}}Preload file path
{{sessionId}}Session identifier

Plus every content and system variable above.

Settings That Shape Variables

SettingAffects
protocols.warmThreshold{{protocol_summaries}} heat cutoff
muscles.fullThreshold{{muscle_digests}} full body vs digest
muscles.maxLoadedMax muscles loaded
guard.mode{{guard_section}} visibility
systemPrompt.identityInSystemPrompt{{soul}} inclusion
systemPrompt.includeSomaDocs{{docs_section}} inclusion
systemPrompt.includeSkills{{skills_block}} inclusion

See Configuration for all settings.

The Soma Chain

Discovery walks up the filesystem:

project/.soma/     ← most specific (wins on collision)

parent/.soma/      ← workspace level

~/.soma/           ← global (least specific)
  • Templates (_mind.md, etc.): first found wins (no merging)
  • Content (non-template): merged across chain, child wins on collision
  • Controlled by inherit.* settings — set false to use only project level

Identity Resolution

The runtime loads identity from the first file found:

1. body/soul.md     ← structured identity (recommended)
2. SOMA.md          ← canonical monolith
3. identity.md      ← legacy (deprecated — no longer created by init, ignored if soul.md exists)

When body/soul.md exists, the others are never read.

Conditional Blocks

Templates support if/else based on variable truthiness:

{{#has_preload}}
Resume Point content here
{{/has_preload}}

{{#is_blank}}
Blank project greeting
{{/is_blank}}

Truthy: non-empty string that isn’t "false". Falsy: empty, missing, or "false".

Boot Lifecycle

soma              → fresh, NO preload
soma inhale       → fresh, WITH most recent preload
soma -c           → resume (full history, delta-only boot)
soma map <name>   → fresh, WITH MAP prompt-config
soma focus <kw>   → fresh, WITH focus overrides
  1. Discovery → find .soma/, walk chain
  2. Settings → load + merge from chain
  3. Identity → soul.mdSOMA.mdidentity.md
  4. Boot steps → protocols, muscles, scripts, git-context
  5. Preload → only on soma inhale / MAP targeting
  6. System prompt → compile _mind.md
  7. Boot message → render _boot.md → send as followUp

Evolution Pattern

When a file outgrows its role, split it:

soul.md (300 lines, outgrown)
  ↓ evolves into
soul.md (30 lines) + voice.md + body.md + journal.md (lazy)

The trigger: when you’re loading 300 lines and only 20 matter per task. Lazy files cost zero at boot.

Known Quirks

  • {{greeting}} is narrative only — session ID and file paths are separate variables
  • Preload sorts by mtime — editing an old preload makes it “newest”
  • Resume skips _boot.md — persistent content belongs in _mind.md
  • Template chain: first found wins — project _mind.md fully replaces parent’s (no merge)
  • Renaming CWD breaks bash — the bash tool validates CWD exists before every command