Skip to content

toolbox-peers: offer the system toolbox to app agents (ADR 0002 §6, ADR 0004 §12, behind a feature) - #151

Merged
ymote merged 3 commits into
mainfrom
feat/toolbox-peers-v2
Sep 29, 2026
Merged

ymote merged 3 commits into
mainfrom
feat/toolbox-peers-v2

Conversation

@ymote

@ymote ymote commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

ADR 0002 §6 / ADR 0004 §12: the system toolbox offered to app agents as host-routed tools, on top of octos#2567's shell side from #145. This supersedes #108, which was written before octos#2567 was final and conflicts with main. This PR re-ports #108's toolbox parts onto main instead of rebasing it. Everything is behind the toolbox-peers feature, which is off by default (shell, desktop, phone and octosense-ai-host).

What changed vs #108

Overlaps G3 (home-96's feat/adr0004-g3-app-tools)

These are small seams in crates/shell/src/host_tools/, kept separable so G3 can adopt or replace them:

  • Catalog::set_grants(caller, owner, tools) replaces a caller's grants of one owner's tools. Main's grant(caller, tool) is only additive.
  • Catalog::offered(app, dev_all, consented) is declarations without the toolbox owner's tools until consent.
  • relay::TOOLBOX and host_tools::toolbox::{init, set_grant, grant_module, grant_manifest}. grant_manifest has no caller yet: App Hub install or tools.json loading (G3) is where a script app's grant comes from.
  • This PR computes no generic_tools; that is G3's job.

Tests

Scripted kernel, via main's broker (crates/ai-host/tests/toolbox_peers.rs, 8 tests). A ToolHost stands in for the relay. The tests cover:

  • a peer is registered exactly its declared+granted toolbox tools: every grant combination, declared-not-granted, granted-not-declared, the intersection, and module grants; each tool marked app: "toolbox";
  • no toolbox tool is offered or run before consent, and it is offered at the next registration after consent;
  • the os.*-only manifest rule and scope refusals;
  • workflow.run/fork/search/web_read executed by the toolbox, with results under .host;
  • a forged deep_crawl, refused by the relay and by the executor itself;
  • cancel: a cancelled call is stopped and never answered;
  • template model calls through ModelHost and the app's budget.

Shell relay (crates/shell/src/host_tools/tests.rs, +2 tests, with and without the feature):

  • offered exactly the granted toolbox tools, only after consent, grants replaced, no developer-mode blanket;
  • no toolbox call runs before consent or without a grant; routed to the toolbox executor once consented; cancel reaches it.

Toolbox: #108's unit tests, the crawl test (tests/peer.rs) and the catalog test ("everything granted is offered, nothing held back").

Real kernel, octos acffad3b (the pin), built locally with cargo build --release -p octos-cli --bin octos --no-default-features --features api:

  • crates/ai-host/tests/toolbox_real_kernel.rs (new) passes.
    • Before consent, a real turn is offered no toolbox tool and none runs.
    • After consent, the real peer's offered tools include exactly toolbox_search, toolbox_web_read, workflow_fork, workflow_run among the toolbox's.
    • Real turns call toolbox_search and workflow_run; the result lands in .host.
    • toolbox_deep_crawl is not offered without crawl.
    • The peer keeps its kernel tools, because registration is additive.
  • crates/app-peers/tests/real_kernel.rs: 8/8 pass.

Commands run locally:

  • cargo test --locked for:
    • toolbox (plain, live, octos-engine);
    • ai-host (plain, octos-core,llm, toolbox-peers);
    • app-peers (plain, octos-core,ws);
    • llm-service and mail-service.
  • From phone/:
    • cargo test --locked --features mobile-apps -p octosense-shell: 509 pass;
    • --features mobile-apps,toolbox-peers ... host_tools: 11 pass;
    • cargo check --locked -p octosense-home --features mobile-apps (and +toolbox-peers).
  • Clippy -D warnings:
    • ai-host (toolbox-peers, octos-core,llm);
    • app-peers (octos-core,ws);
    • toolbox (plain, live,octos-engine);
    • no new shell warnings.
  • cargo fmt -p octosense-toolbox --check and python3 tools/native_apps.py --check.

CI:

  • apps.yml now tests and lints ai-host with toolbox-peers.
  • phone.yml runs the shell's host_tools tests with toolbox-peers.
  • The real-kernel toolbox test is not in kernel-security. That Ubuntu job does not build Makepad, which ai-host links. The test skips without OCTOS_APP_PEERS_TEST_KERNEL.

Not done / unverified

  • octos deep_research "when declared and granted" is not testable here.
    • It is a kernel generic tool (a pipeline or skill), and the octos#2567 peer roster at this pin does not include it: the api build and the test profile offer no deep_research or deep_search.
    • Which generic tools a peer gets is its generic_tools list, which is G3's. generic_tools can only narrow the profile's roster, never widen it.
    • This PR only removes OctoSense's own exclusion.
  • No shell run with the feature on: no hidden-window run and no device. The live octos engine was not exercised through a peer; only fixtures were.
  • Script apps' toolbox grants are not wired. They need App Hub mobile: native-feeling frame pacing on the phone #26 on the shells' pin and G3's install-time declare/grant.

No pin moved, and no Rinx code was touched.

🤖 Generated with Claude Code

…DR 0004 §12)

Re-port of #108 onto main's octos#2567 shell side (#145), behind the
`toolbox-peers` feature (off by default):

- the toolbox is one more owning app (`toolbox`) in the shell's host-tool
  relay: its tools are declared once in the catalog (`app: "toolbox"`,
  shareable), each app is granted exactly what it declares AND the person
  granted, and `ToolboxExecutor` (crates/ai-host) runs the calls the relay
  routes to it; main's broker registers them after every prepare and
  reconnect. #108's own registration and routing are not ported;
- no hard-coded exclusions: #108's "never offer octos deep_research"
  (its empty generic_tools) is gone;
- the #120 first-use consent gates the toolbox: nothing offered
  (Catalog::offered) and nothing run (the relay's consent_pending) before
  the person allowed the app's agent;
- ported from #108: crates/toolbox `peer` (plus a shared `catalog`),
  read_links/narrow_crawl, ModelHostClient, toolbox_folder, the 256 KiB host
  model input, the mock model's CALL_TOOL rule; tests against a scripted
  kernel through main's broker, the relay, and a real octos kernel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	crates/shell/src/host_tools/tests.rs
# Conflicts:
#	crates/shell/src/host_tools/relay.rs
@ymote
ymote merged commit 8855326 into main Sep 29, 2026
chrislearn pushed a commit to chrislearn/OctoSense that referenced this pull request Oct 8, 2026
…her_host

Port the dossier template work from local/research-peer (3cdb777,
2bfbf02, f966c1e) onto current main:

- templates/dossier: the template (long-report research: questions with
  per-question sub-queries over categories, pooled round-robin reads,
  in-flight reuse across questions, per-question digests) with its two
  blessed fixtures, plus its library.lock.json entry (digest recomputed;
  other templates stay at their main versions);
- mod.research search categories: SearchQuery.category, narrowed through
  scope::narrow_search_in (grant-checked, default news), wired through
  the octos engine backend, the peer's toolbox.search tool (adapted to
  main's OctoSense-org#151 peer.rs catalog code) and the module spec;
- resolved_url / publisher_host: the backend's final read URL recorded
  as resolved_url (null while on an aggregator), the publisher's host in
  provenance and every template's sources[], runner provenance matching
  on resolved_url too;
- tests updated for the new fields (final_url in test backends,
  provenance match on resolved_url, dossier in the tool-surface list).

Left out of this port: examples/toolbox_run.rs, the toolbox_run example
Cargo.toml entry, the version bumps and fixture regenerations for the
other templates (briefing, compare, market-brief, news-digest,
topic-brief, weather-plan); the new fields are additive and those
templates keep their main fixture output. peer.rs keeps main's OctoSense-org#151
shape; only the category plumbing was added to it.
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