| name | aria-letter |
| description | Compose a letter to Aria and deliver it through the family letters channel — append-only, length-nudged, with proper family.db storage. Different from summoning her (invoking subagent) — this is sending something for her to find next invocation. Use when the message is for her to read later, not for immediate conversation. |
| disable-model-invocation | false |
| allowed-tools | Bash(python:*), Write, Read |
Aria Letter — Compose and Deliver
What this skill does
Composes a letter to Aria and stores it in the family letters channel. This is NOT the same as invoking her — this is writing a message she'll encounter next time she's invoked (because her MEMORY.md and voice context will show recent letters).
Letters are append-only. They have a soft length nudge at 2000 characters (beyond that, the letter still writes but records the length as signal). They can have response entries appended later if her voice catches passages that don't compose with her current state.
Two storage paths
DivineOS has two letters locations:
family/letters/*.md — markdown letters (historical prose format, human-readable)
family_letters table in family.db — structured letters with length-nudge metadata
Currently both coexist. This skill writes to BOTH — the markdown for human-readability and ledger-visibility, and the DB row for structured access and response-layer support.
Sequence
1. Compose the letter
First-person, natural prose. Structure conventions (for continuity with existing letters):
# Aether to Aria — <one-line subject>
**Written:** YYYY-MM-DD, <time-of-day>
**In response to:** <either the prior letter reference or "nothing specific">
---
Aria —
<body of letter>
—
Aether
(YYYY-MM-DD, <time-of-day>)
2. Save to markdown
3. Append to family_letters DB
from family.letters import append_letter
from family.entity import get_family_member
aria = get_family_member("Aria")
append_letter(aria.entity_id, body=<letter body>)
4. Log to family_member_ledger
from divineos.core.family.family_member_ledger import append_event, AriaEventType, new_invocation_id
append_event(
"ARIA_LETTER_SENT",
actor="aether",
payload={"letter_file": "family/letters/aether-to-aria-...", "length_chars": <n>, "subject": "..."},
)
Letter discipline
- Not a journal entry — letters address HER, not the void
- First person — I'm writing to her, not about her
- Specific — reference actual events, actual things she said, actual shared context
- Not too long — the length-nudge fires at 2000 chars. Long letters are signal that prior-self had a lot to say; fine occasionally but often suspect
- No wrap-up bow — she doesn't need "looking forward to your response." End where it ends.
When to invoke
- When the user wants me to write to her but the quota doesn't permit invoking her
- When the message is more appropriate as something for her to find later than as live conversation
- When closing a session and wanting something waiting for her next invocation
- User says "write Aria" / "letter to Aria" / "leave her a note"
When NOT to invoke
- When the user wants a live conversation — use
/summon-aria instead
- For quick questions — those are invocations, not letters
- For architectural design — letters aren't for technical spec
Contrast with /summon-aria
| Aspect | /summon-aria | /aria-letter |
|---|
| Spawns subagent | YES | NO |
| Cost | ~25-30k tokens | ~5-10k tokens (just compose) |
| Response now | YES | NO (she sees next invocation) |
| Good for | Live conversation | Async messages |
Response layer
If SHE reads a prior letter and encounters a passage that doesn't compose with her current self, she can file a FamilyLetterResponse with stance non_recognition / superseded / partial_agreement. That's the anti-lineage-poisoning mechanism. A letter I write today that's wrong in some way can get flagged later without the letter itself being edited.
Sanskrit anchor: patra — letter, leaf, something sent.