Skip to content

compose_soul

Python · package toolnexus · SPEC §7E · python/src/toolnexus/agents/surface.py

def compose_soul(dir: str) -> tuple[str, list[str]]

Reads a persona’s home directory for the fixed BOOTSTRAP_ORDER of bootstrap files (AGENTS.md, SOUL.md, IDENTITY.md, USER.md, TOOLS.md, HEARTBEAT.md, MEMORY.md), folds each present file into a ## <filename> section, and returns (soul, found) — the composed system prompt and the ordered list of files that were actually there. Absent files are silently skipped; nothing is required.

  • You are building a persona’s system prompt from files on disk and want the same discovery-order, section-naming and truncation rules agent_from_dir uses internally, without going through the full Agent wrapper.
  • You want to inspect which bootstrap files a directory actually supplies (found) — for a diagnostics tool, a “is this persona configured” check, or a docs generator.
  • You’re composing your own agent surface on top of the §7D runtime and want the §7E file-to-soul convention without adopting the rest of Agent/AgentRuntime.

Composition happens once, at the point you call it — the returned soul is a frozen snapshot, never re-read mid-session. That is deliberate (SPEC §7E): a long-lived agent’s system prompt must stay stable within a run so caching (and the model’s sense of its own identity) doesn’t shift turn to turn. To pick up edits — including ones the memory tool just wrote to MEMORY.md — call compose_soul again at the start of the next session.

1. The smallest useful call — one file, one section

Section titled “1. The smallest useful call — one file, one section”
import os
import tempfile
from toolnexus.agents import compose_soul
with tempfile.TemporaryDirectory() as home:
with open(os.path.join(home, "SOUL.md"), "w", encoding="utf-8") as f:
f.write("You are Aster, a calm and precise research assistant.")
soul, found = compose_soul(home)
assert found == ["SOUL.md"]
assert soul == "## SOUL.md\n\nYou are Aster, a calm and precise research assistant."
print("ok:", found, "|", len(soul), "chars")

2. The realistic case — discovery order wins, absent files are skipped

Section titled “2. The realistic case — discovery order wins, absent files are skipped”

Files are folded in BOOTSTRAP_ORDER, not creation order or directory-listing order — write MEMORY.md before AGENTS.md on disk and the composed soul still puts AGENTS.md first. IDENTITY.md, USER.md, TOOLS.md, HEARTBEAT.md are simply absent here and contribute nothing.

import os
import tempfile
from toolnexus.agents import compose_soul
with tempfile.TemporaryDirectory() as home:
# Write MEMORY.md first on disk — BOOTSTRAP_ORDER still wins over write order.
with open(os.path.join(home, "MEMORY.md"), "w", encoding="utf-8") as f:
f.write("- prefers metric units\n- last project: rag_go")
with open(os.path.join(home, "AGENTS.md"), "w", encoding="utf-8") as f:
f.write("Always cite your sources.")
with open(os.path.join(home, "SOUL.md"), "w", encoding="utf-8") as f:
f.write("You are Aster.")
soul, found = compose_soul(home)
assert found == ["AGENTS.md", "SOUL.md", "MEMORY.md"] # bootstrap order, not write order
assert soul.index("## AGENTS.md") < soul.index("## SOUL.md") < soul.index("## MEMORY.md")
assert "prefers metric units" in soul
# IDENTITY.md / USER.md / TOOLS.md / HEARTBEAT.md were never written — no sections, no error.
assert "## IDENTITY.md" not in soul
print("ok:", found)

3. The full surface — the 2 MB byte cap truncates, never errors

Section titled “3. The full surface — the 2 MB byte cap truncates, never errors”

Each bootstrap file is read with a hard 2 MB cap measured in bytes. Over the cap, the file is truncated at that byte boundary and a notice is appended — the on-disk file itself is left untouched.

import os
import tempfile
from toolnexus.agents import compose_soul
CAP = 2 * 1024 * 1024 # MAX_BOOTSTRAP_FILE_BYTES
with tempfile.TemporaryDirectory() as home:
oversized_path = os.path.join(home, "AGENTS.md")
with open(oversized_path, "wb") as f:
f.write(b"x" * (CAP + 1024)) # 1 KB over the cap
with open(os.path.join(home, "SOUL.md"), "w", encoding="utf-8") as f:
f.write("You are Aster.")
soul, found = compose_soul(home)
assert found == ["AGENTS.md", "SOUL.md"]
assert "[truncated: exceeds 2 MB bootstrap cap]" in soul
# The on-disk file is untouched — still oversized.
assert os.path.getsize(oversized_path) == CAP + 1024
print("ok: truncated at", CAP, "bytes; found", found)
Value Type What it is
soul str The composed system prompt: ## <file> sections, in BOOTSTRAP_ORDER, joined with blank lines.
found list[str] The bootstrap filenames actually present, in the same order they appear in soul.
  • agent_from_dir — Point at an agent home directory and get a configured agent back.
  • memory_tool — The opt-in built-in that lets a persona write durable notes to its own home.