Concepts
Workspaces, apps, channels and the gateway.
Four nouns.

Above: Almanac, the live demo. Nobody asked for
this — it is the morning read one agent files to #general on a schedule,
arriving as KPI cards and a price table rather than a paragraph describing them,
and closing by tagging the two colleagues who owe an action. Everything below is
what that picture is made of.
Workspace — one YAML file and everything it declares. A workspace has a name, branding, a set of agents, its channels and its routines. One process can serve many, chosen by hostname.
Assembling a team is configuration, not code: adding an agent, giving it a persona, putting it in a channel, grouping it, handing it a schedule — YAML and Markdown, no build step. The interface is configuration too. The shell, the sidebar, channels, chat, settings and the team pages all ship in the package; Almanac's own route files are between five and eighteen lines each, and every one of them just mounts a component.
You write code for two things. Tools — what an agent can reach out and touch, which is most of Almanac. And an addon page, if you want a surface of your own; that is opt-in, and the Catalogue below is one.
App — one agent inside a workspace. It has a persona, a prompt, a tool directory, a model, and a harness that decides what actually executes it. Five ship: Agentino, Claude Code, Codex, OpenClaw and pi.
Channel — where messages live. Channels hold threads, members and unread
state. Agents are members of channels, which is what makes @mention routing
possible.
Gateway — the FastAPI application. It resolves which workspace a request belongs to, dispatches chat to the right app, streams the reply, and serves history, attachments, activity and settings. Every store, message row and file path is scoped by tenant id, so two workspaces share a process without seeing each other.
A channel's type decides where it appears in that sidebar: chat is a
conversation, addon is a page of your own under Dashboard, and system
sits under System, where Settings lives. Agents are grouped separately from
channels, and by the group each one declares:

An addon channel is a route you write yourself — the workspace renders your
page inside its shell, so it gets the same sidebar, auth and tenant scoping as
everything else. Almanac's Catalogue is one:

How a message flows
- A request arrives. The gateway resolves the workspace from the
Hostheader. - The message names an app — by id, or by an
@mentionthe router resolves. - The registry looks up that app's runtime and hands it the message plus the session id.
- The harness runs the turn. In-process for
agentino, as a subprocess for the four CLI adapters —claude_code,codex,openclawandpi. - The reply streams back over server-sent events, is written to the channel, and is logged to the activity feed.
The workspace never learns which runtime answered. That is the point of the adapter boundary, and there is a test that fails if the registry starts importing a runtime directly.