Skip to content

System apps: every one has its own agent that can notify - #274

Merged
ymote merged 3 commits into
mainfrom
feat/system-app-agents
Oct 2, 2026
Merged

ymote merged 3 commits into
mainfrom
feat/system-app-agents

Conversation

@ymote

@ymote ymote commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

What

  • Photos, Maps, YouTube and Camera get the agent Mail and Calendar have (manifest agent block, the glance capability) with one tool in their own namespace, <app>.notify {title, body, card_id?, priority?}. News keeps news.list and news.read and gains news.notify. The system agent reaches each as the octos peer card.<app id>.
  • One notice card for every app, in the shell (crates/shell/resources/glance/notice.card, moved from Mail's service, filled by glance_notice.rs): the app's icon and manifest name, the time, and the agent's title and text; it opens the app and posts a notification, published as the app only when its manifest is granted glance. Mail's and News's services hand notify to the shell (on_notify); every system app with no service of its own gets the shell's NoticeService.
  • agents.ask waits for the person. It returned "not yet allowed, wait for them" at once, the system agent ended its turn, and after Allow nothing carried the request on (seen live: Photos and News were allowed but never asked). The system chat now holds the call until the person answered the first-use sheet and the agent's peer started, then answers with the peer slug, so the request goes on in the same turn. It is declared outward with confirm: app, which is how octos holds a call the host's own sheet confirms (a read tool gets 30 s).
  • AI providers gets no agent yet: App Hub takes a tool namespace only as [a-z0-9_] (octos a tool name's segments as [a-z][a-z0-9_]), so ai-providers.notify and with it the agent block are refused. A test says so and fails once App Hub admits it.
  • apps/README.md and apps/README.zh-CN.md: the apps table and the App agents section (merged with docs: the system agent and app agents as main has them #269's rewrite).

Verified

  • cargo test --locked -p octosense-shell --features app-hub --lib (753 passed on the combined build), -p octosense-mail-service -p octosense-calendar-service -p octosense-news-service, python3 tools/native_apps.py --check, python3 tools/setup.py --check --cargo, and from phone/: cargo check --locked -p octosense-home --features mobile-apps.
  • End to end in a running desktop shell with deepseek-v4-flash (1 Oct 2026): the system agent asked Maps' agent, which called maps.notify; the card and toast showed. YouTube, never allowed: agents_ask stayed open over 40 s while the sheet waited (no 30 s timeout), and after Allow the system agent sent YouTube the request in the same turn (agents.ask for os.youtube answered: allowed → starts os.youtube's turn → glance: os.youtube published hello.card).
  • Unverified: News's, Photos's and Camera's notices end to end on this exact head (same code path as Maps and YouTube); Camera ships only on the phone and was not run there.
  • Local CI: see the comment tools/ci-local-merge.sh adds.

🤖 Generated with Claude Code

ymote and others added 3 commits October 2, 2026 00:19
Photos, Maps, YouTube and Camera get the agent Mail and Calendar have
(manifest `agent`: read-only profile, `ask_user_question`, a tool-calling
model) and the `glance` capability, with one tool in their own namespace:
`<namespace>.notify {title, body, card_id?, priority?}`. News keeps
`news.list` and `news.read` and gains `news.notify`. The system agent
reaches each as the octos peer `card.<app id>`.

A notice is one fixed L0 card for every app (crates/shell/resources/
glance/notice.card, moved from Mail's service), with the app's icon and
manifest name put in by the shell, the time, and the agent's title and
text; it opens the app and posts a notification, published as the app
only when its manifest is granted `glance` (glance::publish_for). Mail's
and News's services hand `notify` to the shell (`on_notify`); every system
app no service of its own answers gets the shell's NoticeService
(glance_notice.rs), registered after the shell's own services.

AI providers gets no agent yet: App Hub takes a tool namespace only as
[a-z0-9_] (octos a tool name's segments as [a-z][a-z0-9_]), so
`ai-providers.notify` and with it the agent block are refused; a test
says so and fails when App Hub admits one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The system agent asked for a new app's agent (agents.ask raised the
first-use sheet), got "not yet allowed, wait for them" at once, and ended
its turn; when the person allowed it, nothing carried the request on, so
Photos and News were allowed but never asked anything (seen live).

The system chat now holds the call, acknowledged as awaiting confirmation,
until the person answered and the agent's peer started; then it answers
with the peer slug and "send the request now, in this turn"
(`agents::ask_settled`). Denied: the agent is off, say so. A call still
unanswered after two minutes says the person has not answered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Held for the person's answer, agents.ask still failed after 30 s in the
live run ("the app did not answer within 30000 ms"): the kernel gives a
`read` host tool 30 s and accepts "awaiting confirmation" only for a gated
call. Declared as the kernel expects a call the host's own sheet confirms
(`risk: act`, `outward`, `confirm: app`), it is held as long as an approval
(an hour by default); the shell answers within ten minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ymote
ymote force-pushed the feat/system-app-agents branch from 6189c61 to f6973b1 Compare October 2, 2026 07:19
@ymote

ymote commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

Local CI passed on f6973b1 (tools/ci-local.sh --only desktop,phone,apps --linux-host, 6m06s, Darwin arm64; the ubuntu jobs on the Linux build host, Linux x86_64).

GitHub would run for this PR: desktop.yml, phone.yml, apps.yml. Merged on this local pass (macOS runner queue); GitHub CI runs on the merge commit on main.

Job Step Result Time
ci-local / drift The local mapping fits the workflows PASS -
desktop.yml / desktop Prepare the pinned framework sources PASS 0s
desktop.yml / desktop Compile the desktop with the shared runtime PASS 57s
desktop.yml / desktop One copy of every shell source PASS -
desktop.yml / desktop Desktop tools and scripts PASS 8s
desktop.yml / desktop One Makepad, App Hub, octos and Rinx in the locked graph PASS 1s
desktop.yml / desktop The native apps' generated places match native-apps.json PASS 0s
phone.yml / home Prepare pinned sources and the reviewed runtime patch PASS 0s
phone.yml / home Compile Home and its bundled modules PASS 1m03s
phone.yml / home Verify the single runtime graph PASS 1s
phone.yml / home The native apps' generated places match native-apps.json PASS 0s
phone.yml / home The pinned octos revision PASS -
phone.yml / home Build octos (unless cached) PASS -
phone.yml / home Build Home, App Hub admission and runtime policy tests PASS 23s
phone.yml / home Test Home, App Hub admission and runtime policy PASS 2m29s
phone.yml / home Two-lane scenario (real kernel, scripted model) PASS 27s
apps.yml / services (linux) python3 tools/setup.py PASS 0s
apps.yml / services (linux) Kernel service PASS 11s
apps.yml / services (linux) App peers PASS 26s
apps.yml / services (linux) AI providers config PASS 4s
apps.yml / services (linux) L0 in-card chat (sys.chat, host side) PASS 13s
apps.yml / services (linux) System toolbox (workflow templates) PASS 1m30s
apps.yml / kernel-security (linux) python3 tools/setup.py PASS 0s
apps.yml / kernel-security (linux) The pinned octos revision PASS -
apps.yml / kernel-security (linux) Build octos (unless cached) PASS -
apps.yml / kernel-security (linux) Real-kernel tests PASS 33s
apps.yml / apps python3 tools/setup.py PASS 0s
apps.yml / apps Host services (Mail, AI providers, News) PASS 19s
apps.yml / apps Shell AI services (crates/ai-host) PASS 6s
apps.yml / apps AppCard runtime setup safeguards PASS 0s
apps.yml / apps AppCard clippy (own crates; shared runtime compiles) PASS 1s
apps.yml / apps AppCard transport and store PASS 5s
apps.yml / apps One Makepad, App Hub, octos and Rinx in the locked graph PASS 2s
linux-host / sandbox (linux) python3 tools/setup.py PASS 0s
linux-host / sandbox (linux) Process sandbox on Linux (Landlock, seccomp) PASS 1m22s

Notes:

  • GitHub runs Python 3.12; this run used Python 3.9.6
  • GitHub runs Python 3.12; the Linux host used Python 3.14.4

@ymote
ymote merged commit 4f73ab3 into main Oct 2, 2026
5 checks passed
ymote added a commit that referenced this pull request Oct 2, 2026
… no chat in agents' cards)

The headless instrument run of the desktop shell showed where #269's README
was wrong, and #273 and #274 have since changed the same ground:

- Notifications (#273): a new card opens the glance panel unless a card
  window is up, and a notify card always posts a toast that opens it in its
  card window; while the panel is open, toasts stack left of it. Each card
  has a dismiss button, the panel a close button. Phone: a shade
  notification.
- Notice cards (#274): every <app>.notify fills the shell's one notice card
  (crates/shell/resources/glance/notice.card, glance_notice.rs); Mail and
  News hand notify to the shell, Photos, Maps, YouTube and Camera are
  answered by its notice service. The app-agent table gains them.
- No agent-published card has an in-card chat: the notice card and
  Calendar's event and agenda cards declare no sys.chat, so the card flow
  ends at the blackboard (steps 12-14 dropped from the sequence and its
  drawing; step 8 is "toast and glance panel (desktop), shade notification
  (phone)"). The only shipped card with a chat is the
  OCTOSENSE_GLANCE_DEMO=mail demo card, with canned replies. For the system
  apps the way in is "Ask <app>".

English and Chinese, root and apps READMEs together.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
guofoo added a commit that referenced this pull request Oct 2, 2026
main gave every system app its own agent for its notices (#274,
0212ff7). With this branch's `model` for Memories on top, two tests
written on either side no longer held:

- photos_bundle_is_admitted_by_the_shared_app_contract asserted that
  Photos has no agent; it now checks that the agent stays read-only.
  Memories are still one-shot model.complete calls.
- photos_maps_youtube_and_camera_offer_notify_from_their_bundles
  expected Photos' grants to be storage and glance; they are now
  storage, model and glance.
guofoo added a commit that referenced this pull request Oct 3, 2026
main gave every system app its own agent for its notices (#274,
0212ff7). With this branch's `model` for Memories on top, two tests
written on either side no longer held:

- photos_bundle_is_admitted_by_the_shared_app_contract asserted that
  Photos has no agent; it now checks that the agent stays read-only.
  Memories are still one-shot model.complete calls.
- photos_maps_youtube_and_camera_offer_notify_from_their_bundles
  expected Photos' grants to be storage and glance; they are now
  storage, model and glance.
guofoo added a commit that referenced this pull request Oct 3, 2026
main gave every system app its own agent for its notices (#274,
0212ff7). With this branch's `model` for Memories on top, two tests
written on either side no longer held:

- photos_bundle_is_admitted_by_the_shared_app_contract asserted that
  Photos has no agent; it now checks that the agent stays read-only.
  Memories are still one-shot model.complete calls.
- photos_maps_youtube_and_camera_offer_notify_from_their_bundles
  expected Photos' grants to be storage and glance; they are now
  storage, model and glance.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant