How to Use uv with Integration Dependencies

uv is a fast Python package manager that simplifies running OAA Runner integrations with custom dependencies. This guide explains how to manage integration requirements using uv, so your integration’s requirements.txt dependencies are automatically installed and available at runtime.

TL;DR

If your integration has a requirements.txt file (e.g., custom Python modules that need external libraries):

cd /path/to/integration
uv tool run --with-requirements=requirements.txt --from oaa-runner \
  oaa app run --config-file=config.yaml --save-json

That’s it. uv installs dependencies and runs the integration without needing a virtual environment.


When You Need This

Your integration needs requirements.txt if:

  • ✅ Your custom modules import external libraries (e.g., import pandas, import requests)

  • ✅ You have a modules/ folder with custom fetch functions

  • ✅ Your hooks use third-party libraries

Example requirements.txt:

requests==2.31.0
pandas==2.1.0
pyyaml==6.0

If your integration only uses standard library + oaa-runner, you don’t need requirements.txt.


Setup: Create requirements.txt

If you don’t have a requirements.txt yet:

cd /path/to/integration

# Create empty file
touch requirements.txt

# Add your dependencies (one per line)
cat >> requirements.txt << EOF
requests==2.31.0
pandas==2.1.0
EOF

Or use uv to generate it from your environment:

# If you're developing locally
uv pip freeze > requirements.txt

Run Integration with Dependencies

Basic: Run with requirements.txt

uv tool run --with-requirements=requirements.txt --from oaa-runner \
  oaa app run --config-file=config.yaml --save-json

What happens:

  1. uv downloads oaa-runner from PyPI

  2. uv installs dependencies from requirements.txt into a temporary environment

  3. oaa app runs with all dependencies available

  4. Temporary environment is cleaned up after

Dry-run with Dependencies

Test without pushing to Veza:

uv tool run --with-requirements=requirements.txt --from oaa-runner \
  oaa app run --config-file=config.yaml --dry-run=True --save-json

No-push with Dependencies

Test against real API without pushing to Veza:

uv tool run --with-requirements=requirements.txt --from oaa-runner \
  oaa app run --config-file=config.yaml --no-push=True --save-json

Multiple Requirements Files

If you have separate dev and prod requirements:

# Combine both files
uv tool run --with-requirements=requirements.txt \
            --with-requirements=requirements-dev.txt \
            --from oaa-runner \
  oaa app run --config-file=config.yaml --save-json

Common Patterns

Environment Variables in setup

Before running, set your API credentials:

export API_KEY=your_key_here
export VEZA_URL=https://tenant.vezacloud.com
export VEZA_API_KEY=your_veza_key

uv tool run --with-requirements=requirements.txt --from oaa-runner \
  oaa app run --config-file=config.yaml --save-json

Or load from .env:

# Create .env if not present
cat > .env << EOF
API_KEY=your_key_here
VEZA_URL=https://tenant.vezacloud.com
VEZA_API_KEY=your_veza_key
EOF

# Load and run
source .env
uv tool run --with-requirements=requirements.txt --from oaa-runner \
  oaa app run --config-file=config.yaml --save-json

Pinning Versions in requirements.txt

For reproducibility, always pin exact versions:

# Good — reproducible
requests==2.31.0
pandas==2.1.0
pyyaml==6.0.1

# Avoid — may break later
requests
pandas
pyyaml

Checking What’s Installed

See what dependencies uv will install:

cat requirements.txt

Or test without running the integration:

uv tool run --with-requirements=requirements.txt python3 -c \
  "import requests; print(requests.__version__)"

Troubleshooting

Error: “No such file or directory: requirements.txt”

Problem: requirements.txt doesn’t exist or is in wrong location.

Fix:

# Check file exists
ls requirements.txt

# Check you're in correct directory
pwd
ls -la | grep requirements.txt

Error: “Could not find a package with name X”

Problem: Package name is misspelled or doesn’t exist on PyPI.

Fix:

# Check spelling in requirements.txt
cat requirements.txt

# Verify package exists on PyPI
python3 -c "import requests; print(requests.__version__)"

# Update requirements.txt with correct name

Error: “Version X of package Y not found”

Problem: Pinned version doesn’t exist on PyPI.

Fix:

# Find available versions
uv pip search package_name

# Update requirements.txt with available version
cat requirements.txt | grep package_name

Error: “Module X not found” at runtime

Problem: Custom module imports library not in requirements.txt.

Fix:

# Check what modules import
grep -r "^import\|^from" modules/

# Add missing imports to requirements.txt
cat >> requirements.txt << EOF
missing_package==1.0.0
EOF

# Re-run with updated requirements.txt

Memory Issues with Large Integrations

If integration fails due to memory, uv can optimize dependency installation:

# Reduce downloaded dependencies
uv pip install --no-cache-dir -q -r requirements.txt

# Then run
uv tool run --with-requirements=requirements.txt --from oaa-runner \
  oaa app run --config-file=config.yaml --save-json

Advanced: Custom Python Version

If integration requires specific Python version:

# Use Python 3.9
uv tool run --python 3.9 --with-requirements=requirements.txt \
  --from oaa-runner \
  oaa app run --config-file=config.yaml --save-json

Best Practices

✅ Do

  • Pin exact versions — requests==2.31.0 not requests

  • Keep requirements.txt minimal — only add what you need

  • Test locally first — run with --dry-run=True before pushing

  • Document dependencies — add comments explaining why each package is needed

Example with comments:

# API client library
requests==2.31.0

# Data transformation
pandas==2.1.0

# Configuration parsing
pyyaml==6.0

❌ Don’t

  • Pin oaa-runner — uv handles that via --from oaa-runner

  • Mix local + PyPI — keep requirements.txt PyPI-only

  • Use setup.py — stick with requirements.txt for integrations

  • Forget to update — bump versions periodically for security


Integration Lifecycle

Phase 1: Development

# Create integration
uv tool run --from oaa-runner oaa app gen_oaa --folder-location . my_app

# Test with dependencies
uv tool run --with-requirements=my_app/requirements.txt --from oaa-runner \
  oaa app run --config-file=my_app/config.yaml --dry-run=True --save-json

Phase 2: Testing

# Run against real API (no push)
uv tool run --with-requirements=requirements.txt --from oaa-runner \
  oaa app run --config-file=config.yaml --no-push=True --save-json

# Inspect output
jq '.' output.json | head -50

Phase 3: Production

# Push to Veza
source .env
uv tool run --with-requirements=requirements.txt --from oaa-runner \
  oaa app run --config-file=config.yaml --save-json

See Also