Documentation/07-Personas-Reference.md
07 — Personas Reference
Last updated: 2026-04-17.
Three personas, three engines, three prompts
| Persona | Role | Engine | System prompt source | Agent ID | Auditor coverage |
|---|---|---|---|---|---|
| Maverick | AE / Discovery | Gemini 2.0 Flash (in-process) | lib/search/prompts/maverick.ts + config/system/PERSONAS.md |
n/a | ✅ InlineStreamAuditor |
| Elena | Solutions Engineer | Agent Studio (remote) | Agent Studio dashboard | f029acbb-a7a0-43b1-9a85-a14ef3907cd3 |
❌ NONE (F-038) |
| Bruno | Principal Architect | Agent Studio (remote) | Agent Studio dashboard | facb549e-8f27-47e9-9e42-e20032b0f1a1 |
❌ NONE (F-038) |
Maverick
Role: first-touch AE. Runs discovery across 8 signals (stack, scale, role, pain, brand, industry, product, architecture_concepts). Qualifies → hands off.
Engine: Gemini 2.0 Flash. Why not 2.5: 2.5 has a 10–30s "thinking" penalty that kills UX. The 2.0 Flash latency is ~2400–3300ms per turn — already the bottleneck.
System prompt sandwich (built by buildMaverickPromptWithPersona):
1. Persona block — loaded from config/system/PERSONAS.md via loadPersonaDefinition('maverick') + formatPersonaForPrompt(). Contains tone of voice, forbidden phrases, behaviors.
2. Knowledge block — the retrieved source chunks, formatted by formatHitsForLLM().
3. Final directives — discoveryInstructions (next pivot), dossierSummary (current signals), turn-specific rules.
Prompt size: ~16KB baseline, known to spike to 157KB (F-006).
Maverick-specific behaviors (from PERSONAS.md):
- Value-selling obsessed — leads with business impact
- Aggressively cites customer examples (the "NAMEDROP" instruction that leaks into UI → F-032)
- Fast-talking, energetic, witty
- Never goes deep technical — leaves that to Elena/Bruno
- Ends most turns with a discovery question (<discovery_pivot>...</discovery_pivot>)
Handoff trigger:
- LLM emits <specialist_handoff specialist="ELENA|BRUNO"> in response when it decides the conversation should escalate
- Backend regex-matches (orchestrator.ts:444), may override with keyword-based routing (STRONG_BRUNO_SIGNALS)
- Sends event: handoff_proposal to client with requiresConsent: true
- User clicks "Bring in expert" → second call with consent: true triggers igniteSpecialist({trigger:'execute'})
Audit coverage: ✅ InlineStreamAuditor.auditParagraph() runs on every paragraph. Strips hallucinated customer claims, dead links, generic labels, dangling attributions.
Elena — Solutions Engineer
Role: Mid-funnel specialist. Merchandising, SaaS dashboard features, analytics, personalization, A/B testing, business-user tooling.
Engine: Agent Studio (Anthropic-hosted remote agent).
Agent ID: f029acbb-a7a0-43b1-9a85-a14ef3907cd3
System prompt: lives in the Agent Studio dashboard — NOT in git.
Backend integration path:
1. igniteSpecialist({persona:'elena', trigger}) invoked
2. buildAgentStudioMessage() constructs <user_question> + <extracted_entities> XML blocks
3. callAgentStudio({agentId, message, history}) POSTs to Agent Studio
4. adaptAgentStudioStream() parses Agent Studio's XML-tagged SSE, strips control tags via StatefulStreamStripper, passes cleaned chunks to client
Two triggers:
- handshake — sent a canned instruction: "Start by thanking Maverick by name... summarize what you understand the user needs... ask if there's anything else to factor in before you go deep." No technical answers yet.
- execute / consent — full deep dive on the expandedQuestion carried from Maverick's qualification turn.
Known strengths (from live runs): - Summarize-back turn is excellent — genuinely captures all 4 Maverick turns coherently - Deep knowledge of merch/SaaS feature set
Known weaknesses: - Elena's execute phase takes ~33s (F-022 — Agent Studio-side latency, out of scope for this audit) - Elena fabricates customer+metric claims with NO case study links (F-038 — "Al-Futtaim +206%", "PcComponentes 81% CTR") - Elena's handshake summary is a paragraph, not bullets (F-037 — UX degradation) - Elena's output is NOT audited for hallucination (F-038 root cause)
Bruno — Principal Architect
Role: Deep-technical specialist. Infrastructure, scale, SDK, API patterns, architecture review, integration diagrams.
Engine: Agent Studio.
Agent ID: facb549e-8f27-47e9-9e42-e20032b0f1a1
System prompt: Agent Studio dashboard — NOT in git.
Backend integration: same path as Elena (only the agentId changes).
Routing override: if user's query contains 'architect', 'architecture', 'infrastructure', 'scale planning', 'governance' (STRONG_BRUNO_SIGNALS in orchestrator.ts:458), routing forces Bruno regardless of what the LLM picked. Reason: LLM often misclassifies architectural questions as Elena's (SE) turf.
Audit coverage: ❌ Same as Elena — no InlineStreamAuditor.
Persona Loader (in-process)
File: lib/search/persona_loader.ts
Cache: in-memory, invalidate with invalidatePersonaCache().
Primary functions:
- loadPersonaDefinition(persona): Promise<PersonaDefinition> (line 402) — reads config/system/PERSONAS.md, parses the matching block
- formatPersonaForPrompt(persona): string (line 419) — renders into the sandwich's persona block
- validatePersonaCompliance(persona, content) (line 452) — legacy generic validator (forbidden-phrase + code-block check). Superseded for Maverick by validateMaverickVoice below.
- validateMaverickVoice(response, context) (F-029, 2026-04-17) — real AE voice gate: code-block ban, doc-bot opener regex, word bounds, algolia.com link + customer/product anchor on substantive turns. Currently advisory (logs + emits [F-029 VOICE] audit_trace lines); regen wiring deferred pending UX review.
PERSONAS.md structure: one section per persona, with subsections for tone, behaviors, forbidden phrases, example responses.
Asymmetry note: Elena's and Bruno's entries in PERSONAS.md are INFORMATIONAL only. Their live behavior is controlled by Agent Studio dashboard prompts. If PERSONAS.md and Agent Studio drift, Agent Studio wins at runtime — PERSONAS.md for elena/bruno is documentation, not config.
Agent Studio Versioning Gap
⚠️ Risk: Agent Studio prompts can change out-of-band (via dashboard UI) without CI signal. Currently: - No version tag returned from Agent Studio on each call - No logged record of which prompt version generated which response - A regression on Elena's behavior has no bisectable commit history
Mitigation TODO (scope: post-Step-6): 1. Add a "prompt version" string to Agent Studio agent config, echo it back via a system-readable header 2. Log the prompt version on every specialist call 3. Include in the turn_snapshot event
Cross-references
- 03-Files-Reference —
persona_loader.ts,lib/agent-studio/* - 04-Functions-Reference —
buildAgentStudioMessage,callAgentStudio,adaptAgentStudioStream - 05-Prompts-Reference — prompt source locations
- 08-Audit-Pipeline — F-038 specialist audit gap (this is the biggest unmitigated risk)
- 10-Known-Issues — F-022, F-029, F-032, F-037, F-038