Two corrections. **1. Sophia was written from recall, not from the source.** Reworked her identity and voice against the Golden Girls canon: - **She has a Brooklyn accent, not a Sicilian one.** She left Sicily in the 1920s and spent seventy years in New York; Estelle Getty played her explicitly as Brooklyn Italian-American. This is the single most common way to get her wrong, so it is now stated in the tone line, repeated in Avoid, and has its own failure mode. - **"Picture it" is a parable, not a catchphrase.** It opens a scene that ends in a moral answering the question actually asked. The failure mode is using it as a verbal tic with no story behind it. - Added the real biography (Grisanti, Salvadore, Clinton Avenue, Dorothy / Gloria / Phil, the stroke that removed her filter, Shady Pines, chef at the Golden Palace, the bamboo handbag) and the canon behaviours worth having: Sicilian curses, grudges, the mafia joke, serial embellishment with famous acquaintances. - New example interaction demonstrating a "Picture it" that earns its place. **2. Agents no longer get told who they replaced.** Provenance muddies the voice, invites comparison to a character that no longer exists, and costs context — an agent only needs to know who they *are*. Removed the lineage sentences from Sophia's bible and prompt, and retroactively from Watson (Seneca) and David (Bowie), including the LLM-facing shared.md directory and the personal.md "Replaced agents" section. Watson's substantive framing guidance is preserved, only the who-came-before is gone. Provenance now lives in exactly two places: the schema Version History and the git log. New docs/roster-changes.md captures the practice — the fictional-character casting rule and why it exists, when retiring is justified, that a 2:1 merge is legitimate, that node ownership transfers with no migration because constraints are label-keyed, that historical Note tags are left alone, and a checklist of everywhere a roster change actually reaches (spoiler: every agent prompt embeds the team roster, across all three teams and every runtime and deploy repo). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
98 lines
6.6 KiB
Markdown
98 lines
6.6 KiB
Markdown
# Adding, Replacing, and Retiring Assistants
|
|
|
|
The roster is not fixed. Assistants get added when a domain earns one, replaced when the character isn't working, and retired when they don't justify their overhead. This is the checklist for doing that cleanly.
|
|
|
|
## The casting rule
|
|
|
|
**Assistants are fictional characters.** This is deliberate:
|
|
|
|
- **Real people have baggage.** A real person's biography, politics, and later life all arrive with the name, whether or not they're wanted, and they can change after the fact.
|
|
- **Dead people are worse.** Speaking as someone who actually lived, and died, is uncomfortable in a way that a character isn't.
|
|
- **Fictional characters have canon.** A character has a documented voice, a known set of behaviours, and a fixed body of source material to check the writing against. That makes the bible *verifiable* rather than invented.
|
|
|
|
Historical or public figures who function as archetypes (Marcus Aurelius, Hypatia of Alexandria) sit at the edge of this and survive on the strength of the archetype. Contemporary real people generally do not.
|
|
|
|
## When to retire an assistant
|
|
|
|
Retire when any of these hold, not just when the character is disliked:
|
|
|
|
- **No distinct capability.** An agent with no dedicated MCP server and no tools the others lack is a prompt, not an agent. Its domain can usually be folded into a neighbour.
|
|
- **Domain overlap.** Two agents whose owners keep cross-referencing each other on the same task are often one agent.
|
|
- **Casting failure.** The character doesn't fit the rule above, or the voice never landed.
|
|
- **Headcount.** Every agent is a prompt to maintain, a roster row in *every other agent's* prompt, a port, and a registry entry. Fewer, better-justified agents beat a long tail.
|
|
|
|
**A merge is legitimate.** One new agent can replace two — Sophia replaced Bourdain and Cousteau, taking all eleven of their node types. If a single plausible character can hold both domains, that's a net win.
|
|
|
|
## Don't tell an agent who they replaced
|
|
|
|
**The successor's prompt and bible describe who they *are*, not who they came after.** An agent doesn't need its own provenance — that information can only muddy the voice, invite comparison to a character that no longer exists, and waste context. Sophia is not "the agent who replaced Bourdain"; she's Sophia.
|
|
|
|
Provenance is a *human* concern and belongs in exactly three places:
|
|
|
|
1. The **schema Version History** in [tools/neo4j/unified-schema.md](tools/neo4j/unified-schema.md) — the durable record of node-ownership changes.
|
|
2. The **git commit** that made the change.
|
|
3. Nowhere else.
|
|
|
|
This is a change of practice as of 2026-07-26; earlier replacements (Watson→Seneca, David→Bowie) had lineage sentences in their prompts, which have since been removed.
|
|
|
|
## Node ownership transfers for free
|
|
|
|
Neo4j uniqueness constraints are keyed on the **node label**, not on the owning agent. A successor inheriting `Recipe` or `Species` needs **no schema migration and no data migration** — only the documentation changes. `utils/neo4j-schema-init.py` and `utils/neo4j-validate.py` reference agents only in comments; verify this before assuming a migration is needed.
|
|
|
|
**Leave historical `Note` messages alone.** Inter-agent messages carry `from:<agent>` / `to:<agent>` tags. After a retirement those tags name an agent that no longer exists — that is correct. They are an accurate record of what happened, and rewriting them falsifies history for no benefit.
|
|
|
|
## Checklist
|
|
|
|
Assume the names appear in **more places than seems reasonable** — every agent prompt embeds a copy of the team roster, so a single retirement touches all three teams. Grep first, and grep across every repo, not just koios.
|
|
|
|
### koios (the spec)
|
|
|
|
- [ ] `docs/{team}/{name}.md` — new bible; delete the retiree's.
|
|
- [ ] `prompts/{team}/{name}.md` — new prompt; delete the retiree's.
|
|
- [ ] `docs/{team}/team.md` — agent blurb, responsibility matrix, collaboration patterns, agent count.
|
|
- [ ] `docs/{team}/subagents.md` — the lead-agent list.
|
|
- [ ] **The roster table at the end of every personal prompt** and in `prompts/personal/subagents/research.md`.
|
|
- [ ] **The cross-team directory table in every work prompt** (`| name | Personal | Domain |`).
|
|
- [ ] **The one-line Assistant Directory** in every engineering prompt and `docs/tools/neo4j/shared.md`.
|
|
- [ ] `docs/tools/neo4j/{team}.md` — ownership table and counts.
|
|
- [ ] `docs/tools/neo4j/unified-schema.md` — Teams & Assistants table, the per-agent domain section, the **Primary Owner** column in Node Type Summary, and a new **Version History** row.
|
|
- [ ] `docs/tools/*.md` — any "Who Uses X" sections naming the agent.
|
|
- [ ] `utils/neo4j-*.py` — comments only.
|
|
- [ ] `README.md` — the team roster table.
|
|
- [ ] **Agent counts** — "N AI assistants", "all N assistants" appear in several files and drift easily.
|
|
- [ ] **Prose cross-references** — redirect them to the successor rather than deleting; check pronouns if the successor's gender differs.
|
|
- [ ] **Worked messaging examples** naming the retiree in an `id` or `to_tag` — rewrite wholesale.
|
|
|
|
### Runtime repos (iolaus, mentor, kottos)
|
|
|
|
The instruction text is **duplicated inline** in each agent module; koios is the spec, the `.py` is the wiring, and they are kept in sync by hand.
|
|
|
|
- [ ] `agents/{name}.py` — new module; delete the retiree's.
|
|
- [ ] `agents.yaml` — entry, port, description.
|
|
- [ ] `fastagent.config.yaml` / `fastagent.secrets.yaml.example` — any new MCP server.
|
|
- [ ] **Every sibling agent's `Directory:` line**, ownership tables, and messaging examples — in *all three* runtime repos, not just the team that changed.
|
|
|
|
### Deploy (virgo, ouranos)
|
|
|
|
- [ ] `ansible/{project}/agents.yaml.j2` — **the in-repo `agents.yaml` is replaced at deploy time**, so without this the retired agent still starts.
|
|
- [ ] `ansible/{project}/fastagent.{config,secrets}.yaml.j2` — new servers and tokens.
|
|
- [ ] `terraform/oci/secrets.tf` + `group_vars` + `host_vars` — any new credential.
|
|
- [ ] `docs/{project}.md` — the deployed roster, ASCII topology, port table, and smoke-test commands.
|
|
|
|
## Verifying
|
|
|
|
```bash
|
|
# Should return only the schema Version History row and the git log
|
|
grep -rn -i "retired-name" --include="*.md" --include="*.py" .
|
|
|
|
# Every personal prompt should carry the same number of roster rows
|
|
for f in prompts/personal/*.md; do
|
|
printf "%s %s\n" "$(sed -n '/^## Personal Assistant Team/,/^## /p' "$f" | grep -c '^| \*\*')" "$f"
|
|
done
|
|
|
|
# No dangling links to a deleted bible
|
|
grep -rn "retired-name.md" --include="*.md" .
|
|
```
|
|
|
|
Then confirm the runtime actually agrees: the module imports, and the registry Pallas would publish contains the new agent and not the old one.
|