Files
tutti/docs/architecture/tutti-agent-readiness-bootstrap.md
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

9.5 KiB

Tutti Agent Readiness Bootstrap

Status: current implemented architecture

Purpose

Tutti Agent is a first-party provider that the desktop prepares before the user starts a conversation. Readiness spans three separate concerns:

  1. the tutti-agent CLI and app-server adapter are installed;
  2. the desktop Tutti account is signed in;
  3. a Tutti LLM token bundle is written to the provider auth home.

The daemon owns provider discovery, installation, probing, and auth bootstrap. The desktop owns the best-effort proactive install trigger and account login UI. AgentGUI consumes provider readiness but does not install binaries or own Tutti account credentials.

Provider Registration

packages/agent/daemon/providerregistry/providers.go registers tutti-agent with:

  • binary: tutti-agent;
  • adapter command: tutti-agent app-server;
  • minimum CLI version: the registry's TuttiAgentMinVersion;
  • tested install version: the registry's TuttiAgentRecommendedVersion;
  • auth marker: ~/.tutti-agent/auth.json;
  • installer: registry kind InstallerKindManagedNPM (mapped to agentstatus InstallerKindManagedNPMPackage) for @tutti-os/tutti-agent, including optional dependencies.

Provider status is the source of truth for readiness. A successful npm command is not enough: after installation, the daemon resolves the binary again and probes the provider adapter.

Managed NPM Installation

The managed installer places the package in a global prefix searched by the daemon binary resolver. It also repairs an existing npm-owned installation in place when the launcher or a platform package is broken.

New installs and minimum-version repairs install the descriptor's exact tested RecommendedVersion. MinVersion remains the compatibility floor: an existing runtime at or above it is reused without contacting npm. Keeping these values separate makes installation reproducible and permits an explicit downgrade during rollback. The effective command has this shape:

npm install -g --prefix <managed-or-existing-prefix> \
  @tutti-os/tutti-agent@<recommended-version> --include=optional

--include=optional is required because the CLI depends on platform-specific optional packages. The installer verifies the resulting launcher instead of trusting npm's exit status.

Registry selection follows the shared agent npm registry policy:

  1. TUTTI_AGENT_NPM_REGISTRY, when set, pins one registry with no fallback;
  2. otherwise the installer ranks and retries the configured official and mirror registries for the exact package being installed.

The shared packages/agent/daemon/managednpm policy ranks registries in the runtime's own network. A registry is eligible only when it contains the exact aggregate version and the matching optional platform package. A fast but partially synchronized mirror is ranked behind complete sources. Installation still verifies the binary, native payload, and app-server rather than trusting metadata or npm's exit status.

Desktop Proactive Install

registerWorkspaceAgentServices starts startManagedAgentInstallBootstraps once the desktop provider-status service is available. The bootstrap:

  1. loads only the tutti-agent provider status;
  2. treats a missing CLI and a CLI below TuttiAgentMinVersion as installable not_installed states;
  3. stops when the provider is already ready, is not not_installed, has no install action, or already has an install action pending;
  4. runs the normal provider install action;
  5. refreshes provider status after the action.

This path is best-effort and non-modal. It never auto-installs third-party providers and it reuses the same daemon action exposed by manual setup UI.

Concurrent starts are coalesced. At most one install attempt is made per desktop session. A failed automatic attempt is recorded under tutti.agentBootstrap.tutti-agent in renderer local storage and suppresses another automatic attempt for six hours. Manual retry remains available. A successful probe clears the stored failure.

Account And Provider Auth

Desktop account auth and provider auth are related but distinct:

  • IAccountService.startLogin() establishes the desktop Tutti account session;
  • the daemon exchanges that session for a tutti_llm token bundle;
  • tutti-agent login --with-tutti-llm-tokens writes the provider auth marker.

Before launching the login command, the daemon creates the canonical provider auth home when it is missing, then sets TUTTI_AGENT_HOME to that existing directory and clears an inherited CODEX_HOME. This ordering is required because Tutti Agent accepts an absent default home but requires an explicitly configured home to exist before configuration loading. Auth-home creation logs only the structured action and reason; login failures may include bounded CLI diagnostics after access and refresh tokens are redacted.

The daemon wires account lifecycle callbacks at startup:

account login completed
  -> BootstrapTuttiAgentUserAuth
  -> issue Tutti LLM token bundle
  -> tutti-agent login --with-tutti-llm-tokens
  -> ~/.tutti-agent/auth.json

account logout completed
  -> remove ~/.tutti-agent/auth.json synchronously
  -> revoke the removed LLM refresh token in the background

The host-neutral ordering and compensation rules live in packages/agent/daemon/tuttiagentauth; the Tutti daemon supplies the Account, credential-file, and local CLI adapters. Another host may supply VM-backed adapters without importing Tutti product paths or account-session storage. One reconciler instance serializes mutations of one canonical credential file. Hosts must run local cleanup on logout/account switch before reconciling the next account; this does not require a user ID in the credential path.

Reconciliation only establishes usable credential material. It does not prove that the provider accepts the credential and must not be treated as an authenticated or ready product state. Every host must run a provider probe after reconciliation and publish readiness from that authoritative probe.

The same auth bootstrap runs once when the daemon starts and before each Tutti Agent runtime preparation. These fallback entry points cover a login completed before callback wiring, a transient token failure, or a stale provider auth home. A missing, unreadable, or malformed host account file is only an observation failure: preparation retains existing Tutti Agent auth. A rejected token issue also retains existing provider auth. Reconciliation and explicit logout serialize with Tutti Agent refresh through the shared auth.json.refresh.lock; if token issue, validation, provider login, or verification fails, the daemon safely restores the previous auth bytes. Both implementations resolve a symlinked auth.json to its final target before choosing the sibling lock path, so restoration does not replace the symlink. The Go flock and Rust fs2 libraries use the same OS advisory file-lock primitive on a local filesystem; this coordination is not a distributed lock. Only the completed account logout callback authorizes local deletion and background token revocation.

TUTTI_ACCOUNT_BASE_URL overrides the account service used for token issue and revoke. TUTTI_AGENT_LLM_APP_ID overrides the LLM application id for controlled development and test environments.

Desktop Login Routing

When tutti-agent is selected and needs login, the desktop routes both setup actions and conversation auth-failure actions to IAccountService.startLogin(). Other providers continue through their own provider login action.

This routing stays in apps/desktop; shared AgentGUI code must not depend on the desktop account implementation. Account state changes trigger a provider-status refresh so setup UI can move between not_installed, auth_required, and ready without owning the auth workflow.

Invariants

  • Rendering an AgentGUI item never installs a provider.
  • Only tutti-agent uses proactive installation.
  • Installation completion is determined by a fresh provider probe.
  • Missing, unknown, or below-floor versions install the exact recommended version; compatible versions do not contact a registry.
  • Registry ranking happens where npm will run and rejects incomplete platform packages before comparing speed.
  • A Tutti Agent below TuttiAgentMinVersion is not ready and is repaired by the same proactive install path as a missing CLI.
  • Desktop account credentials and Tutti LLM tokens never pass through renderer component state.
  • Only a completed account logout removes the local provider auth marker, and it does so before the renderer observes the completed logout.
  • User-visible setup and login copy goes through desktop i18n.

Validation

The durable test surface covers:

  • provider registry and managed-installer configuration;
  • registry override and fallback behavior;
  • managed prefix selection, optional dependencies, repair, and post-install probing;
  • proactive install gating, coalescing, success refresh, and failure backoff;
  • account token issue, provider login, safe auth restoration after failed reconciliation, shared refresh-lock serialization, and explicit logout cleanup and revocation;
  • desktop routing of Tutti Agent login actions to the account service.
  • canonical auth-home preparation before an explicitly scoped login command, including Windows and POSIX path handling and token-redacted diagnostics.

Related documents: