Skip to main content
Version: 2.0.0

Code deployment

Use this page to read, push or reload the Python that defines a lab on a hosted Orca AI deployment.

The source-available build of Orca ships no cloud backend, so on it these hosted-only verbs are not available: --backend cloud exits 2 with no cloud backend is installed.

Most of it is the hosted code surface. The local daemon builds its system from module:factory specs (topology mount and workflow load), not from a managed code directory, so it has nothing for these verbs to read.

Which verbs go where​

VerbBackend
module list / module get / module deleteHosted only
worktree list / worktree getHosted only
runtime reloadHosted only
topology deleteHosted only
workflow deleteHosted only
topology mount / workflow loadBoth, dispatched on the active backend
topology get / workflow get / method getBoth
runtime statusBoth

On the source-available build the hosted-only verbs are hidden from --help. Running one exits 2:

error: no cloud backend is installed; --backend cloud needs a package that registers entry-point group 'orca.cli_backends' name 'cloud'

With a cloud backend installed, they are hidden only while the backend resolves to local. Running one then exits 2 with a redirect:

error: this command requires a cloud deployment; run with --backend cloud or set ORCA_BACKEND=cloud

A hosted deployment keeps its code as plain Python files in a deployment_package directory, optionally wrapped in a git repo the operator manages.

Read what is deployed​

Two views of the same tree. At git HEAD is what has been committed. The worktree is what is on disk right now. They diverge whenever a file has been written but not committed, which after a submission is always.

orca module list                    # everything at git HEAD
orca module get <kind> <name> # source of one module at HEAD
orca worktree list # every file on disk
orca worktree get <path> # one file from disk

module get takes kind and name as two positional arguments (orca module get workflow smc_assay), not a kind/name path. Kinds are topology, workflow, method and plugin. Both module get and worktree get accept --out <path> (-o) to write the source to a file instead of stdout.

module list reads the git tree and shows only the entries whose path matches a known kind layout (topology/topology.py, workflows/<name>.py, methods/<name>.py, plugins/<name>.py). Package markers and boilerplate are filtered out. worktree list shows every file on disk with its path, derived kind and name, size and modification time, and works regardless of git mode.

Typed reads for specific kinds, both backends:

orca topology get [--source]        # live runtime snapshot, or the source of truth on disk
orca workflow get <name> # one workflow's registry summary
orca method get <name> [--workflow <w>]

workflow get and method get return a registry summary, not source. Read the source with module get. method get needs --workflow when the method name exists in more than one workflow, because method names are unique per workflow, not globally. For a readable account of what a workflow does, use describe workflow <name>.

Push changes​

orca workflow load  <path> --name <name> --message <m>   # write workflows/<name>.py
orca topology mount <path> --message <m> # write topology.py
orca workflow delete <name> --message <m> # remove a workflow file
orca topology delete --message <m> # remove topology.py
orca module delete workflow <name> --message <m> # same as workflow delete

workflow load and topology mount are the same verbs used locally with factory specs, dispatched on the active backend. Against a hosted deployment they take a source-file path. workflow load requires --name, which must match the @orca.workflow(name=...) in the file, and --message. topology mount requires --message. All four exit 2 with a usage error if the path is not a file or the required flag is missing. How a topology file is written is on Topology; how a workflow file is written is on Workflows.

module delete only handles kind=workflow, where it delegates to workflow delete. Topology has no delete through it (submit a replacement instead), and the generic delete for method and plugin kinds was retired: committing one of those now takes a manual git operation against the deployment repo.

What a submission actually does​

  1. The CLI sends the file content to the deployment.
  2. The deployment validates the source. This is an accident guard, not a sandbox: it rejects source that does not compile, that is filed under the wrong kind, that uses a relative import the loader cannot resolve, or that reaches for a builtin no deployment module should need. It reads the source as text, with strings and comments blanked first so a docstring quoting open( is not mistaken for a call. There is deliberately no import allow-list; one blocked legitimate authoring while stopping no attacker, since Python reaches any loaded module without an import statement.
  3. The file is written directly into the worktree.
  4. The runtime is brought up to date. If it is not built yet, this builds it. A topology submission rebuilds it. A workflow submission against a built runtime registers the workflow from source, without a rebuild.
  5. On failure the broken file stays on disk. There is no auto-rollback and no auto-revert. The operator submits a fix, deletes the file, or edits it on the filesystem and calls runtime reload.

There is no automatic git commit anywhere. --message names the change for the audit record; it does not create a commit. The commit_sha in the response is the SHA-256 content hash of the submitted source, and committed_at is the timestamp of the write. Git is the operator's explicit tool, driven from the deployment's own git surface or a real git client on the box.

A submission can also come back with warnings. They are non-blocking advisories about the source and never mean the submission was rejected.

Pitfalls​

  • A submission while executions are active exits 30 (CONFLICT). The runtime refuses to rebuild under live threads. Close and drain them first with execution close.
  • The validator is not a security boundary and cannot be made into one. A submitted module is imported and run by the rebuild at full privilege. Treat submitted source as the operator's own code, because on a single-deployment authenticated service that is what it is.
  • workflow delete cascade-unregisters the workflow template. Later submissions referring to it fail with NOT_FOUND.
  • topology delete tears the runtime down as well as removing the file, so the next topology mount starts cold. Where a previous version exists in git history, git revert is the one-step rollback.

Runtime control​

orca runtime reload [--workflows-only] [--reason "..."]
orca runtime status

reload​

Use it after a filesystem drop, when someone has edited deployment_package/ directly rather than going through a submission. The running runtime holds the old modules in sys.modules and will not see the change until told to.

The default is a full reload: shut down, re-import the deployment package from disk, construct a fresh SystemRuntime. --workflows-only is the lighter path: it walks the workflows/ directory and reconciles it against the running registry, with no shutdown and no topology re-import. It is the one to use for picking up edits to workflow files.

$ orca runtime reload --workflows-only
reload complete: registered=2 removed=0 unchanged=5

registered counts workflows that were not loaded before or whose source hash changed. removed are registered workflows whose file is gone. unchanged matched the registered hash. Both forms are gated on no active executions and exit 30 (CONFLICT) otherwise.

status​

$ orca runtime status
runtime built
$ orca runtime status
runtime NOT built
last error type: ModuleNotFoundError
message: No module named 'deployment_package.system'
hint: drop system.py into deployment_package/ and reload

Call it after any operation that returns RUNTIME_NOT_READY. The local daemon has no submission pipeline, so it never reports a build error and last_build_error is always null there.

The response also carries blockers, one list of everything stopping the run, worst first, each entry with the remedies that clear it. runtime status itself prints only the built flag and the build error, so read the blockers either with --json or with orca status, which renders them as a table against a hosted backend. A separate blockers_known flag distinguishes "nothing is in the way" from "the list could not be read", and the local daemon does not report the field at all.

Pitfalls​

  • reload is unload plus build in one step, but the daemon process survives. Active executions block it.
  • A filesystem drop without reload does nothing. The runtime's module cache holds the old version, and new submissions still see the pre-drop state.
  • A cold start on an empty deployment_package/ fails with ModuleNotFoundError: deployment_package.system, and that is expected. The service stays up and answers runtime_not_ready until something brings the runtime online. system.py is integrator-authored glue, so there is no submission verb for it: drop it on the filesystem and reload, or drop it and then submit topology, which rebuilds.

See also​

  • Lifecycle: the same topology mount and workflow load verbs against a local daemon.
  • CLI overview: backend resolution, and why a hosted-only verb exits 2 on local.
  • Inspect the system: what the rebuilt runtime now contains.
  • Topology: what goes in the topology.py you push.
  • Runtime: what a rebuild constructs and starts.