Background
atomic_agents/agent.py::__init__ reads three specific markdown files at fixed paths:
<agent>/persona/IDENTITY.md — who the agent is
<agent>/persona/SOUL.md — personality / voice
<agent>/persona/USER.md — about the operator
The read order, the file paths, and the composition into the system prompt are all hard-coded.
Why it matters
A SaaS deployment of atomic-agents almost certainly wants persona editable via UI: an admin saves edits to IDENTITY in a web form and the next agent run picks them up. Today that requires writing markdown files, which means giving the SaaS UI write access to a filesystem the agent runtime also reads. That's awkward and racy.
Other reasons to abstract:
- Multi-tenant. A SaaS hosting N agents wants persona records keyed by agent_id in a DB, not per-tenant filesystems.
- Versioning. Persona drift is operationally interesting — "what did SOUL look like a week ago?" Persona-as-row enables history queries.
- A/B testing. Spec/15 (soul evolution) gets cleaner if persona is pluggable: shadow personas, golden eval comparisons, gradual rollouts.
- Templates. A
PersonaTemplateBackend could load IDENTITY/SOUL/USER from a starter library so new agents don't begin blank.
What to change
- New module
atomic_agents/persona/ with backend.py (Protocol) + filesystem.py (default FilesystemPersonaBackend wrapping current 3-file read).
PersonaBackend protocol exposes:
load_identity() → returns Persona dataclass (body + metadata)
load_soul()
load_user()
write_identity(content) / write_soul / write_user (operator-driven edits, UI-friendly)
version_persona(slot) / restore_persona(slot, version) (mirrors memory versioning)
compose_system_prompt(identity, soul, user, ...) — backend may want to control composition for performance / caching
agent.__init__ picks up agent.persona_backend.load_*() instead of direct file reads.
- Spec doc
docs/spec/23-persona-backend.md.
Future backends
DatabasePersonaBackend — SaaS UI editable
GitPersonaBackend — persona changes are commits in a separate repo (audit-friendly)
TemplatePersonaBackend — read-only library of starter personas
Acceptance
- All existing agent tests pass with
FilesystemPersonaBackend as default.
- Protocol conformance suite (~10 tests) — load/write/version round-trip, missing-file behavior, prompt composition.
- One DB-shaped mock backend proves the protocol holds for non-filesystem implementations.
Open questions
- Does SOUL stay separate from IDENTITY at the backend level, or does composition happen in the backend? (Memory: yes, separate per scope §3 — soul has independent lifecycle, do NOT collapse.)
- USER.md is operator-specific; does a multi-tenant backend keep USER per-tenant while sharing IDENTITY? Or should USER live in the user/account layer entirely?
Context
Background
atomic_agents/agent.py::__init__reads three specific markdown files at fixed paths:<agent>/persona/IDENTITY.md— who the agent is<agent>/persona/SOUL.md— personality / voice<agent>/persona/USER.md— about the operatorThe read order, the file paths, and the composition into the system prompt are all hard-coded.
Why it matters
A SaaS deployment of atomic-agents almost certainly wants persona editable via UI: an admin saves edits to IDENTITY in a web form and the next agent run picks them up. Today that requires writing markdown files, which means giving the SaaS UI write access to a filesystem the agent runtime also reads. That's awkward and racy.
Other reasons to abstract:
PersonaTemplateBackendcould load IDENTITY/SOUL/USER from a starter library so new agents don't begin blank.What to change
atomic_agents/persona/withbackend.py(Protocol) +filesystem.py(defaultFilesystemPersonaBackendwrapping current 3-file read).PersonaBackendprotocol exposes:load_identity()→ returnsPersonadataclass (body + metadata)load_soul()load_user()write_identity(content)/write_soul/write_user(operator-driven edits, UI-friendly)version_persona(slot)/restore_persona(slot, version)(mirrors memory versioning)compose_system_prompt(identity, soul, user, ...)— backend may want to control composition for performance / cachingagent.__init__picks upagent.persona_backend.load_*()instead of direct file reads.docs/spec/23-persona-backend.md.Future backends
DatabasePersonaBackend— SaaS UI editableGitPersonaBackend— persona changes are commits in a separate repo (audit-friendly)TemplatePersonaBackend— read-only library of starter personasAcceptance
FilesystemPersonaBackendas default.Open questions
Context
MemoryBackendfrom PR refactor(memory): extract MemoryBackend protocol; FilesystemBackend default #57