cd /news/ai-agents/frona-v2026-6-0-self-hosted-personal… · home topics ai-agents article
[ARTICLE · art-27204] src=github.com ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

Frona v2026.6.0 – self-hosted personal AI assistant

Frona v2026.6.0 introduces a unified human-in-the-loop pause/resume mechanism across all channels, a slash composer for invoking skills and agents, typed file tools to reduce token usage and hallucinations, and per-channel message splitters to prevent truncation. The update also adds button-based approvals on Telegram, Discord, Slack, and WhatsApp Cloud, with text-based prompts on Signal, SMS, and personal WhatsApp.

read7 min publishedJun 14, 2026

This release ships a unified human-in-the-loop /resume mechanism across every channel, a slash composer for invoking skills and other agents directly, typed file tools that cut token usage and hallucinations, and per-channel message splitters so long replies arrive cleanly instead of getting truncated. Approvals (app deploys, multiple-choice questions, credential picks) now render as buttons on Telegram, Discord, Slack, and WhatsApp Cloud, and as Reply YES or NO

prompts on Signal, SMS, and personal WhatsApp, with the inbound parser accepting the obvious variants. Behind the scenes, a new Harness

struct consolidates the agent runtime view of AppState , sandboxing moves to a single SandboxManager

per principal kind, and the channel adapter framework now classifies failures with a typed ChannelError

.

Supported channels: Slack, Discord, Telegram, Signal, SMS, WhatsApp Cloud, WhatsApp Personal.

Human in the loop

  • Replace opaque tool_data

blobs on tool calls with typedHitl

values; build typed HITL tool components and consume new SSE event names. - Persist d

message status and resume with an atomic compare-and-swap; translate the newInferenceResponse

outcomes into /resume persistence. - Add a

POST /api/chats/{chat_id}/tool-calls/resolve endpoint, lift the HITL callback parser and response label into a sharedhitl

module, and drop the legacy app and vault approval routes superseded by the resolve endpoint. - Re-seed pending HITLs from msg.tool_calls

oninference_done

so d turns continue to surface new questions. - Share an inbound reply HITL resolver with YES/NO variant parsing ( y

,yeah

,ok

,nope

, thumbs-up emoji, and the usual variants). - Resume HITL delivery on resolve so sequential adapters render the next prompt; use the absolute public_base_url

for HITL fallback URLs on channels that can't render the picker. - Render HITL prompts and resolve responses on Telegram (inline keyboard), Slack (Block Kit via Socket Mode interactions), Discord (buttons), WhatsApp Cloud (interactive messages and button taps), WhatsApp personal account (quote replies), Signal (quote replies), and SMS ( Reply YES or NO

hint on App-deploy approval prompts). - Hold the Discord and WhatsApp typing indicator across long inferences so the user sees activity while the agent is generating.

  • Rename the manage_service

tool tomanage_app

and adopt typed HITL hooks; exit tasks on HITL and respawn viarun_task

. - Test HITL persistence, rendering, batched resolve, and the resume race.

Slash composer

  • Add a

chat::slash invocation parser for/

and@

prefixes; add aMessageCommand

side field onMessage

for parsed slash invocations. - Wire up /commands

end to end: dispatch, terminal-write refactor, cross-agent attribution, slash parsing. - Add a

GET /api/chats/{id}/commands discovery endpoint and alistCommands

API client. - Frontend: slash composer with Lexical triggers, directive chips, and a /new

builtin that opens a fresh chat with the current agent. @<agent>

per-turn override: the reply is attributed to the target agent and the next message reverts to the chat's default.- Add save_chat

,save_updated_message

, anddelete_messages_for_chat

helpers. - Skills: new SKILL.md frontmatter fields

disable-model-invocation ,argument-hint

, andarguments

; hidedisable-model-invocation skills from the model's available-skills block while keeping them in the/

menu for users to invoke directly. - Add e2e tests for /agent

dispatch and commands discovery.

Channels and message splitter

  • Add a per-format message splitter with shared boundary primitives that break at paragraph, then line, then word, then UTF-8 character, and never inside a code fence or escape sequence.
  • Wire TelegramMarkdownV2Splitter

into the Telegram adapter (4,096-char per-message limit) and render markdown tables as monospace code blocks since Telegram has no native table support. - Wire MarkdownSplitter

into the Discord adapter (2,000-char per-message limit), remove the oldchunk_for_discord

helper, and render markdown tables as monospace code blocks. - Wire PlainSplitter

into the Slack adapter (silent multi-chunk). - Wire PlainSplitter

into the SMS adapter with a 1,600-char hard cap andFull reply: {short-link} overflow that points at aChat

-kind share URL (reused across overflow events in the same chat). - Wire MarkdownSplitter

into the WhatsApp Cloud and WhatsApp Personal adapters. - Wire SignalSplitter

into the Signal adapter with per-chunkSignalText { body, ranges }

. - Add ChannelError

type andMessageDelivery.failure_kind field; migrate channel adapters to typedChannelError

classification (Transient

,Forbidden

,NotFound

,PayloadInvalid

,PayloadTooLarge

,Unauthorized

,Other

) with an optionalretry_hint

. - Make start_with_retry

idempotent so a single start no longer double-spawns the adapter. - Replace the bounded broadcast bus with unbounded fan-out so channel inbound stops losing events.

Share links and preview pages

  • Add a Share

entity withFile

andChat

kinds plus aShareService

for issuing short links; wire the service intoAppState and schedule periodic cleanup. - Add share.ttl_secs

(default 30 days) andshare.cleanup_interval_secs

(default 6 hours) config knobs. - Add
`GET /s/{id}`

short-link resolver with a 303 redirect to the canonical or presigned URL. - Add a /p

preview page that renders markdown and code with syntax highlighting; add aGET /p/{slug}

redirector to the query-param form. - Route channel attachments through outbound_url

in all adapters via a new`chat::channel::attachment`

helper: inline-channel previewable files get`/p/{8-char-id}`

, inline non-previewable files get`/s/{8-char-id}`

, button channels emit long-form`/p/{owner}/{handle}/{path}`

or/api/files/...

URLs. - Add an anonymous_not_found

helper so unknown / expired / unauthorized share IDs return byte-identical 404s. - Extract FilePreviewContent

into a shared module; extractapiFetch

fromrequest<T>

for non-JSON authenticated requests. - Add
`ShareKind::Chat`

variant with lazylookup_or_issue_chat

for SMS chat-share reuse.

Tasks

  • Accept result_description

oncreate_task

andcreate_recurring_task

so prose answers skip schema authoring; reject when bothresult_description

andresult_schema

are passed (or neither). - Require a top-level summary: string

on complex task result schemas; reject complex schemas without it at task creation. - Carry result_schema

onTaskCompletion

events and persist the JSON content. - Render the TaskCompletion

bubble with a schema-driven body and a link to the task chat; renderTaskCompletion

via a shared markdown helper across channel adapters. - Researcher now publishes the full research as a markdown attachment, named after the topic (e.g.

h100-used-prices.md ) so successive research tasks don't overwrite each other.

Typed file tools

  • Add typed read

,write

,edit

,glob

, andgrep

tools. Workspace-scoped by default; absolute and policy-authorized sibling paths allowed; virtual-path URIs rejected. edit

uses Unicode normalization (NFKC, ASCII quotes/dashes/spaces, collapsed whitespace) so a slightly-misremembered snippet still matches its target. The motivation is token usage and hallucinations: a typededit

returns a structured diff in a fraction of the tokens a shell round-trip eats, without the model free-styling shell escapes against a half-remembered path.- Add the frona-text

crate with shared text and search primitives (NormalizedString ,LineEnding

,walk_with_ignore

for.gitignore

-aware traversal). - Refactor sandbox: SandboxManager

is now the single entry point per principal kind.

### Tool views (frontend)

- Extract a per-tool view registry:

ToolRow

primitives,DefaultView

, slim chrome. - Add views for shell, Python, and Node (with sandbox-deny extraction); for the typed file tools ( read

,write

,edit

,glob

,grep

) with syntax highlighting and line numbers; forproduce_file

(filename / size / content-type card); for`web_search`

(result list) and`web_fetch`

(markdown + clickable URL); for task tools (`create_task`

,create_recurring_task

withcronstrue

,delete_task

); for memory tools (auto-expand on large text); for`update_identity`

(set/remove attribute rendering); and for`set_heartbeat`

(humanized interval and next-tick time). - Render the shell tool command as a bash-highlighted block with wrap; render

produce_file

as a filename card with size and content type. - Add vitest

test runner andcronstrue

/unbash

dependencies.

Harness / runtime

  • Add a Harness

struct as the agent runtime view ofAppState ; route session build, voice WS, message stream, and resume-all through it. - Narrow TaskExecutor

to holdArc<Harness>

and own its own resolution-notifier map. - Move HITL resolution onto Harness and drop ChannelCtx.app_state

. - Move task-tool registration into ToolManager

; extractdeliver_event_to_source

soReportSignalTool

no longer needsTaskExecutor

. - Delete agent/execution.rs

and update test fixtures for Harness. - Inject heartbeats as a transient turn so the agent stops replying to them like a user message.

  • Fold per-turn lifecycle events into InferenceEventKind

.

Browser

  • Keep browser sessions alive past Browserless's hard 408-second timeout: pass a long timeout at connect time, self-evict and recycle sessions with a 60-second margin, and evict dead WebSockets immediately.

Chat / Frontend

  • Stop dropping the newest message when a chat crosses the page limit.
  • Move the reasoning toggle from inline content to a sparkle icon in the message header.
  • Disable single-tilde strikethrough in assistant markdown.
── more in #ai-agents 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/frona-v2026-6-0-self…] indexed:0 read:7min 2026-06-14 ·