Base URL
http://localhost:3333/api/· Authentication · Conventions
Workflow Routes
Base path: /api/workflows
Health Check
GET /health
- Authentication: None
- Handler:
WorkflowService.healthCheck - Description: Check if the workflow service is running
- Response:
{
"status": "OK"
}Get All Workflows
GET /
- Authentication: Required
- Handler:
WorkflowService.getAllWorkflows - Description: Retrieve all workflows for the authenticated user
- Response:
[
{
"id": "workflow-id",
"name": "Workflow Name",
"description": "Workflow description",
"status": "active|inactive",
"nodes": [],
"edges": [],
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
]Get All Workflows Summary
GET /summary
- Authentication: Required
- Handler:
WorkflowService.getAllWorkflowsSummary - Description: Retrieve a lightweight summary of all workflows for the authenticated user (no full workflow_data). This is registered before any
/:idroutes in Express to avoid path conflicts. - Response:
[
{
"id": "workflow-id",
"name": "Workflow Name",
"status": "active",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
]Save Workflow
POST /save
- Authentication: Required
- Handler:
WorkflowService.saveWorkflow - Body:
{
"name": "Workflow Name",
"description": "Workflow description",
"nodes": [],
"edges": [],
"config": {}
}- Response:
{
"success": true,
"workflow": {
"id": "workflow-id",
"name": "Workflow Name",
"description": "Workflow description",
"status": "inactive",
"nodes": [],
"edges": [],
"config": {},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}Analyze Dependencies
POST /analyze-dependencies
- Authentication: Required
- Handler:
WorkflowService.analyzeDependencies - Description: Analyze node dependencies within a workflow. This is registered before any
/:idroutes in Express to avoid path conflicts. - Body: Workflow data with nodes and edges
- Response: Dependency analysis result
Get Workflow by ID
GET /:id
- Authentication: Required
- Handler:
WorkflowService.getWorkflowById - Parameters:
id(path): Workflow ID
- Description: Retrieve a specific workflow by ID
- Response:
{
"id": "workflow-id",
"name": "Workflow Name",
"description": "Workflow description",
"status": "active|inactive",
"nodes": [],
"edges": [],
"config": {},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}Update Workflow
PUT /:id
- Authentication: Required
- Handler:
WorkflowService.updateWorkflow - Parameters:
id(path): Workflow ID
- Body:
{
"name": "Updated Workflow Name",
"description": "Updated description",
"nodes": [],
"edges": [],
"config": {}
}- Response:
{
"success": true,
"workflow": {
"id": "workflow-id",
"name": "Updated Workflow Name",
"description": "Updated description",
"status": "inactive",
"nodes": [],
"edges": [],
"config": {},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}Delete Workflow
DELETE /:id
- Authentication: Required
- Handler:
WorkflowService.deleteWorkflow - Parameters:
id(path): Workflow ID
- Description: Delete a workflow by ID
- Response:
{
"success": true,
"message": "Workflow deleted successfully"
}Rename Workflow
PUT /:id/name
- Authentication: Required
- Handler:
WorkflowService.renameWorkflow - Parameters:
id(path): Workflow ID
- Body:
{
"name": "New Workflow Name"
}- Response:
{
"success": true,
"workflow": {
"id": "workflow-id",
"name": "New Workflow Name",
"description": "Workflow description",
"status": "inactive",
"nodes": [],
"edges": [],
"config": {},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}Get Workflow Status
GET /:id/status
- Authentication: Required
- Handler:
WorkflowService.fetchWorkflowState - Parameters:
id(path): Workflow ID
- Description: Fetch the current state of a workflow
- Response:
{
"workflowId": "workflow-id",
"status": "active|inactive|error",
"lastExecution": "2024-01-01T00:00:00Z",
"executionCount": 10,
"errorCount": 0,
"state": {}
}Note: The status values are
active,inactive, orerror. There is nocompleted,failed, orprogressfield. This endpoint returns the workflow's activation state, not an execution progress tracker.
Activate Workflow (Start)
POST /:id/start
- Authentication: Required
- Handler:
WorkflowService.activateWorkflow - Parameters:
id(path): Workflow ID
- Description: Activate a workflow so it begins listening for triggers (e.g., timer, webhook). This does not accept runtime
inputs— it toggles the workflow's active state. - Response:
{
"success": true,
"message": "Workflow activated successfully",
"workflowId": "workflow-id"
}Deactivate Workflow (Stop)
POST /:id/stop
- Authentication: Required
- Handler:
WorkflowService.deactivateWorkflow - Parameters:
id(path): Workflow ID
- Description: Deactivate a workflow so it stops listening for triggers. This does not cancel a currently-running execution — it toggles the workflow's active state to inactive.
- Response:
{
"success": true,
"message": "Workflow deactivated successfully",
"workflowId": "workflow-id"
}Workflow Version Control Routes
These endpoints manage workflow version history, checkpoints, and comparisons.
⚠️ Known Route-Ordering Issue: In the current
WorkflowRoutes.js, the/:workflowId/versions/:versionIdroute is registered before/:workflowId/versions/compareand/:workflowId/versions/stats. Because Express matches top-down, requests to/compareor/statsmay be caught by the:versionIdparameter (withversionId = "compare"or"stats"). This should be fixed by movingcompareandstatsabove the:versionIdroute, or by adding a regex constraint to:versionId.
List Workflow Versions
GET /:workflowId/versions
- Authentication: Required
- Handler:
WorkflowVersionService.getVersionHistory - Parameters:
workflowId(path): Workflow IDlimit(query, optional): Max versions to return (default: 50)offset(query, optional): Pagination offset (default: 0)checkpointsOnly(query, optional): If"true", only return checkpoint versions
- Description: List the version history for a workflow
- Response:
{
"success": true,
"versions": [
{
"version_number": 5,
"source": "chat",
"change_description": "Added new API node",
"is_checkpoint": false,
"checkpoint_name": null,
"created_at": "2024-01-01T00:00:00Z"
}
]
}Get Specific Version
GET /:workflowId/versions/:versionId
- Authentication: Required
- Handler:
WorkflowVersionService.getVersion - Parameters:
workflowId(path): Workflow IDversionId(path): Version number (integer)
- Description: Get the full data for a specific workflow version
- Response:
{
"success": true,
"version": {
"version_number": 3,
"workflow_state": { "...": "..." },
"source": "manual",
"change_description": "Checkpoint before refactor",
"is_checkpoint": true,
"checkpoint_name": "Pre-refactor",
"created_at": "2024-01-01T00:00:00Z"
}
}- Error (404): Version not found
Revert to Version
POST /:workflowId/revert
- Authentication: Required
- Handler:
WorkflowVersionService.revertToVersion - Parameters:
workflowId(path): Workflow ID
- Description: Revert a workflow to a previous version. Broadcasts
workflow:revertedvia WebSocket. - Body:
{
"versionId": 3
}- Validation:
versionIdis required (returns 400 if missing) - Response:
{
"success": true,
"revertedToVersion": 3,
"workflowState": { "...": "..." }
}Create Checkpoint
POST /:workflowId/checkpoint
- Authentication: Required
- Handler:
WorkflowVersionService.createCheckpoint - Parameters:
workflowId(path): Workflow ID
- Description: Save a named checkpoint of the current workflow state
- Body:
{
"name": "Before big changes",
"currentWorkflowState": { "...": "..." }
}- Validation: Both
nameandcurrentWorkflowStateare required (returns 400 if either is missing) - Response:
{
"success": true,
"versionNumber": 6,
"checkpointName": "Before big changes"
}Compare Versions
GET /:workflowId/versions/compare?versionA=1&versionB=3
- Authentication: Required
- Handler:
WorkflowVersionService.compareVersions - Parameters:
workflowId(path): Workflow IDversionA(query, required): First version numberversionB(query, required): Second version number
- Description: Get a diff between two workflow versions
- Validation: Both
versionAandversionBare required (returns 400 if either is missing) - ⚠️ Note: This route may be shadowed by
/:workflowId/versions/:versionId— see route-ordering issue above. - Response:
{
"success": true,
"diff": {
"nodesAdded": [],
"nodesRemoved": [],
"nodesModified": [],
"edgesAdded": [],
"edgesRemoved": []
}
}Version Storage Stats
GET /:workflowId/versions/stats
- Authentication: Required
- Handler:
WorkflowVersionService.getStorageStats - Parameters:
workflowId(path): Workflow ID
- Description: Get storage statistics for a workflow's version history
- ⚠️ Note: This route may be shadowed by
/:workflowId/versions/:versionId— see route-ordering issue above. - Response:
{
"success": true,
"stats": {
"totalVersions": 12,
"checkpoints": 3,
"totalSizeBytes": 45678,
"oldestVersion": "2024-01-01T00:00:00Z",
"newestVersion": "2024-03-01T00:00:00Z"
}
}Export Workflow
GET /:id/export
- Authentication: Required
- Description: Exports a workflow as a portable envelope (PRD-057).
403if the workflow is not shareable and belongs to another user;404if not found. - Response: Workflow envelope JSON
Import Workflow
POST /import
- Authentication: Required
- Description: Imports a workflow envelope (PRD-057).
201on success;400on a malformed envelope. Reports tool types referenced by the workflow that aren't installed locally. - Body:
{ "envelope": {...} }(or the envelope object directly) - Response:
{
"success": true,
"workflowId": "uuid",
"missingToolTypes": []
}Import Routes
Base path: /api/import
Bring a user's existing setup in from the other AI agent tools installed on the
same machine — Hermes, OpenClaw, Claude Code, Codex, Cursor and Gemini CLI.
Skills usually need no import at all.
SkillDiscoveryServicealready
scans every one of these tools'skills/directories, so their skills work in
AGNT untouched. What these routes add is ownership: copying a skill into~/.agnt/skills/so uninstalling the tool it came from no longer takes it
away. Persona and memory have no equivalent in discovery and are genuinely
new records.
Detect Importable Setup
GET /detect
- Authentication: Required
- Description: Read-only scan of the installed harnesses. Runs during
onboarding, so it is bounded by a ~2.5s timeout and answers with an empty
result rather than an error if it cannot finish.skills.importablecounts
only skills AGNT does not already have, deduplicated across tools. - Response:
{
"sources": [
{
"id": "hermes",
"label": "Hermes",
"icon": "agent",
"home": "C:\\Users\\you\\.hermes",
"skills": { "total": 9, "importable": 8, "names": ["media-use"] },
"persona": { "available": true, "origins": ["SOUL.md"], "bytes": 513, "preview": "You are..." },
"memories": { "count": 7 }
}
],
"totals": { "sources": 6, "skillsSeen": 49, "skillsImportable": 8, "personas": 2, "memories": 8 }
}Run Import
POST /run
- Authentication: Required
- Description: Copy the selected items into AGNT. Additive only — a skill
whose name already exists is skipped, never overwritten. Each array holds
harness ids; the server re-scans and ignores any id it does not recognise. - Request Body:
{ "skills": ["hermes"], "personas": ["openclaw"], "memories": ["hermes"] }- Response:
{
"imported": { "skills": 8, "agents": 1, "memories": 7 },
"items": [{ "kind": "skill", "name": "media-use", "source": "hermes", "status": "imported" }],
"failures": [{ "kind": "skill", "name": "broken", "source": "hermes", "error": "Invalid SKILL.md" }]
}- Errors:
400if nothing is selected or the arrays are malformed;401
without a user. Per-item failures are reported infailuresrather than
aborting the run.
Webhook Routes
Base path: /api/webhooks
Get All Webhooks
GET /
- Authentication: Required
- Description: Get all webhooks for the authenticated user
- Response:
{
"success": true,
"webhooks": [
{
"id": "webhook-id",
"workflowId": "workflow-id",
"url": "https://example.com/webhook",
"secret": "webhook-secret",
"events": ["trigger"],
"active": true,
"createdAt": "2024-01-01T00:00:00Z"
}
]
}Get Webhook by Workflow ID
GET /workflow/:workflowId
- Authentication: Required
- Parameters:
workflowId(path): Workflow ID
- Description: Get webhook associated with a specific workflow
- Response:
{
"success": true,
"webhook": {
"id": "webhook-id",
"workflowId": "workflow-id",
"url": "https://example.com/webhook",
"secret": "webhook-secret",
"events": ["trigger"],
"active": true,
"createdAt": "2024-01-01T00:00:00Z"
}
}Delete Webhook by Workflow ID
DELETE /workflow/:workflowId
- Authentication: Required
- Parameters:
workflowId(path): Workflow ID
- Description: Delete webhook associated with a specific workflow
- Response:
{
"success": true,
"message": "Webhook deleted successfully"
}