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
Field Type Description uuidUUID Unique agent identifier namestring DNS-safe agent name dns_namestring Full DNS hostname ({name}.is.plugged.in) stateenum Current lifecycle state (see Lifecycle ) kubernetes_namespacestring Kubernetes namespace (typically “agents”) kubernetes_deploymentstring Deployment name in Kubernetes created_attimestamp When agent was created provisioned_attimestamp When Kubernetes resources were deployed activated_attimestamp When agent sent first heartbeat terminated_attimestamp When agent was terminated (null if active) last_heartbeat_attimestamp Last heartbeat received (null if no heartbeats yet) metadataobject Agent 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
Field Type Required Description namestring Yes DNS-safe agent name (lowercase, alphanumeric, hyphens) descriptionstring No Human-readable description imagestring No Container image (default: nginxinc/nginx-unprivileged:alpine) resourcesobject No Resource requests and limits resources.cpu_requeststring No CPU request (e.g., “100m”, default: “100m”) resources.memory_requeststring No Memory request (e.g., “256Mi”, default: “256Mi”) resources.cpu_limitstring No CPU limit (e.g., “1000m”, default: “1000m”) resources.memory_limitstring No Memory 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
Status Error Description 400 Name is requiredMissing name field 400 Name must be DNS-safe: lowercase alphanumeric and hyphens onlyInvalid name format 401 UnauthorizedMissing or invalid API key 409 Agent with this name already existsDuplicate agent name in profile 500 Failed 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
Field Type Description agentobject Core agent metadata (same as list response) recentHeartbeatsarray Last 10 heartbeats (ordered newest first) recentMetricsarray Last 10 metric reports (ordered newest first) lifecycleEventsarray Complete lifecycle event history (ordered newest first) kubernetesStatusobject Real-time Kubernetes deployment status (null if not deployed)
Error Responses
Status Error Description 401 UnauthorizedMissing or invalid API key 404 Agent not foundAgent doesn’t exist or doesn’t belong to profile 500 Failed 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
Status Error Description 401 UnauthorizedMissing or invalid API key 404 Agent not foundAgent doesn’t exist or doesn’t belong to profile 500 Failed to delete agentInternal server error
Export Agent Data
Export complete agent data including telemetry history for backup or analysis.
curl -X POST https://plugged.in/api/agents/AGENT_UUID/export \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"include_telemetry": true,
"telemetry_limit": 1000
}'
Request Body
Field Type Required Description include_telemetryboolean No Include heartbeat and metrics history (default: true) telemetry_limitinteger No Maximum telemetry records to include (default: 100)
Response
Returns complete agent data including configuration, lifecycle events, and telemetry:
{
"agent" : {
"uuid" : "..." ,
"name" : "my-agent" ,
"dns_name" : "my-agent.is.plugged.in" ,
"state" : "ACTIVE" ,
...
},
"heartbeats" : [ ... ],
"metrics" : [ ... ],
"lifecycle_events" : [ ... ],
"metadata" : {
"exported_at" : "2025-11-13T08:15:00Z" ,
"triggered_by" : "user-uuid" ,
"total_heartbeats" : 250 ,
"total_metrics" : 240
}
}
Submit Heartbeat
Agents send heartbeats to signal liveness. Heartbeats contain ONLY liveness data (zombie prevention).
CRITICAL : Heartbeats must contain ONLY mode and uptime_seconds. Never include resource data (CPU, memory) in heartbeats—use the Metrics endpoint instead. This separation is the core of PAP’s zombie prevention.
curl -X POST https://plugged.in/api/agents/AGENT_UUID/heartbeat \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "IDLE",
"uptime_seconds": 330
}'
Request Body
Field Type Required Description modeenum Yes Heartbeat mode: EMERGENCY (5s), IDLE (30s), SLEEP (15min) uptime_secondsnumber Yes Agent uptime in seconds
Heartbeat Intervals :
EMERGENCY : Every 5 seconds (for critical situations)
IDLE : Every 30 seconds (default)
SLEEP : Every 15 minutes (for low-priority background agents)
Missing one interval triggers AGENT_UNHEALTHY (error code 480).
Response
{
"message" : "Heartbeat recorded"
}
Submit Metrics
Agents send metrics separately from heartbeats. Metrics contain resource telemetry only.
Separation is Key : Metrics are sent on a separate channel from heartbeats (typically every 60 seconds). This ensures large telemetry payloads cannot starve the control path.
curl -X POST https://plugged.in/api/agents/AGENT_UUID/metrics \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"cpu_percent": 12.5,
"memory_mb": 128,
"requests_handled": 45,
"custom_metrics": {
"queue_depth": 3,
"cache_hit_rate": 0.85
}
}'
Request Body
Field Type Required Description cpu_percentnumber Yes CPU usage percentage (0-100) memory_mbnumber Yes Memory usage in megabytes requests_handledinteger Yes Total requests handled since start custom_metricsobject No Agent-specific custom metrics
Response
{
"message" : "Metrics recorded"
}
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:
Tier Requests per Minute Burst Free 60 10 Pro 300 50 Enterprise 1000 100
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 Plugged.in SDKs now include agent management:
TypeScript/Node.js npm install pluggedinkit-js
Access via client.agents
Go go get github.com/pluggedin/pluggedinkit-go
Access via client.Agents
SDK Examples
import { PluggedInClient } from 'pluggedinkit-js' ;
const client = new PluggedInClient ({
apiKey: process . env . PLUGGEDIN_API_KEY
});
// Create an agent
const result = await client . agents . create ({
name: 'my-agent' ,
description: 'My first PAP agent' ,
resources: {
cpu_request: '100m' ,
memory_request: '256Mi' ,
cpu_limit: '1000m' ,
memory_limit: '1Gi'
}
});
console . log ( `Agent created: ${ result . agent . uuid } ` );
console . log ( `DNS: ${ result . agent . dns_name } ` );
// List all agents
const agents = await client . agents . list ();
// Get agent details
const details = await client . agents . get ( agentId );
// Send heartbeat (from within agent)
await client . agents . heartbeat ( agentId , {
mode: 'IDLE' ,
uptime_seconds: process . uptime ()
});
// Send metrics (from within agent)
await client . agents . metrics ( agentId , {
cpu_percent: 12.5 ,
memory_mb: 128 ,
requests_handled: 45
});
// Export agent data
const exportData = await client . agents . export ( agentId , {
include_telemetry: true ,
telemetry_limit: 1000
});
// Delete agent
await client . agents . delete ( agentId );
from pluggedinkit import PluggedInClient
client = PluggedInClient( api_key = os.getenv( 'PLUGGEDIN_API_KEY' ))
# Create an agent
result = client.agents.create({
'name' : 'my-agent' ,
'description' : 'My first PAP agent' ,
'resources' : {
'cpu_request' : '100m' ,
'memory_request' : '256Mi' ,
'cpu_limit' : '1000m' ,
'memory_limit' : '1Gi'
}
})
print ( f "Agent created: { result[ 'agent' ][ 'uuid' ] } " )
print ( f "DNS: { result[ 'agent' ][ 'dns_name' ] } " )
# List all agents
agents = client.agents.list()
# Get agent details
details = client.agents.get(agent_id)
# Send heartbeat (from within agent)
client.agents.heartbeat(
agent_id,
mode = 'IDLE' ,
uptime_seconds = time.process_time()
)
# Send metrics (from within agent)
client.agents.metrics(
agent_id,
cpu_percent = 12.5 ,
memory_mb = 128 ,
requests_handled = 45
)
# Export agent data
export_data = client.agents.export(
agent_id,
include_telemetry = True ,
telemetry_limit = 1000
)
# Delete agent
client.agents.delete(agent_id)
package main
import (
" context "
" fmt "
" os "
" github.com/pluggedin/pluggedinkit-go "
)
func main () {
client := pluggedinkit . NewClient ( os . Getenv ( "PLUGGEDIN_API_KEY" ))
ctx := context . Background ()
// Create an agent
result , err := client . Agents . Create ( ctx , pluggedinkit . CreateAgentRequest {
Name : "my-agent" ,
Description : strPtr ( "My first PAP agent" ),
Resources : & pluggedinkit . ResourceRequirements {
CPURequest : strPtr ( "100m" ),
MemoryRequest : strPtr ( "256Mi" ),
CPULimit : strPtr ( "1000m" ),
MemoryLimit : strPtr ( "1Gi" ),
},
})
if err != nil {
panic ( err )
}
fmt . Printf ( "Agent created: %s \n " , result . Agent . UUID )
fmt . Printf ( "DNS: %s \n " , result . Agent . DNSName )
// List all agents
agents , err := client . Agents . List ( ctx )
// Get agent details
details , err := client . Agents . Get ( ctx , agentID )
// Send heartbeat (from within agent)
_ , err = client . Agents . Heartbeat ( ctx , agentID , "IDLE" , 330.0 )
// Send metrics (from within agent)
_ , err = client . Agents . Metrics ( ctx , agentID , 12.5 , 128 , 45 , nil )
// Export agent data
exportData , err := client . Agents . Export ( ctx , agentID , true , 1000 )
// Delete agent
_ , err = client . Agents . Delete ( ctx , agentID )
}
func strPtr ( s string ) * string { return & s }
Next Steps
Lifecycle Management Understand agent states and transitions
Monitoring Guide Set up observability for your agents