Skip to content

AgentJDrew/ria-client-simulator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RIA Client Simulator

A portable Claude Code workspace for advisor practice. Open a new Claude Code chat in this folder and a random synthetic RIA client greets you in-character. Practice the full advisor workflow — prospecting, onboarding, quarterly reviews, hard conversations, deliverable presentation — then end with /debrief for a scored rubric and session log.

Built by Andrew Lazzeroni. Designed to be copied to any machine and used locally.

Install

Python alias heads-up (read this first): The SessionStart hook is configured to run with python in .claude/settings.json. Windows installs typically work out of the box. On macOS and Linux, your Python 3 is usually python3 and bare python may point to Python 2 or nothing. If your first session opens without a persona, the fix is almost always this: open .claude/settings.json and change python to python3 in the hook's command field. Verify with python3 --version in your terminal (must be 3.9 or newer).

Requirements:

  • Python 3.9 or newer on your PATH (stdlib only — no pip install needed)
  • Claude Code installed

Steps:

  1. Copy this folder to your machine. Anywhere you want — Desktop, Documents, a projects directory.
  2. macOS / Linux only: Apply the Python alias fix above if bare python is not Python 3 on your system.
  3. Open Claude Code with this folder as the workspace (open Claude Code and point it at the folder, or cd into the folder and launch from there).
  4. Open a new chat. The persona auto-spawns via the SessionStart hook. The first message you see will be the client speaking — that is correct, not a bug.

Usage

Expected flow:

  1. Open a new Claude Code chat in this folder.
  2. Claude greets you in-character as a randomly selected synthetic client. You are the advisor — stay in your role. Do not break the fourth wall; respond as you would in a real meeting.
  3. Practice the conversation. Ask fact-finding questions, handle objections, present recommendations, walk through deliverables. Claude will improvise in-character based on a hidden dossier you do not see.
  4. Type /coach at any point for a mid-session tactical critique. A separate observer agent gives 2-4 sentences of feedback without revealing dossier specifics, so your fact-finding practice stays honest.
  5. Type /debrief to close the session. The client drops character for a short reflection, the coach gives tactical bullets, and a 0-5 rubric scores you across 8 dimensions. Everything saves to sessions/YYYY-MM-DD-<name>.md.

Tip: treat the first Claude message as the opening line of a real meeting. Resist the urge to ask meta-questions — if you want tactical input, that is what /coach is for.

Slash commands

  • /coach — summons an observer agent for 2-4 sentences of tactical critique. Hints at categories you missed (e.g., "you haven't asked about held-away assets") without revealing hidden-dossier specifics. This preserves fact-finding practice.
  • /debrief — session close. Client drops character for a human-style reflection on how you handled them, coach gives tactical bullets, the rubric scores 0-5 across 8 dimensions, and everything saves to sessions/YYYY-MM-DD-<name>.md as a permanent log you can review later.

Data room

Each session pre-generates a folder of synthetic documents at personas/documents/ — a "data room" you can browse before or during the meeting. Typical contents:

  • 00-MANIFEST.md — index of what's in the folder
  • 01-401k-statement.md — if the persona has a 401(k) or 403(b)
  • 02-ira-statement.md — if the persona has an IRA
  • 03-brokerage-statement.md — if the persona has a taxable brokerage
  • 04-pay-stub.md — if the persona earns income
  • 05-insurance-binder.md — always
  • 06-will.md — if the persona has a will
  • 07-trust-summary.md — if the persona has a revocable trust
  • 08-1099-prior-year.md — if the persona has a taxable brokerage
  • 09-held-away-notes.md — if the persona has accounts not currently managed at your firm

All numbers in these files are internally consistent with the client's hidden dossier. The folder is overwritten on each new Claude Code session — copy it elsewhere to preserve a set.

The templated docs are the baseline. For richer detail or unusual document types (K-1, Schedule C, specific account positions), ask the client in conversation — they'll generate a more detailed synthetic doc on demand using the generate-artifact skill.

Tuning for your firm

The baseline content is generic RIA practice. To match your actual book and standards, edit:

  • personas/archetypes.json — add or remove archetypes that match your real client base. Adjust the weight field on each archetype to make common client types roll more frequently (higher weight = more likely).
  • scenarios/scenarios.json — add scenarios that reflect meetings you actually run. Tighten difficulty_floor and difficulty_ceiling to control challenge level. Restrict compatible_archetype_ids so unrealistic pairings (e.g., retiree + startup-equity scenario) cannot roll.
  • rubric/dimensions.md — adjust the 8 scoring dimensions or their 0-5 level descriptions if your firm's standards differ from the defaults.
  • rubric/compliance-watchlist.mdIMPORTANT: replace this with your firm's actual compliance rules. The baseline is generic RIA guidance and will not reflect your specific ADV, disclosures, supervision procedures, or state-level obligations.

File layout

RIA Client Simulator/
├── README.md                             # (this file)
├── CLAUDE.md                             # Workspace identity, client-voice rules
├── .gitignore                            # Personal data (ledger, session logs) is gitignored
├── .claude/
│   ├── settings.json                     # SessionStart hook + slash command config
│   ├── hooks/spawn_persona.py            # Persona roller (Python, stdlib only)
│   ├── agents/coach.md                   # /coach observer subagent
│   └── skills/
│       ├── stay-in-character/SKILL.md    # Client voice rules
│       ├── debrief/SKILL.md              # /debrief flow
│       └── generate-artifact/SKILL.md    # On-demand synthetic documents
├── personas/
│   ├── archetypes.json                   # 15 client archetype definitions
│   ├── active.md                         # Current session persona (overwritten per chat, gitignored)
│   └── ledger.jsonl                      # Novelty history (gitignored — personal)
├── scenarios/scenarios.json              # Scenario catalog
├── rubric/
│   ├── dimensions.md                     # 8 scoring dimensions x 0-5 levels
│   └── compliance-watchlist.md           # RIA compliance rules
├── sessions/                             # Debrief logs (gitignored — personal)
└── tests/                                # Python unit tests for the hook

Per-user vs shared data

Anything representing your personal practice history is gitignored so it stays local to your machine:

  • personas/ledger.jsonl — novelty history, used to avoid rerolling the same persona traits back-to-back
  • personas/active.md — the current session's persona, overwritten on each new chat
  • sessions/*.md — your debrief logs

Everything else (archetypes, scenarios, rubric, skills, hook code) is shared content. If you and a coworker both use this workspace, you will have identical client types available but independent practice histories and session logs.

Troubleshooting

Hook did not fire / no persona appeared. Check the path in .claude/settings.json is correct and the workspace is actually this folder. Then run the hook manually from a terminal in this folder:

python .claude/hooks/spawn_persona.py

The error output will tell you whether it is a Python issue, a path issue, or a JSON parse issue in one of the data files.

Python not found. Install Python 3.9 or newer. If you already have it installed as python3, apply the macOS/Linux note above and change python to python3 in the hook's command field.

Persona feels repetitive after many sessions. Open .claude/hooks/spawn_persona.py and search for min_diff=3. That is the novelty threshold — how many traits must differ from recent personas before a roll is accepted. Lower it (e.g., min_diff=2) to allow more variety in rolls, or raise it (e.g., min_diff=4) to force the roller to try harder for a novel combination. Very high values on a small archetype catalog can cause the roller to stall — widen archetypes.json first if you go above 4.

/coach revealed hidden dossier specifics. That is a bug, not a feature. The coach is supposed to hint at categories (e.g., "you skipped discovery on tax situation") without naming the actual dossier values. Open .claude/agents/coach.md and check the hint-vs-answer rule near the top of the mandate — it should explicitly forbid naming concrete dossier facts. Tighten the language if coach drift is happening in practice.

About

A Claude Code workspace that turns any chat session into a randomized, scored role-play trainer for financial advisors — synthetic clients, hidden dossiers, a full data room, and rubric-based debriefs. Pure stdlib Python.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages