Beach for Architects and Senior Technologists
This article is for those whose role is to assess whether Beach is the right choice for an organisation that has been asked to build software around large language models. It assumes a reader who has built and shipped systems for two or three decades, who may not have written code daily for some years, and who is more interested in architectural commitments and operational properties than in the precise shape of any particular API. There is little code here; the practical wiring is in the developer-oriented guides elsewhere in the documentation.
The problem Beach addresses
Software organisations adopting LLM-based applications discover, over time, a recurring shape of difficulty. The initial proof-of-concept is straightforward — an LLM behind an HTTP endpoint, accessed via a chat interface — and is delivered quickly. What follows is harder. The same application now needs to accept inbound traffic over email; then over Microsoft Teams; then via webhook from an enterprise scheduler; and eventually as a peer in an emerging agent-mesh that has reached the rest of the business. Each new channel arrives with its own assumptions about message shape, threading, identity, and acceptable response latency. The team realises, several integrations into the journey, that the orchestrator's prompt, its tool set, and its session-state management have all been gently rewritten to accommodate the differences between channels — and that the application is now substantially harder to reason about than it was at the proof-of-concept stage.
A parallel difficulty arises with downstream integrations. The application's first deterministic backend was a single relational database. By the time the second LLM-driven feature ships, the application is also calling into a CRM by REST, a partner agency by an emerging A2A peer protocol, an internal tool surface by MCP, and a finance system that takes only webhook events. Each of these integrations is implemented somewhat differently, in part because each was added by a different developer at a different point in the project's life, and in part because no architectural commitment was made early about how the application would relate to its surroundings.
Beach is the proposition that these difficulties are not incidental. They follow from the absence of a clear architectural commitment about where the application's interior ends and the protocol-shaped world begins. Beach offers that commitment, at the cost of accepting some specific design constraints, and provides the libraries and the documented patterns that make working within the commitment ergonomic.
The shape of the commitment
Beach's central architectural assertion is that an LLM-based application has — or should have — a sharp distinction between an interior and an edge. The interior is where the orchestrator lives, where the deterministic handlers live, where the audit trail accumulates, and where the application's domain reasoning takes place. The edge is where every protocol that touches the application is implemented: the inbound adapter that translates an email into a routed event; the outbound plugin that sends an SMS; the A2A peer endpoint that publishes the application as something other agents can call.
The commitment is that the interior speaks only in events, manifests, and participants; the edges speak only in protocols; and nothing in the interior knows the name of any particular protocol. The orchestrator does not know whether the message it is replying to arrived by email or by chat. The deterministic handlers do not know whether their results will be served via REST or rendered into a web chat panel. The session state does not include channel-specific metadata.
This is a strong claim and not a casual one. It rules out a number of patterns that are common in less-disciplined LLM applications — the orchestrator that switches behaviour based on channelId, the handler that formats output as either email or chat depending on context, the session that remembers per-channel preferences. Beach treats these as anti-patterns; the documentation flags them and the architecture makes them difficult to express.
In return for this discipline, Beach offers properties that are genuinely valuable in production:
- A new inbound or outbound protocol — be it WhatsApp, Slack, a brand new A2A extension, or whatever the next agent-mesh protocol turns out to be — is added by writing a single adapter at the edge. Nothing in the interior changes.
- A new participant — a new orchestrator for a new domain, a new deterministic handler, a new long-running background process — is added by registering it with the router. Channel-aware logic does not need to be rewritten to accommodate it.
- An audit trail of every cross-component message flows through the same router, with the same shape, regardless of which protocol delivered it or which protocol carried the reply away.
- Replay, observability, and approval interception are properties of the interior; they apply uniformly across every channel and every participant.
What Beach is, in concrete terms
Beach is a set of independently versioned npm packages. The application that adopts Beach selects the packages it needs and composes them in the consumer's own application code; nothing inhibits the team from arranging the application's runtime topology to suit local concerns about deployment, scaling, or hosting.
The architectural centre is two packages: @cool-ai/beach-core, which provides the event router through which all cross-component messages must pass, and @cool-ai/beach-session, which provides the turn lifecycle for orchestrator invocations and the manifest registry for asynchronous coordination. Together, these are what makes Beach a Beach application; everything else is a participant or an edge.
The participant packages — @cool-ai/beach-llm for LLM actors, @cool-ai/beach-starter for the canonical pipeline of glue handlers — provide the conventional shapes of work the interior does. Edge packages — @cool-ai/beach-transport for the wire-protocol adapters (A2A, MCP, SSE), @cool-ai/beach-channel-email and @cool-ai/beach-format-email for the email channel — implement the connections between the interior and the outside world. Adopting teams are free to write additional edges; the patterns for doing so are documented and short.
There is also a documentation surface — the section you are presently reading is part of it — and a set of tooling packages for evaluation (@cool-ai/beach-evals) and local development (@cool-ai/beach-inspect). These are optional; the architectural commitment requires only the centre.
What Beach is not
Beach is not an agent framework in the sense in which that term is most commonly used. It does not impose a particular model of what an LLM agent is, does not ship a particular orchestrator, and does not opine on whether the application's reasoning ought to be done by one large model or several small ones. The orchestrator is something the adopting team writes; Beach provides the surrounding plumbing and a small set of disciplined patterns that the orchestrator must respect.
It is not a runtime. Beach packages are libraries, consumed by an application that the team builds and deploys in whatever fashion suits its existing operations. There is no Beach-specific deployment model, container, or hosted control plane. The application is a normal Node.js process (or several) that imports the Beach packages.
It is not a proxy or a gateway. Some related software in this category sits between an application and the LLM, intercepting calls and adding policy. Beach sits inside the application — it is the application's architecture, not a layer in front of it.
It is not a protocol. The protocols an application speaks are MCP, A2A, REST, the webhook conventions of the systems it integrates with, and so on; Beach uses these and provides adapters for them but does not itself contribute a wire format. (There is one minor exception, an envelope-part type called llm-context that addresses a specific gap in A2A's peer-to-peer story; this is a Beach extension declared in the Agent Card and ignored by non-Beach peers.)
It is not, finally, a complete answer to the question of how to build LLM-based applications. It is a load-bearing answer to one part of that question — how an application's interior should be shaped to survive the churn of the protocol landscape — and pairs deliberately with other technologies (Vercel AI SDK, Inngest, Temporal, OpenTelemetry-compatible observability tools) for the parts of the question it does not address. The documentation is candid about this; the architectural review elsewhere in this corpus details where Beach defers to the ecosystem.
What Beach commits an engineering team to
For the architect's purposes, the specific concrete commitments that adopting Beach implies are worth enumerating. None should be a surprise; they are written down here so that the cost is visible up front.
The orchestrator must be channel-blind. Wherever the application's reasoning lives, it must not branch on the identity of the channel that delivered a request. If branching is genuinely required — different reply tones for different channels, for example — the channel-specific work happens in an edge-positioned actor (a "Composer specialist") that is structurally separate from the interior orchestrator.
LLM output must be structured. Beach enforces a respond() discipline: every LLM-shaped participant emits its output by calling a tool with structured parts and a turn-state marker, never by free text that downstream code parses with regex. This implies that the prompts adopted by the team must teach the LLM the discipline; the supporting prompt snippets ship with the LLM package.
Cross-component messages must go through the router. Two handlers cannot call each other directly. A handler that needs to trigger a follow-on action emits an event through the router; the next handler is dispatched by a routing rule. This is unambiguous and intended; it is what makes the audit trail comprehensive and the application's behaviour legible.
Asynchronous work uses manifests. The pattern of "I need three results from background work; tell me when they all arrive" is implemented in Beach via a Manifest that tracks expected slots and fires onComplete when all are filled. This is one of two manifest patterns in Beach (the other being the Delivery Manifest used to gate batched outbound channels); both are documented thoroughly. There is no separate primitive for "asynchronously wait for several things"; manifests are it.
Each package is independently versioned. Beach commits to per-package semver, with breaking changes flagged by major-version bumps. Adopting teams may pin individual packages and migrate at their own pace; Beach will not force a migration. This implies that adopters may be running mixed versions across a release boundary, which the architecture is designed to accommodate.
These are not many commitments, and several of them are commitments most thoughtful teams would make in any architecture for LLM-based work — channel-agnostic orchestrators and structured LLM output are not Beach inventions. What Beach contributes is the systematic pairing of these commitments with the supporting libraries and documented patterns that make them ergonomic to follow.
How an adoption typically proceeds
Teams that succeed with Beach tend to follow a recognisable progression. The proof-of-concept is built using @cool-ai/beach-starter against a single channel — typically a web chat panel via SSE — with a single orchestrator and a small set of deterministic handlers as tools. This delivers a working application within days and demonstrates the canonical pipeline shape.
Once the canonical pipeline is internalised, additional channels are added one at a time. Email is the most common second channel and is straightforward. A REST surface for conventional internal consumers is often the third addition. The team learns, in the course of adding each, that the orchestrator did not need to change; this is the proof of the architectural commitment, and is generally what causes the team to commit further.
Specialist participants — second LLM actors for triage or domain-specific reasoning, deterministic handlers for compliance and policy enforcement, durable executors for long-running background work — are added when the application's complexity justifies them. The router and the manifest registry support these patterns natively; the team does not need to invent infrastructure.
The application is published as an A2A peer (and possibly as an MCP server) when there is value in being callable by other agents in the organisation's emerging agent mesh. The Agent Card declares what the application offers; the protocol-handling adapters are wired at the edge.
Through all of this, the audit trail is uniform, the observability flows through OpenTelemetry, and the application's session state can be replayed for testing and evaluation. These are not features the team builds; they are properties they get for free by following the architectural commitment.
How to evaluate whether Beach is right
A Beach evaluation is most usefully structured around three questions.
Is the application going to face protocol churn? If the application will live for several years, will integrate with multiple inbound and outbound channels, and is being built in an environment where the protocol landscape (A2A, MCP, future agent-mesh standards) is still settling, the architectural commitment Beach asks for is likely to pay back several times. If the application is genuinely a single-channel single-purpose service whose protocol surface will not change, the commitment is correspondingly less valuable.
Does the team accept the architectural discipline? The orchestrator-must-be-channel-blind rule is unambiguous and load-bearing; teams that find themselves wanting to bend it during the proof-of-concept will continue to find themselves wanting to bend it later, and Beach is not the right framework for them. Teams that find the discipline natural — and there is a self-selecting population of senior engineers who do — will find Beach's structure liberating rather than constraining.
Is the engineering team capable of working in a TypeScript-shaped Node.js ecosystem? Beach is implemented in TypeScript and exposes its discipline through TypeScript packages. Adoption from other ecosystems is possible (the wire protocols are language-agnostic) but is currently a heavier lift; the documentation focuses on the TypeScript story.
If the answer to all three is yes, Beach is likely a good fit. If the answer to any is no, the cost-benefit balance shifts; the team may be better served by lighter-weight or differently-shaped infrastructure.
What to read next
For the developer-oriented walkthrough of building a first Beach application, Getting Started is the appropriate entry point. The architect-oriented complement to this article — a systematic exposition of the architectural invariant — is Reference: design principles, which formalises in four parts the discipline informally described above.
The two governance documents — Reference: contribution policy and Reference: invariant review criterion — articulate how the architectural commitment is sustained as the project's codebase grows and as additional engineers join.
For the practical question of how a Beach application is exposed to its surroundings, Exposing your application through multiple protocols is the natural next reading.