HydraPipeline

AI Agent: Foundation

Automated validation of foundation setup by an AI agent (Claude Code) running in WSL2.


Prerequisites

Input Required Example
Mode Yes local or production
Production tokens Only for production mode Bearer tokens for each service

Both modes: WSL2 environment with bash, curl and jq installed.

Local mode only: Go toolchain, all 5 service repositories cloned (~/workspaces/hydra{organization,venues,release,experiencelibrary,cluster}).

Production mode only: Network access to *.experiencenet.com, valid bearer tokens for each service.


Mode Selection

Set these variables based on the chosen mode. All subsequent commands reference these variables.

Local mode:

MODE="local"
SERVER_ORG="http://localhost:8081"
SERVER_VENUES="http://localhost:8082"
SERVER_RELEASE="http://localhost:8083"
SERVER_EXPLIB="http://localhost:8084"
SERVER_CLUSTER="http://localhost:8085"
TOKEN="dev-token"
Service Port
HydraOrganization 8081
HydraVenues 8082
HydraRelease 8083
HydraExperienceLibrary 8084
HydraCluster 8085

Production mode:

MODE="production"
SERVER_ORG="https://hydraorganization.experiencenet.com"
SERVER_VENUES="https://hydravenues.experiencenet.com"
SERVER_RELEASE="https://releases.experiencenet.com"
SERVER_EXPLIB="https://experiencenet.com"
SERVER_CLUSTER="https://hydracluster.experiencenet.com"
TOKEN="<user-provided-token>"

Test Naming Convention

All resources created by the AI agent use the test-ai- prefix:

Resource ID
Customer organization test-ai-customer
Agency organization test-ai-agency
District test-ai-district
Venue test-ai-venue
Experience test-ai-experience
Render node test-ai-body
Release project test-ai-experience

Error Handling

  1. Verification gate fails: Stop immediately. Do not proceed to the next phase.
  2. API returns 4xx: Log the full response body. If 409 (conflict), the resource may already exist from a previous run — attempt cleanup first, then retry.
  3. API returns 5xx: Retry once after 5 seconds. If still failing, stop and report.
  4. Service unreachable: In local mode, check if the process crashed. In production mode, report the unreachable service.
  5. Partial failure: Roll back what was created before retrying the entire phase.
  6. Cleanup failures: Log but continue — a 404 during cleanup is expected and not an error.

Local Mode — Start Services

Create config directories and config files:

mkdir -p /tmp/hydra-ai-validation/{hydraorganization,hydravenues,hydrarelease/releases,hydraexperiencelibrary,hydracluster}

HydraOrganization (/tmp/hydra-ai-validation/hydraorganization/config.yaml):

server:
  admin_token: "dev-token"

HydraVenues (/tmp/hydra-ai-validation/hydravenues/config.yaml):

server:
  admin_token: "dev-token"

HydraRelease (/tmp/hydra-ai-validation/hydrarelease/config.yaml):

server:
  admin_token: "dev-token"
releases_dir: "/tmp/hydra-ai-validation/hydrarelease/releases"

HydraExperienceLibrary (/tmp/hydra-ai-validation/hydraexperiencelibrary/config.yaml):

server:
  admin_token: "dev-token"
hydracluster:
  url: "http://localhost:8085"
  admin_token: "dev-token"

HydraCluster (/tmp/hydra-ai-validation/hydracluster/config.yaml):

server:
  admin_token: "dev-token"

Start each service:

cd ~/workspaces/hydraorganization && go run ./cmd/hydraorganization serve --dev --listen :8081 \
  --config /tmp/hydra-ai-validation/hydraorganization/config.yaml &

cd ~/workspaces/hydravenues && go run ./cmd/hydravenues serve --dev --listen :8082 \
  --config /tmp/hydra-ai-validation/hydravenues/config.yaml &

cd ~/workspaces/hydrarelease && go run ./cmd/hydrarelease serve --dev --listen :8083 \
  --config /tmp/hydra-ai-validation/hydrarelease/config.yaml &

cd ~/workspaces/hydraexperiencelibrary && go run ./cmd/hydraexperiencelibrary serve --dev --listen :8084 \
  --config /tmp/hydra-ai-validation/hydraexperiencelibrary/config.yaml &

cd ~/workspaces/hydracluster && go run ./cmd/hydracluster serve --dev --listen :8085 \
  --config /tmp/hydra-ai-validation/hydracluster/config.yaml &

Verification gate — all 5 health endpoints must return HTTP 200:

for url in $SERVER_ORG $SERVER_VENUES $SERVER_RELEASE $SERVER_EXPLIB $SERVER_CLUSTER; do
  status=$(curl -sf -o /dev/null -w '%{http_code}' "$url/health")
  echo "$url/health → $status"
  [ "$status" = "200" ] || { echo "FAIL: $url not healthy"; exit 1; }
done

Rollback: kill all background processes and remove /tmp/hydra-ai-validation/.


Phase 0a: Create Organizations

curl -sf -X POST "$SERVER_ORG/api/v1/organizations" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"test-ai-customer","name":"AI Test Customer","type":"customer"}'

curl -sf -X POST "$SERVER_ORG/api/v1/organizations" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"test-ai-agency","name":"AI Test Agency","type":"agency"}'

Verification gate:

curl -sf "$SERVER_ORG/api/v1/organizations/test-ai-customer" -H "Authorization: Bearer $TOKEN" | jq .
curl -sf "$SERVER_ORG/api/v1/organizations/test-ai-agency" -H "Authorization: Bearer $TOKEN" | jq .

Rollback:

curl -sf -X DELETE "$SERVER_ORG/api/v1/organizations/test-ai-agency" -H "Authorization: Bearer $TOKEN"
curl -sf -X DELETE "$SERVER_ORG/api/v1/organizations/test-ai-customer" -H "Authorization: Bearer $TOKEN"

Phase 0b: Create District and Venue (Locations)

curl -sf -X POST "$SERVER_VENUES/api/v1/districts" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"test-ai-district","name":"AI Test District","region":"local"}'

curl -sf -X POST "$SERVER_VENUES/api/v1/venues" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"test-ai-venue","name":"AI Test Venue","district_id":"test-ai-district","organization_id":"test-ai-customer"}'

Verification gate:

curl -sf "$SERVER_VENUES/api/v1/districts/test-ai-district" -H "Authorization: Bearer $TOKEN" | jq .
curl -sf "$SERVER_VENUES/api/v1/venues/test-ai-venue" -H "Authorization: Bearer $TOKEN" | jq .

Rollback:

curl -sf -X DELETE "$SERVER_VENUES/api/v1/venues/test-ai-venue" -H "Authorization: Bearer $TOKEN"
curl -sf -X DELETE "$SERVER_VENUES/api/v1/districts/test-ai-district" -H "Authorization: Bearer $TOKEN"

Phase 0d: Register Experience

Local mode (CLI operates on local YAML store):

hydraexperiencelibrary create test-ai-experience \
  --label "AI Test Experience" \
  --owner test-ai-customer \
  --developer test-ai-agency \
  --release-path test-ai-experience \
  --district test-ai-district \
  --venue test-ai-venue

Production mode (CLI has no remote client):

curl -sf -X POST "$SERVER_EXPLIB/api/v1/experiences" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "test-ai-experience",
    "label": "AI Test Experience",
    "owner": "test-ai-customer",
    "developer": "test-ai-agency",
    "release_path": "test-ai-experience",
    "districts": [{"name": "test-ai-district", "venues": ["test-ai-venue"]}]
  }'

Verification gate:

curl -sf "$SERVER_EXPLIB/api/v1/experiences/test-ai-experience" \
  -H "Authorization: Bearer $TOKEN" | jq .

Must return the experience with owner: test-ai-customer, developer: test-ai-agency, and targeting test-ai-district / test-ai-venue.

Rollback:

curl -sf -X DELETE "$SERVER_EXPLIB/api/v1/experiences/test-ai-experience" \
  -H "Authorization: Bearer $TOKEN"

Cleanup

Delete all test resources in reverse order. Always run cleanup, even if earlier phases failed. A 404 is expected and not an error.

# Delete experience
curl -sf -X DELETE "$SERVER_EXPLIB/api/v1/experiences/test-ai-experience" \
  -H "Authorization: Bearer $TOKEN" || true

# Delete build (upstream)
curl -sf -X DELETE "$SERVER_RELEASE/api/v1/projects/test-ai-experience/builds/1" \
  -H "Authorization: Bearer $TOKEN" || true

# Delete venue
curl -sf -X DELETE "$SERVER_VENUES/api/v1/venues/test-ai-venue" \
  -H "Authorization: Bearer $TOKEN" || true

# Delete district
curl -sf -X DELETE "$SERVER_VENUES/api/v1/districts/test-ai-district" \
  -H "Authorization: Bearer $TOKEN" || true

# Delete organizations
curl -sf -X DELETE "$SERVER_ORG/api/v1/organizations/test-ai-agency" \
  -H "Authorization: Bearer $TOKEN" || true
curl -sf -X DELETE "$SERVER_ORG/api/v1/organizations/test-ai-customer" \
  -H "Authorization: Bearer $TOKEN" || true

Local mode additional cleanup:

pkill -f "hydraorganization serve" || true
pkill -f "hydravenues serve" || true
pkill -f "hydrarelease serve" || true
pkill -f "hydraexperiencelibrary serve" || true
pkill -f "hydracluster serve" || true
rm -rf /tmp/hydra-ai-validation/
rm -rf "/mnt/c/Temp/hydra-ai-validation/"

Verification gate:

curl -sf -o /dev/null -w '%{http_code}' "$SERVER_ORG/api/v1/organizations/test-ai-customer" \
  -H "Authorization: Bearer $TOKEN"  # → 404
curl -sf -o /dev/null -w '%{http_code}' "$SERVER_VENUES/api/v1/districts/test-ai-district" \
  -H "Authorization: Bearer $TOKEN"  # → 404
curl -sf -o /dev/null -w '%{http_code}' "$SERVER_EXPLIB/api/v1/experiences/test-ai-experience" \
  -H "Authorization: Bearer $TOKEN"  # → 404

CLI vs API Reference

Service CLI CRUD? Remote client? Approach
HydraOrganization No N/A curl API only
HydraVenues No N/A curl API only
HydraRelease Yes Yes (--server, --token) CLI commands
HydraExperienceLibrary Yes No (local YAML store) Local: CLI. Production: curl API
HydraCluster Partial Admin API curl for enroll, CLI for approve