XI · Structure & DataMature★★

Channel-Decoupled Agent Core

also known as Channel-Agnostic Agent Core, Delivery-Channel Adapter, Ports-and-Adapters Agent

Put the agent's reasoning, tools, and session state behind channel-agnostic ports, and make each delivery surface (web, voice, email, Slack, background jobs) an adapter, so one core serves every channel.

This pattern helps complete certain larger patterns —

  • used-byManaged Agent RuntimeOffer the agent loop itself as a managed cloud primitive so a caller supplies a model, system prompt, and tools and the platform runs the orchestration in an isolated, session-scoped runtime.

Context

A team that built an agent inside a web chat widget is asked to also offer it over the phone, by email, in Slack, and as a background job that runs with no user present. Each surface has its own transport, turn-taking, latency budget, and message format. The reasoning, tools, and policies are the same in every case, but they were written tangled together with the chat widget's request-response assumptions.

Problem

When the agent loop is wired straight to one channel's mechanics, every new surface forces a partial rewrite of logic that has nothing to do with the channel. Voice needs streaming and interruption handling, email is high-latency and asynchronous, Slack threads carry their own identity, and background automation has no live user to clarify with. Copying the agent into each surface duplicates the reasoning and lets the copies drift, so a policy fix made for chat never reaches the phone line.

Forces

  • Each channel imposes its own transport, turn-taking, modality, and latency, yet the reasoning and policies are identical across them.
  • Duplicating the agent per channel is fast to start but guarantees the copies drift, so a fix in one surface silently misses the others.
  • A channel-agnostic core needs a normalized internal message and event shape, but forcing voice, email, and chat through one shape can strip channel-specific affordances such as streaming, attachments, or threading.
  • Some channels are synchronous and live while others are asynchronous or unattended, so the core cannot assume a user is present to clarify.

Example

A company ships a returns-assistant as a website chat widget, then wants it on the support phone line and in the customer's email inbox. With a decoupled core, the team writes a voice adapter and an email adapter that translate each channel into the same inbound event the chat widget already produces, and the assistant's logic, tools, and refund policy are reused untouched. A later policy change — a stricter refund window — is edited once in the core and takes effect on web, phone, and email at the same time.

Diagram

Solution

Therefore:

Separate the agent into a core and a set of channel adapters. The core holds the reasoning loop, tool calls, policies, and session state, and it speaks only a normalized internal contract: an inbound event (who, session, content, modality, attachments) and an outbound action (reply, tool effect, hand-off, push). Each delivery surface is an adapter that owns that channel's specifics: the web adapter handles request-response and rendering, the voice adapter handles streaming audio, barge-in (the caller interrupting mid-sentence), and turn-taking, the email adapter handles asynchronous threads and long latency, the Slack adapter handles thread identity, and a scheduler adapter drives the core with no live user. Session state lives with the core keyed by a channel-independent conversation id, so the same conversation can move across surfaces and the core can run unattended in the background. Adding a channel means writing one adapter, not touching the core; fixing a policy touches the core once and every channel inherits it.

What this pattern forbids. The agent core must not reference any channel's transport, message format, or turn-taking directly; it may read and emit only the normalized inbound event and outbound action, and all channel-specific handling stays inside adapters.

And the patterns that stand alongside it, or against it —

  • complementsAgent Adapter★★An interface layer connecting an agent's tool-calling protocol to heterogeneous external tools, normalizing their schemas into one the agent expects.
  • complementsVendor Lock-InAnti-pattern: couple application code directly to one model provider's SDK, request shape, and proprietary features so that switching providers requires rewriting application code rather than swapping an adapter.
  • complementsBusiness + LLM Microservice Split★★Split an LLM application into a CPU-bound business microservice (retrieval, prompt assembly, orchestration) and a GPU-bound LLM microservice (only model.generate behind REST), so each tier scales on its own hardware budget.
  • complementsBidirectional Impulse Channel·Let the user inject impulses into the agent and let the agent push messages to the user, both through one channel.
  • complementsEvent-Driven Agent★★Trigger the agent on external events (webhooks, message queues, file changes) instead of user requests or schedules.

Neighbourhood

Click any neighbour to follow the language. Scroll to zoom, drag to pan.