| type | reference | ||
|---|---|---|---|
| topic | cli | ||
| audience |
|
||
| applies_to |
|
Manage persistent agents — long-lived Session instances each with their own profile, history, memory layer, and inbox.
The auto-created default agent always exists; reyn agent new creates additional named agents. See concepts/multi-agent for the model.
reyn agent <subcommand> [args]
Subcommands: list, new, show, rm.
Print all active (non-archived) agents (alphabetical), with last-activity timestamp and the first line of each profile's role. Archived agents are hidden from this listing. Pass --all to include archived agents, shown as <name> (archived), so you can see / recover / purge them.
reyn agent list # active agents only
reyn agent list --all # also show archived agentsNAME LAST ACTIVITY ROLE
default 2026-05-01 13:00
researcher 2026-05-01 12:55 deep technical research, prefers primary sources
writer 2026-04-30 18:20 concise long-form prose
Create a new agent under .reyn/agents/<name>/. The directory is provisioned with a profile.yaml; history.jsonl, events.jsonl, memory/, and runs/ are created on first activity.
reyn agent new researcher --role "deep technical research, prefers primary sources"<name> must match the agent name regex: 1–32 characters of [a-z0-9_-] starting with [a-z0-9].
The --role text is injected into the agent's LLM system prompt — keep it short and specific. To configure allowed_mcp or any other profile field, edit profile.yaml directly after creation; see profile-yaml reference.
Print profile metadata and resolved fields:
reyn agent show researchername: researcher
created_at: 2026-05-01T12:00:00+00:00
workspace: /path/to/project/.reyn/agents/researcher
role:
deep technical research, prefers primary sources
Archive the agent by default (soft-delete — data preserved, not destroyed). Pass --purge for a hard-delete that permanently destroys the agent directory and all rewind history.
reyn agent rm researcher # archive (prompted)
reyn agent rm researcher --yes # archive, skip prompt
reyn agent rm researcher --purge # hard-delete (prompted, irreversible)
reyn agent rm researcher --purge --yesThe default agent cannot be removed.
The agent's .reyn/agents/<name>/ directory is kept in place — the data is not destroyed. This is the key distinction from --purge:
- PITR generations are preserved: the WAL-derived checkpoint history survives, so the data is recoverable.
- Topology membership is preserved: no cascade fires. The agent's team/network membership is not removed.
- A tombstone marker is written recording the archival WAL seq (the WAL-window GC hinge).
- The agent is hidden from active surfaces:
reyn agent list, the TUI Agents tab, default-topology routing, and A2Acan_sendchecks all skip archived agents. It is dormant, not destroyed.
WAL-window auto-purge: when the WAL retention window advances past the archival seq, the archived agent's directory is hard-deleted automatically (the soft-delete left the rewind window — the data is no longer recoverable). At that point the topology cascade fires and removes the agent from all topologies.
Immediately hard-deletes .reyn/agents/<name>/ and destroys all PITR generations. Time-travel to before the purge is intentionally unsupported. The topology cascade fires immediately (agent removed from all topologies; team topologies whose leader is purged are deleted entirely).
Use --purge when you want a clean, permanent delete and do not need the recovery window.
Each agent owns .reyn/agents/<name>/:
| Path | Purpose |
|---|---|
profile.yaml |
name / role / created_at / allowed_mcp / preferences / bounding |
history.jsonl |
append-only conversation + agent message log |
events.jsonl |
runtime event audit log |
memory/MEMORY.md + body files |
agent-scoped memory layer |
runs/<run_id>/ |
per-workflow-spawn workspace |
A preferences: mapping in profile.yaml sets an agent-layer override for
one or more of a fixed set of dotted config keys
(reyn.runtime.preferences.PREFERENCE_KEYS) — today: output_language,
chat.reasoning.display, one warn_ratio per cost.* dimension
(per_agent_tokens / per_agent_cost_usd / daily_tokens /
daily_cost_usd / monthly_tokens / monthly_cost_usd), and
cost.rate_limit_warn_ratio.
# .reyn/agents/researcher/profile.yaml
name: researcher
role: deep technical research, prefers primary sources
created_at: "2026-08-14T00:00:00+00:00"
preferences:
output_language: jaFree override, unlike allowed_mcp's restrict-only intersection: an
agent-layer preference REPLACES the project-level default outright — there
is no "child can only narrow" check, because this axis (owner/lead-coder
classification, #4206) covers settings that don't consume a shared,
bounded resource (unlike model, which is ② bounding — see #4206). A
session spawned under this agent can further override the SAME key in its
own <session-state-dir>/config.yaml preferences: mapping — session
wins over agent wins over the project default.
An unrecognized key under preferences: (a typo, or a key retired from
PREFERENCE_KEYS) fails LOUDLY at load time (reyn.runtime.preferences. UnknownPreferenceKeyError) rather than silently doing nothing — the same
discipline #4655 established for config-schema dict-leaves.
Scope: read/resolve only, all 9 keys now wired (#4206 Slices 1/2/B).
output_language/chat.reasoning.display are live Session properties
(Session.output_language / Session.reasoning_display) re-resolving the
session/agent/project composition on every access. The 7 cost.*.warn_ratio
keys use a DIFFERENT shape ("Design C", #4724): BudgetTracker is
process-shared (one instance across every agent/session in a process, built
once from the project-level config), so it never resolves a session/agent
identity itself — instead Session.warn_ratio_overrides() resolves the ③
composition (the SAME session/agent-preference files, collected into a
dict[str, float] of only the keys actually overridden at either layer)
and the CALLER (RouterLoop, via RouterHostAdapter.warn_ratio_overrides(),
and the /budget display via BudgetGateway) passes that resolved mapping
straight into BudgetTracker.check_pre_llm/record_llm/format_budget_full
as an explicit argument. The tracker's own counters (token/cost totals)
stay PROCESS-SHARED and unaffected by this — only the RATIO that decides
WHEN to warn about an already-shared number is caller-resolvable; an
unknown key in the mapping raises UnknownPreferenceKeyError the same way
validate_preferences does. No preferences-specific CLI/slash write
surface exists yet for any key — set an agent-layer value by editing
profile.yaml directly (the same existing pattern allowed_mcp already
uses); a session-layer value by whatever spawns the session passing a
narrowing dict whose own preferences sub-key is set
(AgentRegistry.spawn_session's existing narrowing= parameter — no new
API).
A bounding: mapping in profile.yaml sets an agent-layer CEILING for one
or more of a fixed set of dotted config keys
(reyn.runtime.bounding.BOUNDING_KEYS) — today: model only. Unlike
preferences: above, this axis exists BECAUSE the key it covers consumes
a shared, bounded resource (the process-shared BudgetTracker's
daily/monthly quota) — a free override here would let a child exhaust the
parent's own budget, so the composition is restrict-only instead.
# .reyn/agents/researcher/profile.yaml
name: researcher
role: deep technical research, prefers primary sources
created_at: "2026-08-14T00:00:00+00:00"
bounding:
model: lightNarrowest wins, restrict-only: the EFFECTIVE model ceiling a session
enforces (Session.model_class_ceiling) is the narrowest (cheapest, per
reyn.llm.model_resolver.STANDARD_CLASSES' own light < standard < strong
order) of three layers — the project's own llm.model_max_class, this
agent's bounding.model, and (session wins over agent, same precedence
③ uses) the spawned session's own <session-state-dir>/config.yaml
bounding.model. A layer that declares a WIDER class than a layer above
it never widens the effective ceiling — only a NARROWER declaration moves
it. A layer that declares no ceiling at all, or a class outside the 3
standard tiers, is simply ignored (not comparable), the same "not an
error, just not a narrowing" shape model_class_exceeds_ceiling itself
already has for an incomparable value.
An unrecognized key under bounding: (a typo, or a key outside
BOUNDING_KEYS) fails LOUDLY at load time (reyn.runtime.bounding. UnknownBoundingKeyError) rather than silently doing nothing — the same
discipline preferences: above uses.
Enforcement: the composed ceiling reaches the SAME #1190 chokepoint
(recorded_acompletion) #4206 T1 already enforced a project-only ceiling
at — a call whose resolved class exceeds it is REJECTED
(ModelClassExceedsCeilingError) before litellm.acompletion is ever
invoked. ②'s own change is only WHERE the ceiling value comes from: a
live per-call 3-layer composition instead of a value read once at
RouterLoop construction.
Scope: model only — timeout/router_max_iterations are explicitly
OUT of BOUNDING_KEYS for now (no driving reason measured yet for
timeout, and router_max_iterations has no config key at all today).
- Reference: profile-yaml
- Reference: chat CLI
- Reference: topology CLI
- Concepts: multi-agent
- Concepts: time-travel — rewind + PITR mechanics