The approval link an OHO prints,
/oho/approve/:token, sits outside the company prefix. Executors,
cloud tasks, work items and the OHO pull loop are on
Cloud tasks and executors. Sandboxes are on
Sandboxes. Skill execution on an OHO is on Skills.
What it does
Connect an OHO machine. An OHO is a local orchestrator a company runs on its own machine. Runningoho connect --server <url> calls POST /api/oho/register, which creates an
OhoRegistration in status pending with a token that expires after 10 minutes. The CLI
prints a verification URL, /oho/approve/<token>, and polls
GET /api/oho/register/{token}/status. A signed-in user opens the URL and approves it with
approveOhoRegistration. Approval creates an OhoInstance in the active company and issues a
device token and a refresh token. The next status poll hands both to the OHO once and clears
them from the server. A new registration from the same machine expires any older pending one.
Registration statuses are pending, approved, rejected and expired.
Presence. The OHO then holds a WebSocket to /api/oho/ws, authenticated by its device
token in the handshake headers. Connecting marks the instance online. A background tracker
runs every 60 s and marks an instance offline when its last heartbeat is older than 90 s.
Instance statuses are pending, online, offline, degraded and revoked. Each instance’s
status is mirrored onto its backend row, so it shows up in the Environments gallery.
Token rotation. Device tokens rotate every 7 days while the OHO is connected, committed on
the OHO’s acknowledgement, and the old token works for a 5-minute grace period. An OHO can also refresh its
tokens with POST /api/oho/refresh and revoke itself with POST /api/oho/self-revoke, which
oho disconnect calls. rotateOhoCredentials asks for an immediate rotation; it refuses a
revoked or disconnected instance.
Revoke, rename, diagnose. revokeOhoInstance is permanent: it clears the tokens, sets the
instance and its backend to revoked, and closes the socket after sending instance.revoked. renameOhoInstance sets the
display name. Diagnostics runs testOhoConnectivity, requestOhoSync, testOhoEventFlow
(a test task’s lifecycle events), testOhoExecution (mocked, no model calls) and
testOhoEnvironment (builds an agent’s image and runs a trivial prompt), and lists the host’s
outstanding evictions (a table at the bottom of the tab, with Refresh): sandbox.destroy calls the server still owes it for sandboxes that
were moved away or force-deleted while it was unreachable (pendingEvictions), delivered when
the host reconnects and retried on heartbeats, up to five attempts.
What an OHO runs. An OHO reports its local agents, executors and runtimes when it connects
(OhoAgent rows, source local). assignAgentToOho pushes a cloud agent’s config to it
(source cloud) and removeAgentFromOho removes it. Task dispatch is on
Cloud tasks and executors.
Execution backends. Every place work can run is an ExecutionBackend in a BackendPool.
Providers are oho, server, gcp and aws; ownership is platform or tenant. Backend
statuses are pending, verifying, online, offline, degraded and revoked. The
Environments gallery (executionEnvironments) shows the company’s own backends plus the
platform backends it is entitled to, in three kinds of card:
- Olyros Cloud. All entitled platform
gcp/awspools merged into one card with the reserved idolyros-cloud. Its status is the best of the set, and its active count is the company’s own in-flight runs only. - Your cloud. One card per bring-your-own GCP backend, with its own lifecycle status.
- OHO. One card per connected OHO.
server worker are never shown. Each card shows
month-to-date execution hours. The detail page /execution/:backendId always has Overview,
Usage and Settings tabs. OHO cards add System Info, Recent Tasks and Diagnostics; Your cloud
adds Storage & Images and Diagnostics; Olyros Cloud adds Storage & Images. environmentRuns
and environmentSandboxes list the runs and sandboxes placed there.
Placement. The selector tries the agent’s “Runs on” pin (setAgentBackend), then the
company default (setCompanyDefaultBackend), then all attached backends, filtered by status,
capabilities and entitlement, least busy first. A pin or default to a backend the company is not
entitled to is refused when set, and a dispatch to one fails rather than falling back to an OHO.
Olyros Cloud switch. setOlyrosCloudEnabled turns Olyros-hosted placement on or off for
the company (olyros_cloud_enabled, default on). When it is off the Olyros Cloud card shows as
disabled and cloud work is refused with “Olyros Cloud is turned off for your company.”
olyrosCloudAccess returns whether the company is entitled, whether the switch is on, and
whether it may connect its own cloud.
Bring your own GCP project. connectByocGcpBackend(projectId, region, displayName) creates
a company-owned pool and a pending backend and returns a provisioning script for the customer
to run in their own project. verifyByocGcpBackend runs the verification ladder (full=false
is the quick check) and moves the backend to online on success. A failed first verify returns
it to pending; a failed re-verify of a live backend moves it to degraded. setByocGcpCaps
sets two courtesy caps, maximum concurrent runs and maximum run duration, enforced at dispatch;
the customer’s own GCP budget alert remains the real cost control. revokeByocGcpBackend is terminal and idempotent: placement stops at once,
in-flight runs are reaped, credentials and grants are removed, and the slot frees for a new
connect.
Runtime images (the Environment model). An environment is a named runtime of type
process or docker, with a Dockerfile (required for docker), build args, env vars,
secrets and a timeout_seconds. Agents reference one as default_environment_id and as
sandbox_environment_id, and cloud tasks carry an environment_id. Each change that alters a
field bumps version. Secrets are stored encrypted. Queries return their key names only, and
revealEnvironmentSecret returns one value and writes an audit row first.
duplicateEnvironment copies an environment, naming it <name>-copy, <name>-copy-2 and so on
when no name is given. deleteEnvironment is a soft delete (is_active false). The name stays
taken, and environments(includeDeleted: true) still lists it. The dockerfileWarnings field
flags ENTRYPOINT, CMD, USER and VOLUME lines, which the OHO overrides.
Cloud worker images. /environments/cloud-images lists the company’s built worker images
per repository (cloudWorkerImages), one group for the Olyros-hosted pool and one for a BYO
project. deleteCloudWorkerImage(backendId, digest) deletes an older image; the current one is
refused. Without an entitled online GCP backend the page reports the list as unavailable.
Who can use it
Role labels follow the roles table on Company settings.- Any company member can view everything here, approve or reject a registration, revoke, rename and diagnose an OHO, rotate its credentials, assign agents to it, set an agent’s “Runs on” pin, set the company default backend, and connect, verify, cap and revoke a BYO GCP backend. These operations check membership only.
- Editor or admin (
environment.manage) can create, update, duplicate and delete runtime images and reveal a secret. Create, update and duplicate need a company admin only in the Dockerfile case below. - Company admin (
environment.manage_dockerfile) is needed to set or change a Dockerfile when the company holds a GCP entitlement, because that Dockerfile is built on the platform. Without a GCP entitlement an editor may set it, since it builds on the company’s own OHO. - Editor or admin (
executor.manage) can delete a cloud worker image. - Company admin (
oho.manage) can allow an OHO to run skill code (setOhoSkillExecutionAllowed). Approval alone does not make an OHO a skill runner. - Company admin (
company.manage) can flip the Olyros Cloud switch. - Company admin (
oho.manage) can upgrade an OHO (upgradeOhoInstance), use Upgrade all and Force, and switch the company to the early-release channel. Every member sees versions, badges and upgrade history. ohoRegistrationByTokenhas no explicit gate: any authenticated user holding the token can read that registration. The OHO’s own endpoints use its tokens, not a user session.
/billing/:companyId, Olyros Cloud
tab), and turns on the company’s cloud-execution capability (cloud_execution_enabled, default
off). Connecting your own GCP project needs that capability and the server flag
byoc_gcp_enabled, which is off by default. Without it the BYO mutations answer “Bring-your-own
GCP execution is not available.” and the gallery shows the connect tile as “Coming soon”. Pools
are managed in the admin app under /execution/pools. The OHO release policy and the
minimum-version enforcement switch are platform-admin settings. No plan or tier gate exists beyond these.
How to configure it
Install OHO on a machine OHO (the Olyros Home Orchestrator) is a service a company runs on its own Linux machine (bare Ubuntu or WSL2) so that agent work runs there. It runs as an ordinary user, never as root, and keeps its configuration, database and logs under~/.olyros/. Agents run in Docker
containers, so Docker should be installed and the OHO user added to the docker group.
- Install the published package with the one-line installer, as the user that will run OHO:
It installs the latest release into a versioned layout that OHO can later upgrade by itself and puts the
ohocommand on the path. Prefixing theshwithOHO_VERSION=<x.y.z>pins a release. Installing withpip install olyros-ohooruv tool install olyros-ohoalso works for a try-out, but such an install cannot upgrade itself (see Upgrading an OHO below). - Create the configuration with
oho init, an interactive wizard that asks for the instance name, the number of parallel tasks, the Olyros server URL and the port of the local web UI, and writes~/.olyros/oho-config.yaml.oho config optionslists every setting. - Start it:
oho startruns in the foreground,oho start --backgroundas a daemon.oho stopstops it,oho statusshows the process, the version and the cloud connection. To run OHO as a system service that restarts on failure,oho service installwrites the systemd unit (--userfor a user unit). oho logs last --followfollows the most recent task log;oho logs listlists the logs.
/oho/connect)
- On the machine, run
oho connect --server <url>with your Olyros server URL, the command the page shows. This callsPOST /api/oho/register. OHO prints the approval URL and opens it in a browser when one is available (--no-browseronly prints it). - Open the approval URL (
/oho/approve/<token>) within 10 minutes while signed in to the company that should own it, and choose Approve:approveOhoRegistration. Reject callsrejectOhoRegistration. An expired or already-handled registration is refused. - OHO picks up its credentials on its next poll, stores them under
~/.olyros/and prints the company it joined. Restart OHO (oho stopthenoho start, or restart the service) to activate the connection;oho statusthen names the company. It appears as an OHO card under Orchestration > Environments and in the connected list on Connections. - To disconnect from the machine, run
oho disconnect: it clears the stored credentials and revokes the instance on the server. To disconnect from the server side, choose Revoke on Connections:revokeOhoInstance. Either way, connecting the machine again takes a newoho connectand a new approval.
/execution/:backendId)
- Rename it on the Settings tab:
renameOhoInstance. Run checks on the Diagnostics tab. - As a company admin, allow it to run skill code on the Settings tab or under Settings >
General (
/settings/general):setOhoSkillExecutionAllowed.
- Company default: Settings > General (
/settings/general), “Default “Runs on"":setCompanyDefaultBackend(backendId). Clear it with no backend. - Per agent: the agent’s “Runs on” field in the agent builder:
setAgentBackend. - Olyros Cloud on or off (company admin): the switch on the Olyros Cloud card under
Orchestration > Environments:
setOlyrosCloudEnabled(enabled).
/execution/connect/gcp)
- Enter the GCP project id, the region and an optional display name:
connectByocGcpBackend. The project id must be 6 to 30 characters, start with a lowercase letter, use lowercase letters, digits and hyphens, and not end with a hyphen. The region must look likeus-central1. A company may hold one verified BYO backend, and a project already claimed by another company is refused. - Run the returned provisioning script in your project.
- Verify:
verifyByocGcpBackend(backendId, full). A second verify while one is running is refused. Re-verify later from the card. - Optionally set caps on the card’s Settings tab:
setByocGcpCaps. Each value must be a positive integer, or empty to clear it. - To disconnect, use the type-the-name Revoke on the Settings tab:
revokeByocGcpBackend.
/environments)
- Choose New (
/environments/new) and fill the form:createEnvironment. The name is 1 to 100 characters of letters, digits, hyphens and underscores, unique among the company’s environments, deleted ones included. The description is under 500 characters.typeisprocessordocker;dockerneeds a Dockerfile under 100 KB. - Set
timeoutSecondsbetween 30 and 7200. Volumes are rejected, because host mounts belong to the execution host. - Add secrets as
KEY= value. Keys must match^[A-Z][A-Z0-9_]*$, appear once, and not repeat an env var name. Values cannot be empty. - Edit at
/environments/:environmentId/edit:updateEnvironment. The submitted secret list replaces the stored one; a key sent without a value keeps its old value. - Duplicate or delete from the list:
duplicateEnvironment,deleteEnvironment. - Reclaim old cloud images at
/environments/cloud-images:deleteCloudWorkerImage.
Upgrading an OHO
An OHO tells the client which version it runs, the platform tells it which version it should run, and a company admin can upgrade it from the client app with no shell or sudo on the machine. Release catalogue and policy (admin app). An hourly job reads the public package indexhttps://pkgs.olyrosstudios.com/simple/olyros-oho/ into the release catalogue (oho_releases:
version, wheel, sha256, release-notes link). Pre-releases and local +build versions are ignored,
and rows are never deleted. Publishing a release changes nothing for customers by itself. A
platform admin sets the release policy on the admin app’s OHO Releases page
(/oho-releases, Execution group) with three pointers, each a version in the catalogue:
The pointers must satisfy minimum ≤ current ≤ early; a version missing from the catalogue or a
wrong order is refused with a message. The page also lists the catalogue, the companies on the
early channel, and a Sync now button that reads the index immediately.
Early-release channel (Company Settings). Settings > General has an OHO early release
channel switch (
updateCompanySettings(ohoReleaseChannel:), stable or early, default
stable). On early, the company’s OHOs are offered the early release version when it is newer
than current. Olyros uses this to test a candidate on its own OHOs before promoting it to current.
Clearing the early pointer stops the offer; nothing is downgraded.
Badges. Each OHO gets offeredVersion, upgradeAvailable and upgradeRequired. The badge
(Upgrade required in red, else Update available) appears on the OHO card and table row in
Environments, in the OHO detail header, and on each instance on Connections. Its hover text names
the offered version and says “(early release)” on the early channel. An OHO running a dev build
compares on its public version; an unparseable version shows no badge.
Upgrade button. On the OHO’s Settings tab the Version row shows the installed and offered
version and an Upgrade button for holders of oho.manage (release notes are visible to platform
admins in the admin app only, because the notes live in a private repository). It is
enabled when all of these hold:
- the OHO is online;
- it advertises the
self_upgradecapability, which it does only when its readiness check passes; - a newer version is offered;
- no upgrade is already open for it.
upgradeOhoInstance(ohoInstanceId, targetVersion). The server checks the same conditions, that the
target is in the catalogue, and that it is not older than the installed version (a downgrade needs
allowDowngrade, which the client does not offer). It records an oho_upgrades row and sends the
OHO the version only. The Upgrade action on a Connections card opens this Settings tab.
Busy OHOs and force. The OHO refuses while it runs a task, a sandbox invocation or a skill.
The client then offers Force, a second confirmation where you type the OHO’s name. Once an
upgrade is accepted the OHO stops taking new work; new sandbox invocations and skill runs are
refused with “upgrading” until it restarts.
Progress and history. Below the Version row a stepper follows the upgrade: requested,
acknowledged, installing, verifying, switching, restarting, then succeeded, rolled back, failed or
timed out. It refreshes with the page’s 5-second poll. A failure or rollback shows the OHO’s
message and log tail. The history lists past upgrades with who asked, when, from and to, outcome
and duration (upgrades on the instance, newest first).
Upgrade all. The Environments gallery has an Upgrade all action with one confirmation that
lists each OHO and its target. The client upgrades the eligible OHOs one at a time, waits for each
to finish, and stops at the first failure. There is no server-side batch.
Upgrade required versus enforcement. “Upgrade required” is a badge only: by default an OHO
below the minimum still receives work. A platform admin can turn on minimum-version enforcement
(platform setting oho_enforce_minimum_version, default off, audited as
platform.oho_enforce_minimum_version.set). With it on, new sandbox runs and skill runs on an OHO below the minimum,
or reporting no parseable version, are refused with OHO <name> is on <version>, below the minimum <min>; upgrade it from Environments (“upgrade it on the host” when the version is
unknown). Cloud
tasks pulled by the OHO are not gated yet.
When an upgrade fails. The OHO installs the new version beside the old one and smoke-tests it
before switching, so a failed download or install leaves the running version untouched and is
reported as failed. After the switch it restarts in place and must reconnect and have its
capabilities acknowledged within 120 seconds. If it does not, or it crash-loops, it switches back
to the previous version automatically and reports rolled_back. Right before the switch it copies
its local database to oho.db.pre-<version> in its data directory (the newest two are kept). The
copy is never restored automatically; the rollback message names it. An upgrade with no answer
within 3 minutes, or no progress for 20 minutes, becomes timed_out (“check the host”).
Hosts that cannot upgrade themselves. An OHO installed the old way (uv tool install), a dev
checkout, or a host whose systemd unit does not run ~/.local/bin/oho with Restart=always or
on-failure does not advertise self_upgrade. Its Version row lists the readiness reasons the
OHO reports (for example “ExecStart points at /opt/oho/bin/oho …”) and a How to upgrade panel
with the two manual commands. The one-time move to the managed layout is
curl -LsSf https://pkgs.olyrosstudios.com/oho.sh | sh on the host, after which
oho self-upgrade --check shows the same readiness report.
Limits and defaults
What it emits
- Audit events:
oho.skill_exec_allowed.set,execution.olyros_cloud.enabledandexecution.olyros_cloud.disabled,backend.byoc.connect_initiated,backend.byoc.revoked,execution.entitlement.grantedandexecution.entitlement.revoked, and for runtime imagesenvironment.secret.created,environment.secret.updated,environment.secret.deletedandenvironment.secret.revealed. OHO upgrades addoho.upgrade.requested,oho.release_channel.setand, in the admin app,platform.oho_release_policy.setandplatform.oho_enforce_minimum_version.set. oho_upgradesrows: who asked, from and to version, status, message, log tail and finish time, kept as the upgrade history.- Status changes on OHO instances and backends (
online,offline,degraded,revoked), which the Environments gallery and the placement selector read. - Month-to-date execution hours per card, from the compute usage meter. A BYO card shows its own hours and they are never counted as billable Olyros Cloud time. See Billing and usage.
Known gaps
- The Connections page says a new OHO “will appear below as a pending request”. The pending
list only shows registrations already bound to the company, and a registration is bound only
when it is approved, so new registrations never appear there. Approval works only through the
printed
/oho/approve/<token>link. - Approving an OHO, revoking it and connecting or revoking a BYO GCP backend are open to any company member. No editor or admin gate exists for them today.
assignAgentToOho,removeAgentFromOho,ohoAgentsandrotateOhoCredentialshave no UI; they are API only.- Only GCP can be connected as your own cloud.
awsexists as a provider value but has no connect flow. - Pool entitlements have no tenant-side request flow; a company asks Olyros.