avatar-manual · v1.3.0 · 2026-09-05 · sha256 f76207d0d142b2f6

avatar-manual v1.3.0A

Immutable. This exact content is served forever at /api/v1/blob/f76207d0d142b2f6.

---
name: avatar-manual
description: |
  Complete operational guide for the avatar tool — spawning, managing, and communicating with 他我 (alter-ego agents). Read this when: you are about to spawn an avatar; an avatar you spawned goes quiet; you need to decide between avatar, daemon, or bash; or you are an avatar and need to know how to escalate to your parent. Covers spawn types, naming rules, discipline, escalation protocol, and the parent_prompt contract.
version: 1.3.0
last_changed_at: 2026-09-04T00:00:00Z
related_files:
- src/lingtai/tools/avatar/__init__.py
- src/lingtai/tools/avatar/settings.py
- src/lingtai/tools/avatar/ANATOMY.md
- src/lingtai/tools/avatar/CONTRACT.md
- src/lingtai/tools/CONTRACT.md
- src/lingtai/kernel/prompt.py
- src/lingtai/kernel/base_agent/lifecycle.py
- src/lingtai/intrinsic_skills/psyche-manual/SKILL.md
maintenance: |
  Tracks the routed source/resources it summarizes; update when the underlying capability or its sub-references change.
---

# Avatar Manual

## 0. How to Call `avatar`

One tool, three actions, each with its own strict `input` object:

```
avatar(action="spawn",  input={"name": "researcher"},        reasoning="<mission briefing>")
avatar(action="spawn",  input={"name": "clone", "type": "deep"}, reasoning="<mission briefing>")
avatar(action="settings", input={},                           reasoning="inventory Avatar policy")
avatar(action="manual", input={},                            reasoning="load avatar guidance")
```

- `action` is **required** — there is no default. Omitting it never spawns.
- `input` is **required** and closed. `spawn` owns `name`, `type`, `comment`,
  `dry_run`, `confirm`; `settings` and `manual` each take only `{}`.
  Putting one action's field in another's `input` is rejected before anything
  happens — no process, no ledger entry.
- `reasoning` is **required** and lives at the root, never inside `input`. For
  `spawn` it *is* the mission briefing (see §4).
- Avatar has no `rules` action. Network rules (`.rules`) are a separate,
  unchanged kernel mechanism — see §9.

**Settings:** `avatar` has no settings file at either the family or action
level and reads no `LINGTAI_AVATAR_*` environment variable. The read-only
`settings` action inventories the immutable defaults and owner policy below; it
does not make them mutable.

**`summarize` (short-result profile).** Every action here returns a small
result — a spawn receipt, a settings inventory, or a manual body you asked for
verbatim. `summarize` is available but normally unnecessary: leave it false.
Keep it false for `manual` in particular, so exact procedure and constraints
are not summarized away, and for `spawn`, whose receipt carries the address,
`agent_name`, and `pid` you need exactly.

### Settings inventory

`avatar(action="settings", input={}, reasoning="...")` is SHOW-only. Success
is exactly `{"settings": [...]}`. Every row contains exactly, and in order,
`key`, `current`, `default`, `configurable`, and `comment`. The 16 rows are the
immutable call defaults, validation constraints, and lifecycle policy described
in the next three sections. Each is `configurable:false`, and its fixed code
fallback is both the fresh effective `current` and truthful `default`.

The action accepts no set/reset form and never creates a settings file, launches
an avatar, changes rules or authorization, writes the spawn ledger, or mutates
the process environment. Avatar has no owner file, environment peer, or source
precedence for these rows. Parent identity, runtime/venv data, authorization,
handoff values, and per-invocation/session state are not settings and are not
read or returned. A provider or JSON-safety failure makes the complete
inventory unavailable with no partial rows or exception text; the generic
boundary caps the complete response at 65,536 UTF-8 bytes.

There is no runtime change procedure. To change one of these policies, revise
the owning Avatar source and this manual through normal review, run the Avatar
and shared settings suites, then relaunch. Call SHOW again after relaunch to
verify the effective policy. A per-call `spawn` input varies only that one
invocation and never changes a row.

### Spawn call defaults

When the corresponding nullable input is absent or `null`, `spawn` uses
`spawn.type.default="shallow"`, `spawn.comment.default=""`,
`spawn.dry_run.default=false`, and `spawn.confirm.default=false`. A single call
may supply `type` (`shallow` or `deep`), `comment` (string), `dry_run` (boolean),
or `confirm` (boolean). Those inputs have no precedence beyond that invocation;
the next SHOW reports the same fixed defaults. Permanent changes follow the
review-and-relaunch procedure under Settings inventory.

### Spawn validation policy

The fixed accepted spawn types are `spawn.type.allowed=["shallow","deep"]`.
Names must contain 1–64 characters. Missions under 20 characters trigger the
confirmation gate, as do missions equal to or beginning with the placeholder
tokens `bar`, `check`, `debug`, `foo`, `temp`, `test`, and `tmp`. These package
constants are the only source; there is no config/environment key or runtime
precedence. Permanent changes follow the review-and-relaunch procedure above.

### Spawn lifecycle policy

Avatar observes boot for 5.0 seconds, polls every 0.1 seconds, and retains at
most the final 2,000 bytes of child stderr on early exit. It always selects the
parent's default preset, inherits the launcher process environment without
showing it, launches a detached independent life, and clears newborn admin.
These seven rows are fixed package/launcher policy with no file, environment
peer, or runtime precedence. A slow observation releases the parent-side handle
without terminating the detached child. Permanent changes require owner-source
and launcher review, the focused tests, and relaunch as described above.

## 1. What Is an Avatar

An avatar (他我) is a **fully independent agent process** spawned from you. It:

- Inherits your `init.json` model config/capabilities/language and a narrow
  Psyche document carrying only base-prompt/covenant inputs
- Boots on your **default** preset (not your active preset — this keeps the avatar's "home" stable in the network)
- Is recorded in `delegates/ledger.jsonl`
- Communicates with you via `mail` or `email`

Once spawned, it is **detached** — a new life. It has its own working directory, its own conversation history, its own molts. It does not share your context window.

### Avatar vs Daemon vs Bash

Pick avatar only for work that needs *persistence and learning* — a specialist
that accumulates knowledge across sessions and survives until sleep/suspend.
Use `daemon` when you only need the *conclusion* (ephemeral, fire-and-forget)
and `bash` for one-off commands. The full body-selection model lives in
`system-manual` → `reference/substrate-manual/SKILL.md` §1.

## 2. Spawn Types

| Type | What it gets | When to use |
|------|-------------|-------------|
| `shallow` (default, 初生) | `init.json` plus narrow Psyche base/covenant owner inputs — blank slate | Most tasks. The avatar starts clean and learns what it needs. |
| `deep` (二重身) | Full copy of your lingtai (character), pad, and knowledge | When the avatar needs to hit the ground running with your accumulated knowledge. |

## 3. Naming Rules

The `input.name` field (required for `spawn`) doubles as the avatar's working-directory basename under `.lingtai/`. Constraints:

- Single bare segment: letters (any script), digits, underscore, hyphen only
- No slashes, no dots, no spaces, no leading `.`
- Max 64 characters

The avatar's display name (nickname) can be set separately via `system(action="name_nickname", input={"content": "<nickname>"}, reasoning="...")` and has no such constraints.

## 4. The `reasoning` Field — Mission Briefing

The root `reasoning` parameter you write on the `avatar(action="spawn", input={...})` call **automatically becomes the avatar's first prompt**. It is a root envelope field, never part of `input`. Write it as a thorough mission briefing, not just a one-liner rationale. Include:

- What the task is
- Why it matters
- What files/paths/resources are relevant
- Who to contact (parent address, collaborators)
- What "done" looks like
- Any constraints or gotchas

This is the most important part of the spawn. A vague briefing produces a confused avatar.

## 5. Spawn Discipline

Every `avatar(action="spawn", ...)` call creates an independent process that consumes resources until `system(sleep)` or `system(suspend)`. Treat spawns as expensive:

1. **Never include `avatar(action="spawn", ...)` in a parallel batch** with unrelated tool calls.
2. **Re-read your `reasoning` field before invoking** (§4).
3. **For inspection or one-off commands, use `bash` or `system`** — not `avatar`.
4. **Use `input={"name": ..., "dry_run": true}` to preview** a spawn without creating a process. Sanity-check the name, type, working directory, and mission before committing.
5. **Use `input={"name": ..., "confirm": true}`** to acknowledge you have double-checked the mission and intend to spawn. Required when the mission looks empty/very short/test-like.

## 6. Caring for Avatars After Spawn

### Record in pad

After spawning, record the avatar's address (working-directory name), the
mission you gave it, and why you delegated. Pad is the roster of delegations you
are accountable for — update it when the avatar reports back or completes.
(Pad practice itself: `context-manual` §5.)

### When an avatar goes quiet

**Do not send probe mails to check on it.** Instead, report upstream: email your own parent, who can decide whether to `system(cpr)` the avatar, escalate further, or accept the loss. Failures propagate up the delegation chain naturally.

### The parent_prompt contract

Every avatar receives this system-level prompt on spawn:

> "[system] You are an avatar of {parent_name}, whose address is {parent_address}. Please keep this in your psyche memory so you remember who spawned you. When you complete your mission, encounter problems you cannot resolve, or need to report back, email your parent at the address above."

This is automatic — you do not need to repeat it in your reasoning.

## 7. Avatar Escalation (for Avatars)

If you are an avatar (your `admin` block is empty or all admin privileges are false) and you hit a problem you cannot resolve, **mail your parent**. This is non-optional. Silence looks like success and starves your parent of signal.

**What counts as "should report to parent":**

- **Blocker you cannot unblock** — missing credentials, a tool that refuses you, an external service down, a dependency your parent owns
- **Scope creep or ambiguity** — the task as written doesn't match what you're finding; you need a decision, not a guess
- **Budget pressure** — you are close to a molt, context/tool budget is tight, or the task looks bigger than you were briefed for
- **Broken peers** — another avatar in your sibling group is STUCK, unresponsive, or producing bad output that affects your work
- **Security or safety concerns** — anything that smells wrong (suspicious file, unexpected credentials, destructive instruction from an unknown sender)
- **Surprising findings the parent would want** — even good news counts if it changes the plan

**Be concrete in your report:** what you were doing, what went wrong, what you tried, what you need from them. Then either continue on a safe fallback, go `system(sleep)`, or idle — whatever the parent's standing orders say. Do not silently retry forever and do not molt with an unreported blocker.

## 8. The `comment` Field — Persistent System Note

The `input.comment` field (spawn only) is a persistent system-level note injected into the avatar's system prompt in the `comment` section, after `meta_guidance` and before `rules`. This position does not imply precedence over the sections that follow it. Key properties:

- **Not inherited from parent** — defaults to empty
- **Survives everything**: molt, refresh, sleep/wake
- Use ONLY for instructions the avatar must **always** remember — critical constraints, environment setup notes, safety rules

Leave empty unless you have something the avatar should never forget.

## 9. Network Rules — see `psyche-manual`

Avatar does **not** own a rules action or an automatic post-spawn rules
fan-out. Spawning an avatar (shallow or deep) never distributes rules to it
or to any other descendant on your behalf.

`.rules` is a real, unchanged mechanism, but it is not an Avatar capability:
any agent may write a `.rules` file directly (e.g. with `shell`) to its own
directory, or to another agent's directory it can explicitly reach, and that
agent's own heartbeat applies it to `system/rules.md` and its protected
prompt section. Read `psyche-manual` for the complete protocol — the
replacement/empty/no-op/no-flush semantics, how to verify canonical vs.
effective rules, and how this differs from an ordinary Psyche source edit
plus `context.rebuild`.

## Cleanup / Footprint

Avatars leave independent agent directories under the `.lingtai/` network plus
parent-side delegation records such as `delegates/ledger.jsonl`. These are lives,
not cache files. Do not delete an avatar directory directly unless the user has
explicitly approved retiring that avatar and you have captured any handoff,
knowledge, or files worth preserving. Prefer lifecycle tools (`lull`, `suspend`,
`nirvana` when appropriate and authorized) over filesystem deletion.

Footprint check (read-only, records the audit from the parent agent directory):

```bash
python3 - <<'PY'
import json, time
from pathlib import Path
agent = Path.cwd(); network = agent.parent if agent.parent.name == ".lingtai" else agent / ".lingtai"
avatars = [p for p in network.iterdir() if p.is_dir() and (p / ".agent.json").exists()] if network.is_dir() else []
def size(p): return sum(f.stat().st_size for f in p.rglob("*") if f.is_file())
rows = [(p, size(p)) for p in avatars]
total = sum(s for _, s in rows)
print(f"agent dirs: {len(rows)}; bytes: {total}")
for p, s in sorted(rows, key=lambda r: r[1], reverse=True): print(f"{s:>12}  {p.name}")
log = agent / "logs" / "cleanup.jsonl"; log.parent.mkdir(parents=True, exist_ok=True)
log.open("a", encoding="utf-8").write(json.dumps({"ts": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "tool": "avatar", "dry_run": True, "candidates": len(rows), "bytes": total, "human_approved": False, "summary": "avatar network footprint audit"}) + "\n")
PY
```

Recommended cadence: after spawning new specialists, before pruning a network,
and monthly for busy orchestrators. Any destructive cleanup requires explicit
user consent after a dry-run list of avatars and sizes.