Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developer.watson-orchestrate.ibm.com/llms.txt

Use this file to discover all available pages before exploring further.

Understanding how Python dependencies work in watsonx Orchestrate is critical for building secure, repeatable deployments across environments. This guide clarifies what gets packaged during export, when dependencies are installed, and which patterns are officially supported for enterprise deployments.

What are “dependencies” in watsonx Orchestrate?

Important: Dependencies in watsonx Orchestrate are the source specifications listed in your requirements.txt file, not the compiled binary packages or installed libraries.
When you export a Python tool or agent, the export includes:
  • ✅ Your Python source code files (.py files)
  • ✅ Your requirements.txt file (dependency specifications)
  • ✅ Any additional resources (data files, configuration files)
  • Does not include the installed binary packages or virtual environment
This is a source-only export model. The actual Python packages (wheels, compiled binaries) are downloaded and installed separately during deployment.

Example: What gets exported

# When you export an agent, you get:
agent/
├── tools/
   └── my_tool/
       ├── my_tool.py              # ✅ Source code
       ├── requirements.txt        # ✅ Dependency specifications
       └── utils.py                # ✅ Additional source files
├── agents/
   └── my_agent.yaml               # ✅ Agent configuration
└── connections/
    └── my_connection.yaml          # ✅ Connection definitions

# What is NOT included:
# - site-packages/ (installed libraries)
# - .venv/ (virtual environment)
# - Binary wheels or compiled packages

When and where are dependencies installed?

Dependencies are installed server-side at agent deployment time, not during export or import.

Installation timeline

  1. Development: You create a tool with a requirements.txt file
  2. Import: You import the tool using orchestrate tools import
  3. Deployment: When the tool is deployed to an environment (Draft or Live):
    • watsonx Orchestrate reads your requirements.txt
    • Runs pip install server-side
    • Creates an isolated virtual environment (venv)
    • Installs all specified packages
This installation happens in every environment where you deploy the tool—DEV, QA, and PROD instances all perform their own dependency installation.

Virtual environment caching

To optimize performance and reduce redundant installations, watsonx Orchestrate uses a canonical hash-based deduplication mechanism:
  1. Hash computation: When you deploy a tool, the system computes a unique fingerprint (hash) of your requirements.txt file
  2. Cache check: The system checks if a virtual environment with this exact hash already exists
  3. Reuse or create:
    • Hash match found: Reuses the existing cached venv (no installation needed)
    • No match: Creates new hash, builds new venv, stores in cache
This means packages are downloaded once per unique requirements.txt within a cluster, not once per tool or tenant.

When a new virtual environment is created

A new venv will be created when the dependency hash changes due to:
  • Dependency version changes: Updating from requests==2.32.3 to requests==2.32.4
  • Adding/removing packages: Adding numpy==1.24.0 to existing dependencies
  • Different registry URLs: Changing --index-url or --extra-index-url
  • ADK version changes: If you re-import with a different ADK version and have unpinned dependencies, ADK may add different “latest” versions
Best practice: Use pinned versions in requirements.txt to ensure consistent hash generation and maximize venv reuse across deployments.

Enterprise dependency management patterns

Using private registries (Artifactory, Nexus)

watsonx Orchestrate supports pulling packages from private PyPI registries like Artifactory or Sonatype Nexus. This is essential for organizations that:
  • Require security scanning of all packages
  • Cannot allow direct downloads from public PyPI
  • Need to control which package versions are available

Configuration with --index-url

Use --index-url to specify your primary package registry:
requirements.txt
--index-url https://artifactory.company.com/api/pypi/python-virtual/simple
ibm-watsonx-orchestrate==2.4.0
requests==2.32.3
pydantic==2.8.2
When using --index-url, pip will only check your specified registry. If a package is not found there, the installation will fail—it will NOT fall back to public PyPI.

Configuration with --extra-index-url

Use --extra-index-url to add your registry as an additional source while keeping PyPI as a fallback:
requirements.txt
--extra-index-url https://artifactory.company.com/api/pypi/python-virtual/simple
ibm-watsonx-orchestrate==2.4.0
requests==2.32.3
pydantic==2.8.2
With --extra-index-url, pip will check both your private registry AND public PyPI. This provides flexibility but may not meet strict security policies that prohibit any public PyPI access.

Direct wheel URLs

You can also specify direct URLs to wheel files hosted in your registry:
requirements.txt
ibm-watsonx-orchestrate==2.4.0
pydantic @ https://artifactory.company.com/python-packages/pydantic-2.8.2-py3-none-any.whl
requests @ https://artifactory.company.com/python-packages/requests-2.32.3-py3-none-any.whl
This approach gives you maximum control over exactly which binary artifacts are used.

Pinned dependencies for reproducibility

To ensure consistent builds across environments, always pin your dependencies to exact versions:
requirements.txt
ibm-watsonx-orchestrate==2.4.0
requests==2.32.3
pydantic==2.8.2
numpy==1.24.0
requirements.txt
# Avoid these patterns for production deployments
ibm-watsonx-orchestrate>=2.4.0  # May pull different versions over time
requests                         # Will pull latest version
pydantic~=2.8                   # May pull 2.8.x updates
Unpinned dependencies can lead to:
  • Different packages installed in DEV vs PROD
  • Unexpected behavior from minor/patch version changes
  • Hash mismatches causing unnecessary venv rebuilds

Hash-based verification for maximum security

For the highest level of reproducibility and security, use pip-compile to generate hashes:
# Generate requirements.txt with hashes
pip-compile --generate-hashes requirements.in -o requirements.txt
This produces a requirements.txt with cryptographic hashes:
requirements.txt
ibm-watsonx-orchestrate==2.4.0 \
    --hash=sha256:abc123... \
    --hash=sha256:def456...
requests==2.32.3 \
    --hash=sha256:789ghi... \
    --hash=sha256:012jkl...
When hashes are present, pip will verify that the downloaded package matches the expected hash, preventing:
  • Compromised packages
  • Registry tampering
  • Accidental version mismatches

Export/import vs Git-based promotion

Understanding the difference between these deployment approaches is crucial for choosing the right strategy.

Export/import model

What it provides:
  • Source code equivalence
  • Configuration portability
  • Quick environment setup
What it does NOT provide:
  • Binary package equivalence (packages are re-installed in target environment)
  • Guaranteed identical dependencies (unless using pinned versions + private registry)
When to use:
  • Moving agents between different watsonx Orchestrate instances
  • Sharing agents with other teams or organizations
  • Backing up agent configurations
Example workflow:
# Export from DEV environment
orchestrate agents export -n my-agent -k native -o my-agent.zip

# Import to QA environment (switch environment first)
orchestrate env set qa-environment
orchestrate agents import -f my-agent.zip
After import, the QA environment will run pip install using its own registry configuration, potentially pulling different package versions if dependencies are not pinned.

Git-based promotion

What it provides:
  • Version control integration
  • Commit-based traceability
  • Code review workflows
What it does NOT provide:
  • Binary package equivalence (packages are still re-installed)
  • Protection against registry changes (unless using locked Artifactory)
When to use:
  • Standard CI/CD pipelines
  • Promoting tested code through environments
  • Maintaining audit trails
Example workflow:
# Tag a tested commit in DEV
git tag v1.2.3-qa-ready
git push origin v1.2.3-qa-ready

# Deploy from that commit in QA
git checkout v1.2.3-qa-ready
orchestrate env set qa-environment
orchestrate agents import -f agents/my-agent.yaml

Achieving binary equivalence

Neither export/import nor Git-based promotion guarantees binary equivalence by default. To achieve it:
  1. Pin all dependencies to exact versions in requirements.txt
  2. Use a locked private registry (Artifactory/Nexus) with controlled package versions
  3. Optional: Add hash verification with pip-compile --generate-hashes
  4. Ensure the same registry configuration across all environments
Example locked requirements.txt:
requirements.txt
--index-url https://artifactory.company.com/api/pypi/python-locked/simple
ibm-watsonx-orchestrate==2.4.0 \
    --hash=sha256:abc123...
requests==2.32.3 \
    --hash=sha256:def456...
pydantic==2.8.2 \
    --hash=sha256:789ghi...
With this configuration:
  • ✅ Same source code (via export/import or Git)
  • ✅ Same dependency versions (pinned)
  • ✅ Same binary packages (locked registry + hashes)
  • ✅ Repeatable across all environments

Air-gapped environments

For deployments in air-gapped or restricted network environments, see the dedicated guide: Operating in an air-gapped environment. Key considerations:
  • ADK and all dependencies must be uploaded to your internal registry
  • Use --index-url to point to your internal registry
  • Ensure all transitive dependencies are available

Best practices summary

Pin all versions

Use exact version pinning (==) in requirements.txt for all dependencies

Use private registries

Configure --index-url to pull from your organization’s Artifactory or Nexus

Add hash verification

Use pip-compile --generate-hashes for maximum security and reproducibility

Lock your registry

Prevent package additions/removals in your Artifactory between deployments
requirements.txt
# Use your organization's private registry
--index-url https://artifactory.company.com/api/pypi/python-virtual/simple

# Pin ADK version
ibm-watsonx-orchestrate==2.4.0

# Pin all dependencies with exact versions
requests==2.32.3
pydantic==2.8.2
python-dotenv==1.0.0

# Optional: Add hashes for verification (generated with pip-compile)
# ibm-watsonx-orchestrate==2.4.0 \
#     --hash=sha256:abc123...

Troubleshooting

Issue: Different packages installed in QA vs PROD

Cause: Unpinned dependencies or registry changes between deployments Solution:
  1. Pin all dependencies to exact versions
  2. Use a locked Artifactory with controlled package versions
  3. Verify registry configuration is identical across environments

Issue: Tool fails to import due to missing packages

Cause: Package not available in private registry Solution:
  1. Verify package exists in your Artifactory/Nexus
  2. Check --index-url configuration in requirements.txt
  3. Ensure network connectivity from watsonx Orchestrate to your registry

Issue: Slow deployment times

Cause: Virtual environment cache misses due to hash changes Solution:
  1. Use pinned versions to maximize cache hits
  2. Avoid unnecessary changes to requirements.txt
  3. Keep ADK version consistent across re-imports

Issue: Security scan failures

Cause: Packages pulled from public PyPI without scanning Solution:
  1. Use --index-url (not --extra-index-url) to prevent PyPI fallback
  2. Configure your Artifactory to scan packages before making them available
  3. Implement package approval workflows in your registry