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 /:id routes 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 /:id routes 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, or error. There is no completed, failed, or progress field. 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/:versionId route is registered before /:workflowId/versions/compare and /:workflowId/versions/stats. Because Express matches top-down, requests to /compare or /stats may be caught by the :versionId parameter (with versionId = "compare" or "stats"). This should be fixed by moving compare and stats above the :versionId route, or by adding a regex constraint to :versionId.

List Workflow Versions

GET /:workflowId/versions

  • Authentication: Required
  • Handler: WorkflowVersionService.getVersionHistory
  • Parameters:
    • workflowId (path): Workflow ID
    • limit (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 ID
    • versionId (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:reverted via WebSocket.
  • Body:
{
  "versionId": 3
}
  • Validation: versionId is 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 name and currentWorkflowState are 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 ID
    • versionA (query, required): First version number
    • versionB (query, required): Second version number
  • Description: Get a diff between two workflow versions
  • Validation: Both versionA and versionB are 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). 403 if the workflow is not shareable and belongs to another user; 404 if not found.
  • Response: Workflow envelope JSON

Import Workflow

POST /import

  • Authentication: Required
  • Description: Imports a workflow envelope (PRD-057). 201 on success; 400 on 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. SkillDiscoveryService already
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.importable counts
    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: 400 if nothing is selected or the arrays are malformed; 401
    without a user. Per-item failures are reported in failures rather 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"
}