Version 1.0 — Multi-model character attribution for Harvey session recordings
Harvey uses the Fountain screenplay format for
session recordings, stored with .spmd (Harvey-native) or
.fountain (compatible with other tools) extensions.
Fountain provides a plain-text, human-readable, and machine-parseable
format that serves as a lingua franca between Harvey,
Claude Code, and other LLM-based agents.
| Requirement | Fountain Solution |
|---|---|
| Human-readable | Plain text, familiar screenplay format |
| Machine-parseable | Strict structure, regex-friendly |
| Version-control friendly | Text files, good diff/merge behavior |
| Multi-participant | Natural character/dialogue model |
| Extensible | Scene descriptions, parenthetical notes |
| Cross-agent compatible | Open format, shared with Claude Code |
| Extension | Created By | Notes |
|---|---|---|
.spmd |
Harvey | Primary format for new recordings |
.fountain |
Any Fountain-compatible tool | Accepted by Harvey for reading |
Harvey Fountain sessions treat each participant (human, Harvey agent, or LLM) as a distinct character in a screenplay. Character names follow specific conventions that reveal their identity and role.
| Type | Naming Convention | Example | Identity |
|---|---|---|---|
| Human User | ALL-CAPS (matches Author:) |
RSDOIEL | Human participant |
| Harvey Agent | HARVEY | HARVEY | Harvey using local Ollama/Llamafile |
| Routed Ollama | ROUTE_NAME (ALL-CAPS) | PI2, NODE1, JULIE | Remote Ollama via /route add |
| Cloud Model | MODEL_NAME (ALL-CAPS) | MISTRAL, CLAUDE, GEMMA4 | Cloud API or forwarded |
HARVEY represents Harvey when: - Using its locally
configured Ollama backend - Using its locally configured Llamafile
backend - The active model is noted in the scene description:
Model: llama3:latest
ROUTE_NAME represents a remote Ollama instance when:
- Defined via /route add NAME URL (e.g.,
/route add pi2 ollama://192.168.1.2:11434) - Harvey
forwards to it: HARVEY\nForwarding to PI2. - The route
appears as a character: PI2\nResponse...
MODEL_NAME represents a cloud/remote model when: -
User uses @mention:
RSDOIEL\n@mistral explain this - Harvey forwards:
HARVEY\nForwarding to MISTRAL. - Model responds:
MISTRAL\nExplanation... - OR in EXT. scenes (direct
conversation without Harvey)
| Pattern | Matches | Example |
|---|---|---|
^[A-Z]{2,}$ |
Cloud model names | CLAUDE, MISTRAL, LLAMA3 |
^[A-Z][a-zA-Z0-9_-]*$ |
Mixed case (rare) | Julie (if configured as route) |
^HARVEY$ |
Harvey agent | HARVEY |
| Author name (from title) | Human user | RSDOIEL |
Harvey uses two scene type prefixes from Fountain: INT. (Interior) and EXT. (Exterior). These distinguish whether Harvey is involved in the conversation.
Harvey is acting as the agent/orchestrator in these scenes. The scene heading lists Harvey and the human participant.
Format:
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 18:30:00
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/project.
RSDOIEL
User prompt here...
HARVEY
Harvey's response (local model) or forwarding...
Use cases: - Harvey responding with its local Ollama/Llamafile model - Harvey forwarding to routed Ollama endpoints - Harvey forwarding to cloud models via @mention - Agent actions (file writes) - Skill activations
Direct conversation between a model and human without Harvey’s intermediation. Harvey is not involved in these scenes.
Format:
EXT. MISTRAL AND RSDOIEL 2026-05-04 18:30:00
MISTRAL and RSDOIEL in direct conversation. Workspace: /home/user/project.
RSDOIEL
Direct prompt to Mistral...
MISTRAL
Mistral's direct response...
Use cases: - Direct API conversations (bypassing Harvey) - Hypothetical: Future direct model access
The title block contains metadata about the session. All fields are
optional except Title: and Author:.
Fields:
| Field | Required | Example | Description |
|---|---|---|---|
Title: |
Yes | Harvey Session |
Session title |
Credit: |
No | Recorded by Harvey |
Recording application |
Author: |
Yes | RSDOIEL |
Human participant (ALL-CAPS) |
Date: |
No | 2026-05-04 18:30:00 |
Session start timestamp |
Draft date: |
No | 2026-05-04 |
Date only |
Characters: |
No | RSDOIEL, HARVEY, MISTRAL |
All characters (summary files only) |
Example:
Title: Harvey Session - Documentation Review
Credit: Recorded by Harvey
Author: RSDOIEL
Date: 2026-05-04 18:30:00
Draft date: 2026-05-04
Characters: RSDOIEL, HARVEY, MISTRAL
FADE IN:
Note: The Characters: field is
typically omitted in streaming sessions (since future
characters are unknown) and added in summary/analysis
files (where all participants are known).
Format:
(INT|EXT)\. CHARACTER1 AND CHARACTER2 (TALKING|) TIMESTAMP
Regex:
(INT|EXT)\. ([A-Z0-9_-]+) AND ([A-Z0-9_-]+) (TALKING)? (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})
Examples:
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 18:30:00
INT. AGENT MODE 2026-05-04 18:35:00
INT. SKILL FOUNTAIN-ANALYSIS 2026-05-04 18:40:00
EXT. MISTRAL AND RSDOIEL 2026-05-04 18:45:00
The scene description appears between the scene heading and the first character/dialogue line. It provides context for the scene.
Required fields: -
Model: <identifier> — The model/route for this
interaction - Workspace: <path> — The workspace
directory
Optional fields: - Any additional context (e.g.,
“Connected: Ollama (llama3:latest)”) - Parenthetical notes about @mentions:
(@modelname mentioned but does not respond)
Examples:
# Harvey-native (local Ollama)
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/project.
# Routed Ollama
Harvey and RSDOIEL are in chat mode. Model: ollama://192.168.1.2:11434. Workspace: /home/user/project.
# With @mention note
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/project.
(@julie mentioned but does not respond)
Dialogue consists of character names (ALL-CAPS) followed by their lines. Character names must match the names in the scene heading or be introduced via forwarding.
Format:
CHARACTER_NAME
Dialogue line 1
Dialogue line 2
ANOTHER_CHARACTER
Response...
Rules: - Character names are always ALL-CAPS - Blank line separates character from dialogue - Blank line between dialogue blocks - Dialogue wraps naturally (no special formatting needed)
When Harvey forwards a prompt to another model:
HARVEY
Forwarding to MODEL_NAME.
MODEL_NAME
Response...
User can direct prompts to specific models:
RSDOIEL
@mistral explain this code
HARVEY
Forwarding to MISTRAL.
MISTRAL
Explanation...
HARVEY
Write path/to/file?
RSDOIEL
yes
[[write: path/to/file — ok]]
[[write: path/to/other — skipped]]
[[write: path/to/error — error: permission denied]]
Status values: ok, skipped,
error: <message>
Every session file must end with:
THE END.
This marker is used by parsers to detect complete sessions.
Harvey responds directly using its configured local model.
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 18:30:00
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/project.
RSDOIEL
What is the capital of France?
HARVEY
The capital of France is Paris.
Character: HARVEY (Harvey agent with local model) Model: llama3:latest (from scene description)
Harvey forwards to a remote Ollama instance registered as a route.
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 18:30:00
Harvey and RSDOIEL are in chat mode. Model: ollama://192.168.1.2:11434. Workspace: /home/user/project.
RSDOIEL
@pi2 analyze this data
HARVEY
Forwarding to PI2.
PI2
Analysis: The data shows a normal distribution with mean 42.
Route: PI2 (registered via
/route add pi2 ollama://192.168.1.2:11434)
Character: PI2 (the route name as character)
User uses @mention to direct a prompt to a specific cloud model.
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 18:30:00
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/project.
RSDOIEL
@mistral review this code
HARVEY
Forwarding to MISTRAL.
MISTRAL
The code follows good practices. Consider adding error handling for the edge case at line 42.
Character: MISTRAL (cloud model) Trigger: @mention in user dialogue
Direct conversation with a model, bypassing Harvey.
EXT. CLAUDE AND RSDOIEL 2026-05-04 18:30:00
CLAUDE and RSDOIEL in direct conversation. Workspace: /home/user/project.
RSDOIEL
Explain quantum computing
CLAUDE
Quantum computing uses quantum bits (qubits) that can exist in superposition...
Note: No HARVEY character appears in EXT. scenes.
User mentions a model that doesn’t respond.
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 18:30:00
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/project.
(@julie mentioned but does not respond)
RSDOIEL
@julie what do you think?
HARVEY
Julie does not respond.
Note: The unfulfilled @mention is noted in the scene description.
Multiple models introduced within a single scene via @mention.
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 18:30:00
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/project.
RSDOIEL
@mistral review this, then @claude give a second opinion
HARVEY
Forwarding to MISTRAL.
MISTRAL
First opinion: The code is well-structured.
HARVEY
Forwarding to CLAUDE.
CLAUDE
Second opinion: I agree, but consider adding tests.
Note: Multiple models can appear in a single INT. scene via sequential forwarding.
INT. … AND … TALKING or EXT. … AND …)Regular conversation between participants.
INT. example:
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 18:30:00
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /path.
RSDOIEL
Prompt...
HARVEY
Response...
EXT. example:
EXT. MISTRAL AND RSDOIEL 2026-05-04 18:30:00
MISTRAL and RSDOIEL in direct conversation. Workspace: /path.
RSDOIEL
Prompt...
MISTRAL
Response...
INT. AGENT MODE)File write operations and other agent actions.
INT. AGENT MODE 2026-05-04 18:35:00
HARVEY
Harvey proposes to write 1 file(s) to the workspace.
HARVEY
Write path/to/file?
RSDOIEL
yes
[[write: path/to/file — ok]]
Fields: - Proposal:
Harvey proposes to write N file(s) to the workspace. -
Prompt: Write path? - Response: User’s
yes/no - Outcome:
[[write: path — status]]
INT. SKILL <NAME>)Skill activation and execution.
INT. SKILL FOUNTAIN-ANALYSIS 2026-05-04 18:40:00
Harvey executes the fountain-analysis skill.
FOUNTAIN-ANALYSIS
Reading agents/sessions/session.spmd for analysis.
Fields: - Skill name (from heading) - Description action line
^Title: .*$
^Credit: .*$
^Author: ([A-Z]+)$
^Date: \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$
^Draft date: \d{4}-\d{2}-\d{2}$
^(Characters: .*)?$
^$
FADE IN:$
^$
(INT|EXT)\. ([A-Z0-9_-]+) AND ([A-Z0-9_-]+) (TALKING)? (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})Model: (.+) → model identifierWorkspace: (.+) → workspace path\(@(\w+) mentioned but does not respond\) → unfulfilled
@mention^[A-Z0-9_-]+$^Forwarding to ([A-Z0-9_-]+)\.$^\[\[write: (.+) — (ok|skipped|error:.+)\]\]@([a-zA-Z][a-zA-Z0-9_-]*)# Pseudocode
def character_type(name, scene_description, known_routes, author):
if name == "HARVEY":
return "harvey-native"
elif name in known_routes:
return "routed-ollama"
elif name == author:
return "human"
elif is_all_caps_alphanumeric(name):
return "cloud-model"
else:
return "unknown"Title: Quick Question
Credit: Recorded by Harvey
Author: RSDOIEL
Date: 2026-05-04 10:00:00
Draft date: 2026-05-04
FADE IN:
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 10:00:00
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/project.
RSDOIEL
What is 2+2?
HARVEY
4
THE END.
Title: Code Review
Credit: Recorded by Harvey
Author: RSDOIEL
Date: 2026-05-04 14:00:00
Draft date: 2026-05-04
FADE IN:
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 14:00:00
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/code.
RSDOIEL
@mistral review this function
HARVEY
Forwarding to MISTRAL.
MISTRAL
The function has a potential off-by-one error at line 23.
RSDOIEL
@claude can you confirm?
HARVEY
Forwarding to CLAUDE.
CLAUDE
Confirmed. The loop should use `<=` not `<`.
THE END.
Title: Fix and Test
Credit: Recorded by Harvey
Author: RSDOIEL
Date: 2026-05-04 15:00:00
Draft date: 2026-05-04
FADE IN:
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 15:00:00
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/code.
RSDOIEL
This function has a bug. Please fix it.
HARVEY
Here is the corrected version:
```go src/calc.go
func Add(a, b int) int {
return a + b
}
RSDOIEL /apply
INT. AGENT MODE 2026-05-04 15:02:00
HARVEY Harvey proposes to write 1 file(s) to the workspace.
HARVEY Write src/calc.go?
RSDOIEL yes
[[write: src/calc.go — ok]]
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 15:03:00
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/code.
RSDOIEL /run go test ./…
HARVEY All tests pass.
THE END.
### Example 4: Routed Ollama
Title: Cluster Query Credit: Recorded by Harvey Author: RSDOIEL Date: 2026-05-04 16:00:00 Draft date: 2026-05-04
FADE IN:
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 16:00:00
Harvey and RSDOIEL are in chat mode. Model: ollama://192.168.1.2:11434. Workspace: /home/user/data.
RSDOIEL @pi2 process this dataset
HARVEY Forwarding to PI2.
PI2 Processing complete. 1000 records analyzed.
THE END.
### Example 5: Unfulfilled @mention
Title: Offline Model Credit: Recorded by Harvey Author: RSDOIEL Date: 2026-05-04 17:00:00 Draft date: 2026-05-04
FADE IN:
INT. HARVEY AND RSDOIEL TALKING 2026-05-04 17:00:00
Harvey and RSDOIEL are in chat mode. Model: llama3:latest. Workspace: /home/user/project. (@offline-model mentioned but does not respond)
RSDOIEL @offline-model what is your status?
HARVEY Offline-model does not respond.
THE END. ```
| Element | Required | Validation |
|---|---|---|
Title: |
Yes | Non-empty |
Author: |
Yes | ALL-CAPS, non-empty |
FADE IN: |
Yes | Exact match |
THE END. |
Yes | Exact match at end |
| Scene headings | Per scene | Valid INT./EXT. format |
| Scene descriptions | Per scene | Contains Model: and Workspace: |
| Rule | Error |
|---|---|
| Character not ALL-CAPS | Warn: “Character name not uppercase: {name}” |
| Character in INT. scene not in heading | Warn: “Character {name} not in scene heading” |
| HARVEY missing from INT. scene | Warn: “INT. scene without HARVEY” |
| HARVEY in EXT. scene | Warn: “EXT. scene contains HARVEY” |
| Unknown character type | Warn: “Unknown character type: {name}” |
| Rule | Error |
|---|---|
Missing Model: in description |
Warn: “Scene missing Model: declaration” |
| Model in description doesn’t match character | Warn: “Model mismatch: description={x}, character={y}” |
Model: and
Workspace: in scene descriptionsHarvey accepts .fountain files created by Claude Code.
These files may use slightly different formatting but follow the same
fundamental structure:
Differences to handle: - Claude Code may use different scene description formats - Model names may appear differently - File operations may use different syntax
Harvey’s parser is designed to be tolerant of these variations while maintaining strict output format for its own recordings.
The Fountain format is designed to be extensible. Future versions may add: - New scene types - Additional metadata fields - New special syntax elements
Older parsers should gracefully ignore unknown elements.
| Version | Date | Changes |
|---|---|---|
| 1.0 | 2026-05-04 | Initial specification with multi-model character attribution |
This document describes Harvey’s use of the Fountain format. For the official Fountain specification, see https://fountain.io.