SkillSource CRD
The SkillSource custom resource fetches AgentSkills.io-formatted skill content from an upstream source (Git, OCI, or ConfigMap) into the workspace content PVC, where PromptPack resources can reference it via spec.skills.
A skill is a directory containing a SKILL.md file with YAML frontmatter (name, description, optional allowed-tools, metadata) and a Markdown body that PromptKit loads on demand.
Short name: skl (e.g. kubectl get skl).
Example
Section titled “Example”apiVersion: omnia.altairalabs.ai/v1alpha1kind: SkillSourcemetadata: name: anthropic-skills namespace: dev-agentsspec: type: git git: url: https://github.com/anthropic/skills ref: tag: v1.4.0 interval: 1h timeout: 5m targetPath: skills/anthropic filter: include: - "ai-safety/*" - "pdf-processing/*" exclude: - "**/draft-*"| Field | Type | Description |
|---|---|---|
type | git | oci | configmap | Required. Selects the source variant; the matching git/oci/configMap block must be set (CEL-validated). |
git | object | Git source: url (http://, https:// or ssh://), optional ref (branch/tag/commit; branch wins over tag, tag over commit; default branch when unset), path (subdirectory), secretRef (username/password for HTTPS, identity/known_hosts for SSH), or instead connectionRef, a Connection whose hosts include the repository’s. |
oci | object | OCI source: url (oci://registry/repo:tag or @digest), insecure (default false), secretRef (username/password or .dockerconfigjson). |
configMap | object | ConfigMap source: name. Every key in the ConfigMap’s data and binaryData becomes a file, with __ in a key decoded to / (e.g. pdf__SKILL.md ⇒ pdf/SKILL.md). Editing the ConfigMap triggers a re-sync. |
interval | duration | Required. How often a git or oci source fetches (e.g. 1h); pattern ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$. A source fetches when status.nextFetchTime passes, and sooner when its spec changes, its last fetch failed, a Connection it fetches with changes, the operator restarts, or its synced content is missing from the volume. A configmap source applies an edit to its ConfigMap at once. |
timeout | duration | Per-fetch timeout (default 60s). |
suspend | bool | Stop reconciling when true (default false). |
targetPath | string | Path under the workspace content PVC where synced content lands. Defaults to skills/{source-name}. Every sync creates a content-addressable version. |
filter | object | Narrows which synced skills are exposed. It decides skillCount and the duplicate-name check, and a PromptPack referencing the source sees only the skills it keeps; spec.skills[].include on the PromptPack narrows further. The synced tree on the PVC still holds every skill. See below. |
Filter
Section titled “Filter”filter: include: # globs matched against each skill's directory path; empty = include all - "safety-*" exclude: # path globs applied after include - "**/draft-*" names: # exact frontmatter `name:` matches; empty = no name filter - "ai-safety"Globs use Go filepath.Match syntax: * does not cross a /, and ** is not
recursive (it behaves like *), so **/draft-* matches x/draft-y but not
draft-y or x/y/draft-z.
Status
Section titled “Status”| Field | Description |
|---|---|
phase | Ready after a successful fetch and sync, Error when the fetch or sync fails (retried after one minute). |
observedGeneration | Last spec generation the controller has processed. |
artifact | Synced revision, contentPath (<targetPath>/.arena/versions/<version>), version (first 12 hex characters of the content’s SHA-256), checksum, size, lastUpdateTime. |
skillCount | Number of skills retained after the filter. |
conditions[type=SourceAvailable] | True when the upstream is reachable and the latest fetch succeeded. |
conditions[type=ContentValid] | True when every SKILL.md parses cleanly and there are no duplicate names within the source. |
conditions[type=Ready] | Roll-up: True when the fetch succeeded and the content is valid. |
lastFetchTime / nextFetchTime | Timestamps of the most recent and next scheduled fetch. |
See Workspace content layout § Skills for how a synced SkillSource reaches a running agent.
Cross-namespace policy
Section titled “Cross-namespace policy”SkillSource resolution is scoped to the PromptPack’s own NAMESPACE, not to a ‘workspace’ — a namespace’s workspace membership is only a label an operator can set, and multiple namespaces can share one workspace name. To share the same upstream content across namespaces you need a SkillSource per NAMESPACE, even when those namespaces belong to the same workspace.