Skip to content

Registry & OCI distribution

The Alquimia Platform registry is a local TinyDB store that holds agent specs, secrets, parameters, tool registrations, knowledge topics, file registrations, and model registrations. Each agentspace maps to a directory on disk and can be packaged as a signed OCI artifact for promotion between environments.

TableHolds
agentsAssistantConfig JSON documents
secretsSecret definitions (name, scope, dtype, required) — never values
parametersParameterDef values for parameterized agents
toolsToolRegistration connection config and per-operation classification
topicsTopicRegistration bindings to vector-store collections
filesFileRegistration metadata for topic files
modelsModelRegistration for reusable LLM connectors

Secrets are stored as references only. Values are resolved at inference time from environment variables or HashiCorp Vault.

$ALQUIMIA_REGISTRY_DIR/
├── metadata.json # agentspace metadata
└── <agentspace_id>/
├── dist.json # current mutable workspace
└── <tag>.json # cached immutable versioned snapshots (0.5.2+)

Set ALQUIMIA_REGISTRY_DIR to change the storage root. In production the registry volume is mounted read/write on the master and read-only on workers (ALQUIMIA_RUNTIME_MODE=worker).

Versioned / “cold” agentspace registries

Section titled “Versioned / “cold” agentspace registries”

Introduced in alquimia-core 0.5.2, versioned registries let you load and run a specific OCI tag without changing the workspace dist.json. This is useful for reproducible inference, safe promotion, and running older snapshots side-by-side.

  • AlquimiaRegistry.load_version(agentspace_name, tag=None, ...) loads a cached <tag>.json snapshot or pulls it from OCI into an isolated temporary directory, then points the registry at that snapshot. The local dist.json stays unchanged.
  • parse_versioned_ref() returns a VersionedRef for strings like <agentspace>/<assistant>[:<tag>].
  • resolve_versioned_ref() is a public helper in alquimia.core that returns a loaded registry plus assistant id.

_validate_cache_tag() rejects path separators and parent-directory references (for example, ../foo), so version tags cannot escape the agentspace directory. list_cached_versions() skips symlinks and unsafe filenames.

See the CLI reference for alquimia registry fetch --tag, alquimia registry versions, alquimia registry flush-version, and alquimia local exec/chat <agentspace>/<assistant>[:<tag>].

Set ALQUIMIA_REGISTRY_KEY to enable transparent AES-256-GCM encryption of all TinyDB JSON files. The key is a Base64-encoded AES-256 key, typically sourced from Vault.

  • Encryption protects against volume or bucket exposure.
  • It does not protect against a compromised runtime process, which can read decrypted data through normal registry APIs.
  • Use ALQUIMIA_RUNTIME_MODE=worker for inference pods so the registry is read-only.
  • The ciphertext envelope stores a kid field from ALQUIMIA_REGISTRY_KEY_ID (default default) for key rotation.
  • If ALQUIMIA_REGISTRY_KEY is absent, the registry stores plaintext for backward compatibility.

Agentspaces can be published to and pulled from any OCI registry (Docker Hub, GHCR, ECR, Harbor, a private ORAS registry, etc.). The registry uses the ORAS CLI under the hood.

As of alquimia-core 0.5.3, the OCI path an agentspace publishes to is a property of the deployment, not of the agentspace metadata. The published repo_id is:

<ALQUIMIA_OCI_REGISTRY_DEFAULT>/<ALQUIMIA_OCI_NAMESPACE_AGENTSPACES>/<name>
VariableDefaultDescription
ALQUIMIA_OCI_REGISTRY_DEFAULTghcr.ioDefault registry host
ALQUIMIA_OCI_NAMESPACE_AGENTSPACESagentsDeployment namespace for agentspace artifacts and their index anchor
ALQUIMIA_OCI_NAMESPACE_BRAINSbrainsDeployment namespace for brain artifacts and their index anchor

RepositoryMetadata.namespace is deprecated and no longer takes part in the published path; OCIRepoID.namespace remains for parsing general foreign references. The alquimia registry create --namespace flag has been removed — -n / --namespace now consistently means the agentspace everywhere.

Two consequences of <namespace>/<name> being the natural key:

  • Name collisions fail loudly. An identical re-publish passes (compared by layer digest). Replacing an artifact whose ai.alquimia.registry.author annotation matches the publisher also passes. Anything else is treated as two agentspaces sharing a name and is refused unless you pass --force / force=True.
  • Stale target_repo_id values are dropped. Records written before 0.5.3 pointed at <registry>/default/<name>; they are discarded on load with a warning. source_repo_id is left untouched because it is intentionally a foreign reference.

To move an artifact published under the old path without re-pushing, use alquimia registry index migrate (see Namespace index).

Media typeContentIncluded by default
application/vnd.alquimia.registry.dist.v1+jsonComplete dist.jsonYes
application/vnd.alquimia.registry.dist.public.v1+jsonPublic layer (legacy)Pull only
application/vnd.alquimia.registry.dist.private.v1+jsonPrivate layer (legacy)Pull only
application/vnd.alquimia.registry.index.entry.v1+jsonIndex catalog entry (repo, tag, digest, kind, metadata)With ALQUIMIA_OCI_INDEX_ENABLED=true

By default the secrets table is excluded from pushes. Pass --include-secrets to also push secret metadata (key, scope, dtype, required — never values) as a separate dist.private.json layer. The public layer becomes dist.public.json. Pulling reassembles both layers back into a single local dist.json.

If the local dist.json is encrypted, push() creates temporary plaintext copies for the OCI layers. The remote artifact is standard, unencrypted JSON so external consumers can read it without your AES key. The local file stays encrypted and temporary plaintext files are deleted after the ORAS transfer.

Every pull() validates the OCI manifest before downloading blobs:

  • schemaVersion must be 2.
  • annotations["ai.alquimia.registry.dist.schema"] (if present) must equal https://alquimia.ai/schema/dist+v1.
  • annotations["ai.alquimia.registry.dist.version"] (if present) must equal v1.
  • Every layer must carry a recognized Alquimia Platform media type.

Mismatched schema versions or unrecognized layer types raise an error immediately.

Introduced in alquimia-core 0.5.3, the namespace index lets a deployment publish a discoverable catalog of its artifacts without relying on registry-specific APIs such as /v2/_catalog. It is enabled with:

VariableDefaultDescription
ALQUIMIA_OCI_INDEX_ENABLEDfalseEnable OCI 1.1 referrers-based namespace index lifecycle
ALQUIMIA_OCI_REFERRERS_FALLBACKerrorBehavior when the registry lacks native referrers support: error or warn
ALQUIMIA_OCI_SUBPROCESS_TIMEOUT120Ceiling (seconds) on any single oras/cosign invocation (0.5.5+)

When enabled, publish attaches an entry to a per-namespace anchor (<ns>/index:v1) using the OCI 1.1 referrers API, and delete detaches it. Discovery reads the index rather than the registry catalog, so explore repos and the runtime’s /explore/repos work with the same credentials that already access the namespace.

The index requires a registry that exposes the native referrers route (for example, zot or Harbor). Without it, ORAS falls back to a mutable sha256-<digest> tag that can silently lose concurrent writes. The code probes for referrers support before writing, pins ORAS to the referrers API, and warns if a fallback tag appears. Set ALQUIMIA_OCI_REFERRERS_FALLBACK=warn only if you accept that risk.

Terminal window
# Browse what the deployment publishes
alquimia registry explore catalog [--kind agentspace|brain] [--last <repo:tag>]
alquimia registry explore entry <repo>:<tag>
# Index maintenance
alquimia registry index ensure # create the anchor (idempotent)
alquimia registry index status # referrers support + unhealed publish errors
alquimia registry index reindex # re-attach entries for locally known publishes
alquimia registry index prune # detach entries whose artifact is gone
alquimia registry index migrate -n <agentspace> [--from <ref>] [--to <ref>]

index migrate copies an artifact with oras cp (preserving its digest) and cosign copy, and never deletes the source. Use it to move artifacts published under the pre-0.5.3 path into the new namespace.

Index entries are unverified claims: anyone who can push to the namespace can attach one. Annotations are display metadata only; the target manifest must still be fetched and verified before use. Under the default ALQUIMIA_OCI_SIGNATURE_POLICY=required, an entry that fails signature verification is hidden from the listing rather than aborting it, with a warning naming how many were hidden. Enabling the index with required but without cosign configured therefore reads as an empty catalog.

If the artifact uploads but the index attach fails, the publish still succeeds (the bytes are live). The error is recorded as index_error on the agentspace, reported by registry index status, and healed by registry index reindex.

OCI artifacts can be signed and verified with cosign.

VariableDefaultDescription
ALQUIMIA_OCI_SIGNATURE_POLICYrequiredrequired, warn, or off
ALQUIMIA_OCI_COSIGN_PUBKEY—Cosign public key used to verify on pull; falls back to ALQUIMIA_OCI_COSIGN_KEY
ALQUIMIA_OCI_COSIGN_KEY—Cosign signing (private) key used on push. Works as the verification fallback only for KMS/env:// references
ALQUIMIA_OCI_COSIGN_CERT_IDENTITY—Keyless verification certificate identity
ALQUIMIA_OCI_COSIGN_CERT_OIDC_ISSUER—Keyless verification OIDC issuer
ALQUIMIA_OCI_COSIGN_SIGN_PUSHautoauto signs only when a key or keyless identity is configured; true / false force it on or off
ALQUIMIA_OCI_COSIGN_TLOG_UPLOADfalseUpload key-based signatures to the public Rekor log
ALQUIMIA_OCI_COSIGN_HOMEtemp dirWritable HOME for cosign (read-only root filesystems)
  • required aborts if cosign is missing or the signature is invalid. With no verification key or keyless identity configured, every pull fails.
  • warn logs a warning and continues on verification failure.
  • off skips verification entirely.

push() signs the artifact automatically when cosign is available and configured.

ORAS and cosign authenticate to the registry with the Docker config ($DOCKER_CONFIG/config.json, default ~/.docker/config.json), for example as written by oras login or docker login.

Insecure ORAS flags are gated behind ALQUIMIA_OCI_DEV_MODE=true to prevent accidental use in production:

VariableDefaultEffect when dev mode is on
ORAS_PLAIN_HTTPfalseAppends --plain-http
ORAS_INSECUREfalseAppends --insecure

If either flag is set while dev mode is off, a warning is emitted and the flag is ignored. Keep ALQUIMIA_OCI_DEV_MODE and both flags off in production.

When the OCI index is enabled and the registry lacks native referrers support, ALQUIMIA_OCI_REFERRERS_FALLBACK decides what happens: only the exact value warn enables ORAS’s lossy fallback (index writes can be silently lost under concurrent attaches); any other value behaves as the default error.

ModeRegistry accessPurpose
masterRead/writeServes the API and mutates the registry
workerRead-onlyConsumes Kafka events and runs inference
allRead/writeSingle-process local development

Run workers as separate pods with the registry mounted read-only so a compromised inference workload cannot alter agent specs, tool registrations, or topic metadata.

Terminal window
# Create an agentspace
alquimia registry create --name myspace
# Publish an agentspace to OCI (uses ALQUIMIA_OCI_NAMESPACE_AGENTSPACES)
alquimia registry publish --namespace myspace --tag v1.2.0
# Pull an agentspace from OCI
alquimia registry pull --namespace myspace --tag v1.2.0
# Explore available artifacts
alquimia explore repos --registry ghcr.io/acme
alquimia explore tags --repository ghcr.io/acme/agents/myspace
# With the index enabled, browse the deployment catalog
alquimia registry explore catalog --registry ghcr.io/acme
alquimia registry explore entry ghcr.io/acme/agents/myspace:v1.2.0

See Publish and pull an agentspace for a step-by-step guide.