Skip to main content
Async execution with webhooks is designed for very long-running tasks (>30 minutes) that would otherwise timeout. The execution happens asynchronously, and results are delivered to your webhook endpoint when complete.

Overview

Async webhook execution is perfect for:
  • ML model training (30+ minutes)
  • Large dataset processing
  • Video encoding/processing
  • Long-running simulations
  • Any task that exceeds normal timeout limits
Async webhook execution returns immediately with an execution_id. The agent executes code in the background and POSTs results to your callback URL when complete.

Basic Usage

Start async execution with a webhook callback:
  • Python
  • JavaScript
from hopx_ai import Sandbox

sandbox = Sandbox.create(template="code-interpreter")

# Start async execution
response = sandbox.run_code_async(
    code='''
import time
print("Starting long task...")
time.sleep(600)  # 10 minutes
print("Task completed!")
''',
    callback_url='https://your-app.com/webhooks/HopX-complete',
    language='python',
    timeout=1800  # 30 minutes max
)

print(f"Execution ID: {response['execution_id']}")
print(f"Status: {response['status']}")
print(f"Callback URL: {response['callback_url']}")

sandbox.kill()

Webhook Callback

Your webhook endpoint will receive a POST request when execution completes:
  • Python (Flask)
  • JavaScript (Express)
from flask import Flask, request
import hmac
import hashlib

app = Flask(__name__)

@app.route('/webhooks/HopX-complete', methods=['POST'])
def hopx_webhook():
    # Verify signature (if secret provided)
    signature = request.headers.get('X-HopX-Signature')
    timestamp = request.headers.get('X-HopX-Timestamp')
    
    # Verify signature if secret was provided
    # secret = 'your-webhook-secret'
    # expected_sig = hmac.new(
    #     secret.encode(),
    #     f"{timestamp}{request.data}".encode(),
    #     hashlib.sha256
    # ).hexdigest()
    # if signature != f"sha256={expected_sig}":
    #     return "Invalid signature", 401
    
    # Process webhook payload
    data = request.json
    execution_id = data['execution_id']
    status = data['status']
    stdout = data.get('stdout', '')
    stderr = data.get('stderr', '')
    exit_code = data.get('exit_code', 0)
    execution_time = data.get('execution_time', 0)
    
    print(f"Execution {execution_id} completed with status: {status}")
    print(f"Output: {stdout}")
    
    if status == 'completed':
        # Handle successful completion
        process_results(execution_id, stdout)
    else:
        # Handle failure
        handle_error(execution_id, stderr)
    
    return "OK", 200

Signature Verification

Verify webhook signatures for security:
  • Python
  • JavaScript
from hopx_ai import Sandbox
import hmac
import hashlib

sandbox = Sandbox.create(template="code-interpreter")

# Start async execution with signature secret
response = sandbox.run_code_async(
    code='import time; time.sleep(600); print("Done")',
    callback_url='https://your-app.com/webhooks/HopX-complete',
    callback_signature_secret='your-webhook-secret-123',
    language='python'
)

print(f"Execution ID: {response['execution_id']}")

# In your webhook handler:
# signature = request.headers.get('X-HopX-Signature')
# timestamp = request.headers.get('X-HopX-Timestamp')
# body = request.data
# 
# expected = hmac.new(
#     'your-webhook-secret-123'.encode(),
#     f"{timestamp}{body}".encode(),
#     hashlib.sha256
# ).hexdigest()
# 
# if signature == f"sha256={expected}":
#     # Valid signature
#     pass

Custom Headers

Include custom headers in webhook callbacks:
  • Python
  • JavaScript
from hopx_ai import Sandbox

sandbox = Sandbox.create(template="code-interpreter")

# Start async execution with custom headers
response = sandbox.run_code_async(
    code='import time; time.sleep(600); print("Done")',
    callback_url='https://your-app.com/webhooks/HopX-complete',
    callback_headers={
        'Authorization': 'Bearer your-api-token',
        'X-Custom-Header': 'custom-value'
    },
    language='python'
)

print(f"Execution ID: {response['execution_id']}")

# Your webhook will receive:
# POST https://your-app.com/webhooks/HopX-complete
# Authorization: Bearer your-api-token
# X-Custom-Header: custom-value
# X-HopX-Signature: sha256=...
# X-HopX-Timestamp: 1698765432

Complete Example

Here’s a complete example with ML model training:
  • Python
  • JavaScript
from hopx_ai import Sandbox

sandbox = Sandbox.create(template="code-interpreter")

# Start ML training with async webhook
response = sandbox.run_code_async(
    code='''
import time
import random

print("Starting ML model training...")
print("Epoch 1/10...")
time.sleep(60)

for epoch in range(2, 11):
    loss = random.uniform(0.1, 0.5)
    accuracy = random.uniform(0.8, 0.95)
    print(f"Epoch {epoch}/10 - Loss: {loss:.4f}, Accuracy: {accuracy:.4f}")
    time.sleep(60)

print("Training completed!")
print("Model saved to /workspace/model.pkl")
''',
    callback_url='https://your-app.com/webhooks/ml-training-complete',
    callback_headers={
        'Authorization': 'Bearer ml-api-token',
        'X-Training-ID': 'training-123'
    },
    callback_signature_secret='ml-webhook-secret',
    language='python',
    timeout=3600,  # 1 hour
    env={
        'WANDB_API_KEY': 'your-wandb-key',
        'HF_TOKEN': 'your-huggingface-token'
    }
)

print(f"✅ Training started")
print(f"Execution ID: {response['execution_id']}")
print(f"Status: {response['status']}")
print(f"Results will be posted to: {response['callback_url']}")

# Your webhook will receive results when training completes
sandbox.kill()

Webhook Payload

The webhook payload structure:
{
  "execution_id": "abc123",
  "status": "completed",
  "stdout": "Task output...",
  "stderr": "",
  "exit_code": 0,
  "execution_time": 600.123
}
Headers:
  • X-HopX-Signature: HMAC-SHA256 signature (if secret provided)
  • X-HopX-Timestamp: Unix timestamp
  • Custom headers from callback_headers

Best Practices

1

1. Always Verify Signatures

Use callback_signature_secret and verify signatures in your webhook handler to ensure requests are authentic.
2

2. Handle Timeouts

Set appropriate timeouts based on expected execution time. Default is 30 minutes, max is typically 1 hour.
3

3. Use Custom Headers

Include authentication tokens or identifiers in callback_headers for secure webhook processing.
4

4. Handle Both Success and Failure

Check the status field in webhook payloads to handle both successful completions and failures.
5

5. Store Execution IDs

Store execution_id when starting async execution to correlate webhook callbacks with your records.

Next Steps