Appearance
Agents vs Chat
Chat is the conversation app. system.agents is the substrate the conversation runs on. The bridge between them is ConversationSurface, a custom element shipped by @open-matrix/chat-component.
ConversationSurface — the bridge
ConversationSurface is an embeddable conversation panel. From the agent-platform side it is a normal client of the system.agents accepts list:
- It addresses a
TargetRef(the actor the conversation is about). - It calls
$promptonsystem.agentswith prompt text + target snapshot. - It listens for activity frames keyed to the request and renders them.
- It uses
$sessionListto populate the session picker. - It uses
session_state.readto load message history.
From the Chat side, ConversationSurface is just a custom element you drop into a panel. Chat does not duplicate any of this logic — ChatApp.ts:1628 reads transcripts from system.agents, never from a chat-local store.
Why you target ConversationSurface, not system.agents directly
You technically can call $prompt on system.agents from any browser actor, but ConversationSurface adds:
- Target snapshot. Builds a snapshot of the target actor (its
accepts,emits,state,children) so the LLM has structured context. - Session continuity. Resumes the most recent session for the
(targetKey, profileKey)pair instead of starting a fresh one each turn. - Activity rendering. Knows how to interpret
$thinking,$token,$response,$toolCall,$toolResultframes. - Permission prompts. Renders approval UIs when
system.agentsemits an approval-required frame.
If you bypass it, you get a generic chatbot without target context, without session resume, and without rendered traces. The agent-orchestration document at projects/matrix-3/packages/docs/content/architecture/agent-orchestration.md:82-89 codifies this: "Target system.agents through ConversationSurface, not directly."
What Chat owns vs what system.agents owns
| Concern | Owner |
|---|---|
| Conversation UI (bubbles, scroll, markdown rendering) | Chat package |
| Session list UI, session-picker, "new conversation" | Chat package, but reads from system.agents |
| Session record (id, target_key, principal_id, turn_count, messages) | system.agents.memory SQLite store |
| LLM call, oracle loop, tool execution | AgentActor (child of AgentsRoot) |
| Activity frames (the wire format streaming up to Chat) | Emitted by AgentActor, not by Chat |
| Inference provider, credentials | system.inference + Factotum |
Chat could be replaced (different UI, different shell) and the cognitive contract would be unchanged. That is the design intent.
See also
- Chat integration — embedding ConversationSurface.
- Sessions
- What is the agent platform?
Source:
projects/matrix-3/packages/chat/src/ChatApp.ts:1628,projects/matrix-3/packages/chat-component/src/ConversationSurface.ts,projects/matrix-3/packages/docs/content/architecture/agent-orchestration.md(canonical "go through ConversationSurface" guidance).