dev
← All ADRs

Skill System (Aggregation, Naming, Discovery)

ACCEPTEDEngine2026-06-06

Context

autograph is composable: packages contribute skills (on-demand competencies) and attitudes (always-on behavioral postures) to the AI agent. Skills come from three sources:

  1. Project-local - Written by the project team in workspace/agent/skills/
  2. Engine core packages - Shipped by autograph's core packages (pkg.agent, pkg.delivery), resolved in engine/deps/modules/
  3. Third-party packages - Community or custom packages, resolved in deps/modules/

OpenCode (the agent runtime) discovers skills by scanning a single directory: OPENCODE_CONFIG_DIR/skills/. This means skills from packages - mounted read-only via /hostspace/ - are invisible to OpenCode without an aggregation mechanism.

Additionally, as the ecosystem grows, skill names may collide between packages and frameworks. A naming convention is needed to identify the origin of a skill at a glance.

Options considered

Aggregation mechanism

The entrypoint script scans package skill directories and creates symlinks in the OpenCode skills directory.

  • Advantage: Simple, no runtime dependency, works with existing OpenCode, reversible
  • Disadvantage: Startup delay (negligible for symlinks), requires write access to skills dir

Option B - OpenCode skill search path

Extend OpenCode to support multiple skill directories via configuration.

  • Advantage: No startup script needed, native solution
  • Disadvantage: Depends on upstream OpenCode feature (not available today), vendor lock-in on a feature that may never exist

Option C - Copy at install time

During augr:install, copy skills from resolved packages into workspace/agent/skills/.

  • Advantage: No startup overhead, skills are "materialized" in workspace
  • Disadvantage: Duplicates content, stale copies if package updates, pollutes workspace with generated files, breaks the RO principle for package content

Naming convention

Option A - Namespace prefix by origin (chosen)

Skills are prefixed with a namespace that identifies their origin tier:

Origin Prefix Example
Engine core packages augr- augr-delivery-tracking, augr-git-conventions
Third-party packages <vendor>- acme-code-review, myframework-testing
Project-local no prefix (or project-specific) onboarding, api-design
  • Advantage: Origin is immediately visible. No collision between tiers. ls skills/ tells you what comes from where.
  • Disadvantage: Longer names. Rename needed if a skill moves between tiers (unlikely).

Option B - No prefix, flat names

Skills use short descriptive names regardless of origin. Collisions resolved by priority.

  • Advantage: Short, simple names. Less typing for /skill command.
  • Disadvantage: Cannot tell origin at a glance. Silent override if names collide (confusing). ls skills/ is opaque.

Option C - Directory-level namespacing

Skills grouped in subdirectories by origin: skills/augr/delivery-tracking/, skills/vendor/acme-review/.

  • Advantage: Clean separation in filesystem.
  • Disadvantage: OpenCode expects skills/<name>/SKILL.md (flat structure). Would require OpenCode customization or flattening at discovery time. Over-engineering.

Priority (override order)

Option A - Local wins (chosen)

Project-local  >  Third-party packages  >  Engine core packages
  • Advantage: Project always has final say. Can override any package skill with a local version. Explicit customization.
  • Disadvantage: A local skill could accidentally shadow a package skill (mitigated by prefix convention - names won't collide if prefixes are different).

Option B - Package wins

Packages override local skills of the same name.

  • Advantage: None meaningful - this is counterintuitive.
  • Disadvantage: Project loses control. Unexpected behavior on package update.

Decision

  1. Aggregation: Symlinks at container startup. The entrypoint scans package skill directories and symlinks them into OPENCODE_CONFIG_DIR/skills/.

  2. Naming: Namespace prefix by origin.

    • Engine core skills: augr-<name> (e.g., augr-delivery-tracking)
    • Third-party skills: <vendor>-<name> (e.g., acme-code-review)
    • Project-local skills: unprefixed or project-prefixed at team's discretion
  3. Priority: Local > third-party > core. If a skill with the same name exists locally, the package version is not linked.

  4. Attitudes: Continue using glob patterns in opencode.json instructions (already working). Same prefix convention applies to attitude directory names.

Consequences

Positive

  • Origin of any skill is identifiable from its name alone
  • No collision risk between engine skills and project skills
  • Project always has override authority
  • Mechanism works today without upstream changes to OpenCode
  • Simple to debug: ls -la workspace/agent/skills/ shows symlinks with targets

Negative / Risks

  • Renaming existing skills (adding augr- prefix) is a breaking change for current lab setup
  • Prefix adds characters to the /skill command invocation
  • If OpenCode adds native multi-directory support later, the symlink mechanism becomes redundant (acceptable - easy to remove)

Implementation notes

Entrypoint aggregation logic

# Scan order (last wins for same name within a tier, but local always wins)
# 1. Engine core: /hostspace/engine/deps/modules/*/agent/skills/*/
# 2. Third-party: /hostspace/deps/modules/*/agent/skills/*/
# Local skills (already in OPENCODE_CONFIG_DIR/skills/) are never overwritten.

Skill directory naming

The skill directory name IS the name used in the /skill command. Therefore:

  • Package autograph.pkg.delivery ships skill at agent/skills/augr-delivery-tracking/SKILL.md
  • After aggregation: /workspace/agent/skills/augr-delivery-tracking → symlink
  • Agent loads it via: /skill augr-delivery-tracking

Readiness gate

The container is not ready until aggregation + config generation complete. A healthcheck validates the presence of a readiness file (/tmp/.augr-agent-ready).

Attitudes follow the same prefix convention

  • Engine attitudes: augr-<name> (e.g., augr-egoless-augmentation)
  • Third-party attitudes: <vendor>-<name>
  • Project attitudes: unprefixed

Attitudes are loaded via glob patterns in opencode.json instructions and do not require symlinks (they support glob paths natively).