Start here

Connect an existing app

You do not restructure the app. You register it, set four environment variables, install agent-control-panel, and wait for the first heartbeat.

Create the app and agents

Register the app and create its agents in the dashboard. Copy the agent ID into ACP_AGENT_ID. Each SDK client represents one agent; create a client for each agent you want to report.

Set four environment variables

Server environment
ACP_URL=https://acp.skaigroup.tech
ACP_API_KEY=acp_…          # shown once at creation
ACP_AGENT_ID=agt_84c1       # the agent this process reports as
ACP_WEBHOOK_SECRET=…       # shared with the receiver

createClient throws at startup if url, apiKey, agentId or webhookSecret is missing; it refuses to accept unsigned control commands. Everything after startup is fail-open.

Install the SDK and mount one route

Save the generated file as acp.ts. The webhook handler reads the raw body to verify the HMAC, so it must not sit behind express.json().

acp.ts · agent-control-panel
// npm i agent-control-panel
import { createClient } from "agent-control-panel";

export const acp = createClient({
  url: process.env.ACP_URL,
  apiKey: process.env.ACP_API_KEY,
  agentId: process.env.ACP_AGENT_ID,
  webhookSecret: process.env.ACP_WEBHOOK_SECRET,
});

acp.start();

// Mount without express.json() — the handler needs the raw body.
app.post("/api/acp/webhook", acp.expressWebhookHandler());

The long-form generated client is still available for apps that cannot add a dependency. It is the same protocol written out by hand.

Confirm the first heartbeat

The client sends one heartbeat immediately, then every 30 seconds. The dashboard marks the app connected on the first accepted beat.

Connected on first accepted heartbeat