Status: Accepted Date: January 21, 2026 (Accepted) Original Date: January 13, 2026 Author: Chief Architect Input: Ted Nadeau, “MultiChat – Multi-Party, Multi-Agent Conversational Modeling Platform” PRD v1.0 Related: PDR-101 (Multi-Entity Conversation Support), ADR-046 (Moment.type Agent Architecture), ADR-054 (Cross-Session Memory)
Piper Morgan currently models conversations as linear sequences of ConversationTurn records—each turn storing a user message and assistant response in chronological order. This mirrors traditional chatbot design but fails to capture the structural complexity of real collaborative work.
Ted Nadeau’s MultiChat PRD (January 2026) proposes treating conversation as a graph model rather than a linear log. His working proof-of-concept demonstrates:
This architectural pattern addresses fundamental limitations:
Ted’s insight: “Real conversations have complex non-linear relationships… the same underlying model supports multiple views (tasks, questions, agreements, domain-specific projections).”
Adopt Ted’s graph-based conversation model as the foundation for Piper’s multi-entity conversation capability, implemented incrementally per PDR-101 phases.
Extend current domain models with graph primitives:
# services/domain/models.py additions
class ConversationNodeType(str, Enum):
MESSAGE = "message"
TASK = "task"
WHISPER = "whisper"
DECISION = "decision"
QUESTION = "question"
class ConversationLinkType(str, Enum):
"""
Base link types. Per Ted's clarification (Jan 13, 2026):
- Link types are EXTENSIBLE, not a fixed set
- RELATES_TO is the default/generic type
- Elements can have MULTIPLE links to the same target
- Link types themselves have meta-relationships
- Conversation sponsors can define domain-specific types
"""
RELATES_TO = "relates_to" # Default/generic relationship
REPLY = "reply" # Direct response
REFERENCE = "reference" # Non-sequential citation
BLOCKING = "blocking" # Dependency relationship
VARIANT_OF = "variant_of" # Alternative version
ANNOTATES = "annotates" # Commentary on content
RESOLVES = "resolves" # Closes/answers something
# Extensible: conversation sponsors may define additional types
@dataclass
class ConversationNode:
"""Graph node representing a typed conversation element."""
id: str
type: ConversationNodeType
content: str
author_id: str
timestamp: datetime
parent_id: Optional[str] = None # For simple threading
data: Optional[Dict[str, Any]] = None # Type-specific payload
@dataclass
class ConversationLink:
"""
Explicit relationship between conversation elements.
Design notes (per Ted, Jan 13, 2026):
- One source can have multiple links to same target (different types)
- Single link can carry multiple type annotations (multi-type)
- Links relate to "reaction-deck" and "gesture-palette" concepts
"""
id: str
source_id: str
target_id: str
type: ConversationLinkType
additional_types: Optional[List[str]] = None # For multi-type links
created_at: datetime = None
created_by: str = None
@dataclass
class ConversationGraph:
"""Graph-structured conversation with typed elements and relationships."""
id: str
nodes: List[ConversationNode]
links: List[ConversationLink]
participants: List[str] # User IDs
owner_id: str
created_at: datetime
updated_at: datetime
Phase 0 (Current): No changes—methodology continues as prototype
Phase 1 (Participant Mode):
parent_id to ConversationTurn for threadingConversationLink table for explicit relationshipsPhase 2 (Host Mode Foundation):
ConversationNode modelPhase 3 (Personal Agents):
WhisperNode for private AI suggestionsPer Ted’s clarification (Jan 13, 2026), facilitators use an AI layering model:
┌─────────────────────┐
│ Orchestrator │
│ Facilitator │
└─────────┬───────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ GitHub Agent │ │ Calendar Agent│ │ Wiki Agent │
│ (tasks/epics) │ │ (scheduling) │ │ (artifacts) │
└───────────────┘ └───────────────┘ └───────────────┘
Key tuning parameters:
Human analogs for facilitator patterns:
Per Ted’s clarification: Whisper agents have full conversation visibility by default (same view as user). Complexity arises at “prior insertion points” (e.g., user reviewing earlier content—”no spoilers” mode). Input tokens are cheap; “see all” is default unless problematic.
The graph model enables multiple view projections over the same data:
| View | Query Pattern | Use Case |
|---|---|---|
| Timeline | Nodes ordered by timestamp | Default chat experience |
| Thread | Nodes grouped by parent_id | Discussion navigation |
| Tasks | Nodes where type = ‘task’ | Kanban/action tracking |
| Decisions | Nodes where type = ‘decision’ | Agreement tracking |
| Questions | Nodes where type = ‘question’ | Q&A extraction |
ADR-046 (Moment.type): Moment.types map to ConversationNodeTypes. The decomposition pipeline produces typed nodes that populate the graph.
ADR-045 (Object Model): “Entities experience Moments in Places” — a ConversationGraph is a Place where multiple Entities collaborate through typed Moments (Nodes).
ADR-054 (Cross-Session Memory): The graph model defines conversation structure; cross-session memory (ADR-054) handles persistence across sessions. A ConversationGraph may span multiple sessions; memory retrieval queries the graph.
ConversationSession/Turn: Existing models become a simplified view over the graph—ConversationTurn is a shorthand for a message Node and its assistant response Node linked by ‘reply’.
Ted’s MultiChat POC (external/ted-multichat/poc/) provides:
Extract patterns into Piper’s Python/FastAPI stack rather than merging Next.js code.
external/ted-multichat/multichat_prd_v1.md)external/ted-multichat/multichat_uiux_v1.md)| *ADR-050 | Proposed | January 13, 2026* |