API reference
Control Tower has two programmatic surfaces: the HTTP API served by
agenticops-control-tower serve (or create_app()), and the Python API
(ControlTowerAPI), which the HTTP layer and CLI both use. The routes below are
taken from api/http.py in 0.8.0. While the server runs, FastAPI's generated
OpenAPI page at /docs lists the exact request and response schemas.
Authentication
Send Authorization: Bearer <token>. Roles come from the server's configured
tokens (server settings):
| Role column | Accepted tokens |
|---|---|
| read | reader, writer or approval token (anonymous if no tokens are configured) |
| write | writer token (anonymous if no tokens are configured) |
| operator | any configured token; the route then checks the role it needs (writer to propose and execute, approval token to approve, deny and revoke). Anonymous access is refused. |
Errors: 401 missing or invalid token, 403 wrong role, 404 unknown agent,
409 rejected state transition, 411/413 missing or oversized body on
POST /evidence and POST /bulk/preview (limit 1 MiB).
HTTP routes
Inventory and health
| Method and path | Role | Purpose |
|---|---|---|
POST /agents/register |
write | Register an agent (AgentRegistrationPayload); returns 201 and the record. |
POST /agents/{agent_id}/heartbeat |
write | Record a heartbeat (HeartbeatPayload). |
GET /agents |
read | List agents. Query: status, environment, capability, missing_capability. |
GET /agents/{agent_id} |
read | One agent record. |
GET /capabilities |
read | Capability → versions across all agents. |
GET /status |
read | Fleet health and capability coverage. Query: environment. |
GET /versions |
read | Minimum-version assessment. Query: capability, minimum_version, environment. |
Evidence and posture
| Method and path | Role | Purpose |
|---|---|---|
POST /evidence |
write | {"link": {...}, "artifact": {...}, "gate": {...}}. Idempotent per observation. |
GET /agents/{agent_id}/evidence |
read | Per-producer posture for one agent. |
GET /agents/{agent_id}/evidence/history |
read | Stored records, newest first. |
GET /posture |
read | Fleet posture by producer. Query: environment, stale_after_seconds. |
Controlled configuration and bulk operations
| Method and path | Role | Purpose |
|---|---|---|
GET /agents/{agent_id}/config/{capability} |
read | Ownership, desired values and revision. |
GET /agents/{agent_id}/audit |
read | Configuration audit trail. |
POST /actions/preview |
operator (writer) | Create an immutable preview. |
GET /actions/{action_id} |
read | Read a stored proposal. |
POST /actions/{action_id}/approval |
operator (approver) | {"approved": true} or false. |
POST /actions/{action_id}/revoke |
operator (approver) | Revoke a pending or approved proposal. |
POST /actions/{action_id}/execute |
operator (writer) | Execute an approved, unexpired action. |
POST /bulk/preview, GET /bulk/{id}, POST /bulk/{id}/approval, POST /bulk/{id}/revoke, POST /bulk/{id}/execute |
operator | The same lifecycle for a frozen fleet target set. |
Alerts and incidents
| Method and path | Role | Purpose |
|---|---|---|
GET /alerts |
read | Query: environment, active_only. |
POST /alerts/evaluate |
operator (writer) | Run a detection scan now. |
POST /alerts/{alert_id}/acknowledge |
operator (writer) | Acknowledge an alert. |
GET /incidents, GET /incidents/{id}, GET /incidents/{id}/view |
operator | Read incidents; view is the joined timeline. |
POST /incidents/detect, POST /incidents/{id}/investigate, /preview, /approval, /revoke, /execute, /verify, /control/{action}, /reconcile |
operator | Approved staging recovery; see incident recovery. |
Console
| Method and path | Purpose |
|---|---|
GET /console/ |
The read-only console shell. It contains no fleet data; the page reads the routes above with the token you paste. Served with a restrictive Content-Security-Policy and Cache-Control: no-store. |
Python API
ControlTowerAPI is the facade every other surface goes through. The base
package (no api extra) is enough.
from agenticops_control_tower.snapshot import create_api, load_snapshot
api = create_api() # empty, in memory
api = load_snapshot("examples/sample_fleet_snapshot.json") # pre-filled, read-only use
print(api.get_status().degraded_agents)
1
| Method | Returns |
|---|---|
register(payload) / register_agent |
AgentRecord |
heartbeat(agent_id, payload) / record_heartbeat |
AgentRecord |
list_agents(*, status, environment, capability, missing_capability) |
list[AgentRecord] |
get_agent(agent_id) |
AgentRecord (raises AgentNotFoundError) |
get_agent_capabilities(agent_id) |
dict[str, str] |
list_capabilities() |
list[CapabilityInventoryRecord] |
list_all_capabilities() |
dict[str, list[str]] |
get_status(*, environment) |
FleetStatusSummary |
assess_versions(capability, minimum_version, *, environment) |
list[VersionAssessment] |
summarize_evidence(link, artifact, *, gate) |
EvidenceSummary (not stored) |
ingest_evidence(request, *, ingested_by) |
EvidenceIngestResult |
evidence_history(agent_id, *, source, limit) |
list[EvidenceRecord] |
agent_posture(agent_id, *, stale_after_seconds, now) |
AgentEvidencePosture |
fleet_posture(*, environment, stale_after_seconds, now) |
FleetEvidencePosture |
Further services hang off the facade: api.config (controlled configuration),
api.bulk (fleet operations), api.operations (detection, alerts, incident
views) and api.incidents (investigation and recovery). Their usage is shown in
examples/controlled_configuration.py, examples/fleet_operations.py,
examples/live_operations.py and examples/incident_recovery.py.
Models are importable from agenticops_control_tower.models, including
AgentRegistrationPayload, HeartbeatPayload, AgentRecord, AgentStatus,
EvidenceIngestRequest and FleetStatusSummary.
To serve HTTP from your own process, see server settings → Python hosts.