Skip to content

Provider agent

Thibaut Rey edited this page Sep 7, 2026 · 1 revision

Embedded provider agent

The public extension contract is documented in runtimebackend/CONTRIBUTING.md, RUNTIME_PROFILES.md and RUNTIME_BENCHMARKS.md.

The provider agent is a bounded Go component shipped with MultiVibe Core. Core supervises the packaged binary when PROVIDER_AGENT_ENABLED=true; no separate installer is supported.

The Core container build compiles this module for its target architecture and installs the static executable at /opt/multivibe/bin/multivibe-provider-agent. The agent is therefore present in every supported Core image without a runtime download, while remaining disabled by default until the operator explicitly enables it.

This foundation exposes loopback health and a consent-bounded manifest containing only explicitly selected model identifiers. It enforces the ordered lifecycle detected -> selected -> submitted -> approved -> online -> compensation-eligible, with independent suspension and terminal revocation. It never scans LAN addresses, mDNS, processes, files, command lines, environment variables, or arbitrary ports.

An empty selection remains detected; only a non-empty, explicit selection is reported as selected. Selected identifiers are unique, sorted and bounded to 100 entries, and URL-, IP- or filesystem-like values are rejected before they can enter the consent manifest.

Core persists that explicit selection locally in a schema-versioned mode-0600 JSON document. Updates use an atomic replacement and an expected revision, so a stale dashboard cannot silently overwrite a newer choice. Selection, runtime, enrollment and relay-shadow controls are available only through authenticated loopback routes that Core exposes through its existing authenticated admin API. The process-local bearer is generated by Core for every child launch, is never accepted from the parent environment, and is not returned by manifests, responses or logs. In supervised mode, the child binds a literal loopback port chosen by the operating system before announcing the exact address to Core over a dedicated inherited pipe. Core strictly validates and closes that bootstrap frame before making any bearer-authenticated request; it never probes or falls back to the fixed standalone port.

GET /v1/adapters exposes the bounded runtime contract embedded in the agent: protocol, health and catalog paths, capabilities, authentication, measurement dimensions, limits and reviewed automatic candidates. The registry covers the full Core runtime list and keeps every adapter manual except the reviewed literal IPv4/IPv6 Ollama, LM Studio, OMLX, MTPLX and Exo loopback candidates. Ollama uses only its official default port 11434 and documented OpenAI-compatible /v1/models surface; the review source is the official Ollama OpenAI compatibility reference. OMLX and MTPLX share port 8000 and are accepted only when every returned model carries the matching owned_by signature. Exo uses its documented loopback port 52415 and /models catalog path, with the same owned_by: "exo" signature requirement. The standalone agent preserves the documented literal 127.0.0.1 or ::1 port 1460. The embedded supervisor instead forces port 0 on one of those literal loopback addresses and learns the resulting non-zero port only through the private bootstrap pipe.

GET /v1/detected-models performs an on-demand local inventory through those reviewed candidates and explicitly configured manual endpoints only. Manual endpoints must use literal 127.0.0.1 or ::1, HTTP and an explicit port; userinfo, paths, queries, fragments, LAN names and public addresses are rejected. Catalog calls are redirect-free, deadline- and size-bounded, and the response contains only the adapter ID and validated model identifiers. Unavailable candidates expose no local error or network details. The inventory remains local and does not select, enroll, advertise or upload a model.

Core manages manual endpoints through authenticated GET /v1/runtime-endpoints and PUT /v1/runtime-endpoints. The state is a separate schema-versioned mode-0600 document using atomic revisioned replacement. Optional local runtime bearers are persisted only in that file, are sent only to the selected loopback catalog endpoint, and are never present in API responses or logs. Omitting bearer_token preserves the secret for an unchanged adapter and endpoint; sending an explicit empty value removes it.

Live provider activation, dedicated-tailnet tsnet transport, mutually authenticated HTTP/2/WebSocket fallback, signed metering envelopes, and remote workload handling remain fail-closed until their credentials, protocol and Cloud gates are implemented and verified. The current binary does not advertise capacity, accept community work, become routable or create compensation eligibility.

The agent can execute the existing Cloud enrollment shadow protocol after an authenticated Core administrator supplies the one-time mve_… grant and the exact consent manifest. POST /v1/cloud-shadow/enroll accepts the exact 29 runtime families in the embedded adapter registry, requires every submitted model to exactly match the local explicit selection, derives a stable client-node UUID from the public device key, and sends the challenge only to https://auth.multivibe.cloud (literal loopback HTTP is accepted for tests). It signs the returned challenge with the same local Ed25519 identity under the multivibe-provider-control-shadow-v1 domain. Redirects, arbitrary origins, unknown fields, oversized bodies, altered challenges and commercial flags fail closed.

Only the submitted node view, runtime family, declared concurrency and non-commercial locks are stored in a separate atomic mode-0600 file. The enrollment grant, proof, private key and response bodies are never persisted or returned. After submission the local selection is frozen, the manifest advances to submitted, and a second enrollment is rejected locally. Approval, availability, transport, routing and compensation still require later explicit protocol states; submission cannot skip them.

The agent does implement the transport-independent Cloud relay-shadow session-open envelope. A local Ed25519 identity is stored in an atomic mode-0600 document together with its monotonic sequence. The local manifest contains only the public SPKI and its derived key ID. Authenticated POST /v1/relay-shadow/session-open generates its own 32-byte nonce, uses a 30-second canonical UTC window and signs the exact multivibe-provider-relay-shadow-v1 domain. The payload hardcodes shadowOnly=true and every customer-traffic, routing and compensation flag to false. It contains no prompt, output, media, usage or price and does not create a network session by itself.

Core starts the embedded process with a closed environment allowlist containing only its loopback URL, the agent loopback listen address and the optional initial selected-model seed. Core separately supplies the explicit selection and runtime state paths, the device-identity path and its newly generated control bearer. Parent-provided state paths or control tokens, provider credentials, Stripe or OAuth secrets, control-plane tokens, API keys and unrelated variables are never inherited by the agent.

The selection file and the detected inventory remain on the machine. This preview corridor does not submit either one to Cloud, enroll the node, publish capacity, enable routing, or create compensation eligibility.

Agent readiness calls Core's credential-free loopback /health endpoint. It never receives or forwards the proxy API key merely to prove that the packaged Core process is reachable.

Capacity consent and model planning foundation

capacity_policy.go defines the fail-closed capacity contract that a future host application can present to the machine owner. There are no defaults: the owner must explicitly choose all of the following values before the policy is accepted:

  • maximum GPU utilization percentage (1 through 100);
  • maximum percentage of GPU-addressable VRAM (1 through 100);
  • maximum bytes occupied in the managed model store;
  • the managed model store's clean, absolute, non-root path;
  • maximum model download bytes in a rolling 24-hour window;
  • a positive minimum active-model residency;
  • maximum model-set changes in a rolling 24-hour window; and
  • a positive amount of physical disk space that must remain free.

An explicit zero download limit disables new model downloads. An explicit zero model-change limit freezes the current active set. Those values use pointer fields in the operator-facing document so they cannot be confused with an omitted choice. Invalid percentages, missing fields, zero safety values, relative or unclean paths, filesystem roots and overflowing durations are rejected rather than normalized.

model_planner.go is a dependency-free, deterministic and declarative planning slice. Its caller supplies a capacity snapshot for exactly the configured storage path, a bounded candidate catalog, the provider agent's managed model state and a fresh authoritative demand snapshot. The planner never searches a home directory, mounted volume, process table, runtime, network endpoint or any other filesystem location. It does not call stat, walk directories, infer installed models, download or delete model files, or start and stop runtimes. Its output is only a proposed selected-model list plus proposed download sizes.

For each demanded model, the planner requires the candidate context window to cover the requested context and ranks utility as demand units × required context tokens. Ties prefer larger requested contexts, existing active and installed models, smaller artifacts and finally lexical model ID. It greedily admits candidates only while the sum of their GPU utilization reservations and VRAM fits the owner's percentages. A not-yet-installed candidate must also fit the lesser of the remaining managed-store allowance and physical free space after the owner's reserve, as well as the remaining rolling download budget. The existing active set itself must fit the policy or planning fails closed.

Active models inside the minimum residency window remain selected even if demand changes. Successful active-set transitions are counted over the rolling 24-hour history supplied by managed state; when the owner's change limit is exhausted the plan preserves the current set and proposes no downloads. This slice never proposes deletion, so existing managed artifacts are not evicted to manufacture room for a more popular model.

Signed demand and the managed Ollama runtime

The managed runtime is reached through the compiled, process-local backend contract documented in runtimebackend/CONTRIBUTING.md. That contract defines explicit primary/fallback selection, immutable launch and provenance allowlists, normalized metrics and lifecycle capabilities. The managed Ollama adapter can execute signed Cloud jobs through the outbound relay only while the owner has enabled allow_cloud_workloads; runtime registration alone never grants customer traffic.

POST /v1/cloud-shadow/demand accepts only the bounded multivibe-provider-demand-envelope-v1 contract. The agent rejects duplicate JSON keys and unknown fields, canonicalizes the signed payload, verifies an Ed25519 signature against the explicitly configured trust map, and fences every accepted generation and digest. Issued, observed and expiry times, privacy policy, runtime version, catalog artifact digest and model-license assessment must all match the local policy and approved catalog before a plan can be persisted. The RFC interoperability key in the tests is not a production trust root and is never a runtime default.

Managed Ollama configuration is all-or-nothing. It requires the signed-demand service, a persistent capacity policy, the packaged model catalog and dependency manifest, a private managed root, the bundled runtime root and separate planner history. On Linux and Windows, the runtime defaults to the first compatible physical GPU reported by the bounded NVIDIA probe; both that pin and the literal-loopback Ollama port can be changed only through validated configuration. Runtime, HOME, XDG, temporary files, logs and the managed model inventory stay below the private root. The packaged Ollama tree is verified and adopted atomically; the credential-free HTTPS download is only a bounded, SHA-256-pinned fallback.

On macOS arm64 and amd64, the host reads total physical memory only through the fixed /usr/sbin/sysctl -n hw.memsize probe with a short timeout and strict numeric bounds. The planner exposes at most 50% of the physical total as compute capacity, leaving the other half to macOS and CPU pressure; the operator's configured gpu_vram_percent limit is applied after this conservative cap. A missing, malformed, zero or implausibly large probe result disables managed compute capacity instead of guessing.

Authenticated lifecycle routes expose status plus explicit install, start, stop and reconcile actions. Every expanding action carries the current local policy revision; reconciliation additionally carries the exact signed plan generation and envelope digest. The controller serializes operations, cancels work when either fence changes, persists model residency and rolling download and model-change histories, and stops immediately when pause or Cloud workload consent is withdrawn. An expired plan also invalidates the active set and stops the managed runtime even when no further request arrives.

Reconciliation can only install catalog-pinned artifacts and mark a verified managed manifest active. The reconciliation path never receives a prompt or output. The separate community outbound worker polls Cloud only after signed enrollment, inventory admission and workload consent are current. Its local GET /v1/community-outbound/status route requires the provider control token and exposes counters and sanitized error categories only; it never exposes prompts, outputs, bearer tokens or device credentials. The announced commercial split is 85% to the host operator and a 15% MultiVibe service fee for eligible, cleared community-workload revenue, before applicable taxes, reserves, disputes and reversals; the separate 5% fee applies only to customer purchases or top-ups.

License

The provider agent, public runtime SDK, extension contracts, examples and documentation in this repository are part of MultiVibe Core and are licensed under Apache License 2.0. See NOTICE for attribution and notices.

That license does not grant rights to MultiVibe Cloud, MultiVibe trademarks, credentials or customer data. Model weights, packaged runtimes and other third-party dependencies remain subject to their own licenses and notices.


Migrated from provider-agent/README.md on 2026-09-07.

Clone this wiki locally