Dependencies¶
Dependencies enable artifact reuse and composition in AAM. A package can depend on other packages, and AAM automatically resolves, downloads, and deploys all required dependencies.
Why Dependencies?¶
Dependencies solve several problems:
- Reuse — Build on existing skills and agents without copying code
- Composition — Combine multiple packages into complex workflows
- Consistency — Everyone uses the same version of shared artifacts
- Updates — Update a dependency once, all dependents benefit
Example: Agent with Dependencies¶
# @author/asvc-auditor/aam.yaml
name: "@author/asvc-auditor"
version: 1.0.0
artifacts:
agents:
- name: asvc-audit
path: agents/asvc-audit/
description: "ASVC compliance auditor"
skills:
- name: asvc-report
path: skills/asvc-report/
description: "Generate ASVC audit reports"
dependencies:
"@author/generic-auditor": ">=1.0.0" # Reuse generic auditing skill
report-templates: "^2.0.0" # Reuse report templates
When you install @author/asvc-auditor, AAM automatically:
- Resolves dependencies (
@author/generic-auditorandreport-templates) - Downloads all packages
- Deploys all artifacts (agent + skills from all 3 packages)
Declaring Dependencies¶
Dependencies are declared in aam.yaml:
Both scoped (@scope/name) and unscoped (name) package names are supported.
Example¶
dependencies:
"@author/generic-auditor": ">=1.0.0"
report-templates: "^2.0.0"
python-linter: "~1.5.0"
code-formatter: "2.1.0"
optional-helper: "*"
Version Constraint Syntax¶
AAM uses semantic versioning (semver) with flexible constraint syntax:
| Syntax | Meaning | Matches | Use Case |
|---|---|---|---|
1.0.0 | Exact version | Only 1.0.0 | Pin to specific version |
>=1.0.0 | Minimum version | 1.0.0, 1.5.0, 2.0.0, etc. | Accept any newer version |
^1.0.0 | Compatible release | >=1.0.0, <2.0.0 | Accept compatible updates |
~1.0.0 | Approximate | >=1.0.0, <1.1.0 | Accept patch updates only |
* | Any version | Latest available | Always use latest |
>=1.0.0,<2.0.0 | Range constraint | Explicit range | Complex requirements |
Caret (^) — Compatible Release¶
The caret (^) allows changes that do not modify the left-most non-zero digit:
| Constraint | Matches | Does NOT Match |
|---|---|---|
^1.0.0 | 1.0.0, 1.0.1, 1.1.0, 1.9.9 | 2.0.0, 0.9.0 |
^0.2.0 | 0.2.0, 0.2.1, 0.2.9 | 0.3.0, 1.0.0 |
^0.0.3 | 0.0.3 | 0.0.4, 0.1.0 |
Rationale: Semver convention says breaking changes increment the major version (for >=1.0.0) or minor version (for 0.x.y).
Tilde (~) — Approximate¶
The tilde (~) allows patch-level changes only:
| Constraint | Matches | Does NOT Match |
|---|---|---|
~1.0.0 | 1.0.0, 1.0.1, 1.0.9 | 1.1.0, 2.0.0 |
~2.3.0 | 2.3.0, 2.3.1, 2.3.99 | 2.4.0, 3.0.0 |
Rationale: Patch versions should be backwards-compatible bug fixes.
Range Constraints¶
Multiple conditions can be combined with commas:
dependencies:
my-package: ">=1.0.0,<2.0.0" # 1.x only
other-package: ">=1.5.0,<1.8.0" # Specific range
Choosing the Right Constraint¶
| Scenario | Constraint | Example |
|---|---|---|
| Tested with specific version | Exact | 1.0.0 |
| Need specific feature | Minimum | >=1.5.0 |
| Trust semver compatibility | Caret | ^1.0.0 |
| Only want bug fixes | Tilde | ~1.0.0 |
| Always use latest | Wildcard | * |
| Complex requirements | Range | >=1.0.0,<2.0.0 |
Recommendation: Use ^ (caret) for most dependencies. It balances flexibility and safety.
Resolution Algorithm¶
AAM uses a greedy breadth-first search (BFS) algorithm with conflict detection. This is simpler than npm's nested dependencies but more flexible than pip's strict single-version resolution.
Algorithm Overview¶
def resolve(root_package):
queue = [root_package]
resolved = {}
while queue:
package = queue.pop(0)
for dep_name, constraint in package.dependencies:
if dep_name in resolved:
# Already resolved — check compatibility
if resolved[dep_name].version satisfies constraint:
continue # Compatible, skip
else:
raise ConflictError # Incompatible versions
# Find best matching version
version = find_best_match(dep_name, constraint)
resolved[dep_name] = version
queue.append(version) # Resolve transitive deps
return resolved
Key Principles¶
- Single version per dependency — No nested dependencies like npm
- Greedy selection — Always pick the highest compatible version
- Fail on conflict — Report conflicts clearly, don't try to resolve automatically
- Breadth-first — Process dependencies level-by-level
find_best_match Logic¶
When resolving a constraint like ^1.0.0:
- Query all registries — Get all available versions of the package
- Filter by constraint — Keep only versions matching
^1.0.0 - Pick highest — Select the highest version from filtered list
- Return — Download and parse manifest
def find_best_match(package_name, constraint):
# Get all versions from registries
all_versions = registry.get_versions(package_name)
# Filter by constraint
matching = [v for v in all_versions if constraint.satisfies(v)]
if not matching:
raise PackageNotFoundError(f"No version of {package_name} matches {constraint}")
# Return highest matching version
return max(matching, key=parse_semver)
Resolution Order¶
Dependencies are resolved in breadth-first order:
Package A
├── Dependency B (^1.0.0)
│ ├── Dependency D (>=2.0.0)
│ └── Dependency E (~3.0.0)
└── Dependency C (^2.0.0)
└── Dependency D (>=2.1.0)
Resolution order:
- Resolve
A(root) - Resolve
BandC(level 1) - Resolve
DandE(level 2) - Check that
D's version satisfies bothB's andC's constraints
Example: Successful Resolution¶
# Package A
dependencies:
B: "^1.0.0"
C: "^2.0.0"
# Package B
dependencies:
D: ">=2.0.0"
# Package C
dependencies:
D: ">=2.1.0"
Available versions: - B: 1.0.0, 1.5.0, 1.9.0 - C: 2.0.0, 2.3.0 - D: 2.0.0, 2.1.0, 2.5.0
Resolution:
- Install
A(root) - Resolve
B: ^1.0.0→ Pick1.9.0(highest matching) - Resolve
C: ^2.0.0→ Pick2.3.0(highest matching) - Resolve
DfromB: >=2.0.0→ Pick2.5.0(highest matching) - Check
DfromC: >=2.1.0→2.5.0satisfies, continue - Success
Final resolved versions: - A: 1.0.0 - B: 1.9.0 - C: 2.3.0 - D: 2.5.0
Conflict Handling¶
A conflict occurs when two packages require incompatible versions of the same dependency.
Example: Conflicting Constraints¶
# Package A
dependencies:
B: "^1.0.0"
C: "^2.0.0"
# Package B
dependencies:
D: ">=3.0.0" # Requires D >= 3.0.0
# Package C
dependencies:
D: "<3.0.0" # Requires D < 3.0.0
No version of D satisfies both constraints.
Conflict Error Message¶
When AAM detects a conflict, it reports it clearly:
ERROR: Dependency conflict
Package B@1.5.0 requires D >=3.0.0
Package C@2.1.0 requires D <3.0.0
No version of D satisfies both constraints.
Suggestions:
1. Check if newer versions of B or C relax the constraint
2. Use `aam info B` and `aam info C` to see latest versions
3. Install packages in separate projects if truly incompatible
Resolving Conflicts¶
When you encounter a conflict:
-
Check for updates — Newer versions may have relaxed constraints
-
Review dependency chains — Understand why the conflict exists
-
Contact package authors — Ask them to relax overly strict constraints
-
Use separate projects — If packages are truly incompatible, install in different workspaces
-
Fork and modify — As a last resort, fork a package and adjust its constraints
Why No Multiple Versions?¶
Unlike npm (which allows multiple versions of the same package via nested node_modules), AAM enforces single-version resolution.
Rationale:
- Agent artifacts must converge — Skills and instructions can't have conflicting behaviors
- Simpler mental model — Easier to reason about what's installed
- Smaller deployments — No duplication of artifacts
- Platform limitations — Most platforms don't support multiple versions of the same artifact
Lock File: aam-lock.yaml¶
The lock file records the exact versions resolved during installation. This ensures reproducible installs across machines and time.
Lock File Schema¶
# aam-lock.yaml — DO NOT EDIT MANUALLY
lockfile_version: 1
resolved_at: "2026-02-05T14:30:00Z"
packages:
"@author/asvc-auditor":
version: 1.0.0
source: aam-central
checksum: sha256:abc123...
dependencies:
"@author/generic-auditor": 1.2.3
report-templates: 2.1.0
"@author/generic-auditor":
version: 1.2.3
source: aam-central
checksum: sha256:def456...
dependencies: {}
report-templates:
version: 2.1.0
source: aam-central
checksum: sha256:789ghi...
dependencies: {}
Fields:
| Field | Type | Description |
|---|---|---|
lockfile_version | integer | Lock file format version |
resolved_at | string | ISO 8601 timestamp of resolution |
packages | dict | Map of package name → locked version info |
Per-package fields:
| Field | Type | Description |
|---|---|---|
version | string | Exact version installed |
source | string | Registry name where package was found |
checksum | string | SHA-256 hash of package archive |
dependencies | dict | Resolved dependency versions (exact, not constraints) |
When the Lock File is Generated¶
The lock file is created/updated in these scenarios:
aam install <package>— First install or adding new packageaam update— Updating to newer versions- Dependency resolution changes — When resolved versions differ from lock file
Lock File Workflow¶
# Developer A: Create package and install dependencies
cd my-project
aam install @author/asvc-auditor
# Lock file created: .aam/aam-lock.yaml
# Contains exact versions: generic-auditor@1.2.3, report-templates@2.1.0
# Commit lock file to git
git add .aam/aam-lock.yaml
git commit -m "Add ASVC auditor and dependencies"
git push
# Developer B: Clone project and install
git clone https://github.com/myorg/my-project.git
cd my-project
aam install
# AAM reads aam-lock.yaml and installs EXACT same versions
# generic-auditor@1.2.3, report-templates@2.1.0 (not 1.2.4 or 2.1.1)
Why Lock Files Matter¶
Without lock files:
- Time A:
aam installresolves^1.0.0→1.2.3 - Time B: (2 weeks later)
aam installresolves^1.0.0→1.2.4 - Result: Different versions installed, potential bugs
With lock files:
- Time A:
aam installresolves^1.0.0→1.2.3, writes lock file - Time B:
aam installreads lock file → installs1.2.3(exact) - Result: Consistent installs
Updating Dependencies¶
To update to newer versions:
# Update all packages to latest compatible versions
aam update
# Update specific package
aam update @author/generic-auditor
# Lock file is updated with new versions
Lock File Best Practices¶
- Always commit lock files — Ensures reproducible builds
- Review lock file changes — Understand what's being updated
- Don't edit manually — Let AAM manage it
- Update regularly — Keep dependencies current with
aam update - CI/CD uses lock file — Install from lock file in automated environments
Transitive Dependencies¶
Transitive dependencies are dependencies of your dependencies:
AAM automatically resolves and installs all transitive dependencies.
Example¶
# Your package
name: my-agent
dependencies:
code-reviewer: "^1.0.0"
# code-reviewer package
name: code-reviewer
dependencies:
python-linter: "^2.0.0"
js-linter: "^3.0.0"
# python-linter package
name: python-linter
dependencies:
ast-parser: "^1.0.0"
When you run aam install, AAM installs: - my-agent (root) - code-reviewer (direct dependency) - python-linter (transitive) - js-linter (transitive) - ast-parser (transitive)
Viewing Dependency Trees¶
Output:
my-agent@1.0.0
└── code-reviewer@1.5.0
├── python-linter@2.3.0
│ └── ast-parser@1.2.0
└── js-linter@3.1.0
Resolution Process Diagram¶
flowchart TD
Start[aam install package]
Start --> Parse[Parse package manifest]
Parse --> Queue[Add to resolution queue]
Queue --> CheckQueue{Queue empty?}
CheckQueue -->|No| PopQueue[Pop next package]
CheckQueue -->|Yes| WriteLock[Write lock file]
PopQueue --> ForEachDep[For each dependency]
ForEachDep --> CheckResolved{Already resolved?}
CheckResolved -->|Yes| CheckCompat{Compatible version?}
CheckResolved -->|No| FindBest[Find best match from registries]
CheckCompat -->|Yes| NextDep[Next dependency]
CheckCompat -->|No| Conflict[CONFLICT ERROR]
FindBest --> NotFound{Found?}
NotFound -->|No| Error[PACKAGE NOT FOUND]
NotFound -->|Yes| AddResolved[Add to resolved set]
AddResolved --> AddQueue[Add to queue for transitive resolution]
AddQueue --> NextDep
NextDep --> MoreDeps{More deps?}
MoreDeps -->|Yes| ForEachDep
MoreDeps -->|No| CheckQueue
WriteLock --> Download[Download all packages]
Download --> Extract[Extract to .aam/packages/]
Extract --> Deploy[Deploy to platforms]
Deploy --> Done[Installation complete]
Conflict --> End[Exit with error]
Error --> End
style Start fill:#e1f5fe
style Done fill:#e8f5e9
style Conflict fill:#ffebee
style Error fill:#ffebee
style End fill:#ffebee Best Practices¶
For Package Authors¶
- Use caret constraints —
^1.0.0allows compatible updates - Avoid overly strict constraints — Don't pin unnecessarily
- Test with latest — Ensure your package works with newer dependencies
- Document breaking changes — Increment major version for breaking changes
- Minimize dependencies — Only depend on what you actually need
For Package Consumers¶
- Commit lock files — Ensure reproducible installs
- Review dependency trees — Understand what you're installing
- Update regularly — Keep dependencies current
- Check for conflicts — Run
aam installto detect issues early - Pin in production — Use exact versions for production deployments
For Teams¶
- Shared registries — Use private registries for internal packages
- Dependency policies — Set rules for approved dependencies
- Regular audits — Review dependencies periodically
- Update cadence — Establish a regular update schedule
- CI/CD validation — Test with lock file in CI
Comparison with Other Package Managers¶
| Feature | AAM | npm | pip | Go modules |
|---|---|---|---|---|
| Multiple versions | No | Yes (nested) | No | Yes (MVS) |
| Conflict resolution | Fail fast | Nested dependencies | Fail fast | Minimal version |
| Lock file | Yes | Yes (package-lock.json) | Yes (requirements.txt) | Yes (go.sum) |
| Transitive deps | Yes | Yes | Yes | Yes |
| Constraint syntax | Semver + operators | Semver + operators | Various | Semver + operators |
AAM's approach:
- Simpler than npm — No nested dependencies
- Stricter than pip — Always enforces lock files
- Faster resolution — Greedy BFS, no complex backtracking
- Clear errors — Explicit conflict messages
Next Steps¶
- Learn about lock files: See Workspaces for lock file management
- Understand security: See Security for dependency verification
- Create packages: See Tutorial: Create a Package
- Deploy artifacts: See Platform Adapters