Skip to main content
Home›Docs›API Reference›Agents and runs
API Reference

Agents and runs

Create and manage autonomous agents, control their isolated runtimes, dispatch runs, and respond to approvals.

Agents and runs

An agent is an autonomous worker with its own isolated runtime. You create agents from a persona or a catalog template, manage their runtime lifecycle, configuration, and secrets, then dispatch work to them. A run is one execution of an agent; a run that pauses on a guardrail creates an approval a human answers before the run resumes.

Base URL: https://api.perceive8.com. Authenticate with X-API-Key: pk_live_... or Authorization: Bearer <jwt-or-key>. All endpoints are workspace-scoped: pass X-Workspace-Id (or the workspace_id query parameter); when omitted, your Personal workspace is used. {agent_id} and {run_id} path parameters are UUIDs.

Scopes

Scope Required for
mcp:agents:read Reading agents, runtimes, logs, configs, secret names, runs, approvals, templates
mcp:agents:run Dispatching runs; the agent webhook
mcp:agents:write Agent mutations, runtime lifecycle, config and secret writes, approval responses

API keys must carry the listed scope (or *). User-JWT callers bypass read scopes, but write operations require an admin or owner role in the workspace.

Agents

The agent object:

Field Type Description
id string (UUID) Agent ID
workspace_id string (UUID) Owning workspace
summoro_agent_id string | null Orchestrator-side ID; null until synced
name string Display name
persona string System prompt / persona
default_model_tier string Model tier (for example small)
skills string[] Enabled skills
has_sensitive_tools boolean True when skills include sensitive integrations (google, microsoft, hubspot, notion, n8n, whatsapp, telegram, calls)
runtime_kind string Runtime kind, for example openclaw
deployment_status string pending, published, or failed
guardrails object Guardrail configuration
created_at, updated_at string Timestamps (list/get responses only)
archived_at string | null Set when archived

GET /v1/agents

List non-archived agents in the workspace, newest first. Response: an array of agent objects.

curl https://api.perceive8.com/v1/agents \
  -H "X-API-Key: pk_live_xxxxxxxxxxxx" \
  -H "X-Workspace-Id: <workspace-uuid>"

POST /v1/agents

Create an agent and mirror it to the orchestrator. Requires mcp:agents:write (JWT: admin/owner).

Request body

{
  "name": "Support triager",
  "template_id": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
  "business_description": "B2B SaaS helpdesk, 40 seats",
  "communication_styles": ["concise"],
  "channels": ["email"],
  "skills": [],
  "guardrails": {}
}
Field Type Description
name string (required, 1–120 chars) Agent name
workspace_id string Optional; if sent, must match the active workspace
persona string System prompt; when omitted with template_id, compiled from the template
template_id string (UUID) Create from a catalog template (see GET /v1/agent-templates)
business_description, communication_styles string / string[] Template inputs folded into the compiled persona
channels string[] Channels the agent operates on
model_tier / default_model_tier string Model tier; defaults to the template tier, then small
skills string[] Skill slugs; defaults to the template's default_skills
guardrails object Guardrail configuration

Template-based creation compiles persona, skills, and tier from the template and fails with 400 if the template yields no skills. New agents get runtime_kind: "openclaw". Response: the agent object (without created_at/updated_at).

GET /v1/agents/{agent_id}

Get a single agent; 404 when archived or outside the workspace. Response: the agent object.

PATCH /v1/agents/{agent_id}

Update an agent and mirror the change. Requires mcp:agents:write (JWT: admin/owner). Archived agents cannot be updated (400).

Request body — all fields optional:

{
  "name": "Support triager v2",
  "persona": "You are a support triage assistant...",
  "default_model_tier": "medium",
  "skills": ["web_search", "email"],
  "guardrails": {}
}

Response: the updated agent object (without created_at/updated_at).

POST /v1/agents/{agent_id}/archive

Archive an agent and tear down its runtime. Requires mcp:agents:write. Response: the agent object with archived_at set.

Runtime lifecycle

GET /v1/agents/{agent_id}/runtime

Get current runtime status; null when the agent is not synced yet. The response is the orchestrator's runtime record:

Field Type Description
agent_id, workspace_id string Owning IDs
runtime_kind string Runtime kind
status string Runtime state (for example started, suspended)
fly_app, fly_machine_id, fly_region string Compute placement
fly_public_url string Public edge URL of the runtime
cpu_kind, cpu_count, memory_mb string / number Machine size
image_ref string Deployed image
last_seen_at, last_error string | null Health and last error
created_at, updated_at string Timestamps

POST /v1/agents/{agent_id}/runtime/provision

Provision the runtime. Requires mcp:agents:write.

Request body — all fields optional; runtime_kind and secrets are accepted but currently only region and image_ref are applied:

{ "region": "iad", "image_ref": "registry.fly.io/p8-runtime:latest" }

Response

{
  "agent_id": "2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
  "status": "created",
  "fly_app": "p8-agent-2b3c4d5e",
  "fly_machine_id": "5683dd9c12e989",
  "fly_private_host": "p8-agent-2b3c4d5e.internal",
  "fly_public_url": "https://p8-agent-2b3c4d5e.fly.dev",
  "error": null
}

POST /v1/agents/{agent_id}/runtime/redeploy

Destroy and reprovision the runtime. Requires mcp:agents:write. Response: same shape as provision.

POST /v1/agents/{agent_id}/runtime/suspend

Suspend the runtime. Requires mcp:agents:write. Response: { "ok": true }.

DELETE /v1/agents/{agent_id}/runtime

Destroy the runtime. Requires mcp:agents:write. Response: { "ok": true }.

POST /v1/agents/{agent_id}/republish

Retry a failed or destroyed runtime: redeploys when the agent is synced, otherwise provisions from scratch. Requires mcp:agents:write. Response: same shape as provision.

GET /v1/agents/{agent_id}/logs

Fetch runtime logs on demand. Logs are not stored by Perceive8; the list is empty when the orchestrator has none.

Parameter In Description
limit query Max entries, default 100

Response: { "logs": [...], "nextToken": null } — log entry objects as returned by the orchestrator.

Configuration

GET /v1/agents/{agent_id}/config/{config_type}

Get agent config by type. env is read from local storage; other types are best-effort reads from the orchestrator and return {} when unavailable. Response: the config object, for example { "LOG_LEVEL": "debug" }.

PUT /v1/agents/{agent_id}/config/{config_type}

Set agent config. env config is persisted locally and mirrored to the orchestrator; other types are written to the orchestrator only. Requires mcp:agents:write.

Request body: { "config": { "LOG_LEVEL": "debug" } } Response: the stored config object.

Secrets

Secret values are write-only — they are stored on the agent's runtime and can never be read back. Only secret names are listed.

GET /v1/agents/{agent_id}/secrets

List an agent's secret names. Response: [{ "secret_name": "HUBSPOT_API_KEY" }].

PUT /v1/agents/{agent_id}/secrets/{secret_name}

Set a secret on the agent's runtime. Requires mcp:agents:write. secret_name must match ^[A-Za-z_][A-Za-z0-9_]*$.

Request body: { "value": "pat-na1-xxxx" } Response: { "secret_name": "HUBSPOT_API_KEY" }.

DELETE /v1/agents/{agent_id}/secrets/{secret_name}

Delete a secret from the runtime. Requires mcp:agents:write. Response: { "ok": true }.

Webhook

POST /v1/agents/{agent_id}/webhook

Proxy an inbound webhook to the agent's runtime. Requires mcp:agents:run; 400 when the agent is not synced. The body is an arbitrary JSON object forwarded verbatim; the response is whatever the runtime returns.

Catalog

GET /v1/agent-templates

List templates visible to the workspace (system templates plus the caller's own), ordered by usage.

Response — array of template objects:

Field Type Description
id, slug, name string Identity
description, category string Catalog metadata
persona, system_prompt string Prompt material used to compile new agents
default_skills string[] Skills applied to new agents
communication_style string Default style hint
default_model_tier string Default tier
runtime_kind string Runtime kind
is_system boolean Built-in template
usage_count number Times used
created_at, updated_at string Timestamps

GET /v1/runtime-kinds

List available runtime kinds.

Response — array of objects with fields runtime_kind, label, description, image_ref (all strings).

Runs

The run object:

Field Type Description
id string (UUID) Local run ID
agent_id, workspace_id string (UUID) Owning agent and workspace
task_id number | null Linked board task
status string For example queued, running, done, failed, cancelled
summoro_run_id string | null Orchestrator-side run ID
trigger object Trigger payload; type is api unless overridden
started_at, ended_at string | null Filled from live status when available
error, provider, model, tokens_in, tokens_out, zdr_eligible, used_free_tier — Reserved; currently null
created_at, updated_at string Timestamps

POST /v1/runs

Dispatch a run. Requires mcp:agents:run. The agent must belong to the workspace and be synced (404/502 otherwise). Dispatch is synchronous: the response carries the terminal result.

Parameter In Description
stream query 1 or true to receive the result as an SSE stream instead of JSON

Request body

{
  "agent_id": "5f1c9c2e-2a4b-4e0d-9f3a-1b2c3d4e5f60",
  "message": "Summarize this week's inbound leads",
  "model": { "tier": "medium" }
}
Field Type Description
agent_id string (UUID, required) Agent to run
message string Single user message
messages object[] Full message history; overrides message when given
trigger object Trigger metadata; defaults to { "type": "api" }. The workspace ID is injected server-side
model object Model override, for example { "tier": "small" | "medium" | "expert" | "free" }. Defaults to the agent's configured tier

Response (default, JSON)

{
  "run_id": "7d8e9f0a-1b2c-3d4e-5f6a-7b8c9d0e1f2a",
  "local_run_id": "0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
  "status": "done",
  "agent_id": "5f1c9c2e-2a4b-4e0d-9f3a-1b2c3d4e5f60",
  "workspace_id": "9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d",
  "trigger": { "type": "api", "workspace_id": "9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d" }
}

Response (with ?stream=true) — text/event-stream. Events arrive in one batch after the run completes; on dispatch failure the stream carries error + status: failed instead of an HTTP error.

Event When sent Payload
message The run produced an assistant reply The assistant message object
metrics The run produced metrics The metrics object
error The run failed { "message": string }
status Always, last { "status": string } — failed after an error event

GET /v1/runs

List local runs for an agent or board task, enriched with live status. Requires mcp:agents:read; 400 when neither filter is given.

Parameter In Description
agent_id query Agent UUID (this or task_id required)
task_id query Board task ID
limit query Max rows, default 50

Response: array of run objects, newest first.

GET /v1/runs/{run_id}

Get a single run, enriched with live status. Response: the run object.

GET /v1/runs/{run_id}/messages

Get the run's message history; empty array when unavailable. Response: array of message objects ordered by seq, each with at least role, content (for example { "text": "..." }), and seq.

Approvals

A run pauses when a guardrail requires human sign-off; the approval names the tool and arguments under review. Responding resumes the paused run.

The approval object:

Field Type Description
id string Approval ID
run_id string Paused run
workspace_id, agent_id string Owning workspace and agent
tool_name string Tool awaiting approval
arguments object Proposed tool arguments
resume_state object State used to resume the run
status string pending, approved, or rejected
comment string | null Responder's comment
responded_at, responded_by string | null Response metadata
created_at, updated_at string Timestamps

GET /v1/approvals

List approvals in the workspace, newest first. Requires mcp:agents:read.

Parameter In Description
status query Filter by status, default pending

Response: array of approval objects.

POST /v1/approvals/{approval_id}/respond

Approve or reject a pending approval. Requires mcp:agents:write (JWT: admin/owner). Responding resumes the paused run.

Request body

{
  "decision": "approved",
  "comment": "Looks correct",
  "answer": "Use the Q3 pricing sheet"
}
Field Type Description
decision string (required) approved or rejected
comment string Optional comment stored on the approval
answer string (max 2000 chars) Optional free-text answer forwarded to the run for question-style approvals

Response: { "id": "<approval-id>", "status": "approved" }.