Agent Upgrade API
The Agent Upgrade API enables automated upgrading of software agents by listing available versions and triggering upgrades for specified agent installations in a single call
This document provides detailed information on using the Agent Upgrade API, designed to simplify and consolidate the agent upgrade process into two main endpoints for headless CI/CD usage.
Overview
The existing UI upgrade flow requires five sequential API calls under the internal /controller/restui/ path. With this API, you can consolidate these calls into two endpoints under /controller/rest/, designed for automated and headless CI/CD workflows:
| Endpoint | Method | Purpose |
|---|---|---|
/controller/rest/agent-management/v2/upgrades/versions |
GET | List available agent upgrade versions |
/controller/rest/agent-management/v2/upgrades |
POST | Trigger agent upgrade (validate and create in one call) |
/controller/restui/agent-management/inventory/tasks/ids with the following payload:
{
"requestFilter": [
12, 13
],
"resultColumns": [
],
"offset": 0,
"limit": 10,
"searchFilters": [],
"columnSorts": [],
"timeRangeStart": 0,
"timeRangeEnd": 0
}
{
"id": 1,
"version": 0,
"name": "Deploy updated configuration",
"type": "CONFIGURE",
"triggerTs": 1762941714549,
"createdBy": 5,
"createTs": 1762941714549,
"modifiedBy": 5,
"modifyTs": 1762941714549,
"accountId": 2,
"deployments": [
{
"id": 1,
"version": 1,
"taskId": 1,
"agentType": "SMART_AGENT",
"smartAgentId": "01K2KDF2TZA83RP71HB6WB40XN",
"agentInstanceId": "01K2KDF2TZA83RP71HB6WB40XN",
"configYaml": "{}\n",
"configHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"configFilesJson": "[{\"fileName\":\"config.json\",\"fileFormat\":\"json\",\"fileContent\":\"{\\\"key\\\": \\\"value\\\"}\",\"targetPath\":\"/opt/appdynamics/config/\"}]",
"status": "TRIGGERED",
"logs": "",
"agentId": null,
"endTs": 1762941714550,
"deploymentV1": 0,
"config": {}
}
],
"profileId": 0
}
Prerequisites
curl -X POST "https://<controller-host>/controller/rest/v2/agent-management/inventory/query"
-H "Content-Type: application/json"
-u "user@account:password"
-d '{ "agentType": "SMART_AGENT", "limit": 25, "offset": 0 }'
-
agentId: legacy agent entity ID
-
agentInstallationV2: agent installation V2 ID (use this as the value for
agentInstallationIdsin the upgrade API).For example, if the inventory response contains
"agentId": 100,"agentInstallationV2": 2, pass"agentInstallationIds": [2]to the upgrade API.
Get Available Upgrade Versions
Endpoint: GET /controller/rest/agent-management/v2/upgrades/versions?agentType={agentType}
Description: Returns a list of available agent versions that can be used as the targetVersion in an upgrade request. Versions are ordered from newest to oldest.
Authorization: Requires Agent Management Viewer role (read-only access).
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| agentType | String | Agent type (see Supported Agent Types below) |
Supported Agent Types:
| agentType Value | Description | Aliases (also accepted) |
|---|---|---|
| SMART_AGENT | Smart Agent | smart_agent, smartagent |
| APP_AGENT | Java App Server Agent | app, java, java_agent |
| MACHINE_AGENT | Machine Agent | machine, machine_agent |
| DB_AGENT | Database Agent | db, db_agent |
| DOT_NET_APP_AGENT | .NET Agent | dotnet, .net, dot_net |
| PHP_APP_AGENT | PHP Agent | php |
| NODEJS_APP_AGENT | Node.js Agent | node, nodejs |
| PYTHON_APP_AGENT | Python Agent | python |
| NATIVE_WEB_SERVER | Native Web Server Agent | webserver |
Sample Request:
curl -X GET "https://<controller-host>/controller/rest/agent-management/v2/upgrades/versions?agentType=SMART_AGENT"
-H "Accept: application/json"
-u "user@account:password"
Sample Response (200 OK):
{ "agentType": "SMART_AGENT", "versions": [ "26.2.0.779", "25.12.0.661", "25.10.0.500", "25.8.0.432" ] }
Error Responses:
| Status Code | Condition | Example |
|---|---|---|
| 400 Bad Request | Missing or invalid agentType |
{"code":"validation-1","message":"Invalid agentType 'UNKNOWN'..."} |
| 403 Forbidden | Caller lacks viewer role | {"code":"auth-1","message":"Agent management viewer role required"} |
Upgrade Agents
Endpoint:
POST /controller/rest/agent-management/v2/upgrades
Description: Triggers an agent upgrade in a single atomic call. This endpoint performs:
- Validation: checks all agents for eligibility (active smart agent, no pending deployments).
- Agent resolution: looks up smart agent IDs and metadata from installation IDs.
- Config generation: builds the deployment YAML config from the provided parameters.
- Task creation & trigger: creates the upgrade task and triggers it to the Fleet Management service.
Authorization: Requires Agent Management Admin role.
Request Body:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| agentInstallationIds | List<Long> | Yes | — | Agent installation V2 IDs to upgrade. Use agentInstallationV2 from inventory API response. |
| agentType | String | Yes | — | Agent type (see Supported Agent Types above). |
| targetVersion | String | Yes | — | Version to upgrade to (from versions API). |
| downloadSource | String | No | "appd" | Download source: appd (AppD portal), local (local directory), http (HTTP URL), npm (npm registry, Node.js only). |
| downloadUri | String | Conditional | null | Required when downloadSource is local or http. Local file path or HTTP URL to the agent binary. |
| enableSsl | Boolean | No | true | Whether to enable SSL for agent-to-controller communication. |
| reuseConfig | Boolean | No | true | Whether to reuse existing agent config. |
| customConfig | Map<String, String> | No | null | Additional key-value properties for the deployment YAML (e.g., sim_enabled, flags). Reserved keys are silently ignored. |
| skipIneligible | Boolean | No | true | If true, skip ineligible agents and proceed. If false, fail if any agent is ineligible. |
customConfig: The following keys are auto-derived from dedicated request fields and will be silently ignored if passed in customConfig:
-
install_agent_from
-
download_protocol, agent_version
-
download_uri, enable_ssl
-
reuse_config
Configuration Derivation Logic: The API automatically derives internal configuration fields based on the downloadSource value. You do not need to set install_agent_from because it is automatically determined by the server.
downloadSource |
Derived install_agent_from |
downloadUri Required? |
Notes |
|---|---|---|---|
| appd (default) | appd-portal | No | Downloads from AppDynamics portal |
| local | local | Yes (local path) | This is an example: /opt/agents/binaries |
| http | http | Yes (HTTP URL) | This is an example: https://artifacts.example.com/agent.zip |
| npm | — | No | Only valid for NODEJS_APP_AGENT |
Sample Requests:
Minimal (Default Upgrade):
# agentInstallationIds should contain agentInstallationV2 values from the inventory API
curl -X POST "https://<controller-host>/controller/rest/agent-management/v2/upgrades" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-u "user@account:password" \
-d '{
"agentInstallationIds": [1, 2, 3],
"agentType": "SMART_AGENT",
"targetVersion": "26.2.0.779"
}'
Full (Custom Upgrade):
curl -X POST "https://<controller-host>/controller/rest/agent-management/v2/upgrades" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-u "user@account:password" \
-d '{
"agentInstallationIds": [1, 2, 3],
"agentType": "SMART_AGENT",
"targetVersion": "26.2.0.779",
"downloadSource": "http",
"downloadUri": "https://artifacts.example.com/smart-agent-26.2.0.779.zip",
"enableSsl": true,
"reuseConfig": true,
"customConfig": {
"flags": "-Dsome.property=value",
"sim_enabled": "true"
},
"skipIneligible": true
}'
Sample Request for Node.js Agent using npm
curl -X POST "https://<controller-host>/controller/rest/agent-management/v2/upgrades" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-u "user@account:password" \
-d '{
"agentInstallationIds": [5, 6],
"agentType": "NODEJS_APP_AGENT",
"targetVersion": "26.1.0.100",
"downloadSource": "npm"
}'
curl -X POST "https://<controller-host>/controller/rest/agent-management/v2/upgrades" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-u "user@account:password" \
-d '{
"agentInstallationIds": [1],
"agentType": "SMART_AGENT",
"targetVersion": "26.2.0.779",
"downloadSource": "local",
"downloadUri": "/opt/agents/binaries"
}'
{
"taskId": 456,
"status": "TRIGGERED",
"deploymentCount": 3,
"deployments": [
{
"deploymentId": 4561,
"agentId": 1,
"status": "TRIGGERED",
"agentType": "SMART_AGENT"
},
{
"deploymentId": 4562,
"agentId": 2,
"status": "TRIGGERED",
"agentType": "SMART_AGENT"
},
{
"deploymentId": 4563,
"agentId": 3,
"status": "TRIGGERED",
"agentType": "SMART_AGENT"
}
],
"skippedAgents": {}
}
{
"taskId": 457,
"status": "TRIGGERED",
"deploymentCount": 1,
"deployments": [
{
"deploymentId": 4571,
"agentId": 1,
"status": "TRIGGERED",
"agentType": "SMART_AGENT"
}
],
"skippedAgents": {
"INACTIVE_SMART_AGENT": [2],
"EXISTING_DEPLOYMENTS": [3]
}
}
{
"taskId": 0,
"status": "NO_ELIGIBLE_AGENTS",
"deploymentCount": 0,
"deployments": [],
"skippedAgents": {
"INACTIVE_SMART_AGENT": [1, 2, 3]
}
}
Error Responses:
| Status Code | Condition | Description |
|---|---|---|
| 400 Bad Request | Missing/invalid required fields | Missing agentInstallationIds, agentType, or targetVersion; invalid agentType or downloadSource value; missing downloadUri when required; npm used for non-Node.js agent |
| 403 Forbidden | Insufficient permissions | Caller does not have Agent Management Admin role |
| 409 Conflict | Ineligible agents with skipIneligible=false |
Some or all agents failed validation; response body contains details |
| 500 Internal Server Error | Server-side failure | Task creation failed, Fleet Management service unavailable, etc. |
Error Response Format:
{
"code": "validation-1",
"message": "agentInstallationIds is required and cannot be empty",
"refCode": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
Security Considerations
-
Basic Auth:
username@accountname:password -
API Token:
username@accountname:api-token
Session cookies (as used by the UI) are not required. These APIs are designed for headless/automated access.
Authorization (RBAC)
The following roles are required for API access:
| Endpoint | Required Role |
|---|---|
| GET /upgrades/versions | Agent Management Viewer |
| POST /upgrades | Agent Management Admin |
Additionally, the upgrade endpoint enforces per-agent RBAC: the caller can only upgrade agents they have permission to manage. Agents outside the caller's permission scope are silently excluded.
Account Isolation
The buildAgentInfoForUpgrade method verifies that all requested agent installation IDs belong to the account associated with the request. Cross-account upgrade attempts are rejected to ensure account isolation.
Input Sanitization
- Controller host name and port values in the deployment configuration are sanitized to ensure proper YAML string output.
- The
customConfigmap values are added as strings to prevent injection into the Ansible playbook YAML. - Reserved configuration keys (
install_agent_from,download_protocol,agent_version,download_uri,enable_ssl,reuse_config) are silently stripped fromcustomConfigto prevent callers from overriding auto-derived internal values. - Sensitive fields such as account access key and account name are populated server-side and never accepted from the client.
- Unknown fields in the request JSON are silently ignored (
@JsonIgnoreProperties(ignoreUnknown = true)).
Audit Logging
Every upgrade request is logged with the following details for traceability and auditing:
- Unique reference code (
refCode) - User identity and account ID
- Number of agents targeted and number skipped
- Task ID created
CI/CD Pipeline Example
#!/bin/bash
set -euo pipefail
CONTROLLER="https://controller.example.com:8090"
AUTH="apiuser@customer1:api-token-here"
# Step 1: Discover agents to upgrade
echo "=== Discovering agents ==="
AGENTS=$(curl -s -X POST "$CONTROLLER/controller/rest/v2/agent-management/inventory/query" \
-H "Content-Type: application/json" \
-u "$AUTH" \
-d '{
"agentType": "SMART_AGENT",
"limit": 100,
"offset": 0,
"filters": [
{ "field": "VERSION_STATUS", "operator": "IN", "value": ["UpdateAvailable"] }
]
}')
# IMPORTANT: Use agentInstallationV2 (not agentId) for the upgrade API
AGENT_INSTALLATION_IDS=$(echo "$AGENTS" | jq '[.data[].agentInstallationV2]')
echo "Found agent installation IDs: $AGENT_INSTALLATION_IDS"
# Step 2: Check available versions
echo "=== Checking available versions ==="
VERSIONS=$(curl -s -X GET "$CONTROLLER/controller/rest/agent-management/v2/upgrades/versions?agentType=SMART_AGENT" \
-H "Accept: application/json" \
-u "$AUTH")
LATEST=$(echo "$VERSIONS" | jq -r '.versions[0]')
echo "Latest version: $LATEST"
# Step 3: Trigger upgrade
echo "=== Triggering upgrade to $LATEST ==="
RESULT=$(curl -s -w "\n%{http_code}" -X POST "$CONTROLLER/controller/rest/agent-management/v2/upgrades" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-u "$AUTH" \
-d "{
\"agentInstallationIds\": $AGENT_INSTALLATION_IDS,
\"agentType\": \"SMART_AGENT\",
\"targetVersion\": \"$LATEST\",
\"skipIneligible\": true
}")
HTTP_CODE=$(echo "$RESULT" | tail -1)
BODY=$(echo "$RESULT" | head -1)
if [ "$HTTP_CODE" = "201" ]; then
TASK_ID=$(echo "$BODY" | jq '.taskId')
DEPLOY_COUNT=$(echo "$BODY" | jq '.deploymentCount')
echo "SUCCESS: Task $TASK_ID created with $DEPLOY_COUNT deployments"
echo "Track progress using task ID $TASK_ID via the existing task status API."
else
echo "FAILED: HTTP $HTTP_CODE - $BODY"
exit 1
fi