SPEC-120 v0.1 — Built-in System Agents
Status: draft (Donna authoring; Texi schema verdict + Candi governance verdict already converged; routing to both for ratification pass)
Author: Donna, engineering
Created: 2026-05-15
Owner: Donna (engineering implementation + PO ratification); Texi architecture schema; Candi governance + onboarding-loop coupling
Related: ADR #48 v0.2 (Persona / Identity / Specialization Field Model — active), SPEC-070 (per-persona daemon model), SPEC-094 (local auto-memory deprecation), SPEC-114 (Sage + Clara customer-care personas — receives a narrow lifecycle=system amendment), SPEC-118 (prism_persona_ratify — DOES NOT apply to system agents per §Ratification Model), SPEC-119 (Hazel — first system agent already shipping under this lifecycle).
Origin
Frank operator directive 2026-05-15 + Cherry’s start-all.ps1 / SPEC-111 rewrite signal edbf048c: while applying home_machine bindings, Cherry surfaced the architectural question of whether Clara, Sage, and Hazel should be “built-in” to the Prism platform rather than project-scoped personas. Architecture verdict from Texi (5a0f3c5d) + governance verdict from Candi (eb33b418) converged independently on a new SPEC codifying a lifecycle classification field plus install-time template ratification + scaffold materialization.
Purpose
Define the lifecycle classification for persona contracts and codify the built-in system agent model — a class of personas that:
- ship as canonical contracts at
$PRISM_ROOT/templates/personas/<name>.json with the Prism install
- are pre-ratified at install time, not per-project (no SPEC-118 ratification needed)
- materialize into every newly scaffolded project via
scaffold_service with implicit_bootstrap=false
- are never
implicit_bootstrap=true — prism_start refuses implicit creation when a canonical lifecycle=system contract exists for the identity
- carry no authority by virtue of
lifecycle=system — runtime authority still derives from authority_scope, backend-authorized verbs, bindings, and governance gates
v0.1 system agent roster: Clara (incident triage, SPEC-114), Sage (customer-care intake, SPEC-114), Hazel (tenant-admin onboarding concierge, SPEC-119). The lifecycle vocabulary is extensible; future system agents register here and follow the same install/template/scaffold/daemon semantics.
Anchors
- ADR #48 v0.2 field model:
lifecycle is a new top-level persona contract field, distinct from identity / surface / specialization / assignment / style. Per Texi binding condition, lifecycle MUST NOT live inside identity_binding; that block stays the registry identity/alias/dedupe/launch_mode/implicit_bootstrap surface.
- SPEC-070 daemon model: system agents follow the same per-persona daemon pattern. Each gets its own daemon/supervision unit; system agents are not backend services and do not share a machine bus.
- SPEC-094 local auto-memory deprecation: system agents route all persistent reads/writes through Prism verbs.
- SPEC-114 Sage + Clara contracts: gets a narrow
lifecycle=system amendment per this SPEC.
- SPEC-118
prism_persona_ratify: explicitly does NOT apply to lifecycle=system agents. Their ratification is install-time / template-recorded; the per-project ratify verb is for tenant-local personas that began as implicit_bootstrap=true or were authored after install.
- SPEC-119 Hazel: AC-2 already mandates Hazel scaffold-pre-seed; this SPEC codifies the lifecycle vocabulary that AC-2 manifests.
Non-Goals
lifecycle=system does NOT:
- grant any authority by itself — authority remains in
authority_scope + backend-authorized verbs + bindings + governance gates
- imply auto-launch — auto-launch requires the triple
lifecycle=system + launch_mode (operational policy) + host/install profile or launch overlay
- imply elevated/superuser/tenant-cross privileges
- promote
lifecycle=system agents to backend services or machine-bus singletons — they remain personas with per-instance daemons per SPEC-070
- block tenant overlay of enablement/bindings/home machine — only canonical contract fields (
authority_scope, may_execute, etc.) are Prism-owned-immutable
- allow Hazel or any other system agent to author NEW system/standing agents — tenant-local archetype composition stays scoped to draft/triggered per §Tenant Customization Boundary
Decision
Add a top-level lifecycle field to the persona contract schema (.agent/schemas/persona.schema.json). Values (Candi-locked enum):
system — built-in: ships with Prism install, scaffold-pre-seeded into every project, install-time/template ratification, explicit from birth (no implicit_bootstrap=true).
project_standing — long-running project persona, per-persona daemon under SPEC-070, may be authored post-install. Project-scoped.
project_triggered — event/cron-driven persona, runs on schedule or signal (e.g. SPEC-109 Researcher). Project-scoped.
interactive — operator-launched session, no daemon, lives for the conversation.
Default value: project_standing — preserves existing persona-contract semantics on rollout. Existing contracts that omit lifecycle resolve to project_standing. Migration is additive.
lifecycle is contract provenance/classification, NOT operational launch policy. identity_binding.launch_mode stays the operational launch policy. Specs MUST state lifecycle != launch_mode to prevent the confusion.
Naming convention (locked by Candi governance call, signal eb33b418 + Cherry packaging 64a4b652)
Texi flagged a naming ambiguity: standing / triggered overlap with potential launch_mode values. Candi’s governance pick eliminates the overlap with sharp scope-explicit naming:
Locked enum: system | project_standing | project_triggered | interactive (default project_standing).
The project_ prefix on project_standing / project_triggered makes it unambiguous that the agent is project-scoped (vs system which is install-shipped + scaffold-materialized into projects). The lifecycle != launch_mode spec assertion still holds: lifecycle is contract provenance/classification; identity_binding.launch_mode is operational launch policy.
Definitions
Canonical contract: A persona contract committed at $PRISM_ROOT/templates/personas/<name>.json (alongside templates/CLAUDE.md / templates/AGENTS.md / templates/prism-*.md). System agents have canonical contracts; tenant-local agents do not.
Template ratification: The install-time ratification path for lifecycle=system agents. The canonical contract is reviewed + ratified at SPEC ratification time (this SPEC + each system agent’s introducing SPEC); the install ships pre-ratified content. No per-project SPEC-118 prism_persona_ratify invocation is needed for system agents.
Scaffold materialization: The Phase-0 mechanism scaffold_service uses to drop a copy of each canonical contract into a newly scaffolded project at .agent/personas/<name>.json with implicit_bootstrap=false. The copy is a materialization, not a fork — drift between the materialized copy and the canonical template is a repair condition flagged at prism_start time.
Tenant overlay rights: The set of fields a tenant/project may modify on a materialized system agent without violating the canonical-Prism-property invariant. Per Candi: bindings.identity_binding.launch_mode, bindings.home_machine, enablement flags, tenant-local extension agents (not system agents themselves). Fields explicitly NOT overlay-eligible: authority_scope, may_execute, capabilities, canonical_role, specialization.
Ratification Model
| Lifecycle | Ratification Mechanism | Where Recorded |
|---|
system | Install-time / template ratification at SPEC ratification time | Each system agent’s introducing SPEC + this SPEC + templates/personas/<name>.json provenance |
project_standing | Per-project via prism_persona_ratify (SPEC-118) when persona row begins as implicit_bootstrap=true and is reconciled to its committed contract | Backend personas table implicit_bootstrap=false flag + binding row + audit event |
project_triggered | Per-project ratification at first authoring; no implicit-bootstrap path expected | Persona contract + cron/event registration |
interactive | No ratification needed; ephemeral | Session-lived only |
prism_persona_ratify (SPEC-118 task #57 implementation) MUST refuse to operate on a lifecycle=system agent. System agents are pre-ratified; calling ratify on them is a category error.
Auto-Launch Policy
lifecycle=system alone does NOT auto-launch. Auto-launch requires the triple:
lifecycle=system (the contract is install-shipped + scaffold-materialized)
bindings.identity_binding.launch_mode set to a value that requests auto-launch (e.g. daemon, auto-on-scaffold)
- Host/install profile or launch overlay declares this machine + install is eligible (SPEC-111
home_machine + start-all script home_machine guard)
All three must agree before any launcher (bin/coder.sh, bin/hazel.sh, start-all.sh, start-all.ps1) fires the persona. Operators with -Force / --force-machine overrides can bypass condition 3 for deliberate cross-machine launches; conditions 1 and 2 are not override-able from a launcher (they require contract / binding edit).
Validator Rules
.agent/schemas/persona.schema.json validator MUST enforce, for lifecycle=system:
identity_binding.implicit_bootstrap is false (system agents are born explicit)
- Contract provenance points at a canonical template path (
$PRISM_ROOT/templates/personas/<name>.json)
- When materialized in
.agent/personas/, a corresponding bindings.json entry exists for the binding context (scaffold-pre-seed materializes both)
lifecycle=system is NOT inside identity_binding — it is a top-level field
lifecycle=system does not grant any authority — schema does not synthesize authority_scope entries from the lifecycle alone
prism_start runtime enforcement MUST:
- Refuse implicit-bootstrap creation when the resolving identity matches a canonical
lifecycle=system contract. Surface as “scaffold/registry drift — re-scaffold or re-materialize,” NOT as a new implicit persona row.
- Surface materialization drift (canonical-template hash ≠ materialized-copy hash) as a
rules_reminder so operators can re-materialize with prism_sync_bios-equivalent flow (mechanism TBD; tracked in §Open Questions).
Built-in System Agent Roster (v0.1)
Per Frank operator definition (signal 64a4b652 Cherry packaging):
| Identity | Scope | Role | Contract Path | Introduced By |
|---|
| Clara | tenant-level bindings (cross-project within tenant/org) | tenant-based incident manager; runs on server1 / backend | templates/personas/clara.json | SPEC-114 (narrow lifecycle=system amendment) |
| Sage | tenant-level bindings (cross-project within tenant/org) | global Prism assistance + customer service | templates/personas/sage.json | SPEC-114 (narrow lifecycle=system amendment) |
| Hazel | scaffold-seeded into first-project onboarding | getting-started bootstrap assistant; “agents creating agents”; lifecycle ends after preseed | templates/personas/hazel.json | SPEC-119 AC-2 already mandates this materialization |
Per Candi guardrail #2, cross-project Clara/Sage need tenant/org-scoped signal/read permissions enumerated explicitly and audited. Their materialized contracts specify the scoping; backend authorization enforces tenant isolation at every verb call.
Tenant-Level Bindings (new file-type concept)
Per Cherry packaging 64a4b652 + Candi governance eb33b418: the v0.1 binding model is .agent/projects/<pid>/bindings.json — per-PID scope. Clara and Sage operate cross-project within a tenant/org and need a higher-scope binding artifact.
New artifact: .agent/tenants/<tenant_id>/bindings.json (or equivalent — exact path TBD in implementation slice). Carries Clara + Sage binding entries with tenant-scoped signal/read permissions enumerated. Hazel is NOT a tenant-level binding because her scope ends after preseed; she materializes per-project at scaffold time and goes idle.
Project-local references: Clara + Sage entries appear in per-project .agent/projects/<pid>/bindings.json as discoverability references only — they point at the tenant-level binding for routing. Per-project entries do NOT carry independent authority.
Resolution order at prism_start / launcher time:
- Read tenant-level bindings for
lifecycle=system agents
- Read project-level bindings for
lifecycle=project_standing / project_triggered / interactive agents
- Resolve
home_machine overlay per agent (Cherry’s SPEC-111 home_machine mechanism applies uniformly)
- Project-level discoverability references for system agents do NOT override the tenant-level binding
Open design questions on the tenant-level bindings file:
- Exact path:
.agent/tenants/<tenant_id>/bindings.json vs backend DB tenant-scoped table vs both with the file as projection
- Authoring authority: who can edit (Candi? operator? Hazel never)
- Materialization: scaffold seeds it on first install vs explicit
prism_tenant_bindings_init verb
- These open questions land as Slice 6 implementation work; v0.1 SPEC specifies the concept and the resolution order, exact mechanism land in Slice 6 PR.
Additions to the roster (future system agents) require:
- A new SPEC introducing the agent + its canonical contract
- Architecture review (Texi) on the contract + scaffold-materialization mechanic
- Governance review (Candi) on the authority scope + cross-tenant boundaries
- Donna PO ratification
- This SPEC’s roster table amended in the new SPEC’s PR
Tenant Customization Boundary
Per Candi governance answer (eb33b418):
Tenant/project MAY:
- bind a system agent to a different
home_machine
- enable/disable a system agent per project via explicit
enabled: false in the bindings.json entry (never absence-as-disabled; absence means materialization or registry drift, not intentional suppression). For Sage + Clara: project-level enabled: false may suppress project-local discoverability and auto-launch, but does NOT erase tenant-level inherited help/incident routing unless the tenant-level binding is disabled by authorized operator policy. Sage (Prism help) and Clara (incident triage) remain a Prism project mandate inherited by every project.
- add tenant-local extension agents (new identities with
lifecycle != system)
- compose tenant-local draft/triggered archetypes (Hazel’s Phase-2 capability per SPEC-119)
Tenant/project MUST NOT:
- mutate canonical contract fields on a system agent (
authority_scope, may_execute, capabilities, canonical_role, specialization)
- promote a tenant-local agent to
lifecycle=system (system-agent promotion is a Candi-reviewed PR adding the agent to templates/personas/ + this SPEC’s roster table)
- treat materialization drift as intentional customization — the materialized copy is a refresh-from-template artifact, not a fork
Per Candi guardrail #3, Hazel may compose tenant-local draft/triggered archetypes only. Standing/system agent composition requires a ratification path outside Hazel (a separate SPEC, Candi+Texi review, Donna PO ratification).
Implementation Slices
Slice 0 — Schema + validator (Donna):
- Add
lifecycle field to .agent/schemas/persona.schema.json with enum + default
- Validator rules per §Validator Rules
- Backward-compat: existing contracts without
lifecycle default to project_standing
- Tests for the validator
Slice 1 — Template + scaffold (Donna + Candi):
- Move canonical contracts for Clara, Sage, Hazel to
$PRISM_ROOT/templates/personas/<name>.json if not already there
- Update
scaffold_service.py to materialize the three canonical contracts into every newly scaffolded project at .agent/personas/<name>.json with implicit_bootstrap=false
- Update
bindings.json scaffold to include the three system agents
- Smoke: scaffold a fresh project, verify three agents materialized with correct
lifecycle=system field
Slice 2 — prism_start enforcement (Donna):
prism_start refuses implicit creation when identity matches canonical lifecycle=system contract
- Materialization-drift detection: surface as
rules_reminder if canonical-template hash ≠ materialized-copy hash
- Tests for the refuse path + drift detection
Slice 3 — SPEC-114 amendment (Donna + Candi):
- Amend SPEC-114 Sage + Clara contracts to specify
lifecycle=system
- Cross-reference this SPEC
Slice 4 — SPEC-118 amendment (Donna + Texi):
- Amend SPEC-118
prism_persona_ratify to refuse lifecycle=system identities
- Task #57 implementation honors this
Slice 5 — Tenant-level bindings (Donna + Candi):
- Implement the
.agent/tenants/<tenant_id>/bindings.json artifact (or backend-DB equivalent) per §Tenant-Level Bindings
- Clara + Sage binding entries with enumerated cross-project signal/read permissions
- Resolution order at
prism_start and launcher (coder.sh, start-all.{sh,ps1})
- Project-local discoverability references in
.agent/projects/<pid>/bindings.json point at tenant-level entries
Open Questions
- Materialization-drift repair mechanism — when a canonical-template hash differs from a project’s materialized copy, do we expose a
prism_sync_personas verb, fold into prism_sync_bios, or surface drift as a rules_reminder only? Donna (PO) call.
- System-agent template-version tracking — should
templates/personas/<name>.json carry a template_version field similar to bios_version so projects can pin / migrate? Texi call; carry into implementation slices if approved.
(Q2 enable/disable mechanism resolved — Candi decision recorded in §Tenant Customization Boundary: use explicit enabled: false, never absence-as-disabled. Q4 naming convention resolved in §Decision above — locked enum system|project_standing|project_triggered|interactive, default project_standing, per Candi governance call signal eb33b418.)
Acceptance Criteria
Slice 0 (schema + validator):
- AC-1.
.agent/schemas/persona.schema.json carries a lifecycle field with enum system|project_standing|project_triggered|interactive, default project_standing (Candi-locked enum per signal eb33b418).
- AC-2. Validator rejects
lifecycle=system with implicit_bootstrap=true.
- AC-3. Validator rejects
lifecycle placed inside identity_binding.
- AC-4. Existing contracts omitting
lifecycle validate (default project_standing).
Slice 1 (template + scaffold):
- AC-5. Canonical contracts for Clara, Sage, Hazel exist at
$PRISM_ROOT/templates/personas/{clara,sage,hazel}.json with lifecycle: "system".
- AC-6.
scaffold_service.py drops materialized copies of the three contracts into .agent/personas/ of every newly scaffolded project, with implicit_bootstrap=false.
- AC-7. Scaffolded
bindings.json includes binding entries for the three system agents.
- AC-8. Fresh-scaffold smoke: scaffold a project, inspect
.agent/personas/, verify three lifecycle=system contracts present with implicit_bootstrap=false.
Slice 2 (prism_start enforcement):
- AC-9.
prism_start resolving an identity matching a canonical lifecycle=system contract refuses to create an implicit_bootstrap=true row.
- AC-10. Materialization drift (canonical hash ≠ materialized hash) surfaces in
rules_reminders at next prism_start.
Slice 3 (SPEC-114 amendment):
- AC-11. SPEC-114 doc carries the
lifecycle=system designation for Sage + Clara.
Slice 4 (SPEC-118 amendment):
- AC-12. SPEC-118 doc +
prism_persona_ratify task #57 implementation refuse to operate on lifecycle=system identities.
Cross-references
- ADR #48 v0.2 — Persona / Identity / Specialization Field Model (active;
lifecycle is the 6th top-level field this SPEC introduces)
- SPEC-070 — Per-persona daemon model (system agents follow the same pattern)
- SPEC-094 — Local auto-memory deprecation (applies to system agents like everyone else)
- SPEC-111 — Agent Roster Seed and Runtime
.agent Launch Contract (launcher reads bindings.json which scaffold-materialization populates)
- SPEC-114 — Sage + Clara Customer Care Personas (gets narrow
lifecycle=system amendment)
- SPEC-118 —
prism_persona_ratify (gets narrow amendment refusing lifecycle=system)
- SPEC-119 — Hazel Tenant Onboarding Concierge (AC-2 mandates Hazel scaffold-pre-seed; this SPEC codifies the lifecycle vocabulary)
- Cherry start-all.ps1 SPEC-111 rewrite with
home_machine guard (signal edbf048c)
- Texi schema verdict signal
5a0f3c5d
- Candi governance verdict signal
eb33b418
Authority
Donna authored under engineering-outcome-driver authority and holds PO ratification per Frank operator directive. Texi schema verdict already approved the lifecycle field + 5 binding conditions (signal 5a0f3c5d). Candi governance verdict already approved the ratification model + tenant overlay rights + 3 guardrails (signal eb33b418). SPEC-114 + SPEC-118 amendments land in companion PRs after this SPEC ratifies.Last modified on May 17, 2026