observal.lock and the local lockfile.
Synopsis
namespace/slug, unambiguous bare names, aliases, or row numbers from the latest Agent list.
Examples
Options
Unknown harnesses, unsupported scopes, malformed assignments, unused harness model overrides, unsupported model or tool options, invalid versions, and
--upgrade combined with --version fail locally with validation exit code 7.
Pinned versions
Pulls are pinned at two levels. Components. Every Agent version pins each of its MCP servers, skills, hooks, prompts, and sandboxes to one exact component version, identified by its version id and a content digest. Pull always installs those pinned versions. A component that ships a newer version never changes what an existing Agent version installs; the Agent’s author releases a new Agent version to move it (seeobserval agent release --refresh-components).
The Agent version. Pull chooses the Agent version in this order:
--version X: exactly that version.--upgrade: the latest approved version.observal.lockin--dir: the version the project locked.~/.observal/lockfile.json: the version this machine already installed for this harness and directory.- Otherwise, a first install: the latest approved version.
--upgrade or --version moves it.
observal.lock
Project-scope pulls write observal.lock to --dir. Commit it: teammates and CI pulling the same Agent in that project install the same Agent version, and so the same component versions, until someone runs --upgrade or --version and commits the change.
namespace/slug and carry the Agent’s registry id, so an Agent that was renamed or transferred keeps its locked version; the next pull rewrites the entry under the new name.
User-scope installs are not tied to a project and neither read nor write observal.lock. --dry-run never writes it. A malformed or unsupported observal.lock fails with validation exit code 7 before anything is installed. If observal.lock or the local lockfile names an Agent version this server does not have, pull fails with not-found exit code 5 and says which lock pinned it; --upgrade or --version moves past it and rewrites the lock.
Strict mode
Without strict mode, pull installs and warns when:- a component of an Agent version released before pinning has no lock, so its latest version is installed;
- a pinned component version no longer matches the digest recorded when the Agent version was locked;
- a pinned component version is not approved;
- the Agent version no longer matches the lock digest recorded in
observal.lock.
--strict, or OBSERVAL_STRICT=1 for CI, turns each of these into a conflict (exit code 6) before any file is written. The flag wins over the environment variable, so --no-strict is the escape hatch in a strict pipeline. A server that predates component locks cannot check any of this, so a strict pull against it fails with version-mismatch exit code 10 instead of installing unchecked.
JSON mode cannot prompt and requires --no-prompt. Missing required component values fail before config generation with error.result.needs_input: true and a list of names and component labels.
Secrets
Pull discovers required MCP environment variables and headers from the Agent’s components. Interactive mode prompts for missing values. Non-interactive mode uses matching--env and --header assignments and stops before installation when any required value is missing. Optional values may remain unset.
Values are sent only in the installation request and generated config. They are not included in JSON results, success messages, traces, or error details.
Prefer environment expansion or secure shell input so secrets do not remain in shell history.
File safety
Generated relative paths are confined to--dir. Home paths are allowed only for an explicit user-scope installation supported by that harness. Absolute paths, parent traversal, and symlink escapes are rejected before installation tracking is updated.
Pull behavior by file type:
- JSON MCP and hook sections merge into existing objects.
- YAML sections merge only when the existing top level and target section are mappings.
- TOML managed tables are replaced idempotently while unrelated tables remain.
- Generated text, prompt, Agent, and hook config files use atomic replacement.
- Malformed or structurally incompatible existing config is never overwritten. The command exits with conflict code 6 and leaves it untouched.
OTEL_* or harness telemetry environment variables are generated. Session telemetry continues through Observal-managed hooks and reconciliation.
Installation sequence
Pull performs these steps:- Validate harness, scope, model, tool, assignment, version, and output combinations.
- Resolve the canonical Agent, collect install options, and choose the Agent version (see Pinned versions).
- Load MCP environment and header requirements from the pinned component versions.
- Check installed component version conflicts.
- Request the harness-specific installation config and its lock; refuse here in strict mode.
- Resolve and validate every generated path.
- Write or preview files and install bundled skills.
- Run required harness MCP registration commands.
- Record the installed Agent and component versions in the Registry-scoped lockfile and, for project-scope installs, in
observal.lock. - Refresh the local layer snapshot and active-Agent state.
error.result, including the stage, written file statuses, setup executable status, and tracking state. Setup arguments and secret values are omitted. A layer-snapshot failure is returned as a visible warning because the generated harness installation remains usable.
JSON result
Successful JSON output has this shape:created, updated, merged, installed, cloned, would write, and would clone.
agent.version is the version that was installed and agent.resolved_from says why: requested, upgrade, project-lock, installed, or latest. lock.status is locked, partial, or unlocked; each component’s source is lock, version (matched by its recorded version string), or fallback-latest. lock.problems lists what strict mode would refuse. project_lock is null for user-scope installs and dry runs. reports_sessions is true when written hook files contain Observal session push commands, including hooks retained during a merge. These hooks can report prompts, tool calls, and tool output to the configured server when they run, whether or not observal doctor patch was run. It does not guarantee successful delivery. For Pi, it is also true when the Observal Pi extension is installed, because the extension reports every Pi session. On a failed pull, check error.result.reports_sessions when available: a hook file may already be on disk and active even when this pull wrote no files and the Agent was not recorded as installed.
Dry-run returns the same shape with dry_run: true, planned statuses, and would_run setup actions. In dry-run, reports_sessions predicts whether session hooks would be present after applying the plan; it does not mean the preview installed them. Dry-run does not write files, execute setup commands, update the lockfile or observal.lock, persist an active Agent, or emit a pull audit event.
Human output
Human mode lists every created, updated, merged, installed, cloned, or planned path. Component version conflicts, server warnings, snapshot warnings, and setup commands are printed explicitly. When session push hooks are configured, a telemetry line names the server they can report to.Exit codes
Related
observal agent: create and publish Agentsobserval scan: inspect installed harness contentobserval outdated: compare installed Agent versionsobserval agent outdated: see which components an Agent version pins behind their latest releaseobserval doctor: verify hooks and local installation state

