π Related Documentation: API.md Β· CONFIGURATION.md Β· ARCHITECTURE.md Β· tools Orchestrate/README.md
π§ Where to start?
- Want to run it locally? β You're in the right place (README.md)
- Want to configure it? β CONFIGURATION.md
- Want to integrate via API? β API.md
- Want to understand design choices? β ARCHITECTURE.md
- Want to use it in WXO? β tools Orchestrate/README.md
Asynchronous image processing tools for IBM watsonx Orchestrate (WXO) with AI-powered transformations via OpenAI and persistent storage in IBM Cloud Object Storage.
π‘ Design Philosophy: This project is production-ready by design (async patterns, error handling, observability), but intentionally simplified (in-process background tasks) for demo and enablement purposes. See ARCHITECTURE.md for production scaling options.
β Single image processing with AI (OpenAI image editing) β Batch image processing from IBM Cloud Object Storage β Asynchronous execution with callback mechanism β Fallback local processing when OpenAI is unavailable β Enterprise-ready for demos, prototyping, and production workflows
- Python 3.10+ (3.9+ supported, 3.10+ recommended)
- IBM Cloud Object Storage account with HMAC credentials
- OpenAI API key from https://platform.openai.com/api-keys
- For local development on Mac: Lima VM with watsonX Orchestrate ADK
- Clone and setup:
git clone https://github.com/Estepa-F/wxo-fastapi-callback.git
cd wxo-fastapi-callback
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt- Configure environment:
cp .env.example .env
# Edit .env with your credentials (see CONFIGURATION.md for details)- Load environment variables:
β οΈ CRITICAL: You MUST load.envbefore running the server!
set -a
source .env
set +aVerify variables are loaded:
echo $COS_ENDPOINT
# Should print: https://s3.eu-de.cloud-object-storage.appdomain.cloud
echo $OPENAI_API_KEY | wc -c
# Should print a number > 10 (without exposing the key)- Run the server:
uvicorn main:app --host 0.0.0.0 --port 8000 --log-level debug
β οΈ Important: Use--host 0.0.0.0(not127.0.0.1) to make the server accessible from Lima VM.Troubleshooting: If
curl http://host.lima.internal:8000/healthfails from inside the VM, it's almost always because FastAPI was started with127.0.0.1instead of0.0.0.0.
- Verify it's running:
curl http://localhost:8000/health
# Expected: {"ok": true}The easiest way to verify your setup:
# 1. Make the script executable
chmod +x scripts/test_local.sh
# 2. Load environment variables
set -a
source .env
set +a
# 3. Start FastAPI (in a separate terminal)
uvicorn main:app --host 0.0.0.0 --port 8000
# 4. Run the test script
./scripts/test_local.shWhat it does:
- β Verifies all required environment variables
- β Checks FastAPI server health
- β Validates COS configuration
- β Starts a local callback server automatically
- β Tests single image processing (Base64)
- β Tests batch image processing
- β Cleans up resources on exit
Prerequisites:
- Test image
burger.jpegin project root (for single image test) - Input bucket with test images (for batch test)
Before testing batch operations, ensure:
β
Input bucket exists and contains test images (JPEG, PNG)
β
Output bucket exists (can be the same as input)
β
HMAC credentials have permissions: list, get, put
β
Configuration is valid:
curl http://localhost:8000/cos/config
# Verify: endpoint, input_bucket, output_bucket match your setupIn a new terminal:
python - <<'PY'
from fastapi import FastAPI
import uvicorn
from datetime import datetime, timezone
app = FastAPI()
@app.post("/callback")
def cb(data: dict):
print(f"\n--- {datetime.now(timezone.utc).isoformat()} ---")
print(data)
return {"ok": True}
uvicorn.run(app, host="127.0.0.1", port=9999)
PYexport B64=$(base64 -i your-image.jpg | tr -d '\n')
curl -X POST http://localhost:8000/process-image-async-b64 \
-H "Content-Type: application/json" \
-H "callbackUrl: http://localhost:9999/callback" \
-d "{
\"prompt\": \"add a sunset background\",
\"filename\": \"test.jpg\",
\"image_base64\": \"$B64\"
}"You should see:
- Immediate response:
{"accepted": true, "job_id": "..."} - Callback in terminal 1 with the processed image (base64)
Mac (Host)
βββ FastAPI Server (port 8000)
β βββ http://0.0.0.0:8000
β
βββ Lima VM (ibm-watsonx-orchestrate)
βββ watsonX Orchestrate ADK (port 4321)
β βββ Accessible via SSH tunnel: localhost:14321
β
βββ Access to Mac host via: host.lima.internal:8000
Lima VM uses an isolated network. The special DNS alias host.lima.internal resolves to the Mac host's IP from within the VM, allowing Orchestrate to communicate with your FastAPI server.
1. Start FastAPI on Mac:
cd wxo-fastapi-callback
source .venv/bin/activate
uvicorn main:app --host 0.0.0.0 --port 8000 --log-level debug2. Start Lima VM:
limactl start ibm-watsonx-orchestrate3. Create SSH Tunnel:
ssh -o 'IdentityFile="/Users/YOUR_USERNAME/.lima/_config/user"' \
-o StrictHostKeyChecking=no \
-o Hostname=127.0.0.1 \
-o Port=YOUR_LIMA_SSH_PORT \
-N \
-L 14321:127.0.0.1:4321 \
lima-ibm-watsonx-orchestrateπ Replace
YOUR_USERNAMEandYOUR_LIMA_SSH_PORT(check withlimactl list)
4. Access Orchestrate:
http://localhost:14321
5. Test Connectivity:
limactl shell ibm-watsonx-orchestrate
curl http://host.lima.internal:8000/health
# Expected: {"ok": true}6. Import Tools:
Import these files from tools Orchestrate/ into watsonX Orchestrate:
- YAML files as API tools
- Python file as Python tool
- JSON files as workflows
See tools Orchestrate/README.md for detailed instructions.
callbackUrlheader is case-sensitive - Use exactlycallbackUrl, notcallbackurlorcallback_url- No
data:prefix in Base64 - Send raw Base64 string withoutdata:image/...;base64,prefix - Use
--host 0.0.0.0- Required for Lima VM access,127.0.0.1won't work - Source
.envbefore running - Runset -a && source .env && set +aor server will fail - COS buckets must exist - Create input/output buckets in IBM Cloud before testing batch
Endpoint: POST /process-image-async-b64
Use case: Process one image, return result directly in chat/workflow
Best for: Quick demos, visual preview, lightweight interactions
Endpoint: POST /process-image-async
Use case: Process one image, store in COS, return presigned URL
Best for: Persistent storage, sharing, integration with other systems
Endpoint: POST /batch-process-images
Use case: Apply same instruction to all images in a COS folder
Best for: Mass content updates, e-commerce catalogs, marketing assets
| Document | Purpose |
|---|---|
| API.md | Complete API reference with endpoints, schemas, and examples |
| CONFIGURATION.md | Environment variables and setup guide |
| ARCHITECTURE.md | Technical architecture, patterns, and design decisions |
| tools Orchestrate/README.md | watsonX Orchestrate integration guide |
- π¨ Product demos β Showcase AI capabilities
- π’ Client workshops β Hands-on training
- π Internal accelerators β Rapid prototyping
- π watsonx Orchestrate best practices β Reference implementation
- Never commit
.envto version control - Use environment variables for all credentials
- Rotate API keys regularly
- Use presigned URLs with appropriate expiration
- See CONFIGURATION.md for production security recommendations
This is a demo project for IBM watsonx Orchestrate. For questions or suggestions, please contact the maintainer.
This project is for demonstration and educational purposes.