AgentStack
SKILL verified Apache-2.0 Self-run

Automation Pilot Content Management Via Api

skill-sap-automation-pilot-agent-skills-automation-pilot-content-management-via-api · by SAP

Manage SAP Automation Pilot content (commands, catalogs, inputs) via Content API. Use when importing or exporting commands, listing catalogs, or managing automation content programmatically.

No reviews yet
0 installs
7 views
0.0% view→install

Install

$ agentstack add skill-sap-automation-pilot-agent-skills-automation-pilot-content-management-via-api

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Automation Pilot Content Management Via Api? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

SAP Automation Pilot Content API Management

This skill manages catalogs, commands, and inputs in SAP Automation Pilot using the Content API.

Command Release Policy

⚠️ Commands deploy in DRAFT state. Never release automatically — only when the user explicitly requests it and the command has been tested. See ../automation-pilot-command-generation/SKILL.md for the full policy.

Naming Conventions

| Type | Convention | Example | |------|------------|---------| | Commands | PascalCase | RestartCfApp, GetHanaInstance | | Inputs | PascalCase | BtpCredentials, JiraConfig | | Catalogs | kebab-case | my-automations-xxx |

Names must not contain spaces (causes API failures with URL encoding).

Prerequisites

  1. Set the following required environment variables:
export AUTOPI_HOSTNAME="emea.autopilot.cloud.sap"
export AUTOPI_USERNAME="your-username"
export AUTOPI_PASSWORD="your-password"
export AUTOPI_DEFAULT_CATALOG="mycommands->>"

Supported hostnames:

  • emea.autopilot.cloud.sap (default - Europe)
  • aus.autopilot.cloud.sap (Australia)
  • apac.autopilot.cloud.sap (Asia Pacific)
  • amer.autopilot.cloud.sap (Americas)
  • ksa.autopilot.cloud.sap (Saudi Arabia)
  1. Ensure curl is available in your environment.

Values Are Always Strings on the Wire

When creating or updating inputs via the API, every entry in values and defaultValue must be a JSON string, regardless of the declared type in keys.

| Declared type | Wire representation | |-----------------|---------------------| | string | "my-app" | | number | "42" | | boolean | "true" | | array | "[\"a\",\"b\"]" | | object | "{\"url\":\"...\",\"user\":\"...\"}" |

This also applies to inputValues on trigger and schedule endpoints — every value must be a string on the wire. The runtime converts it to the declared type inside the executor.


Catalogs

List Catalogs

# List all catalogs owned by the tenant
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/catalogs?own=true"
# List catalogs provided by SAP
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/catalogs?provided=true"
# List all catalogs (owned + provided)
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/catalogs"
# List catalogs filtered by tag
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/catalogs?tag=environment:production"

Get Catalog by ID

CATALOG_ID="mycatalog-xxx"
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/catalogs/$CATALOG_ID"

Create Catalog

curl -s -X POST \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-catalog",
    "description": "My custom catalog for automation commands",
    "tags": {
      "environment": "development"
    }
  }' \
  "https://$AUTOPI_HOSTNAME/api/v1/catalogs"

Update Catalog

CATALOG_ID="mycatalog-xxx"
curl -s -X PUT \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Updated description",
    "tags": {
      "environment": "production"
    }
  }' \
  "https://$AUTOPI_HOSTNAME/api/v1/catalogs/$CATALOG_ID"

Delete Catalog

Note: Catalog must be empty (no commands or inputs) before deletion.

CATALOG_ID="mycatalog-xxx"
curl -s -X DELETE -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/catalogs/$CATALOG_ID"

Commands

List Commands

# List all commands in a catalog
CATALOG="mycatalog-xxx"
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/commands?catalog=$CATALOG"
# List commands with design-time issues
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/commands?catalog=$CATALOG&includeIssues=true"
# List commands by tag
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/commands?tag=type:monitoring"
# List only command IDs (lightweight)
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/commands/ids?catalog=$CATALOG"

Get Command by ID

Command ID format: catalog:name:version

COMMAND_ID="mycatalog-xxx:MyCommand:1"
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/commands/$COMMAND_ID"

Create/Upload Command

Upload a command from a .command.json file:

COMMAND_FILE="path/to/MyCommand.command.json"

# Create the command
curl -s -X POST \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  -H "Content-Type: application/json" \
  -d @"$COMMAND_FILE" \
  "https://$AUTOPI_HOSTNAME/api/v1/commands"

Create command inline:

curl -s -X POST \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MyCommand",
    "catalog": "mycatalog-xxx",
    "description": "My custom command",
    "version": 1,
    "inputKeys": {
      "message": {
        "type": "string",
        "description": "Message to process",
        "required": true
      }
    },
    "outputKeys": {
      "result": {
        "type": "string",
        "description": "Processing result"
      }
    },
    "configuration": null,
    "tags": {}
  }' \
  "https://$AUTOPI_HOSTNAME/api/v1/commands"

Update Command

COMMAND_ID="mycatalog-xxx:MyCommand:1"
COMMAND_FILE="path/to/MyCommand.command.json"

curl -s -X PUT \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  -H "Content-Type: application/json" \
  -d @"$COMMAND_FILE" \
  "https://$AUTOPI_HOSTNAME/api/v1/commands/$COMMAND_ID"

Delete Command

COMMAND_ID="mycatalog-xxx:MyCommand:1"
curl -s -X DELETE -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/commands/$COMMAND_ID"

Release Command

⚠️ USE ONLY IF THE USER EXPLICITLY REQUESTED IT

Release a draft command:

COMMAND_ID="mycatalog-xxx:MyCommand:1"
curl -s -X PUT -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/commands/$COMMAND_ID/release"

Deprecate Command

Mark a command as deprecated:

COMMAND_ID="mycatalog-xxx:MyCommand:1"
curl -s -X PUT -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/commands/$COMMAND_ID/deprecate"

Restore Command

Restore a deprecated command:

COMMAND_ID="mycatalog-xxx:MyCommand:1"
curl -s -X PUT -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/commands/$COMMAND_ID/restore"

Bulk Create Commands

Upload multiple commands at once:

curl -s -X POST \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{
    "commands": [
      {"name": "Cmd1", "catalog": "mycatalog-xxx", ...},
      {"name": "Cmd2", "catalog": "mycatalog-xxx", ...}
    ]
  }' \
  "https://$AUTOPI_HOSTNAME/api/v1/bulk/commands"

Inputs

List Inputs

# List inputs in a catalog
CATALOG="mycatalog-xxx"
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/inputs?catalog=$CATALOG"
# List inputs by tag
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/inputs?tag=type:credentials"

Get Input by ID

Input ID format: catalog:name:version

INPUT_ID="mycatalog-xxx:MyInput:1"
curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/inputs/$INPUT_ID"

Create Input

curl -s -X POST \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MyCredentials",
    "catalog": "mycatalog-xxx",
    "description": "Service credentials",
    "version": 1,
    "keys": {
      "username": {
        "type": "string",
        "description": "Service username",
        "sensitive": false
      },
      "password": {
        "type": "string",
        "description": "Service password",
        "sensitive": true
      }
    },
    "values": {
      "username": "",
      "password": ""
    },
    "tags": {
      "type": "credentials"
    }
  }' \
  "https://$AUTOPI_HOSTNAME/api/v1/inputs"

Update Input (Full)

INPUT_ID="mycatalog-xxx:MyInput:1"
curl -s -X PUT \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MyCredentials",
    "catalog": "mycatalog-xxx",
    "description": "Updated credentials",
    "version": 1,
    "keys": {...},
    "values": {...}
  }' \
  "https://$AUTOPI_HOSTNAME/api/v1/inputs/$INPUT_ID"

Update Input (Partial - Values Only)

Update only specific values without replacing the entire input:

INPUT_ID="mycatalog-xxx:MyInput:1"
curl -s -X PATCH \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  -H "Content-Type: application/merge-patch+json" \
  -d '{
    "values": {
      "password": ""
    }
  }' \
  "https://$AUTOPI_HOSTNAME/api/v1/inputs/$INPUT_ID"

Delete Input

INPUT_ID="mycatalog-xxx:MyInput:1"
curl -s -X DELETE -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/inputs/$INPUT_ID"

Release Input

⚠️ USE ONLY IF THE USER EXPLICITLY REQUESTED IT

INPUT_ID="mycatalog-xxx:MyInput:1"
curl -s -X PUT -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/inputs/$INPUT_ID/release"

Deprecate Input

INPUT_ID="mycatalog-xxx:MyInput:1"
curl -s -X PUT -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/inputs/$INPUT_ID/deprecate"

Restore Input

INPUT_ID="mycatalog-xxx:MyInput:1"
curl -s -X PUT -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/inputs/$INPUT_ID/restore"

Bulk Create Inputs

curl -s -X POST \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": [
      {"name": "Input1", "catalog": "mycatalog-xxx", ...},
      {"name": "Input2", "catalog": "mycatalog-xxx", ...}
    ]
  }' \
  "https://$AUTOPI_HOSTNAME/api/v1/bulk/inputs"

Working with Inputs

Inputs are reusable parameter sets stored in Automation Pilot. They allow you to save credentials, configurations, or commonly-used values that can be referenced when triggering command executions.

Input Structure

{
  "name": "MyCfCredentials",
  "catalog": "mycatalog-xxx",
  "description": "CF credentials for eu10 region",
  "version": 1,
  "keys": {
    "region": { "type": "string", "sensitive": false },
    "user": { "type": "string", "sensitive": false },
    "password": { "type": "string", "sensitive": true }
  },
  "values": {
    "region": "cf-eu10",
    "user": "technical-user",
    "password": ""
  },
  "tags": {}
}
  • keys: Defines the schema (type and sensitivity) for each value
  • values: The actual stored values
  • sensitive: true: Value is masked in logs and UI

Common Input Patterns

CF Credentials (for applm-sapcp, cf-sapcp commands)

{
  "name": "CfCredentials-EU10",
  "catalog": "mycatalog-xxx",
  "description": "Cloud Foundry credentials for EU10",
  "version": 1,
  "keys": {
    "region": { "type": "string", "sensitive": false },
    "user": { "type": "string", "sensitive": false },
    "password": { "type": "string", "sensitive": true }
  },
  "values": {
    "region": "cf-eu10",
    "user": "cf-technical-user@example.com",
    "password": "your-password"
  }
}

Service Key (for sm-sapcp, aicore-sapcp commands)

{
  "name": "HanaCloudServiceKey",
  "catalog": "mycatalog-xxx",
  "description": "HANA Cloud service binding credentials",
  "version": 1,
  "keys": {
    "serviceKey": { "type": "object", "sensitive": true }
  },
  "values": {
    "serviceKey": "{\"url\":\"https://hana-instance.hana.cloud.sap\",\"user\":\"DBADMIN\",\"password\":\"\",\"certificate\":\"...\"}"
  }
}

API Token (for jira-sapcp, github-sapcp commands)

{
  "name": "JiraCredentials",
  "catalog": "mycatalog-xxx",
  "description": "JIRA API credentials",
  "version": 1,
  "keys": {
    "host": { "type": "string", "sensitive": false },
    "user": { "type": "string", "sensitive": false },
    "password": { "type": "string", "sensitive": true }
  },
  "values": {
    "host": "https://jira.example.com",
    "user": "automation@example.com",
    "password": "api-token-here"
  }
}

Kubernetes Config (for kubernetes-sapcp commands)

{
  "name": "K8sClusterConfig",
  "catalog": "mycatalog-xxx",
  "description": "Kubernetes cluster kubeconfig",
  "version": 1,
  "keys": {
    "kubeconfig": { "type": "object", "sensitive": true }
  },
  "values": {
    "kubeconfig": "{\"apiVersion\":\"v1\",\"kind\":\"Config\",\"clusters\":[...],\"users\":[...],\"contexts\":[...]}"
  }
}

Best Practices

  1. Separate inputs by environment - Create distinct inputs for dev/staging/prod
  2. Mark sensitive values - Always set "sensitive": true for passwords, tokens, and keys
  3. Use descriptive names - Include region/environment in the name (e.g., CfCredentials-EU10-Prod)
  4. Keep inputs minimal - Store only reusable values; command-specific values go in inputValues at trigger time

Utility Patterns

Export Command to File

COMMAND_ID="mycatalog-xxx:MyCommand:1"
OUTPUT_FILE="MyCommand.command.json"

curl -s -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  "https://$AUTOPI_HOSTNAME/api/v1/commands/$COMMAND_ID" > "$OUTPUT_FILE"

echo "Command exported to $OUTPUT_FILE"

Upload All Commands from Directory

DIRECTORY="./commands"

for file in "$DIRECTORY"/*.command.json; do
  echo "Uploading: $file"
  curl -s -X POST \
    -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
    -H "Content-Type: application/json" \
    -d @"$file" \
    "https://$AUTOPI_HOSTNAME/api/v1/commands"
done

Check if Command Exists

COMMAND_ID="mycatalog-xxx:MyCommand:1"
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  "https://$AUTOPI_HOSTNAME/api/v1/commands/$COMMAND_ID")

if [[ "$STATUS" == "200" ]]; then
  echo "Command exists"
elif [[ "$STATUS" == "404" ]]; then
  echo "Command not found"
else
  echo "Error: HTTP $STATUS"
fi

Create or Update Command (Upsert Pattern)

COMMAND_FILE="MyCommand.command.json"
COMMAND_ID=""

# Check if exists
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
  -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
  "https://$AUTOPI_HOSTNAME/api/v1/commands/$COMMAND_ID")

if [[ "$STATUS" == "200" ]]; then
  echo "Updating existing command..."
  curl -s -X PUT \
    -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
    -H "Content-Type: application/json" \
    -d @"$COMMAND_FILE" \
    "https://$AUTOPI_HOSTNAME/api/v1/commands/$COMMAND_ID"
else
  echo "Creating new command..."
  curl -s -X POST \
    -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" \
    -H "Content-Type: application/json" \
    -d @"$COMMAND_FILE" \
    "https://$AUTOPI_HOSTNAME/api/v1/commands"
fi

Error Handling

The API returns standard HTTP status codes:

| Code | Description | |------|-------------| | 200 | Success (GET, PUT) | | 201 | Created (POST) | | 204 | No Content (DELETE) | | 400 | Bad request - invalid JSON or missing required fields | | 401 | Unauthorized - invalid credentials | | 403 | Forbidden - insufficient permissions | | 404 | Not found - resource doesn't exist | | 409 | Conflict - resource already exists or invalid state | | 429 | Too many requests - rate limited | | 500 | Internal server error | | 503 | Service unavailable |

Always check the response for error messages:

RESPONSE=$(curl -s -w "\n%{http_code}" -u "$AUTOPI_USERNAME:$AUTOPI_PASSWORD" "https://$AUTOPI_HOSTNAME/api/v1/commands")
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | head -n -1)

if [[ "$HTTP_CODE" != "200" && "$HTTP_CODE" != "201" ]]; then
  echo "Error ($HTTP_CODE): $BODY"
  exit 1
fi

echo "$BODY"

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.