forked from Rockachopa/Timmy-time-dashboard
222 lines
6.9 KiB
Markdown
222 lines
6.9 KiB
Markdown
|
|
# 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.
|