Shared Canvas¶
A canvas is a markdown file multiple agents can read, write, and
subscribe to. When one agent writes, every other subscriber wakes up
with a notification carrying the diff — same ✉ inbox channel queues
and handoffs already use.
This is the blackboard pattern: shared structure + specialists + event-driven coordination. Aegis has three coordination primitives now:
| Primitive | Verb | Wake trigger |
|---|---|---|
| Queue | "do this, tell me when done" | Worker completes |
| Inbox / handoff | "wake — message for you" | Sender posts |
| Canvas | "wake — shared state changed" | Subscriber writes |
The model¶
- A canvas is a real markdown file on disk — Alex can grep it, commit it, open it in his editor.
- Sections are
## headings. Each section is the unit of write and the unit of notification. - Any subscriber can write any section. The ledger records who wrote what; the inbox notification names the writer. No enforcement of ownership in v1 — trust the agents, surface conflicts loudly.
Special section names:
_preamble— the body before the first##heading.body— the entire file, only valid when the file has no##headings.
MCP tools¶
| Tool | Args | Returns |
|---|---|---|
aegis_canvas_open |
name, file (only on first open), from_handle |
{name, file, sections, created_at} |
aegis_canvas_read |
name, section (optional), from_handle |
{content} |
aegis_canvas_write_section |
name, section, content, from_handle |
{ok, canvas, section, op, writer, added, removed, timestamp} |
aegis_canvas_append_to_section |
name, section, text, from_handle |
same as above with op=append |
aegis_canvas_subscribe |
name, from_handle, sections (optional filter) |
{ok, subscribers} |
aegis_canvas_unsubscribe |
name, from_handle |
{ok} |
aegis_canvas_list |
— | list of canvas metadata |
from_handle is the calling agent's aegis handle (read from the
system prompt). It's used as the writer in the ledger and to
suppress the writer's own inbox echo.
Notifications¶
When agent alice writes a section, every subscriber except alice gets an inbox message like:
✉ from canvas:report-q3 · 2026-05-21T20:30:00Z
section "data" · 2026-05-21T20:30:00Z
written by agent:alice (+18 / -3 lines)
──
## Data
Q3 numbers came in stronger than projected. Revenue up 14% YoY
driven by enterprise tier expansion. Net new logos hit 47 …
… (5 more lines)
append_to_section shows only the appended text (not the whole new
body). Subscription filters (sections=["data"]) only fire for
matching sections.
If aegis is restarted, the file + ledger persist but subscribers don't — agents must re-subscribe.
Worked example¶
# PM agent
aegis_canvas_open(name="report-q3", file="vault/reports/q3.md",
from_handle="pm")
aegis_canvas_subscribe(name="report-q3", from_handle="pm")
aegis_canvas_write_section(
name="report-q3", section="intro",
content="Q3 was a quarter of consolidation…",
from_handle="pm")
aegis_handoff(target_handle="researcher",
context="fill the data section of canvas report-q3",
from_handle="pm")
# researcher agent (woken by handoff)
aegis_canvas_open(name="report-q3", from_handle="researcher")
aegis_canvas_subscribe(name="report-q3", from_handle="researcher",
sections=["data"])
aegis_canvas_write_section(
name="report-q3", section="data",
content="Q3 numbers came in stronger…",
from_handle="researcher")
# Done; returns.
# PM wakes with:
> from canvas:report-q3 · 2026-05-21T20:30:00Z
section "data" · 2026-05-21T20:30:00Z
written by agent:researcher (+1 / -0 lines)
──
Q3 numbers came in stronger…
State on disk¶
.aegis/state/canvases/<name>/
meta.json # {name, file, created_at}
ledger.jsonl # one append per write
The canvas content lives at whatever file path was passed on first
open — usually a project file or a vault note. The state dir is
gitignored by aegis defaults.
Limitations (v1)¶
- No external-edit detection. If Alex edits the file in his editor between agent writes, agents don't get notified. The next write reads the current file state, so Alex's edits aren't lost, but they don't fan out as events. (A file watcher is on the follow-up list.)
- No ownership enforcement. Any subscriber can write any section.
- Markdown only. No HTML / JSON / structured canvases yet.
- No subscription persistence across restarts. Re-subscribe on each session.
- No TUI surface. Canvas content is the on-disk file; open it in your editor. Notifications appear in the agent's transcript as inbox blocks.
Full spec¶
See docs/superpowers/specs/2026-05-21-shared-canvas-design.md.