Build Your FutureTM

Changelog

What shipped on the platform, and every new release of the agent templates you can deploy.

v0.31.1
NovaTests passing

Nova v0.31.1

Patch on v0.31.0.
Merged in #32.

Picking a file in the hosted chat's composer crashed the whole surface with:

`Tooltip` must be used within `TooltipProvider`

The vendored chat components use Radix tooltips, and the attachment chip opens a bare <Tooltip> with
no provider above it. Radix's context helper throws on a missing provider rather than degrading, so
the error propagates to the nearest boundary and the chat goes with it.

It survived this long because TooltipIconButton wraps its own provider — every other tooltip in the
bundle works, and the chip was the only bare one. The thread root now provides one for everything
under it, which also keeps the bundle self-sufficient rather than depending on whatever a host wraps
it in.

Synced from the control plane's chat-ui:export, where the fix and its regression test live.

Upgrade: no config or data changes.

v0.31.0
NovaTests passing

Nova v0.31.0

Three things that turned out to be one thing: Nova can format a reply properly, move files in both
directions, and keep those files somewhere everyone can reach them.

Merged in #31.

Rich replies (Bot API 10.1/10.2)

sendRichMessage is a method, not a parse_mode — the reply goes out as raw GFM and Telegram
renders real tables, checkboxes, heading levels and nested lists.

Used selectively: a plain answer still goes out as a plain message, because mixing the two
surfaces makes font weight and spacing jump mid-conversation. needsRich() decides per message,
after stripping code fences — a fence is not a reason to escalate.

Three failure modes, three behaviours. The rule that matters is never re-send a transient
failure
, which is how a user ends up with the same answer twice:

FailureResponse
Method unknown (older Bot API)latch off for the process, fall back to plain
Content rejected (bad markup)fall back to plain, once
Transient (429/5xx)honour retry_after, retry the same send

Also fixes a pre-existing truncation: chunk() dropped everything past 4000 characters of a line
containing no newline, so a long paragraph lost most of the answer. It now hard-splits and re-opens
straddled code fences.

Files, both directions

In — photos, albums, video, audio, voice notes, documents. An album arrives as ONE turn, debounced
by media_group_id: answering the first item treated item #2 as a new question and interrupted the
run item #1 had started. Images and PDFs reach the brain as native file parts, text-ish files
inline. Anything over Telegram's 20 MB bot-download cap is reported to the model rather than silently
dropped. Every upload also lands in the drive's inbox/.

Out — attach_file sends a real file: a rich media block for images/video/audio, a native
document bubble otherwise, a file card in both web chats.

Chat action is held for the whole run (Telegram expires it after 5 s) and switches to
upload_photo / upload_voice / upload_video / upload_document for what is about to arrive.

Nova Drive

One folder — $DATA_DIR/files. The pre-drive workspace/ is renamed into it on boot, so Nova's tools
and the user's files are one tree: a chart bash renders is a file the user downloads a second later.

Three doors, one implementation:

DoorWhoProofReach
/drive/api/*the ownerhosted-chat cookie, or CONTROL_TOKEN when the dashboard proxieseverything
/nova/drive/*a mesh agentits own mesh-signed credentialonly what a grant covers
/d/<token>anyonethe linkone file or folder, within its limits

A grant is authorization — the credential already proves identity. Scoping is prefix+separator, so a
grant on shared/ deliberately does not cover shared-notes/. Public links take any combination of
expiry, download cap (1 = one-time) and argon2 password; answering the password sets a cookie scoped
to that one link, so a folder share does not ask per file.

Every mutation and every download records its actor (user / nova / agent:<id> /
share:<token> / telegram) — the only way a shared drive answers "did that link get used?". Text
overwrites and deletes keep bounded snapshots, so an edit is restorable; a rename carries its history.

Path safety is one tested function: lexical .. rejection plus a realpath check on the deepest
existing ancestor, because string cleaning never catches link -> /etc. HTML and SVG always download
— serving attacker-authored markup inline from the agent's own origin is stored XSS. Range is
honoured everywhere, so video scrubs.

Nova's own tools are ungated, since NOVA_SYSTEM_TOOLS is about giving it a shell, not about reading
a CSV the user just uploaded: list_drive, read_drive_file, write_drive_file, move_drive_file,
delete_drive_file, share_file, grant_agent_access.

Backups are a hand-written streaming ZIP — no dependency, no zip in the image, one file in memory at
a time.

Attachments in chat

Both web chats show a file card: glyph and tint by type, name, size, image thumbnail, click to
download. The bytes still never ride the reply — a 20 MB attachment would be re-serialized on every
poll of the task — but the reference now carries the file's size and drive path, which is the
difference between prose and a file the user can take.

The hosted chat fetches from its transcript row rather than the drive path: the row is what the
reply was, so the download survives Nova moving or deleting the original.

Upgrade notes

  • $DATA_DIR/workspace is renamed to $DATA_DIR/files once, on boot. Anything referring to
    workspace/ is stale.
  • TELEGRAM_RICH=0 disables rich replies without a rollback.
  • No breaking API changes; file parts on the wire gain optional size and path.
v2026.7.31
Swarm Network HermesTests passing

Swarm Network Hermes v2026.7.31

Your agent can now generate videos and send them to you, and there is a new channel to reach it on. Photos and files on Telegram now land reliably.

v0.28.0
NovaTests passing

Nova v0.28.0

Opening your Nova's own domain now gives you the same chat as the dashboard — the same components, not a lookalike — with one history shared across every surface.

The dashboard's chat, verbatim

web/vendor/chat-ui/ is the control plane's own component set plus its design tokens, generated by its chat-ui:export and synced by CI. This repo supplies only the host glue (runtime adapters over the linear store, roster, schedules). Composer, message layout, action bars, animations and scrolling are therefore identical, and future dashboard changes arrive as a sync PR instead of a re-implementation.

Light and dark

Both themes from the same token file the dashboard uses, applied before first paint. The toggle in the rail follows the OS until you pin a choice.

What the chat gained

  • Markdown replies — headings, lists, tables, code fences, and @mention tags for mesh agents (replies used to arrive as raw markdown text).
  • How Nova answered — the orchestration trace as an animated stepper; steps carrying a payload expand to the exact input/output of a member call, skill or system tool. Reasoning has its own panel; both stream live.
  • Composer — agent quick-insert chips from the live roster, a reasoning-effort pill, attachments (images reach the model as images, text files are inlined), and Web Speech voice input.
  • Edit, regenerate, branches — with a ‹ 2/3 › picker; the tree is persisted per session as the web view of the conversation.
  • Sessions rail — search, Today / Yesterday / Earlier grouping, archive and delete.
  • Schedules tab — scheduled runs (docs/15) with a friendly cron builder, pause / resume / cancel, and a run-history timeline where each fire renders exactly like a chat reply.

One history across surfaces

Sessions carry the contextId their turns run under, and turns arriving over /nova/message — the dashboard's chat — are mirrored into this Nova's own store. A conversation held in the dashboard now shows up here (badged with where it came from), and continuing it here continues the same conversation and the same memory rather than starting a parallel one. Telegram threads and scheduled runs are in the same list.

API

/chat/api gains roster, capability flags, session delete, the transcript blob, and the memory / tasks / cron routes — which now share one handler with /setup/api, so the control channel and the chat can't drift apart.

Fixes

  • peers.json pins the package versions the vendored bundle is built against, checked by typecheck: a react-lexical minor bump had silently killed the composer (Send disabled, Enter inserting a newline) with no build error.
v2026.7.29.2
Swarm Network HermesTests passing

Swarm Network Hermes v2026.7.29.2

The first reply arrives much sooner, and models that think out loud show their thinking live. There are new models to choose from, fewer interruptions for routine actions, and finished answers are kept safe even if the agent restarts.

v2026.7.29.1
Swarm Network HermesTests passing

Swarm Network Hermes v2026.7.29.1

Maintenance and reliability improvements.

v2026.7.29
Swarm Network HermesTests passing

Swarm Network Hermes v2026.7.29

Maintenance and reliability improvements.

v2026.7.28
Swarm Network MercuryTests passing

Swarm Network Mercury v2026.7.28

Your Telegram bot now recognises you from your first message, anyone you've approved stays approved across updates, and connecting Telegram is faster.

v2026.7.28.2
Swarm Network Hermes

Swarm Network Hermes v2026.7.28.2

Your Telegram bot now recognises you from your first message. Everyone else still needs your approval before it will answer.

v0.26.0
NovaTests passing

Nova v0.26.0

Nova's Telegram bot answered anyone who found its username: no allowlist, no pairing. A stranger could hold a full conversation and spend the owner's balance.

Nova now takes an allowlist with its credentials (runtime push, plus TELEGRAM_ALLOWED_USERS as a boot seed) and checks the sender before anything else — an unauthorized one gets a single plain refusal and no session, transcript, or model call. The control plane fills it with the account Telegram says created the bot.

An empty list stays open, so a Nova connected before this keeps working unchanged.

v2026.7.28.1
Swarm Network HermesTests passing

Swarm Network Hermes v2026.7.28.1

Fixes an issue where your own Telegram bot might not recognise you. Update to the next release, which includes a better version of this fix.

v0.25.1
NovaTests passing

Nova v0.25.1

Telegram queues updates for a bot that has no webhook yet. The child bot exists for minutes before its token reaches Nova, and Telegram shows a START button the moment the user opens the chat — so pressing it queued the /start, and drop_pending_updates discarded that queue on arrival.

Telegram never offers the button twice, so first contact was lost: the generated welcome never came and the bot only replied once the user typed something by hand. The pending queue is now kept.

v2026.7.28
Swarm Network HermesTests passing

Swarm Network Hermes v2026.7.28

Your agent now recovers from problems on its own, reports ready only when it truly is, and keeps your approved users, conversations and connections across restarts.

v0.25.0
Nova

Nova v0.25.0

Connecting Telegram no longer restarts the Nova, and first contact is answered by Nova itself.

Runtime Telegram credentials

  • POST /setup/api/telegram { token, webhookSecret, botUsername? } (bearer CONTROL_TOKEN) installs the child-bot credentials, persists them in Nova's own SQLite (app_config), and calls setWebhook immediately — the bot answers seconds after the QR scan, with no env push and no redeploy.
  • DELETE disconnects (drops the webhook before clearing), GET reports {connected, botUsername, webhookUrl} and never returns the token.
  • TELEGRAM_BOT_TOKEN / TELEGRAM_WEBHOOK_SECRET are now a boot seed only; stored config wins, so Novas connected the old way keep working.
  • setWebhook sends drop_pending_updates (a reconnected bot doesn't replay its old queue) and setMyCommands gives a fresh chat a menu.

Personalized welcome

/start is answered by an introduction the model writes at that moment from the live roster, the enabled persistent capabilities and the global-memory digest — static fallback if the gateway is down. It's mirrored into the hosted-chat transcript and never routed through orchestrate().

Full changelog: https://github.com/Swarm-Agent-Aggregator/Swarm-Network-Nova/compare/v0.24.0...v0.25.0

v2026.7.27
Swarm Network MercuryTests passing

Swarm Network Mercury v2026.7.27

Updates no longer report a problem while they're still starting up, and messages passed to your agent by other agents are no longer turned away.

v2026.7.27
Swarm Network OpenClawTests passing

Swarm Network OpenClaw v2026.7.27

Your agent runs on a newer engine with everything shipped since June, and updates no longer report a problem while they're still starting up.

v2026.7.27.2
Swarm Network HermesTests passing

Swarm Network Hermes v2026.7.27.2

Maintenance and reliability improvements.

v2026.7.27.1
Swarm Network HermesTests passing

Swarm Network Hermes v2026.7.27.1

  • Download a backup of your agent and restore it later.
  • The agent's own dashboard now works properly on phones and tablets.
v2026.7.27
Swarm Network HermesTests passing

Swarm Network Hermes v2026.7.27

Maintenance and reliability improvements.

v0.24.0
NovaTests passing

Nova v0.24.0

Nova's system prompt now plainly declares what it can do (shell/filesystem, persistent memory, task list, scheduled runs) instead of instructing or guardrailing. The previous 'if you don't have the tool say so' / 'never crontab' phrasing confused weaker models (gemini-flash, openrouter auto) into falsely refusing to schedule or falling back to bash, even though the tools were present. Verified injection on live meshes: all capability flags were correctly set — this was purely a prompt-clarity fix.

Follow along by RSS. The feed carries platform entries only.