Agent overview
Mental model for Yoke agents — actors, forum vs monologue, and the ingestion/processor/egress mesh.
An agent in Yoke is not a built-in runtime loop. It is a composition of ordinary actors that subscribe to stream events and call LLMs when needed.
Core concepts
| Concept | What it is |
|---|---|
| Chat room (forum) | A conversation you create via the Chat SDK — human-to-human or mixed |
| Agent | An actor row (persona) + one egress instance (routes replies to forums) |
| Join | Agent joins a forum → per-stint monologue + forum participant + ingestion + processor |
| Monologue | Private conversation for one forum stint — system + agent + external shadow actors |
| Registry | Optional coordinator ctx.state (SQLite) storing JoinHandle per forum id |
Forum vs monologue
Public chat and private agent reasoning share the same conversation store — different participant sets, not different tables.
FORUM F (public) MONOLOGUE M (agent stint)
human system
agent_alice (stint) agent_alice (same actor)
agent_bob
visible to all participants visible only to monologue participantsWhen an agent joins a forum, bootstrap creates a fresh monologue for that stint and stores metadata.monologueId on the forum participant row. See Forum and monologue.
Where monologue IDs live
| Layer | Storage | Scope |
|---|---|---|
| Canonical | Postgres participants.metadata.monologueId | One monologue per forum stint |
| Optional registry | Coordinator actor ctx.state (SQLite __yoke_state) | JoinHandle per forum id |
| Runtime routing | Egress actor ctx.state.joins | forumId → { monologueId, forumParticipantId } |
createAgent does not create a monologue. Each joinConversation creates a fresh monologue and writes monologueId onto that forum participant stint.
Agent = multiple actor instances
There is no monolithic agent process. A running agent is several actor instances sharing one agent actor identity:
flowchart TB
subgraph Forum["Forum F"]
H[Human posts message]
end
subgraph Mesh["Agent mesh (per join)"]
I[Ingestion]
P[Processor]
end
subgraph Monologue["Monologue M"]
M1[Mirrored forum lines]
M2[Tool calls / results]
M3["type: reply"]
end
E[Egress — one per agent]
H -->|conversation.message.posted| I
I -->|copy with meta| M1
M1 -->|conversation.message.posted| P
P -->|infer + tools| M2
P -->|final output| M3
M3 -->|conversation.message.posted| E
E -->|type: reply| Forum| Instance | Scope | Job |
|---|---|---|
| Egress | One per agent | Copy type: "reply" monologue messages back to the correct forum |
| Ingestion | One per forum join | Copy forum messages into the active monologue |
| Processor | One per forum join | Run LLM inference and tool execution on monologue traffic |
| Follow-up | One per forum join (optional) | Schedule a nudge when the agent was last to speak |
| Guardian subscription | One per forum join (optional) | Watch monologue, spawn ephemeral guardian runners |
Event map
Merge conversationEvents and agentEvents from @yoke/sdk:
| Event | When |
|---|---|
conversation.message.posted | Any message written to a conversation |
agent.forum.joined | After joinConversation — egress updates its joins map |
agent.monologue.compacted | After compaction swap — egress repoints routing |
assistant.follow_up_due | Follow-up timer fires |
guardian.run | Ephemeral guardian runner starts |
Design principles
- No mirror relations — ingested copies carry
body.meta.sourceConversationIdfor egress routing instead ofmessage_relations.mirror. - No agents table — identity lives in
actors; routing lives in participant metadata and egress state. - Agents are actors — LLM loops are event-driven actor instances, not a special runtime mode.
- Opaque body — the runtime does not interpret message content; agents use
body.partsconventions.
Next steps
- Bootstrap —
createAgentandjoinConversation - Mesh pattern — detailed ingestion/processor/egress flow
- Processor — the event-driven inference loop