L5 Persona Spec
Defines a digital staff training pipeline with role-based promotion gates, benchmark tracking, and correction logging for lab members.
What this file does
Defines a digital staff training pipeline with role-based promotion gates, benchmark tracking, and correction logging for lab members.
When to use it
- Building a system with role-based progression for AI agents
- Implementing automated promotion gates with minimum score thresholds
- Tracking benchmark performance and corrections for digital staff
- Managing human and digital member profiles in a lab or team
Assumes this stack
L5 Persona Spec
Design doc reference: section 7 (Digital Staff Training & Promotion)
Purpose
The persona subsystem manages human and digital staff within the lab. Digital members progress through a training pipeline (Intern -> Analyst -> Specialist) based on benchmark performance. Each member has a SOUL.md (identity) and MEMORY.md (accumulated experience) managed via the Tier A memory backend.
Corrections are logged when mistakes are found, and promotion gates enforce minimum competency thresholds before role advancement.
Roles
Defined in MemberRole enum (core/schemas.py):
| Role | Type | Description |
|---|---|---|
pi | Human | Principal Investigator |
postdoc | Human | Postdoctoral researcher |
graduate | Human | Graduate student |
undergraduate | Human | Undergraduate student |
technician | Human | Lab technician |
digital_intern | Digital | Entry-level digital staff |
digital_analyst | Digital | Mid-level digital staff |
digital_specialist | Digital | Senior digital staff |
Pydantic Schemas
All models live in src/labclaw/persona/schemas.py.
MemberProfile
class MemberProfile(BaseModel):
member_id: str # uuid4
name: str
role: MemberRole
is_digital: bool
expertise: list[str]
created_at: datetime
promoted_at: datetime | None
BenchmarkResult
class BenchmarkResult(BaseModel):
member_id: str
task_type: str
score: float # 0.0 - 1.0
completed_at: datetime
details: dict[str, Any]
CorrectionEntry
class CorrectionEntry(BaseModel):
member_id: str
category: str
detail: str
corrected_by: str
timestamp: datetime
PromotionGate
class PromotionGate(BaseModel):
from_role: MemberRole
to_role: MemberRole
min_benchmarks: int
min_avg_score: float
requires_approval: bool
Promotion Ladder
| From | To | Min Benchmarks | Min Avg Score | Requires Approval |
|---|---|---|---|---|
digital_intern | digital_analyst | 10 | 0.70 | No |
digital_analyst | digital_specialist | 25 | 0.85 | Yes |
Public Interface -- PersonaManager
class PersonaManager:
def create_member(name: str, role: MemberRole, is_digital: bool) -> MemberProfile
def get_member(member_id: str) -> MemberProfile
def record_benchmark(member_id: str, task_type: str, score: float, details: dict | None) -> BenchmarkResult
def record_correction(member_id: str, category: str, detail: str, corrected_by: str) -> CorrectionEntry
def check_promotion(member_id: str) -> PromotionGate | None
def promote(member_id: str, approver: str | None = None) -> MemberProfile
def demote(member_id: str) -> MemberProfile
Constraints
promote()/demote()only change digital member roles along the ladder.- If the matched
PromotionGate.requires_approvalisTrue,promote()requires a non-emptyapprover. - Human members cannot be demoted below their actual role.
check_promotion()returns the matchingPromotionGateif the member meets all criteria, orNoneif not eligible.demote()raisesValueErrorfor human members or members already atdigital_intern.
Events
| Event Name | Payload | Emitted When |
|---|---|---|
persona.member.created | member_id, name, role | create_member() |
persona.benchmark.recorded | member_id, task_type, score | record_benchmark() |
persona.correction.recorded | member_id, category, corrected_by | record_correction() |
persona.member.promoted | member_id, from_role, to_role | promote() |
persona.member.demoted | member_id, from_role, to_role | demote() |
Storage
- In-memory dicts for MVP (no SQLite persistence yet).
- Future: persist via Tier A markdown files and Tier B knowledge graph.
What's inside
5 sections: roles enum, 4 Pydantic schemas, promotion ladder table, 8-method PersonaManager interface, 5 event types
Change this for your project
- Replace
src/labclaw/persona/schemas.pywith your own module path - Replace
core/schemas.pywith your own schema location - Replace
labclawin package references with your project name
Where it goes
Use as the system prompt for your model call, or as the base instructions in your agent framework.
Worth borrowing
- Promotion gates as configurable Pydantic models with min benchmarks and approval flags
- Event-driven architecture for persona lifecycle changes (created, promoted, demoted)
Related Documents
Character Persona
Defines a Fallout 2 roleplay persona for an LLM agent: charming rogue with social-first combat and moral code.
How to implement tool use
Explains how to define, configure, and control tool use with the Anthropic API, including model selection, tool definitions, output control, and parallel calls.
Gemini by Example
Collects 20+ Gemini API code examples covering text, images, audio, video, PDFs, agents, and token counting.
Claude Tool Use (Function Calling) Documentation
Teaches how to define and use Claude tool use (function calling) with Python, including schema rules, execution patterns, and best practices.