Skip to main content

PAP Agents API Reference

This document provides comprehensive API documentation for creating and managing PAP agents.

Base URL

https://plugged.in/api/agents

Authentication

All endpoints require API key authentication via the Authorization header:
Authorization: Bearer YOUR_API_KEY
API Keys: Generate API keys from your Plugged.in project settings. Keys are scoped to profiles within projects.

Endpoints

List Agents

Retrieve all agents for the authenticated user’s active profile.
curl https://plugged.in/api/agents \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

[
  {
    "uuid": "123e4567-e89b-12d3-a456-426614174000",
    "name": "my-agent",
    "dns_name": "my-agent.is.plugged.in",
    "state": "ACTIVE",
    "kubernetes_namespace": "agents",
    "kubernetes_deployment": "my-agent",
    "created_at": "2025-11-13T08:00:00Z",
    "provisioned_at": "2025-11-13T08:00:15Z",
    "activated_at": "2025-11-13T08:00:45Z",
    "terminated_at": null,
    "last_heartbeat_at": "2025-11-13T08:05:30Z",
    "metadata": {
      "description": "My autonomous agent",
      "image": "nginxinc/nginx-unprivileged:alpine",
      "resources": {
        "cpu_request": "100m",
        "memory_request": "256Mi",
        "cpu_limit": "1000m",
        "memory_limit": "1Gi"
      }
    }
  }
]

Response Fields

FieldTypeDescription
uuidUUIDUnique agent identifier
namestringDNS-safe agent name
dns_namestringFull DNS hostname ({name}.is.plugged.in)
stateenumCurrent lifecycle state (see Lifecycle)
kubernetes_namespacestringKubernetes namespace (typically “agents”)
kubernetes_deploymentstringDeployment name in Kubernetes
created_attimestampWhen agent was created
provisioned_attimestampWhen Kubernetes resources were deployed
activated_attimestampWhen agent sent first heartbeat
terminated_attimestampWhen agent was terminated (null if active)
last_heartbeat_attimestampLast heartbeat received (null if no heartbeats yet)
metadataobjectAgent configuration and metadata

Create Agent

Deploy a new PAP agent to Kubernetes infrastructure.
curl -X POST https://plugged.in/api/agents \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-agent",
    "description": "My autonomous agent",
    "resources": {
      "cpu_request": "100m",
      "memory_request": "256Mi",
      "cpu_limit": "1000m",
      "memory_limit": "1Gi"
    }
  }'

Request Body

FieldTypeRequiredDescription
namestringYesDNS-safe agent name (lowercase, alphanumeric, hyphens)
descriptionstringNoHuman-readable description
imagestringNoContainer image (default: nginxinc/nginx-unprivileged:alpine)
resourcesobjectNoResource requests and limits
resources.cpu_requeststringNoCPU request (e.g., “100m”, default: “100m”)
resources.memory_requeststringNoMemory request (e.g., “256Mi”, default: “256Mi”)
resources.cpu_limitstringNoCPU limit (e.g., “1000m”, default: “1000m”)
resources.memory_limitstringNoMemory limit (e.g., “1Gi”, default: “1Gi”)
DNS-Safe Names: Agent names must match the pattern ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$. Invalid names will return HTTP 400.

Response (Success)

{
  "agent": {
    "uuid": "123e4567-e89b-12d3-a456-426614174000",
    "name": "my-agent",
    "dns_name": "my-agent.is.plugged.in",
    "state": "NEW",
    "kubernetes_namespace": "agents",
    "kubernetes_deployment": "my-agent",
    "created_at": "2025-11-13T08:00:00Z",
    "provisioned_at": null,
    "activated_at": null,
    "terminated_at": null,
    "last_heartbeat_at": null,
    "metadata": {
      "description": "My autonomous agent",
      "resources": {
        "cpu_request": "100m",
        "memory_request": "256Mi",
        "cpu_limit": "1000m",
        "memory_limit": "1Gi"
      }
    }
  },
  "deployment": {
    "success": true,
    "message": "Agent my-agent deployed successfully",
    "deploymentName": "my-agent"
  }
}

Error Responses

StatusErrorDescription
400Name is requiredMissing name field
400Name must be DNS-safe: lowercase alphanumeric and hyphens onlyInvalid name format
401UnauthorizedMissing or invalid API key
409Agent with this name already existsDuplicate agent name in profile
500Failed to create agentInternal server error

Get Agent Details

Retrieve comprehensive information about a specific agent, including recent heartbeats, metrics, and lifecycle events.
curl https://plugged.in/api/agents/AGENT_UUID \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "agent": {
    "uuid": "123e4567-e89b-12d3-a456-426614174000",
    "name": "my-agent",
    "dns_name": "my-agent.is.plugged.in",
    "state": "ACTIVE",
    "created_at": "2025-11-13T08:00:00Z",
    "last_heartbeat_at": "2025-11-13T08:05:30Z",
    "metadata": {...}
  },
  "recentHeartbeats": [
    {
      "id": "1001",
      "agent_uuid": "123e4567-e89b-12d3-a456-426614174000",
      "mode": "IDLE",
      "uptime_seconds": 330,
      "timestamp": "2025-11-13T08:05:30Z"
    }
  ],
  "recentMetrics": [
    {
      "id": "2001",
      "agent_uuid": "123e4567-e89b-12d3-a456-426614174000",
      "cpu_percent": 12,
      "memory_mb": 128,
      "requests_handled": 45,
      "custom_metrics": {},
      "timestamp": "2025-11-13T08:05:00Z"
    }
  ],
  "lifecycleEvents": [
    {
      "id": "3001",
      "agent_uuid": "123e4567-e89b-12d3-a456-426614174000",
      "event_type": "ACTIVATED",
      "from_state": "PROVISIONED",
      "to_state": "ACTIVE",
      "metadata": {
        "triggered_by": "system"
      },
      "timestamp": "2025-11-13T08:00:45Z"
    }
  ],
  "kubernetesStatus": {
    "ready": true,
    "replicas": 1,
    "readyReplicas": 1,
    "unavailableReplicas": 0,
    "conditions": [
      {
        "type": "Available",
        "status": "True",
        "reason": "MinimumReplicasAvailable",
        "message": "Deployment has minimum availability."
      }
    ]
  }
}

Response Fields

FieldTypeDescription
agentobjectCore agent metadata (same as list response)
recentHeartbeatsarrayLast 10 heartbeats (ordered newest first)
recentMetricsarrayLast 10 metric reports (ordered newest first)
lifecycleEventsarrayComplete lifecycle event history (ordered newest first)
kubernetesStatusobjectReal-time Kubernetes deployment status (null if not deployed)

Error Responses

StatusErrorDescription
401UnauthorizedMissing or invalid API key
404Agent not foundAgent doesn’t exist or doesn’t belong to profile
500Failed to fetch agentInternal server error

Delete Agent

Terminate and delete an agent, removing all Kubernetes resources.
curl -X DELETE https://plugged.in/api/agents/AGENT_UUID \
  -H "Authorization: Bearer YOUR_API_KEY"

Response (Success)

{
  "message": "Agent terminated successfully",
  "kubernetes": {
    "success": true,
    "message": "Agent my-agent deleted successfully"
  }
}
State Transition: User-initiated deletion transitions agent to TERMINATED state. Only the Station (control plane) can issue KILLED state.

Cleanup Operations

The DELETE operation removes:
  • Kubernetes Deployment
  • Kubernetes Service
  • Kubernetes Ingress
  • TLS Secret (Let’s Encrypt certificate)
The agent record remains in database with state=TERMINATED for audit purposes.

Error Responses

StatusErrorDescription
401UnauthorizedMissing or invalid API key
404Agent not foundAgent doesn’t exist or doesn’t belong to profile
500Failed to delete agentInternal server error

Common Patterns

Create and Wait for Activation

#!/bin/bash

# Create agent
RESPONSE=$(curl -s -X POST https://plugged.in/api/agents \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "test-agent"}')

AGENT_UUID=$(echo $RESPONSE | jq -r '.agent.uuid')
echo "Created agent: $AGENT_UUID"

# Poll until ACTIVE
while true; do
  STATE=$(curl -s https://plugged.in/api/agents/$AGENT_UUID \
    -H "Authorization: Bearer $API_KEY" \
    | jq -r '.agent.state')

  echo "Current state: $STATE"

  if [ "$STATE" = "ACTIVE" ]; then
    echo "Agent is now ACTIVE!"
    break
  fi

  sleep 5
done

List Healthy Agents

// Fetch all agents and filter by state
const response = await fetch('https://plugged.in/api/agents', {
  headers: { 'Authorization': `Bearer ${API_KEY}` }
});

const agents = await response.json();

const healthy = agents.filter(agent =>
  agent.state === 'ACTIVE' &&
  agent.last_heartbeat_at &&
  (Date.now() - new Date(agent.last_heartbeat_at) < 60000) // < 1 minute ago
);

console.log(`${healthy.length} healthy agents`);

Bulk Termination

import requests

# Get all agents
response = requests.get(
    'https://plugged.in/api/agents',
    headers={'Authorization': f'Bearer {API_KEY}'}
)
agents = response.json()

# Filter agents to terminate (e.g., by name pattern)
to_terminate = [a for a in agents if a['name'].startswith('test-')]

# Terminate each
for agent in to_terminate:
    response = requests.delete(
        f'https://plugged.in/api/agents/{agent["uuid"]}',
        headers={'Authorization': f'Bearer {API_KEY}'}
    )
    print(f"Terminated {agent['name']}: {response.json()}")

Rate Limits

API endpoints are subject to rate limits to ensure fair usage:
TierRequests per MinuteBurst
Free6010
Pro30050
Enterprise1000100
Rate limit headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1699999999
429 Too Many Requests: If you exceed rate limits, wait for the reset time indicated in X-RateLimit-Reset header.

Webhook Events (Coming Soon)

Subscribe to agent lifecycle events via webhooks:
{
  "event": "agent.activated",
  "agent_uuid": "...",
  "agent_name": "my-agent",
  "timestamp": "2025-11-13T08:00:45Z",
  "data": {
    "from_state": "PROVISIONED",
    "to_state": "ACTIVE"
  }
}
Available Events:
  • agent.created
  • agent.provisioned
  • agent.activated
  • agent.draining
  • agent.terminated
  • agent.killed
  • agent.unhealthy

SDK Support

Official SDKs for popular languages (coming soon):

TypeScript/Node.js

npm install @pluggedin/agents-sdk

Python

pip install pluggedin-agents

Go

go get github.com/pluggedin/agents-go

Next Steps