Yoke.sh
Agents

Agent mesh pattern

The ingestion, processor, and egress actor mesh — how forum messages become agent replies.

The agent mesh is the standard composition for LLM agents on Yoke: three core actor types (ingestion, processor, egress) plus optional follow-up and guardian actors. Each reacts to conversation.message.posted on the global stream.

End-to-end flow

flowchart LR
  subgraph Forum["Forum F"]
    H[Human message]
    A[Agent text reply]
  end

  subgraph Ingestion["Ingestion (per join)"]
    I[Copy to monologue]
  end

  subgraph Monologue["Monologue M"]
    U[User lines via external actors]
    T[Tool calls / results]
    AT[Agent text]
  end

  subgraph Processor["Processor (per join)"]
    P[LLM + tools]
  end

  subgraph Egress["Egress (per agent)"]
    E[Forward agent text to forum]
  end

  H -->|posted| I
  I --> U
  U -->|posted| P
  P --> T
  P --> AT
  AT -->|posted| E
  E --> A

Ingestion

One instance per forum join. Silently copies forum messages into the agent's active monologue.

PropertyValue
Filterconversation.message.posted where conversationId === sourceConversationId
SkipsmessageType === "reply", system messages (no author)
QueueFIFO, concurrency 1

On each forum message:

  1. Resolves the active monologue from forum participant metadata.monologueId (supports compaction swaps)
  2. Finds or creates an external shadow actor for the forum author
  3. Posts a copy to the monologue with routing metadata:
{
  "parts": [{ "type": "text", "text": "hello", "format": "plain" }],
  "meta": {
    "sourceConversationId": "forum-id",
    "sourceMessageId": "original-message-id",
    "sourceActorId": "forum-author-actor-id"
  }
}

External actors let the processor treat ingested forum lines as user turns at inference time without the agent actor authoring them.

Processor

One instance per forum join. Runs LLM inference and tool execution on monologue traffic. See Processor for the event-driven loop.

PropertyValue
Filterconversation.message.posted on monologue, excluding forum traffic
QueueFIFO, concurrency 1
OutputPosts type: "message" to monologue (text, tool_call, tool_result)

The processor does not decide user visibility. It persists whatever the LLM and tools produce.

Egress

One instance per agent (not per join). Reads monologue message events and forwards agent text to the forum. See Egress for the visibility rules.

PropertyValue
Filteragent.forum.joined, agent.monologue.compacted, and all conversation.message.posted
ForwardsAgent-authored monologue messages with non-empty text parts
Skipstool_call-only, tool_result, ingested user copies
Routingctx.state.joins[forumId] → { monologueId, monologueParticipantId, forumParticipantId }
QueueFIFO, concurrency 1

On agent.forum.joined:

joins[forumId] = { forumParticipantId, monologueId, monologueParticipantId };

When an agent posts text to the monologue, egress reads body.meta.sourceConversationId, looks up the join, and posts text parts only to the forum as the agent's forum participant.

Optional actors

Follow-up

Schedules a follow-up message when the agent was last to speak on the forum. Cancels when a human speaks. See Follow-up.

Guardian angel

Subscription watches monologue activity; spawns ephemeral runners that can inject steering messages. The primary processor has no knowledge of guardians. See Guardian angel.

Comparison with legacy three-actor docs

Older documentation described mirror / processor / publisher actors with message_relations.mirror. The current SDK uses:

LegacyCurrent SDK
Mirror actorIngestion — copies via external shadow actors, no mirror relations
Processor actorProcessor — same role, event-driven single steps
Publisher actorEgress — one per agent, multi-forum routing via joins map

Metadata pairing

Forum stint ↔ monologue pairing is stored in participant metadata, not a separate table:

participants.metadata.monologueId  →  monologue conversation id

After compaction, this key is updated and agent.monologue.compacted notifies egress.

Building your mesh

Register defineIngestionActor, defineProcessorActor, and defineEgressActor in your yoke.ts, then use createAgent and joinConversation from Bootstrap. Add Compaction and Guardian as needed per join.

On this page