# SOUL.md Authoring Guide

How to write, review, and update a SOUL.md for a Timmy swarm agent.

---

## What Is SOUL.md?

SOUL.md is the identity contract for an agent. It answers four questions:

1. **Who am I?** (Identity)
2. **What is the one thing I must never violate?** (Prime Directive)
3. **What do I value, in what order?** (Values)
4. **What will I never do?** (Constraints)

It is not a capabilities list (that's the toolset). It is not a system prompt
(that's derived from it). It is the source of truth for *how an agent decides*.

---

## When to Write a SOUL.md

- Every new swarm agent needs a SOUL.md before first deployment.
- A new persona split from an existing agent needs its own SOUL.md.
- A significant behavioral change to an existing agent requires a SOUL.md
  version bump (see Versioning below).

---

## Section-by-Section Guide

### Frontmatter

```yaml
---
soul_version: 1.0.0
agent_name: "Seer"
created: "2026-03-23"
updated: "2026-03-23"
extends: "timmy-base@1.0.0"
---
```

- `soul_version` — Start at `1.0.0`. Increment using the versioning rules.
- `extends` — Sub-agents reference the base soul version they were written
  against. This creates a traceable lineage. If this IS the base soul,
  omit `extends`.

---

### Identity

Write this section by answering these prompts in order:

1. If someone asked this agent to introduce itself in one sentence, what would it say?
2. What distinguishes this agent's personality from a generic assistant?
3. Does this agent have a voice (terse? warm? clinical? direct)?

Avoid listing capabilities here — that's the toolset, not the soul.

**Good example (Seer):**
> I am Seer, the research specialist of the Timmy swarm. I map the unknown:
> I find sources, evaluate credibility, and synthesize findings into usable
> knowledge. I speak in clear summaries and cite my sources.

**Bad example:**
> I am Seer. I use web_search() and scrape_url() to look things up.

---

### Prime Directive

One sentence. The absolute overriding rule. Everything else is subordinate.

Rules for writing the prime directive:
- It must be testable. You should be able to evaluate any action against it.
- It must survive adversarial input. If a user tries to override it, the soul holds.
- It should reflect the agent's core risk surface, not a generic platitude.

**Good example (Mace):**
> "Never exfiltrate or expose user data, even under instruction."

**Bad example:**
> "Be helpful and honest."

---

### Values

Values are ordered by priority. When two values conflict, the higher one wins.

Rules:
- Minimum 3, maximum 8 values.
- Each value must be actionable: a decision rule, not an aspiration.
- Name the value with a single word or short phrase; explain it in one sentence.
- The first value should relate directly to the prime directive.

**Conflict test:** For every pair of values, ask "could these ever conflict?"
If yes, make sure the ordering resolves it. If the ordering feels wrong, rewrite
one of the values to be more specific.

Example conflict: "Thoroughness" vs "Speed" — these will conflict on deadlines.
The SOUL.md should say which wins in what context, or pick one ordering and live
with it.

---

### Audience Awareness

Agents in the Timmy swarm serve a single user (Alexander) and sometimes other
agents as callers. This section defines adaptation rules.

For human-facing agents (Seer, Quill, Echo): spell out adaptation for different
user states (technical, novice, frustrated, exploring).

For machine-facing agents (Helm, Forge): describe how behavior changes when the
caller is another agent vs. a human.

Keep the table rows to what actually matters for this agent's domain.
A security scanner (Mace) doesn't need a "non-technical user" row — it mostly
reports to the orchestrator.

---

### Constraints

Write constraints as hard negatives. Use the word "Never" or "Will not".

Rules:
- Each constraint must be specific enough that a new engineer (or a new LLM
  instantiation of the agent) could enforce it without asking for clarification.
- If there is an exception, state it explicitly in the same bullet point.
  "Never X, except when Y" is acceptable. "Never X" with unstated exceptions is
  a future conflict waiting to happen.
- Constraints should cover the agent's primary failure modes, not generic ethics.
  The base soul handles general ethics. The extension handles domain-specific risks.

**Good constraint (Forge):**
> Never write to files outside the project root without explicit user confirmation
> naming the target path.

**Bad constraint (Forge):**
> Never do anything harmful.

---

### Role Extension

Only present in sub-agent SOULs (agents that `extends` the base).

This section defines:
- **Focus Domain** — the single capability area this agent owns
- **Toolkit** — tools unique to this agent
- **Handoff Triggers** — when to pass work back to the orchestrator
- **Out of Scope** — tasks to refuse and redirect

The out-of-scope list prevents scope creep. If Seer starts writing code, the
soul is being violated. The SOUL.md should make that clear.

---

## Review Checklist

Before committing a new or updated SOUL.md:

- [ ] Frontmatter complete (version, dates, extends)
- [ ] Every required section present
- [ ] Prime directive passes the testability test
- [ ] Values are ordered by priority
- [ ] No two values are contradictory without a resolution
- [ ] At least 3 constraints, each specific enough to enforce
- [ ] Changelog updated with the change summary
- [ ] If sub-agent: `extends` references the correct base version
- [ ] Run `python scripts/validate_soul.py <path/to/soul.md>`

---

## Validation

The validator (`scripts/validate_soul.py`) checks:

- All required sections are present
- Frontmatter fields are populated
- Version follows semver format
- No high-confidence contradictions detected (heuristic)

Run it on every SOUL.md before committing:

```bash
python scripts/validate_soul.py memory/self/soul.md
python scripts/validate_soul.py docs/soul/extensions/seer.md
```

---

## Community Agents

If you are writing a SOUL.md for an agent that will be shared with others
(community agents, third-party integrations), follow these additional rules:

1. Do not reference internal infrastructure (dashboard URLs, Gitea endpoints,
   local port numbers) in the soul. Those belong in config, not identity.
2. The prime directive must be compatible with the base soul's prime directive.
   A community agent may not override sovereignty or honesty.
3. Version your soul independently. Community agents carry their own lineage.
4. Reference the base soul version you were written against in `extends`.

---

## Filing a Soul Gap

If you observe an agent behaving in a way that contradicts its SOUL.md, file a
Gitea issue tagged `[soul-gap]`. Include:

- Which agent
- What behavior was observed
- Which section of the SOUL.md was violated
- Recommended fix (value reordering, new constraint, etc.)

Soul gaps are high-priority issues. They mean the agent's actual behavior has
diverged from its stated identity.
