@desplega.ai/agent-swarm 1.53.1 → 1.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/openapi.json +1909 -1848
  2. package/package.json +1 -1
  3. package/plugin/commands/work-on-task.md +0 -1
  4. package/plugin/skills/artifacts/skill.md +0 -1
  5. package/src/artifact-sdk/browser-sdk.ts +0 -1
  6. package/src/be/db-queries/tracker.ts +4 -4
  7. package/src/be/db.ts +49 -531
  8. package/src/be/migrations/024_add_was_paused.sql +1 -0
  9. package/src/be/migrations/025_workflow_run_cancelled_status.sql +58 -0
  10. package/src/be/migrations/026_drop_epics.sql +106 -0
  11. package/src/be/migrations/runner.ts +0 -1
  12. package/src/commands/runner.ts +48 -194
  13. package/src/commands/templates.ts +0 -28
  14. package/src/heartbeat/heartbeat.ts +107 -11
  15. package/src/http/agents.ts +3 -0
  16. package/src/http/heartbeat.ts +43 -0
  17. package/src/http/index.ts +4 -4
  18. package/src/http/poll.ts +4 -21
  19. package/src/http/tasks.ts +27 -7
  20. package/src/http/utils.ts +1 -1
  21. package/src/http/workflows.ts +145 -2
  22. package/src/prompts/session-templates.ts +1 -2
  23. package/src/providers/pi-mono-adapter.ts +25 -0
  24. package/src/scheduler/scheduler.ts +1 -0
  25. package/src/server.ts +7 -24
  26. package/src/tests/artifact-sdk.test.ts +0 -2
  27. package/src/tests/db-queries-tracker.test.ts +2 -14
  28. package/src/tests/events-db.test.ts +0 -1
  29. package/src/tests/events-http.test.ts +10 -4
  30. package/src/tests/gitlab-vcs-db.test.ts +0 -33
  31. package/src/tests/heartbeat.test.ts +148 -6
  32. package/src/tests/http-api-integration.test.ts +147 -220
  33. package/src/tests/oauth-wrapper.test.ts +6 -4
  34. package/src/tests/prompt-template-remaining.test.ts +1 -2
  35. package/src/tests/runner-polling-api.test.ts +1 -1
  36. package/src/tests/self-improvement.test.ts +3 -30
  37. package/src/tests/tool-annotations.test.ts +3 -19
  38. package/src/tests/tracker-tools.test.ts +2 -23
  39. package/src/tests/workflow-hitl-routing.test.ts +545 -0
  40. package/src/tests/workflow-http-v2.test.ts +130 -1
  41. package/src/tests/workflow-patch.test.ts +169 -0
  42. package/src/tools/send-task.ts +2 -26
  43. package/src/tools/store-progress.ts +10 -37
  44. package/src/tools/tool-config.ts +4 -11
  45. package/src/tools/tracker/index.ts +0 -1
  46. package/src/tools/tracker/tracker-sync-status.ts +1 -1
  47. package/src/tools/workflows/cancel-workflow-run.ts +41 -0
  48. package/src/tools/workflows/index.ts +3 -0
  49. package/src/tools/workflows/patch-workflow-node.ts +93 -0
  50. package/src/tools/workflows/patch-workflow.ts +130 -0
  51. package/src/tracker/types.ts +1 -1
  52. package/src/types.ts +37 -59
  53. package/src/workflows/cooldown.ts +24 -7
  54. package/src/workflows/definition.ts +71 -1
  55. package/src/workflows/engine.ts +75 -19
  56. package/src/workflows/executors/raw-llm.ts +17 -0
  57. package/src/workflows/executors/validate.ts +17 -0
  58. package/src/workflows/index.ts +1 -1
  59. package/src/workflows/recovery.ts +4 -4
  60. package/src/workflows/resume.ts +65 -15
  61. package/templates/official/coder/CLAUDE.md +1 -1
  62. package/templates/official/content-reviewer/CLAUDE.md +1 -1
  63. package/templates/official/content-strategist/CLAUDE.md +1 -1
  64. package/templates/official/content-writer/CLAUDE.md +1 -1
  65. package/templates/official/forward-deployed-engineer/CLAUDE.md +1 -1
  66. package/templates/official/lead/IDENTITY.md +1 -1
  67. package/templates/official/lead/config.json +1 -1
  68. package/templates/official/researcher/CLAUDE.md +1 -1
  69. package/templates/official/reviewer/CLAUDE.md +1 -1
  70. package/templates/official/tester/CLAUDE.md +1 -1
  71. package/src/http/epics.ts +0 -460
  72. package/src/tests/epics.test.ts +0 -370
  73. package/src/tools/epics/assign-task-to-epic.ts +0 -129
  74. package/src/tools/epics/create-epic.ts +0 -112
  75. package/src/tools/epics/delete-epic.ts +0 -121
  76. package/src/tools/epics/get-epic-details.ts +0 -92
  77. package/src/tools/epics/index.ts +0 -7
  78. package/src/tools/epics/list-epics.ts +0 -85
  79. package/src/tools/epics/unassign-task-from-epic.ts +0 -109
  80. package/src/tools/epics/update-epic.ts +0 -174
  81. package/src/tools/tracker/tracker-link-epic.ts +0 -64
package/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Agent Swarm API",
5
- "version": "1.53.0",
5
+ "version": "1.55.0",
6
6
  "description": "Multi-agent orchestration API for Claude Code, Codex, and Gemini CLI. Enables task distribution, agent communication, and service discovery.\n\nMCP tools are documented separately in [MCP.md](./MCP.md)."
7
7
  },
8
8
  "servers": [
@@ -1411,53 +1411,11 @@
1411
1411
  }
1412
1412
  }
1413
1413
  },
1414
- "/api/epics": {
1415
- "get": {
1416
- "summary": "List epics with optional filters",
1417
- "tags": [
1418
- "Epics"
1419
- ],
1420
- "security": [
1421
- {
1422
- "bearerAuth": []
1423
- }
1424
- ],
1425
- "parameters": [
1426
- {
1427
- "schema": {
1428
- "type": "string"
1429
- },
1430
- "required": false,
1431
- "name": "status",
1432
- "in": "query"
1433
- },
1434
- {
1435
- "schema": {
1436
- "type": "string"
1437
- },
1438
- "required": false,
1439
- "name": "search",
1440
- "in": "query"
1441
- },
1442
- {
1443
- "schema": {
1444
- "type": "string"
1445
- },
1446
- "required": false,
1447
- "name": "leadAgentId",
1448
- "in": "query"
1449
- }
1450
- ],
1451
- "responses": {
1452
- "200": {
1453
- "description": "Epic list with progress"
1454
- }
1455
- }
1456
- },
1414
+ "/api/events": {
1457
1415
  "post": {
1458
- "summary": "Create a new epic",
1416
+ "summary": "Store a single event",
1459
1417
  "tags": [
1460
- "Epics"
1418
+ "Events"
1461
1419
  ],
1462
1420
  "security": [
1463
1421
  {
@@ -1470,36 +1428,89 @@
1470
1428
  "schema": {
1471
1429
  "type": "object",
1472
1430
  "properties": {
1473
- "name": {
1431
+ "category": {
1474
1432
  "type": "string",
1475
- "minLength": 1
1433
+ "enum": [
1434
+ "tool",
1435
+ "skill",
1436
+ "session",
1437
+ "api",
1438
+ "task",
1439
+ "workflow",
1440
+ "system"
1441
+ ]
1476
1442
  },
1477
- "goal": {
1443
+ "event": {
1478
1444
  "type": "string",
1479
- "minLength": 1
1445
+ "enum": [
1446
+ "tool.start",
1447
+ "tool.end",
1448
+ "skill.invoke",
1449
+ "skill.complete",
1450
+ "session.start",
1451
+ "session.end",
1452
+ "session.resume",
1453
+ "session.cost",
1454
+ "api.request",
1455
+ "api.error",
1456
+ "task.poll",
1457
+ "task.assign",
1458
+ "task.timeout",
1459
+ "workflow.step.start",
1460
+ "workflow.step.end",
1461
+ "workflow.run.start",
1462
+ "workflow.run.end",
1463
+ "system.boot",
1464
+ "system.migration",
1465
+ "system.error"
1466
+ ]
1480
1467
  },
1481
- "description": {
1468
+ "status": {
1469
+ "type": "string",
1470
+ "enum": [
1471
+ "ok",
1472
+ "error",
1473
+ "timeout",
1474
+ "skipped"
1475
+ ]
1476
+ },
1477
+ "source": {
1478
+ "type": "string",
1479
+ "enum": [
1480
+ "worker",
1481
+ "api",
1482
+ "hook",
1483
+ "scheduler",
1484
+ "cli"
1485
+ ]
1486
+ },
1487
+ "agentId": {
1482
1488
  "type": "string"
1483
1489
  },
1484
- "leadAgentId": {
1490
+ "taskId": {
1485
1491
  "type": "string"
1486
1492
  },
1487
- "repoId": {
1493
+ "sessionId": {
1488
1494
  "type": "string"
1489
1495
  },
1490
- "branch": {
1496
+ "parentEventId": {
1491
1497
  "type": "string"
1492
1498
  },
1493
- "tags": {
1494
- "type": "array",
1495
- "items": {
1496
- "type": "string"
1497
- }
1499
+ "numericValue": {
1500
+ "type": "number"
1501
+ },
1502
+ "durationMs": {
1503
+ "type": "integer"
1504
+ },
1505
+ "data": {
1506
+ "type": "object",
1507
+ "additionalProperties": {}
1498
1508
  }
1499
1509
  },
1500
1510
  "required": [
1501
- "name",
1502
- "goal"
1511
+ "category",
1512
+ "event",
1513
+ "source"
1503
1514
  ]
1504
1515
  }
1505
1516
  }
@@ -1507,19 +1518,17 @@
1507
1518
  },
1508
1519
  "responses": {
1509
1520
  "201": {
1510
- "description": "Epic created"
1521
+ "description": "Event stored"
1511
1522
  },
1512
1523
  "400": {
1513
1524
  "description": "Validation error"
1514
1525
  }
1515
1526
  }
1516
- }
1517
- },
1518
- "/api/epics/{id}": {
1527
+ },
1519
1528
  "get": {
1520
- "summary": "Get epic with progress and tasks",
1529
+ "summary": "Query events with filters",
1521
1530
  "tags": [
1522
- "Epics"
1531
+ "Events"
1523
1532
  ],
1524
1533
  "security": [
1525
1534
  {
@@ -1529,184 +1538,143 @@
1529
1538
  "parameters": [
1530
1539
  {
1531
1540
  "schema": {
1532
- "type": "string"
1541
+ "type": "string",
1542
+ "enum": [
1543
+ "tool",
1544
+ "skill",
1545
+ "session",
1546
+ "api",
1547
+ "task",
1548
+ "workflow",
1549
+ "system"
1550
+ ]
1533
1551
  },
1534
- "required": true,
1535
- "name": "id",
1536
- "in": "path"
1537
- }
1538
- ],
1539
- "responses": {
1540
- "200": {
1541
- "description": "Epic with tasks"
1552
+ "required": false,
1553
+ "name": "category",
1554
+ "in": "query"
1542
1555
  },
1543
- "404": {
1544
- "description": "Epic not found"
1545
- }
1546
- }
1547
- },
1548
- "put": {
1549
- "summary": "Update an epic",
1550
- "tags": [
1551
- "Epics"
1552
- ],
1553
- "security": [
1554
1556
  {
1555
- "bearerAuth": []
1556
- }
1557
- ],
1558
- "parameters": [
1557
+ "schema": {
1558
+ "type": "string",
1559
+ "enum": [
1560
+ "tool.start",
1561
+ "tool.end",
1562
+ "skill.invoke",
1563
+ "skill.complete",
1564
+ "session.start",
1565
+ "session.end",
1566
+ "session.resume",
1567
+ "session.cost",
1568
+ "api.request",
1569
+ "api.error",
1570
+ "task.poll",
1571
+ "task.assign",
1572
+ "task.timeout",
1573
+ "workflow.step.start",
1574
+ "workflow.step.end",
1575
+ "workflow.run.start",
1576
+ "workflow.run.end",
1577
+ "system.boot",
1578
+ "system.migration",
1579
+ "system.error"
1580
+ ]
1581
+ },
1582
+ "required": false,
1583
+ "name": "event",
1584
+ "in": "query"
1585
+ },
1559
1586
  {
1560
1587
  "schema": {
1561
- "type": "string"
1588
+ "type": "string",
1589
+ "enum": [
1590
+ "ok",
1591
+ "error",
1592
+ "timeout",
1593
+ "skipped"
1594
+ ]
1562
1595
  },
1563
- "required": true,
1564
- "name": "id",
1565
- "in": "path"
1566
- }
1567
- ],
1568
- "requestBody": {
1569
- "content": {
1570
- "application/json": {
1571
- "schema": {
1572
- "type": "object",
1573
- "additionalProperties": {}
1574
- }
1575
- }
1576
- }
1577
- },
1578
- "responses": {
1579
- "200": {
1580
- "description": "Epic updated"
1596
+ "required": false,
1597
+ "name": "status",
1598
+ "in": "query"
1581
1599
  },
1582
- "404": {
1583
- "description": "Epic not found"
1584
- }
1585
- }
1586
- },
1587
- "delete": {
1588
- "summary": "Delete an epic",
1589
- "tags": [
1590
- "Epics"
1591
- ],
1592
- "security": [
1593
1600
  {
1594
- "bearerAuth": []
1595
- }
1596
- ],
1597
- "parameters": [
1601
+ "schema": {
1602
+ "type": "string",
1603
+ "enum": [
1604
+ "worker",
1605
+ "api",
1606
+ "hook",
1607
+ "scheduler",
1608
+ "cli"
1609
+ ]
1610
+ },
1611
+ "required": false,
1612
+ "name": "source",
1613
+ "in": "query"
1614
+ },
1598
1615
  {
1599
1616
  "schema": {
1600
1617
  "type": "string"
1601
1618
  },
1602
- "required": true,
1603
- "name": "id",
1604
- "in": "path"
1605
- }
1606
- ],
1607
- "responses": {
1608
- "200": {
1609
- "description": "Epic deleted"
1619
+ "required": false,
1620
+ "name": "agentId",
1621
+ "in": "query"
1610
1622
  },
1611
- "404": {
1612
- "description": "Epic not found"
1613
- }
1614
- }
1615
- }
1616
- },
1617
- "/api/epics/{id}/tasks": {
1618
- "post": {
1619
- "summary": "Add task to epic (create new or assign existing)",
1620
- "tags": [
1621
- "Epics"
1622
- ],
1623
- "security": [
1624
1623
  {
1625
- "bearerAuth": []
1626
- }
1627
- ],
1628
- "parameters": [
1624
+ "schema": {
1625
+ "type": "string"
1626
+ },
1627
+ "required": false,
1628
+ "name": "taskId",
1629
+ "in": "query"
1630
+ },
1629
1631
  {
1630
1632
  "schema": {
1631
1633
  "type": "string"
1632
1634
  },
1633
- "required": true,
1634
- "name": "id",
1635
- "in": "path"
1636
- }
1637
- ],
1638
- "requestBody": {
1639
- "content": {
1640
- "application/json": {
1641
- "schema": {
1642
- "type": "object",
1643
- "properties": {
1644
- "taskId": {
1645
- "type": "string"
1646
- },
1647
- "task": {
1648
- "type": "string"
1649
- },
1650
- "agentId": {
1651
- "type": "string"
1652
- },
1653
- "taskType": {
1654
- "type": "string"
1655
- },
1656
- "tags": {
1657
- "type": "array",
1658
- "items": {
1659
- "type": "string"
1660
- }
1661
- },
1662
- "priority": {
1663
- "type": "integer"
1664
- },
1665
- "offeredTo": {
1666
- "type": "string"
1667
- }
1668
- }
1669
- }
1670
- }
1671
- }
1672
- },
1673
- "responses": {
1674
- "200": {
1675
- "description": "Existing task assigned"
1635
+ "required": false,
1636
+ "name": "sessionId",
1637
+ "in": "query"
1676
1638
  },
1677
- "201": {
1678
- "description": "New task created in epic"
1639
+ {
1640
+ "schema": {
1641
+ "type": "string"
1642
+ },
1643
+ "required": false,
1644
+ "name": "since",
1645
+ "in": "query"
1679
1646
  },
1680
- "400": {
1681
- "description": "Missing task or taskId"
1647
+ {
1648
+ "schema": {
1649
+ "type": "string"
1650
+ },
1651
+ "required": false,
1652
+ "name": "until",
1653
+ "in": "query"
1682
1654
  },
1683
- "404": {
1684
- "description": "Epic or task not found"
1685
- }
1686
- }
1687
- }
1688
- },
1689
- "/api/channels": {
1690
- "get": {
1691
- "summary": "List all channels",
1692
- "tags": [
1693
- "Channels"
1694
- ],
1695
- "security": [
1696
1655
  {
1697
- "bearerAuth": []
1656
+ "schema": {
1657
+ "type": "integer",
1658
+ "minimum": 1,
1659
+ "maximum": 1000
1660
+ },
1661
+ "required": false,
1662
+ "name": "limit",
1663
+ "in": "query"
1698
1664
  }
1699
1665
  ],
1700
1666
  "responses": {
1701
1667
  "200": {
1702
- "description": "Channel list"
1668
+ "description": "List of events"
1703
1669
  }
1704
1670
  }
1705
- },
1671
+ }
1672
+ },
1673
+ "/api/events/batch": {
1706
1674
  "post": {
1707
- "summary": "Create a new channel",
1675
+ "summary": "Store multiple events in a batch",
1708
1676
  "tags": [
1709
- "Channels"
1677
+ "Events"
1710
1678
  ],
1711
1679
  "security": [
1712
1680
  {
@@ -1719,23 +1687,102 @@
1719
1687
  "schema": {
1720
1688
  "type": "object",
1721
1689
  "properties": {
1722
- "name": {
1723
- "type": "string",
1724
- "minLength": 1
1725
- },
1726
- "description": {
1727
- "type": "string"
1728
- },
1729
- "type": {
1730
- "type": "string",
1731
- "enum": [
1732
- "public",
1733
- "dm"
1734
- ]
1690
+ "events": {
1691
+ "type": "array",
1692
+ "items": {
1693
+ "type": "object",
1694
+ "properties": {
1695
+ "category": {
1696
+ "type": "string",
1697
+ "enum": [
1698
+ "tool",
1699
+ "skill",
1700
+ "session",
1701
+ "api",
1702
+ "task",
1703
+ "workflow",
1704
+ "system"
1705
+ ]
1706
+ },
1707
+ "event": {
1708
+ "type": "string",
1709
+ "enum": [
1710
+ "tool.start",
1711
+ "tool.end",
1712
+ "skill.invoke",
1713
+ "skill.complete",
1714
+ "session.start",
1715
+ "session.end",
1716
+ "session.resume",
1717
+ "session.cost",
1718
+ "api.request",
1719
+ "api.error",
1720
+ "task.poll",
1721
+ "task.assign",
1722
+ "task.timeout",
1723
+ "workflow.step.start",
1724
+ "workflow.step.end",
1725
+ "workflow.run.start",
1726
+ "workflow.run.end",
1727
+ "system.boot",
1728
+ "system.migration",
1729
+ "system.error"
1730
+ ]
1731
+ },
1732
+ "status": {
1733
+ "type": "string",
1734
+ "enum": [
1735
+ "ok",
1736
+ "error",
1737
+ "timeout",
1738
+ "skipped"
1739
+ ]
1740
+ },
1741
+ "source": {
1742
+ "type": "string",
1743
+ "enum": [
1744
+ "worker",
1745
+ "api",
1746
+ "hook",
1747
+ "scheduler",
1748
+ "cli"
1749
+ ]
1750
+ },
1751
+ "agentId": {
1752
+ "type": "string"
1753
+ },
1754
+ "taskId": {
1755
+ "type": "string"
1756
+ },
1757
+ "sessionId": {
1758
+ "type": "string"
1759
+ },
1760
+ "parentEventId": {
1761
+ "type": "string"
1762
+ },
1763
+ "numericValue": {
1764
+ "type": "number"
1765
+ },
1766
+ "durationMs": {
1767
+ "type": "integer"
1768
+ },
1769
+ "data": {
1770
+ "type": "object",
1771
+ "additionalProperties": {}
1772
+ }
1773
+ },
1774
+ "required": [
1775
+ "category",
1776
+ "event",
1777
+ "source"
1778
+ ]
1779
+ },
1780
+ "minItems": 1,
1781
+ "maxItems": 500
1735
1782
  }
1736
1783
  },
1737
1784
  "required": [
1738
- "name"
1785
+ "events"
1739
1786
  ]
1740
1787
  }
1741
1788
  }
@@ -1743,22 +1790,19 @@
1743
1790
  },
1744
1791
  "responses": {
1745
1792
  "201": {
1746
- "description": "Channel created"
1793
+ "description": "Events stored"
1747
1794
  },
1748
1795
  "400": {
1749
1796
  "description": "Validation error"
1750
- },
1751
- "409": {
1752
- "description": "Duplicate name"
1753
1797
  }
1754
1798
  }
1755
1799
  }
1756
1800
  },
1757
- "/api/channels/{id}": {
1758
- "delete": {
1759
- "summary": "Delete a channel",
1801
+ "/api/events/counts": {
1802
+ "get": {
1803
+ "summary": "Get event counts grouped by event name",
1760
1804
  "tags": [
1761
- "Channels"
1805
+ "Events"
1762
1806
  ],
1763
1807
  "security": [
1764
1808
  {
@@ -1768,53 +1812,58 @@
1768
1812
  "parameters": [
1769
1813
  {
1770
1814
  "schema": {
1771
- "type": "string"
1815
+ "type": "string",
1816
+ "enum": [
1817
+ "tool",
1818
+ "skill",
1819
+ "session",
1820
+ "api",
1821
+ "task",
1822
+ "workflow",
1823
+ "system"
1824
+ ]
1772
1825
  },
1773
- "required": true,
1774
- "name": "id",
1775
- "in": "path"
1776
- }
1777
- ],
1778
- "responses": {
1779
- "200": {
1780
- "description": "Channel deleted"
1781
- },
1782
- "400": {
1783
- "description": "Cannot delete general channel"
1826
+ "required": false,
1827
+ "name": "category",
1828
+ "in": "query"
1784
1829
  },
1785
- "404": {
1786
- "description": "Channel not found"
1787
- }
1788
- }
1789
- }
1790
- },
1791
- "/api/channels/{id}/messages": {
1792
- "get": {
1793
- "summary": "Get messages in a channel",
1794
- "tags": [
1795
- "Channels"
1796
- ],
1797
- "security": [
1798
- {
1799
- "bearerAuth": []
1800
- }
1801
- ],
1802
- "parameters": [
1803
1830
  {
1804
1831
  "schema": {
1805
- "type": "string"
1806
- },
1807
- "required": true,
1808
- "name": "id",
1809
- "in": "path"
1832
+ "type": "string",
1833
+ "enum": [
1834
+ "worker",
1835
+ "api",
1836
+ "hook",
1837
+ "scheduler",
1838
+ "cli"
1839
+ ]
1840
+ },
1841
+ "required": false,
1842
+ "name": "source",
1843
+ "in": "query"
1810
1844
  },
1811
1845
  {
1812
1846
  "schema": {
1813
- "type": "integer",
1814
- "minimum": 1
1847
+ "type": "string"
1815
1848
  },
1816
1849
  "required": false,
1817
- "name": "limit",
1850
+ "name": "agentId",
1851
+ "in": "query"
1852
+ },
1853
+ {
1854
+ "schema": {
1855
+ "type": "string"
1856
+ },
1857
+ "required": false,
1858
+ "name": "taskId",
1859
+ "in": "query"
1860
+ },
1861
+ {
1862
+ "schema": {
1863
+ "type": "string"
1864
+ },
1865
+ "required": false,
1866
+ "name": "sessionId",
1818
1867
  "in": "query"
1819
1868
  },
1820
1869
  {
@@ -1830,37 +1879,47 @@
1830
1879
  "type": "string"
1831
1880
  },
1832
1881
  "required": false,
1833
- "name": "before",
1882
+ "name": "until",
1834
1883
  "in": "query"
1835
1884
  }
1836
1885
  ],
1837
1886
  "responses": {
1838
1887
  "200": {
1839
- "description": "Channel messages"
1840
- },
1841
- "404": {
1842
- "description": "Channel not found"
1888
+ "description": "Event counts"
1843
1889
  }
1844
1890
  }
1845
- },
1891
+ }
1892
+ },
1893
+ "/api/heartbeat/sweep": {
1846
1894
  "post": {
1847
- "summary": "Post a message to a channel",
1895
+ "summary": "Trigger an immediate heartbeat sweep",
1848
1896
  "tags": [
1849
- "Channels"
1897
+ "Heartbeat"
1850
1898
  ],
1851
1899
  "security": [
1852
1900
  {
1853
1901
  "bearerAuth": []
1854
1902
  }
1855
1903
  ],
1856
- "parameters": [
1904
+ "responses": {
1905
+ "200": {
1906
+ "description": "Sweep completed successfully"
1907
+ },
1908
+ "401": {
1909
+ "description": "Unauthorized"
1910
+ }
1911
+ }
1912
+ }
1913
+ },
1914
+ "/api/memory/index": {
1915
+ "post": {
1916
+ "summary": "Ingest content into memory system (async embedding)",
1917
+ "tags": [
1918
+ "Memory"
1919
+ ],
1920
+ "security": [
1857
1921
  {
1858
- "schema": {
1859
- "type": "string"
1860
- },
1861
- "required": true,
1862
- "name": "id",
1863
- "in": "path"
1922
+ "bearerAuth": []
1864
1923
  }
1865
1924
  ],
1866
1925
  "requestBody": {
@@ -1869,17 +1928,42 @@
1869
1928
  "schema": {
1870
1929
  "type": "object",
1871
1930
  "properties": {
1931
+ "agentId": {
1932
+ "type": "string",
1933
+ "format": "uuid"
1934
+ },
1872
1935
  "content": {
1873
1936
  "type": "string",
1874
1937
  "minLength": 1
1875
1938
  },
1876
- "agentId": {
1877
- "type": "string"
1939
+ "name": {
1940
+ "type": "string",
1941
+ "minLength": 1
1942
+ },
1943
+ "scope": {
1944
+ "type": "string",
1945
+ "enum": [
1946
+ "agent",
1947
+ "swarm"
1948
+ ]
1949
+ },
1950
+ "source": {
1951
+ "type": "string",
1952
+ "enum": [
1953
+ "manual",
1954
+ "file_index",
1955
+ "session_summary",
1956
+ "task_completion"
1957
+ ]
1958
+ },
1959
+ "sourceTaskId": {
1960
+ "type": "string",
1961
+ "format": "uuid"
1878
1962
  },
1879
- "replyToId": {
1963
+ "sourcePath": {
1880
1964
  "type": "string"
1881
1965
  },
1882
- "mentions": {
1966
+ "tags": {
1883
1967
  "type": "array",
1884
1968
  "items": {
1885
1969
  "type": "string"
@@ -1887,30 +1971,75 @@
1887
1971
  }
1888
1972
  },
1889
1973
  "required": [
1890
- "content"
1974
+ "content",
1975
+ "name",
1976
+ "scope",
1977
+ "source"
1891
1978
  ]
1892
1979
  }
1893
1980
  }
1894
1981
  }
1895
1982
  },
1896
1983
  "responses": {
1897
- "201": {
1898
- "description": "Message posted"
1984
+ "202": {
1985
+ "description": "Content queued for embedding"
1899
1986
  },
1900
1987
  "400": {
1901
- "description": "Invalid content or agentId"
1988
+ "description": "Validation error"
1989
+ }
1990
+ }
1991
+ }
1992
+ },
1993
+ "/api/memory/search": {
1994
+ "post": {
1995
+ "summary": "Search memories by natural language query",
1996
+ "tags": [
1997
+ "Memory"
1998
+ ],
1999
+ "security": [
2000
+ {
2001
+ "bearerAuth": []
2002
+ }
2003
+ ],
2004
+ "requestBody": {
2005
+ "content": {
2006
+ "application/json": {
2007
+ "schema": {
2008
+ "type": "object",
2009
+ "properties": {
2010
+ "query": {
2011
+ "type": "string",
2012
+ "minLength": 1
2013
+ },
2014
+ "limit": {
2015
+ "type": "integer",
2016
+ "minimum": 1,
2017
+ "maximum": 20,
2018
+ "default": 5
2019
+ }
2020
+ },
2021
+ "required": [
2022
+ "query"
2023
+ ]
2024
+ }
2025
+ }
2026
+ }
2027
+ },
2028
+ "responses": {
2029
+ "200": {
2030
+ "description": "Search results"
1902
2031
  },
1903
- "404": {
1904
- "description": "Channel not found"
2032
+ "400": {
2033
+ "description": "Missing query or agent ID"
1905
2034
  }
1906
2035
  }
1907
2036
  }
1908
2037
  },
1909
- "/api/channels/{channelId}/messages/{messageId}/thread": {
2038
+ "/api/prompt-templates/resolved": {
1910
2039
  "get": {
1911
- "summary": "Get thread messages for a message",
2040
+ "summary": "Resolve a prompt template for a given event type and scope chain",
1912
2041
  "tags": [
1913
- "Channels"
2042
+ "PromptTemplates"
1914
2043
  ],
1915
2044
  "security": [
1916
2045
  {
@@ -1923,33 +2052,59 @@
1923
2052
  "type": "string"
1924
2053
  },
1925
2054
  "required": true,
1926
- "name": "channelId",
1927
- "in": "path"
2055
+ "name": "eventType",
2056
+ "in": "query"
1928
2057
  },
1929
2058
  {
1930
2059
  "schema": {
1931
2060
  "type": "string"
1932
2061
  },
1933
- "required": true,
1934
- "name": "messageId",
1935
- "in": "path"
2062
+ "required": false,
2063
+ "name": "agentId",
2064
+ "in": "query"
2065
+ },
2066
+ {
2067
+ "schema": {
2068
+ "type": "string"
2069
+ },
2070
+ "required": false,
2071
+ "name": "repoId",
2072
+ "in": "query"
1936
2073
  }
1937
2074
  ],
1938
2075
  "responses": {
1939
2076
  "200": {
1940
- "description": "Thread messages"
2077
+ "description": "Resolved template info"
1941
2078
  },
1942
- "404": {
1943
- "description": "Channel not found"
2079
+ "400": {
2080
+ "description": "Missing eventType"
1944
2081
  }
1945
2082
  }
1946
2083
  }
1947
2084
  },
1948
- "/api/events": {
2085
+ "/api/prompt-templates/events": {
2086
+ "get": {
2087
+ "summary": "List all registered event types with their available variables",
2088
+ "tags": [
2089
+ "PromptTemplates"
2090
+ ],
2091
+ "security": [
2092
+ {
2093
+ "bearerAuth": []
2094
+ }
2095
+ ],
2096
+ "responses": {
2097
+ "200": {
2098
+ "description": "List of event template definitions"
2099
+ }
2100
+ }
2101
+ }
2102
+ },
2103
+ "/api/prompt-templates/preview": {
1949
2104
  "post": {
1950
- "summary": "Store a single event",
2105
+ "summary": "Dry-run render a template with provided variables",
1951
2106
  "tags": [
1952
- "Events"
2107
+ "PromptTemplates"
1953
2108
  ],
1954
2109
  "security": [
1955
2110
  {
@@ -1962,107 +2117,87 @@
1962
2117
  "schema": {
1963
2118
  "type": "object",
1964
2119
  "properties": {
1965
- "category": {
1966
- "type": "string",
1967
- "enum": [
1968
- "tool",
1969
- "skill",
1970
- "session",
1971
- "api",
1972
- "task",
1973
- "workflow",
1974
- "system"
1975
- ]
1976
- },
1977
- "event": {
1978
- "type": "string",
1979
- "enum": [
1980
- "tool.start",
1981
- "tool.end",
1982
- "skill.invoke",
1983
- "skill.complete",
1984
- "session.start",
1985
- "session.end",
1986
- "session.resume",
1987
- "session.cost",
1988
- "api.request",
1989
- "api.error",
1990
- "task.poll",
1991
- "task.assign",
1992
- "task.timeout",
1993
- "workflow.step.start",
1994
- "workflow.step.end",
1995
- "workflow.run.start",
1996
- "workflow.run.end",
1997
- "system.boot",
1998
- "system.migration",
1999
- "system.error"
2000
- ]
2001
- },
2002
- "status": {
2003
- "type": "string",
2004
- "enum": [
2005
- "ok",
2006
- "error",
2007
- "timeout",
2008
- "skipped"
2009
- ]
2010
- },
2011
- "source": {
2012
- "type": "string",
2013
- "enum": [
2014
- "worker",
2015
- "api",
2016
- "hook",
2017
- "scheduler",
2018
- "cli"
2019
- ]
2020
- },
2021
- "agentId": {
2120
+ "eventType": {
2022
2121
  "type": "string"
2023
2122
  },
2024
- "taskId": {
2025
- "type": "string"
2026
- },
2027
- "sessionId": {
2123
+ "body": {
2028
2124
  "type": "string"
2029
2125
  },
2030
- "parentEventId": {
2126
+ "variables": {
2127
+ "type": "object",
2128
+ "additionalProperties": {}
2129
+ }
2130
+ },
2131
+ "required": [
2132
+ "eventType"
2133
+ ]
2134
+ }
2135
+ }
2136
+ }
2137
+ },
2138
+ "responses": {
2139
+ "200": {
2140
+ "description": "Rendered template preview"
2141
+ },
2142
+ "400": {
2143
+ "description": "Validation error"
2144
+ }
2145
+ }
2146
+ }
2147
+ },
2148
+ "/api/prompt-templates/render": {
2149
+ "post": {
2150
+ "summary": "Full scope-aware template resolution with interpolation (used by workers via HTTP)",
2151
+ "tags": [
2152
+ "PromptTemplates"
2153
+ ],
2154
+ "security": [
2155
+ {
2156
+ "bearerAuth": []
2157
+ }
2158
+ ],
2159
+ "requestBody": {
2160
+ "content": {
2161
+ "application/json": {
2162
+ "schema": {
2163
+ "type": "object",
2164
+ "properties": {
2165
+ "eventType": {
2031
2166
  "type": "string"
2032
2167
  },
2033
- "numericValue": {
2034
- "type": "number"
2035
- },
2036
- "durationMs": {
2037
- "type": "integer"
2038
- },
2039
- "data": {
2168
+ "variables": {
2040
2169
  "type": "object",
2041
2170
  "additionalProperties": {}
2171
+ },
2172
+ "agentId": {
2173
+ "type": "string"
2174
+ },
2175
+ "repoId": {
2176
+ "type": "string"
2042
2177
  }
2043
2178
  },
2044
2179
  "required": [
2045
- "category",
2046
- "event",
2047
- "source"
2180
+ "eventType"
2048
2181
  ]
2049
2182
  }
2050
2183
  }
2051
2184
  }
2052
2185
  },
2053
2186
  "responses": {
2054
- "201": {
2055
- "description": "Event stored"
2187
+ "200": {
2188
+ "description": "Fully resolved and interpolated template"
2056
2189
  },
2057
2190
  "400": {
2058
2191
  "description": "Validation error"
2059
2192
  }
2060
2193
  }
2061
- },
2062
- "get": {
2063
- "summary": "Query events with filters",
2194
+ }
2195
+ },
2196
+ "/api/prompt-templates/{id}/checkout": {
2197
+ "post": {
2198
+ "summary": "Checkout a specific version of a prompt template from history",
2064
2199
  "tags": [
2065
- "Events"
2200
+ "PromptTemplates"
2066
2201
  ],
2067
2202
  "security": [
2068
2203
  {
@@ -2070,273 +2205,110 @@
2070
2205
  }
2071
2206
  ],
2072
2207
  "parameters": [
2073
- {
2074
- "schema": {
2075
- "type": "string",
2076
- "enum": [
2077
- "tool",
2078
- "skill",
2079
- "session",
2080
- "api",
2081
- "task",
2082
- "workflow",
2083
- "system"
2084
- ]
2085
- },
2086
- "required": false,
2087
- "name": "category",
2088
- "in": "query"
2089
- },
2090
- {
2091
- "schema": {
2092
- "type": "string",
2093
- "enum": [
2094
- "tool.start",
2095
- "tool.end",
2096
- "skill.invoke",
2097
- "skill.complete",
2098
- "session.start",
2099
- "session.end",
2100
- "session.resume",
2101
- "session.cost",
2102
- "api.request",
2103
- "api.error",
2104
- "task.poll",
2105
- "task.assign",
2106
- "task.timeout",
2107
- "workflow.step.start",
2108
- "workflow.step.end",
2109
- "workflow.run.start",
2110
- "workflow.run.end",
2111
- "system.boot",
2112
- "system.migration",
2113
- "system.error"
2114
- ]
2115
- },
2116
- "required": false,
2117
- "name": "event",
2118
- "in": "query"
2119
- },
2120
- {
2121
- "schema": {
2122
- "type": "string",
2123
- "enum": [
2124
- "ok",
2125
- "error",
2126
- "timeout",
2127
- "skipped"
2128
- ]
2129
- },
2130
- "required": false,
2131
- "name": "status",
2132
- "in": "query"
2133
- },
2134
- {
2135
- "schema": {
2136
- "type": "string",
2137
- "enum": [
2138
- "worker",
2139
- "api",
2140
- "hook",
2141
- "scheduler",
2142
- "cli"
2143
- ]
2144
- },
2145
- "required": false,
2146
- "name": "source",
2147
- "in": "query"
2148
- },
2149
- {
2150
- "schema": {
2151
- "type": "string"
2152
- },
2153
- "required": false,
2154
- "name": "agentId",
2155
- "in": "query"
2156
- },
2157
2208
  {
2158
2209
  "schema": {
2159
2210
  "type": "string"
2160
2211
  },
2161
- "required": false,
2162
- "name": "taskId",
2163
- "in": "query"
2212
+ "required": true,
2213
+ "name": "id",
2214
+ "in": "path"
2215
+ }
2216
+ ],
2217
+ "requestBody": {
2218
+ "content": {
2219
+ "application/json": {
2220
+ "schema": {
2221
+ "type": "object",
2222
+ "properties": {
2223
+ "version": {
2224
+ "type": "number"
2225
+ }
2226
+ },
2227
+ "required": [
2228
+ "version"
2229
+ ]
2230
+ }
2231
+ }
2232
+ }
2233
+ },
2234
+ "responses": {
2235
+ "200": {
2236
+ "description": "Checked-out template"
2164
2237
  },
2165
- {
2166
- "schema": {
2167
- "type": "string"
2168
- },
2169
- "required": false,
2170
- "name": "sessionId",
2171
- "in": "query"
2238
+ "400": {
2239
+ "description": "Validation error"
2172
2240
  },
2241
+ "404": {
2242
+ "description": "Template or version not found"
2243
+ }
2244
+ }
2245
+ }
2246
+ },
2247
+ "/api/prompt-templates/{id}/reset": {
2248
+ "post": {
2249
+ "summary": "Reset a prompt template to its code-defined default",
2250
+ "tags": [
2251
+ "PromptTemplates"
2252
+ ],
2253
+ "security": [
2173
2254
  {
2174
- "schema": {
2175
- "type": "string"
2176
- },
2177
- "required": false,
2178
- "name": "since",
2179
- "in": "query"
2180
- },
2255
+ "bearerAuth": []
2256
+ }
2257
+ ],
2258
+ "parameters": [
2181
2259
  {
2182
2260
  "schema": {
2183
2261
  "type": "string"
2184
2262
  },
2185
- "required": false,
2186
- "name": "until",
2187
- "in": "query"
2188
- },
2189
- {
2190
- "schema": {
2191
- "type": "integer",
2192
- "minimum": 1,
2193
- "maximum": 1000
2194
- },
2195
- "required": false,
2196
- "name": "limit",
2197
- "in": "query"
2263
+ "required": true,
2264
+ "name": "id",
2265
+ "in": "path"
2198
2266
  }
2199
2267
  ],
2200
2268
  "responses": {
2201
2269
  "200": {
2202
- "description": "List of events"
2270
+ "description": "Reset template"
2271
+ },
2272
+ "404": {
2273
+ "description": "Template not found or no code default available"
2203
2274
  }
2204
2275
  }
2205
2276
  }
2206
2277
  },
2207
- "/api/events/batch": {
2208
- "post": {
2209
- "summary": "Store multiple events in a batch",
2278
+ "/api/prompt-templates/{id}": {
2279
+ "get": {
2280
+ "summary": "Get a single prompt template with its version history",
2210
2281
  "tags": [
2211
- "Events"
2282
+ "PromptTemplates"
2212
2283
  ],
2213
2284
  "security": [
2214
2285
  {
2215
2286
  "bearerAuth": []
2216
2287
  }
2217
2288
  ],
2218
- "requestBody": {
2219
- "content": {
2220
- "application/json": {
2221
- "schema": {
2222
- "type": "object",
2223
- "properties": {
2224
- "events": {
2225
- "type": "array",
2226
- "items": {
2227
- "type": "object",
2228
- "properties": {
2229
- "category": {
2230
- "type": "string",
2231
- "enum": [
2232
- "tool",
2233
- "skill",
2234
- "session",
2235
- "api",
2236
- "task",
2237
- "workflow",
2238
- "system"
2239
- ]
2240
- },
2241
- "event": {
2242
- "type": "string",
2243
- "enum": [
2244
- "tool.start",
2245
- "tool.end",
2246
- "skill.invoke",
2247
- "skill.complete",
2248
- "session.start",
2249
- "session.end",
2250
- "session.resume",
2251
- "session.cost",
2252
- "api.request",
2253
- "api.error",
2254
- "task.poll",
2255
- "task.assign",
2256
- "task.timeout",
2257
- "workflow.step.start",
2258
- "workflow.step.end",
2259
- "workflow.run.start",
2260
- "workflow.run.end",
2261
- "system.boot",
2262
- "system.migration",
2263
- "system.error"
2264
- ]
2265
- },
2266
- "status": {
2267
- "type": "string",
2268
- "enum": [
2269
- "ok",
2270
- "error",
2271
- "timeout",
2272
- "skipped"
2273
- ]
2274
- },
2275
- "source": {
2276
- "type": "string",
2277
- "enum": [
2278
- "worker",
2279
- "api",
2280
- "hook",
2281
- "scheduler",
2282
- "cli"
2283
- ]
2284
- },
2285
- "agentId": {
2286
- "type": "string"
2287
- },
2288
- "taskId": {
2289
- "type": "string"
2290
- },
2291
- "sessionId": {
2292
- "type": "string"
2293
- },
2294
- "parentEventId": {
2295
- "type": "string"
2296
- },
2297
- "numericValue": {
2298
- "type": "number"
2299
- },
2300
- "durationMs": {
2301
- "type": "integer"
2302
- },
2303
- "data": {
2304
- "type": "object",
2305
- "additionalProperties": {}
2306
- }
2307
- },
2308
- "required": [
2309
- "category",
2310
- "event",
2311
- "source"
2312
- ]
2313
- },
2314
- "minItems": 1,
2315
- "maxItems": 500
2316
- }
2317
- },
2318
- "required": [
2319
- "events"
2320
- ]
2321
- }
2322
- }
2289
+ "parameters": [
2290
+ {
2291
+ "schema": {
2292
+ "type": "string"
2293
+ },
2294
+ "required": true,
2295
+ "name": "id",
2296
+ "in": "path"
2323
2297
  }
2324
- },
2298
+ ],
2325
2299
  "responses": {
2326
- "201": {
2327
- "description": "Events stored"
2300
+ "200": {
2301
+ "description": "Template with history"
2328
2302
  },
2329
- "400": {
2330
- "description": "Validation error"
2303
+ "404": {
2304
+ "description": "Template not found"
2331
2305
  }
2332
2306
  }
2333
- }
2334
- },
2335
- "/api/events/counts": {
2336
- "get": {
2337
- "summary": "Get event counts grouped by event name",
2307
+ },
2308
+ "delete": {
2309
+ "summary": "Delete a prompt template override",
2338
2310
  "tags": [
2339
- "Events"
2311
+ "PromptTemplates"
2340
2312
  ],
2341
2313
  "security": [
2342
2314
  {
@@ -2346,50 +2318,44 @@
2346
2318
  "parameters": [
2347
2319
  {
2348
2320
  "schema": {
2349
- "type": "string",
2350
- "enum": [
2351
- "tool",
2352
- "skill",
2353
- "session",
2354
- "api",
2355
- "task",
2356
- "workflow",
2357
- "system"
2358
- ]
2321
+ "type": "string"
2359
2322
  },
2360
- "required": false,
2361
- "name": "category",
2362
- "in": "query"
2323
+ "required": true,
2324
+ "name": "id",
2325
+ "in": "path"
2326
+ }
2327
+ ],
2328
+ "responses": {
2329
+ "200": {
2330
+ "description": "Template deleted"
2363
2331
  },
2364
- {
2365
- "schema": {
2366
- "type": "string",
2367
- "enum": [
2368
- "worker",
2369
- "api",
2370
- "hook",
2371
- "scheduler",
2372
- "cli"
2373
- ]
2374
- },
2375
- "required": false,
2376
- "name": "source",
2377
- "in": "query"
2332
+ "400": {
2333
+ "description": "Cannot delete default template"
2378
2334
  },
2335
+ "404": {
2336
+ "description": "Template not found"
2337
+ }
2338
+ }
2339
+ }
2340
+ },
2341
+ "/api/prompt-templates": {
2342
+ "get": {
2343
+ "summary": "List prompt templates with optional filters",
2344
+ "tags": [
2345
+ "PromptTemplates"
2346
+ ],
2347
+ "security": [
2379
2348
  {
2380
- "schema": {
2381
- "type": "string"
2382
- },
2383
- "required": false,
2384
- "name": "agentId",
2385
- "in": "query"
2386
- },
2349
+ "bearerAuth": []
2350
+ }
2351
+ ],
2352
+ "parameters": [
2387
2353
  {
2388
2354
  "schema": {
2389
2355
  "type": "string"
2390
2356
  },
2391
2357
  "required": false,
2392
- "name": "taskId",
2358
+ "name": "eventType",
2393
2359
  "in": "query"
2394
2360
  },
2395
2361
  {
@@ -2397,7 +2363,7 @@
2397
2363
  "type": "string"
2398
2364
  },
2399
2365
  "required": false,
2400
- "name": "sessionId",
2366
+ "name": "scope",
2401
2367
  "in": "query"
2402
2368
  },
2403
2369
  {
@@ -2405,30 +2371,32 @@
2405
2371
  "type": "string"
2406
2372
  },
2407
2373
  "required": false,
2408
- "name": "since",
2374
+ "name": "scopeId",
2409
2375
  "in": "query"
2410
2376
  },
2411
2377
  {
2412
2378
  "schema": {
2413
- "type": "string"
2379
+ "type": "string",
2380
+ "enum": [
2381
+ "true",
2382
+ "false"
2383
+ ]
2414
2384
  },
2415
2385
  "required": false,
2416
- "name": "until",
2386
+ "name": "isDefault",
2417
2387
  "in": "query"
2418
2388
  }
2419
2389
  ],
2420
2390
  "responses": {
2421
2391
  "200": {
2422
- "description": "Event counts"
2392
+ "description": "List of prompt templates"
2423
2393
  }
2424
2394
  }
2425
- }
2426
- },
2427
- "/api/memory/index": {
2428
- "post": {
2429
- "summary": "Ingest content into memory system (async embedding)",
2395
+ },
2396
+ "put": {
2397
+ "summary": "Create or update a prompt template override",
2430
2398
  "tags": [
2431
- "Memory"
2399
+ "PromptTemplates"
2432
2400
  ],
2433
2401
  "security": [
2434
2402
  {
@@ -2441,61 +2409,50 @@
2441
2409
  "schema": {
2442
2410
  "type": "object",
2443
2411
  "properties": {
2444
- "agentId": {
2445
- "type": "string",
2446
- "format": "uuid"
2447
- },
2448
- "content": {
2449
- "type": "string",
2450
- "minLength": 1
2451
- },
2452
- "name": {
2412
+ "eventType": {
2453
2413
  "type": "string",
2454
2414
  "minLength": 1
2455
2415
  },
2456
2416
  "scope": {
2457
2417
  "type": "string",
2458
2418
  "enum": [
2419
+ "global",
2459
2420
  "agent",
2460
- "swarm"
2421
+ "repo"
2461
2422
  ]
2462
2423
  },
2463
- "source": {
2424
+ "scopeId": {
2425
+ "type": "string"
2426
+ },
2427
+ "state": {
2464
2428
  "type": "string",
2465
2429
  "enum": [
2466
- "manual",
2467
- "file_index",
2468
- "session_summary",
2469
- "task_completion"
2430
+ "enabled",
2431
+ "default_prompt_fallback",
2432
+ "skip_event"
2470
2433
  ]
2471
2434
  },
2472
- "sourceTaskId": {
2473
- "type": "string",
2474
- "format": "uuid"
2435
+ "body": {
2436
+ "type": "string"
2475
2437
  },
2476
- "sourcePath": {
2438
+ "changedBy": {
2477
2439
  "type": "string"
2478
2440
  },
2479
- "tags": {
2480
- "type": "array",
2481
- "items": {
2482
- "type": "string"
2483
- }
2441
+ "changeReason": {
2442
+ "type": "string"
2484
2443
  }
2485
2444
  },
2486
2445
  "required": [
2487
- "content",
2488
- "name",
2489
- "scope",
2490
- "source"
2446
+ "eventType",
2447
+ "body"
2491
2448
  ]
2492
2449
  }
2493
2450
  }
2494
2451
  }
2495
2452
  },
2496
2453
  "responses": {
2497
- "202": {
2498
- "description": "Content queued for embedding"
2454
+ "200": {
2455
+ "description": "Upserted template"
2499
2456
  },
2500
2457
  "400": {
2501
2458
  "description": "Validation error"
@@ -2503,11 +2460,35 @@
2503
2460
  }
2504
2461
  }
2505
2462
  },
2506
- "/api/memory/search": {
2463
+ "/api/poll": {
2464
+ "get": {
2465
+ "summary": "Poll for triggers (tasks, mentions)",
2466
+ "tags": [
2467
+ "Poll"
2468
+ ],
2469
+ "security": [
2470
+ {
2471
+ "bearerAuth": []
2472
+ }
2473
+ ],
2474
+ "responses": {
2475
+ "200": {
2476
+ "description": "Trigger data or null"
2477
+ },
2478
+ "400": {
2479
+ "description": "Missing X-Agent-ID"
2480
+ },
2481
+ "404": {
2482
+ "description": "Agent not found"
2483
+ }
2484
+ }
2485
+ }
2486
+ },
2487
+ "/api/channel-activity/commit-cursors": {
2507
2488
  "post": {
2508
- "summary": "Search memories by natural language query",
2489
+ "summary": "Commit channel activity cursors after successful processing",
2509
2490
  "tags": [
2510
- "Memory"
2491
+ "Poll"
2511
2492
  ],
2512
2493
  "security": [
2513
2494
  {
@@ -2520,19 +2501,27 @@
2520
2501
  "schema": {
2521
2502
  "type": "object",
2522
2503
  "properties": {
2523
- "query": {
2524
- "type": "string",
2525
- "minLength": 1
2526
- },
2527
- "limit": {
2528
- "type": "integer",
2529
- "minimum": 1,
2530
- "maximum": 20,
2531
- "default": 5
2504
+ "cursorUpdates": {
2505
+ "type": "array",
2506
+ "items": {
2507
+ "type": "object",
2508
+ "properties": {
2509
+ "channelId": {
2510
+ "type": "string"
2511
+ },
2512
+ "ts": {
2513
+ "type": "string"
2514
+ }
2515
+ },
2516
+ "required": [
2517
+ "channelId",
2518
+ "ts"
2519
+ ]
2520
+ }
2532
2521
  }
2533
2522
  },
2534
2523
  "required": [
2535
- "query"
2524
+ "cursorUpdates"
2536
2525
  ]
2537
2526
  }
2538
2527
  }
@@ -2540,19 +2529,19 @@
2540
2529
  },
2541
2530
  "responses": {
2542
2531
  "200": {
2543
- "description": "Search results"
2532
+ "description": "Cursors committed"
2544
2533
  },
2545
2534
  "400": {
2546
- "description": "Missing query or agent ID"
2535
+ "description": "Invalid request"
2547
2536
  }
2548
2537
  }
2549
2538
  }
2550
2539
  },
2551
- "/api/prompt-templates/resolved": {
2540
+ "/api/repos/{id}": {
2552
2541
  "get": {
2553
- "summary": "Resolve a prompt template for a given event type and scope chain",
2542
+ "summary": "Get a repo by ID",
2554
2543
  "tags": [
2555
- "PromptTemplates"
2544
+ "Repos"
2556
2545
  ],
2557
2546
  "security": [
2558
2547
  {
@@ -2562,66 +2551,105 @@
2562
2551
  "parameters": [
2563
2552
  {
2564
2553
  "schema": {
2565
- "type": "string"
2554
+ "type": "string",
2555
+ "format": "uuid"
2566
2556
  },
2567
2557
  "required": true,
2568
- "name": "eventType",
2569
- "in": "query"
2570
- },
2571
- {
2572
- "schema": {
2573
- "type": "string"
2574
- },
2575
- "required": false,
2576
- "name": "agentId",
2577
- "in": "query"
2578
- },
2579
- {
2580
- "schema": {
2581
- "type": "string"
2582
- },
2583
- "required": false,
2584
- "name": "repoId",
2585
- "in": "query"
2558
+ "name": "id",
2559
+ "in": "path"
2586
2560
  }
2587
2561
  ],
2588
2562
  "responses": {
2589
2563
  "200": {
2590
- "description": "Resolved template info"
2564
+ "description": "Repo details",
2565
+ "content": {
2566
+ "application/json": {
2567
+ "schema": {
2568
+ "type": "object",
2569
+ "properties": {
2570
+ "id": {
2571
+ "type": "string",
2572
+ "format": "uuid"
2573
+ },
2574
+ "url": {
2575
+ "type": "string",
2576
+ "minLength": 1
2577
+ },
2578
+ "name": {
2579
+ "type": "string",
2580
+ "minLength": 1,
2581
+ "maxLength": 100
2582
+ },
2583
+ "clonePath": {
2584
+ "type": "string",
2585
+ "minLength": 1
2586
+ },
2587
+ "defaultBranch": {
2588
+ "type": "string",
2589
+ "default": "main"
2590
+ },
2591
+ "autoClone": {
2592
+ "type": "boolean",
2593
+ "default": true
2594
+ },
2595
+ "createdAt": {
2596
+ "type": "string"
2597
+ },
2598
+ "lastUpdatedAt": {
2599
+ "type": "string"
2600
+ }
2601
+ },
2602
+ "required": [
2603
+ "id",
2604
+ "url",
2605
+ "name",
2606
+ "clonePath",
2607
+ "createdAt",
2608
+ "lastUpdatedAt"
2609
+ ]
2610
+ }
2611
+ }
2612
+ }
2591
2613
  },
2592
- "400": {
2593
- "description": "Missing eventType"
2614
+ "404": {
2615
+ "description": "Repo not found",
2616
+ "content": {
2617
+ "application/json": {
2618
+ "schema": {
2619
+ "type": "object",
2620
+ "properties": {
2621
+ "error": {
2622
+ "type": "string"
2623
+ }
2624
+ },
2625
+ "required": [
2626
+ "error"
2627
+ ]
2628
+ }
2629
+ }
2630
+ }
2594
2631
  }
2595
2632
  }
2596
- }
2597
- },
2598
- "/api/prompt-templates/events": {
2599
- "get": {
2600
- "summary": "List all registered event types with their available variables",
2633
+ },
2634
+ "put": {
2635
+ "summary": "Update a repo",
2601
2636
  "tags": [
2602
- "PromptTemplates"
2637
+ "Repos"
2603
2638
  ],
2604
2639
  "security": [
2605
2640
  {
2606
2641
  "bearerAuth": []
2607
2642
  }
2608
2643
  ],
2609
- "responses": {
2610
- "200": {
2611
- "description": "List of event template definitions"
2612
- }
2613
- }
2614
- }
2615
- },
2616
- "/api/prompt-templates/preview": {
2617
- "post": {
2618
- "summary": "Dry-run render a template with provided variables",
2619
- "tags": [
2620
- "PromptTemplates"
2621
- ],
2622
- "security": [
2644
+ "parameters": [
2623
2645
  {
2624
- "bearerAuth": []
2646
+ "schema": {
2647
+ "type": "string",
2648
+ "format": "uuid"
2649
+ },
2650
+ "required": true,
2651
+ "name": "id",
2652
+ "in": "path"
2625
2653
  }
2626
2654
  ],
2627
2655
  "requestBody": {
@@ -2630,138 +2658,120 @@
2630
2658
  "schema": {
2631
2659
  "type": "object",
2632
2660
  "properties": {
2633
- "eventType": {
2661
+ "url": {
2634
2662
  "type": "string"
2635
2663
  },
2636
- "body": {
2664
+ "name": {
2637
2665
  "type": "string"
2638
2666
  },
2639
- "variables": {
2640
- "type": "object",
2641
- "additionalProperties": {}
2667
+ "clonePath": {
2668
+ "type": "string"
2669
+ },
2670
+ "defaultBranch": {
2671
+ "type": "string"
2672
+ },
2673
+ "autoClone": {
2674
+ "type": "boolean"
2642
2675
  }
2643
- },
2644
- "required": [
2645
- "eventType"
2646
- ]
2676
+ }
2647
2677
  }
2648
2678
  }
2649
2679
  }
2650
2680
  },
2651
2681
  "responses": {
2652
2682
  "200": {
2653
- "description": "Rendered template preview"
2654
- },
2655
- "400": {
2656
- "description": "Validation error"
2657
- }
2658
- }
2659
- }
2660
- },
2661
- "/api/prompt-templates/render": {
2662
- "post": {
2663
- "summary": "Full scope-aware template resolution with interpolation (used by workers via HTTP)",
2664
- "tags": [
2665
- "PromptTemplates"
2666
- ],
2667
- "security": [
2668
- {
2669
- "bearerAuth": []
2670
- }
2671
- ],
2672
- "requestBody": {
2673
- "content": {
2674
- "application/json": {
2675
- "schema": {
2676
- "type": "object",
2677
- "properties": {
2678
- "eventType": {
2679
- "type": "string"
2680
- },
2681
- "variables": {
2682
- "type": "object",
2683
- "additionalProperties": {}
2684
- },
2685
- "agentId": {
2686
- "type": "string"
2683
+ "description": "Repo updated",
2684
+ "content": {
2685
+ "application/json": {
2686
+ "schema": {
2687
+ "type": "object",
2688
+ "properties": {
2689
+ "id": {
2690
+ "type": "string",
2691
+ "format": "uuid"
2692
+ },
2693
+ "url": {
2694
+ "type": "string",
2695
+ "minLength": 1
2696
+ },
2697
+ "name": {
2698
+ "type": "string",
2699
+ "minLength": 1,
2700
+ "maxLength": 100
2701
+ },
2702
+ "clonePath": {
2703
+ "type": "string",
2704
+ "minLength": 1
2705
+ },
2706
+ "defaultBranch": {
2707
+ "type": "string",
2708
+ "default": "main"
2709
+ },
2710
+ "autoClone": {
2711
+ "type": "boolean",
2712
+ "default": true
2713
+ },
2714
+ "createdAt": {
2715
+ "type": "string"
2716
+ },
2717
+ "lastUpdatedAt": {
2718
+ "type": "string"
2719
+ }
2687
2720
  },
2688
- "repoId": {
2689
- "type": "string"
2690
- }
2691
- },
2692
- "required": [
2693
- "eventType"
2694
- ]
2721
+ "required": [
2722
+ "id",
2723
+ "url",
2724
+ "name",
2725
+ "clonePath",
2726
+ "createdAt",
2727
+ "lastUpdatedAt"
2728
+ ]
2729
+ }
2695
2730
  }
2696
2731
  }
2697
- }
2698
- },
2699
- "responses": {
2700
- "200": {
2701
- "description": "Fully resolved and interpolated template"
2702
2732
  },
2703
- "400": {
2704
- "description": "Validation error"
2705
- }
2706
- }
2707
- }
2708
- },
2709
- "/api/prompt-templates/{id}/checkout": {
2710
- "post": {
2711
- "summary": "Checkout a specific version of a prompt template from history",
2712
- "tags": [
2713
- "PromptTemplates"
2714
- ],
2715
- "security": [
2716
- {
2717
- "bearerAuth": []
2718
- }
2719
- ],
2720
- "parameters": [
2721
- {
2722
- "schema": {
2723
- "type": "string"
2724
- },
2725
- "required": true,
2726
- "name": "id",
2727
- "in": "path"
2728
- }
2729
- ],
2730
- "requestBody": {
2731
- "content": {
2732
- "application/json": {
2733
- "schema": {
2734
- "type": "object",
2735
- "properties": {
2736
- "version": {
2737
- "type": "number"
2738
- }
2739
- },
2740
- "required": [
2741
- "version"
2742
- ]
2733
+ "404": {
2734
+ "description": "Repo not found",
2735
+ "content": {
2736
+ "application/json": {
2737
+ "schema": {
2738
+ "type": "object",
2739
+ "properties": {
2740
+ "error": {
2741
+ "type": "string"
2742
+ }
2743
+ },
2744
+ "required": [
2745
+ "error"
2746
+ ]
2747
+ }
2743
2748
  }
2744
2749
  }
2745
- }
2746
- },
2747
- "responses": {
2748
- "200": {
2749
- "description": "Checked-out template"
2750
- },
2751
- "400": {
2752
- "description": "Validation error"
2753
2750
  },
2754
- "404": {
2755
- "description": "Template or version not found"
2751
+ "409": {
2752
+ "description": "Duplicate repo",
2753
+ "content": {
2754
+ "application/json": {
2755
+ "schema": {
2756
+ "type": "object",
2757
+ "properties": {
2758
+ "error": {
2759
+ "type": "string"
2760
+ }
2761
+ },
2762
+ "required": [
2763
+ "error"
2764
+ ]
2765
+ }
2766
+ }
2767
+ }
2756
2768
  }
2757
2769
  }
2758
- }
2759
- },
2760
- "/api/prompt-templates/{id}/reset": {
2761
- "post": {
2762
- "summary": "Reset a prompt template to its code-defined default",
2770
+ },
2771
+ "delete": {
2772
+ "summary": "Delete a repo",
2763
2773
  "tags": [
2764
- "PromptTemplates"
2774
+ "Repos"
2765
2775
  ],
2766
2776
  "security": [
2767
2777
  {
@@ -2771,7 +2781,8 @@
2771
2781
  "parameters": [
2772
2782
  {
2773
2783
  "schema": {
2774
- "type": "string"
2784
+ "type": "string",
2785
+ "format": "uuid"
2775
2786
  },
2776
2787
  "required": true,
2777
2788
  "name": "id",
@@ -2780,19 +2791,49 @@
2780
2791
  ],
2781
2792
  "responses": {
2782
2793
  "200": {
2783
- "description": "Reset template"
2794
+ "description": "Repo deleted",
2795
+ "content": {
2796
+ "application/json": {
2797
+ "schema": {
2798
+ "type": "object",
2799
+ "properties": {
2800
+ "success": {
2801
+ "type": "boolean"
2802
+ }
2803
+ },
2804
+ "required": [
2805
+ "success"
2806
+ ]
2807
+ }
2808
+ }
2809
+ }
2784
2810
  },
2785
2811
  "404": {
2786
- "description": "Template not found or no code default available"
2812
+ "description": "Repo not found",
2813
+ "content": {
2814
+ "application/json": {
2815
+ "schema": {
2816
+ "type": "object",
2817
+ "properties": {
2818
+ "error": {
2819
+ "type": "string"
2820
+ }
2821
+ },
2822
+ "required": [
2823
+ "error"
2824
+ ]
2825
+ }
2826
+ }
2827
+ }
2787
2828
  }
2788
2829
  }
2789
2830
  }
2790
2831
  },
2791
- "/api/prompt-templates/{id}": {
2832
+ "/api/repos": {
2792
2833
  "get": {
2793
- "summary": "Get a single prompt template with its version history",
2834
+ "summary": "List repos with optional filters",
2794
2835
  "tags": [
2795
- "PromptTemplates"
2836
+ "Repos"
2796
2837
  ],
2797
2838
  "security": [
2798
2839
  {
@@ -2802,114 +2843,94 @@
2802
2843
  "parameters": [
2803
2844
  {
2804
2845
  "schema": {
2805
- "type": "string"
2846
+ "type": "string",
2847
+ "enum": [
2848
+ "true",
2849
+ "false"
2850
+ ]
2806
2851
  },
2807
- "required": true,
2808
- "name": "id",
2809
- "in": "path"
2810
- }
2811
- ],
2812
- "responses": {
2813
- "200": {
2814
- "description": "Template with history"
2852
+ "required": false,
2853
+ "name": "autoClone",
2854
+ "in": "query"
2815
2855
  },
2816
- "404": {
2817
- "description": "Template not found"
2818
- }
2819
- }
2820
- },
2821
- "delete": {
2822
- "summary": "Delete a prompt template override",
2823
- "tags": [
2824
- "PromptTemplates"
2825
- ],
2826
- "security": [
2827
- {
2828
- "bearerAuth": []
2829
- }
2830
- ],
2831
- "parameters": [
2832
2856
  {
2833
2857
  "schema": {
2834
2858
  "type": "string"
2835
2859
  },
2836
- "required": true,
2837
- "name": "id",
2838
- "in": "path"
2860
+ "required": false,
2861
+ "name": "name",
2862
+ "in": "query"
2839
2863
  }
2840
2864
  ],
2841
2865
  "responses": {
2842
2866
  "200": {
2843
- "description": "Template deleted"
2844
- },
2845
- "400": {
2846
- "description": "Cannot delete default template"
2847
- },
2848
- "404": {
2849
- "description": "Template not found"
2850
- }
2851
- }
2852
- }
2853
- },
2854
- "/api/prompt-templates": {
2855
- "get": {
2856
- "summary": "List prompt templates with optional filters",
2857
- "tags": [
2858
- "PromptTemplates"
2859
- ],
2860
- "security": [
2861
- {
2862
- "bearerAuth": []
2863
- }
2864
- ],
2865
- "parameters": [
2866
- {
2867
- "schema": {
2868
- "type": "string"
2869
- },
2870
- "required": false,
2871
- "name": "eventType",
2872
- "in": "query"
2873
- },
2874
- {
2875
- "schema": {
2876
- "type": "string"
2877
- },
2878
- "required": false,
2879
- "name": "scope",
2880
- "in": "query"
2881
- },
2882
- {
2883
- "schema": {
2884
- "type": "string"
2885
- },
2886
- "required": false,
2887
- "name": "scopeId",
2888
- "in": "query"
2889
- },
2890
- {
2891
- "schema": {
2892
- "type": "string",
2893
- "enum": [
2894
- "true",
2895
- "false"
2896
- ]
2897
- },
2898
- "required": false,
2899
- "name": "isDefault",
2900
- "in": "query"
2901
- }
2902
- ],
2903
- "responses": {
2904
- "200": {
2905
- "description": "List of prompt templates"
2867
+ "description": "List of repos",
2868
+ "content": {
2869
+ "application/json": {
2870
+ "schema": {
2871
+ "type": "object",
2872
+ "properties": {
2873
+ "repos": {
2874
+ "type": "array",
2875
+ "items": {
2876
+ "type": "object",
2877
+ "properties": {
2878
+ "id": {
2879
+ "type": "string",
2880
+ "format": "uuid"
2881
+ },
2882
+ "url": {
2883
+ "type": "string",
2884
+ "minLength": 1
2885
+ },
2886
+ "name": {
2887
+ "type": "string",
2888
+ "minLength": 1,
2889
+ "maxLength": 100
2890
+ },
2891
+ "clonePath": {
2892
+ "type": "string",
2893
+ "minLength": 1
2894
+ },
2895
+ "defaultBranch": {
2896
+ "type": "string",
2897
+ "default": "main"
2898
+ },
2899
+ "autoClone": {
2900
+ "type": "boolean",
2901
+ "default": true
2902
+ },
2903
+ "createdAt": {
2904
+ "type": "string"
2905
+ },
2906
+ "lastUpdatedAt": {
2907
+ "type": "string"
2908
+ }
2909
+ },
2910
+ "required": [
2911
+ "id",
2912
+ "url",
2913
+ "name",
2914
+ "clonePath",
2915
+ "createdAt",
2916
+ "lastUpdatedAt"
2917
+ ]
2918
+ }
2919
+ }
2920
+ },
2921
+ "required": [
2922
+ "repos"
2923
+ ]
2924
+ }
2925
+ }
2926
+ }
2906
2927
  }
2907
2928
  }
2908
2929
  },
2909
- "put": {
2910
- "summary": "Create or update a prompt template override",
2930
+ "post": {
2931
+ "summary": "Create a new repo",
2911
2932
  "tags": [
2912
- "PromptTemplates"
2933
+ "Repos"
2913
2934
  ],
2914
2935
  "security": [
2915
2936
  {
@@ -2922,159 +2943,35 @@
2922
2943
  "schema": {
2923
2944
  "type": "object",
2924
2945
  "properties": {
2925
- "eventType": {
2946
+ "url": {
2926
2947
  "type": "string",
2927
2948
  "minLength": 1
2928
2949
  },
2929
- "scope": {
2930
- "type": "string",
2931
- "enum": [
2932
- "global",
2933
- "agent",
2934
- "repo"
2935
- ]
2936
- },
2937
- "scopeId": {
2938
- "type": "string"
2939
- },
2940
- "state": {
2950
+ "name": {
2941
2951
  "type": "string",
2942
- "enum": [
2943
- "enabled",
2944
- "default_prompt_fallback",
2945
- "skip_event"
2946
- ]
2952
+ "minLength": 1
2947
2953
  },
2948
- "body": {
2954
+ "clonePath": {
2949
2955
  "type": "string"
2950
2956
  },
2951
- "changedBy": {
2957
+ "defaultBranch": {
2952
2958
  "type": "string"
2953
2959
  },
2954
- "changeReason": {
2955
- "type": "string"
2956
- }
2957
- },
2958
- "required": [
2959
- "eventType",
2960
- "body"
2961
- ]
2962
- }
2963
- }
2964
- }
2965
- },
2966
- "responses": {
2967
- "200": {
2968
- "description": "Upserted template"
2969
- },
2970
- "400": {
2971
- "description": "Validation error"
2972
- }
2973
- }
2974
- }
2975
- },
2976
- "/api/poll": {
2977
- "get": {
2978
- "summary": "Poll for triggers (tasks, mentions, epic updates)",
2979
- "tags": [
2980
- "Poll"
2981
- ],
2982
- "security": [
2983
- {
2984
- "bearerAuth": []
2985
- }
2986
- ],
2987
- "responses": {
2988
- "200": {
2989
- "description": "Trigger data or null"
2990
- },
2991
- "400": {
2992
- "description": "Missing X-Agent-ID"
2993
- },
2994
- "404": {
2995
- "description": "Agent not found"
2996
- }
2997
- }
2998
- }
2999
- },
3000
- "/api/channel-activity/commit-cursors": {
3001
- "post": {
3002
- "summary": "Commit channel activity cursors after successful processing",
3003
- "tags": [
3004
- "Poll"
3005
- ],
3006
- "security": [
3007
- {
3008
- "bearerAuth": []
3009
- }
3010
- ],
3011
- "requestBody": {
3012
- "content": {
3013
- "application/json": {
3014
- "schema": {
3015
- "type": "object",
3016
- "properties": {
3017
- "cursorUpdates": {
3018
- "type": "array",
3019
- "items": {
3020
- "type": "object",
3021
- "properties": {
3022
- "channelId": {
3023
- "type": "string"
3024
- },
3025
- "ts": {
3026
- "type": "string"
3027
- }
3028
- },
3029
- "required": [
3030
- "channelId",
3031
- "ts"
3032
- ]
3033
- }
2960
+ "autoClone": {
2961
+ "type": "boolean"
3034
2962
  }
3035
2963
  },
3036
2964
  "required": [
3037
- "cursorUpdates"
2965
+ "url",
2966
+ "name"
3038
2967
  ]
3039
2968
  }
3040
2969
  }
3041
2970
  }
3042
2971
  },
3043
2972
  "responses": {
3044
- "200": {
3045
- "description": "Cursors committed"
3046
- },
3047
- "400": {
3048
- "description": "Invalid request"
3049
- }
3050
- }
3051
- }
3052
- },
3053
- "/api/repos/{id}": {
3054
- "get": {
3055
- "summary": "Get a repo by ID",
3056
- "tags": [
3057
- "Repos"
3058
- ],
3059
- "security": [
3060
- {
3061
- "bearerAuth": []
3062
- }
3063
- ],
3064
- "parameters": [
3065
- {
3066
- "schema": {
3067
- "type": "string",
3068
- "format": "uuid"
3069
- },
3070
- "required": true,
3071
- "name": "id",
3072
- "in": "path"
3073
- }
3074
- ],
3075
- "responses": {
3076
- "200": {
3077
- "description": "Repo details",
2973
+ "201": {
2974
+ "description": "Repo created",
3078
2975
  "content": {
3079
2976
  "application/json": {
3080
2977
  "schema": {
@@ -3124,8 +3021,8 @@
3124
3021
  }
3125
3022
  }
3126
3023
  },
3127
- "404": {
3128
- "description": "Repo not found",
3024
+ "400": {
3025
+ "description": "Validation error",
3129
3026
  "content": {
3130
3027
  "application/json": {
3131
3028
  "schema": {
@@ -3141,150 +3038,127 @@
3141
3038
  }
3142
3039
  }
3143
3040
  }
3144
- }
3145
- }
3146
- },
3147
- "put": {
3148
- "summary": "Update a repo",
3041
+ },
3042
+ "409": {
3043
+ "description": "Duplicate repo",
3044
+ "content": {
3045
+ "application/json": {
3046
+ "schema": {
3047
+ "type": "object",
3048
+ "properties": {
3049
+ "error": {
3050
+ "type": "string"
3051
+ }
3052
+ },
3053
+ "required": [
3054
+ "error"
3055
+ ]
3056
+ }
3057
+ }
3058
+ }
3059
+ }
3060
+ }
3061
+ }
3062
+ },
3063
+ "/api/schedules": {
3064
+ "post": {
3065
+ "summary": "Create a new schedule",
3149
3066
  "tags": [
3150
- "Repos"
3067
+ "Schedules"
3151
3068
  ],
3152
3069
  "security": [
3153
3070
  {
3154
3071
  "bearerAuth": []
3155
3072
  }
3156
3073
  ],
3157
- "parameters": [
3158
- {
3159
- "schema": {
3160
- "type": "string",
3161
- "format": "uuid"
3162
- },
3163
- "required": true,
3164
- "name": "id",
3165
- "in": "path"
3166
- }
3167
- ],
3168
3074
  "requestBody": {
3169
3075
  "content": {
3170
3076
  "application/json": {
3171
3077
  "schema": {
3172
3078
  "type": "object",
3173
3079
  "properties": {
3174
- "url": {
3175
- "type": "string"
3176
- },
3177
3080
  "name": {
3081
+ "type": "string",
3082
+ "minLength": 1
3083
+ },
3084
+ "description": {
3178
3085
  "type": "string"
3179
3086
  },
3180
- "clonePath": {
3087
+ "cronExpression": {
3181
3088
  "type": "string"
3182
3089
  },
3183
- "defaultBranch": {
3090
+ "intervalMs": {
3091
+ "type": "integer"
3092
+ },
3093
+ "taskTemplate": {
3094
+ "type": "string",
3095
+ "minLength": 1
3096
+ },
3097
+ "taskType": {
3184
3098
  "type": "string"
3185
3099
  },
3186
- "autoClone": {
3100
+ "tags": {
3101
+ "type": "array",
3102
+ "items": {
3103
+ "type": "string"
3104
+ }
3105
+ },
3106
+ "priority": {
3107
+ "type": "integer"
3108
+ },
3109
+ "targetAgentId": {
3110
+ "type": "string",
3111
+ "format": "uuid"
3112
+ },
3113
+ "enabled": {
3187
3114
  "type": "boolean"
3115
+ },
3116
+ "timezone": {
3117
+ "type": "string"
3118
+ },
3119
+ "model": {
3120
+ "type": "string"
3121
+ },
3122
+ "scheduleType": {
3123
+ "type": "string",
3124
+ "enum": [
3125
+ "recurring",
3126
+ "one_time"
3127
+ ]
3128
+ },
3129
+ "delayMs": {
3130
+ "type": "integer"
3131
+ },
3132
+ "runAt": {
3133
+ "type": "string"
3188
3134
  }
3189
- }
3135
+ },
3136
+ "required": [
3137
+ "name",
3138
+ "taskTemplate"
3139
+ ]
3190
3140
  }
3191
3141
  }
3192
3142
  }
3193
3143
  },
3194
3144
  "responses": {
3195
- "200": {
3196
- "description": "Repo updated",
3197
- "content": {
3198
- "application/json": {
3199
- "schema": {
3200
- "type": "object",
3201
- "properties": {
3202
- "id": {
3203
- "type": "string",
3204
- "format": "uuid"
3205
- },
3206
- "url": {
3207
- "type": "string",
3208
- "minLength": 1
3209
- },
3210
- "name": {
3211
- "type": "string",
3212
- "minLength": 1,
3213
- "maxLength": 100
3214
- },
3215
- "clonePath": {
3216
- "type": "string",
3217
- "minLength": 1
3218
- },
3219
- "defaultBranch": {
3220
- "type": "string",
3221
- "default": "main"
3222
- },
3223
- "autoClone": {
3224
- "type": "boolean",
3225
- "default": true
3226
- },
3227
- "createdAt": {
3228
- "type": "string"
3229
- },
3230
- "lastUpdatedAt": {
3231
- "type": "string"
3232
- }
3233
- },
3234
- "required": [
3235
- "id",
3236
- "url",
3237
- "name",
3238
- "clonePath",
3239
- "createdAt",
3240
- "lastUpdatedAt"
3241
- ]
3242
- }
3243
- }
3244
- }
3145
+ "201": {
3146
+ "description": "Schedule created"
3245
3147
  },
3246
- "404": {
3247
- "description": "Repo not found",
3248
- "content": {
3249
- "application/json": {
3250
- "schema": {
3251
- "type": "object",
3252
- "properties": {
3253
- "error": {
3254
- "type": "string"
3255
- }
3256
- },
3257
- "required": [
3258
- "error"
3259
- ]
3260
- }
3261
- }
3262
- }
3148
+ "400": {
3149
+ "description": "Validation error"
3263
3150
  },
3264
3151
  "409": {
3265
- "description": "Duplicate repo",
3266
- "content": {
3267
- "application/json": {
3268
- "schema": {
3269
- "type": "object",
3270
- "properties": {
3271
- "error": {
3272
- "type": "string"
3273
- }
3274
- },
3275
- "required": [
3276
- "error"
3277
- ]
3278
- }
3279
- }
3280
- }
3152
+ "description": "Duplicate name"
3281
3153
  }
3282
3154
  }
3283
- },
3284
- "delete": {
3285
- "summary": "Delete a repo",
3155
+ }
3156
+ },
3157
+ "/api/schedules/{id}/run": {
3158
+ "post": {
3159
+ "summary": "Run a schedule immediately",
3286
3160
  "tags": [
3287
- "Repos"
3161
+ "Schedules"
3288
3162
  ],
3289
3163
  "security": [
3290
3164
  {
@@ -3294,8 +3168,7 @@
3294
3168
  "parameters": [
3295
3169
  {
3296
3170
  "schema": {
3297
- "type": "string",
3298
- "format": "uuid"
3171
+ "type": "string"
3299
3172
  },
3300
3173
  "required": true,
3301
3174
  "name": "id",
@@ -3304,49 +3177,22 @@
3304
3177
  ],
3305
3178
  "responses": {
3306
3179
  "200": {
3307
- "description": "Repo deleted",
3308
- "content": {
3309
- "application/json": {
3310
- "schema": {
3311
- "type": "object",
3312
- "properties": {
3313
- "success": {
3314
- "type": "boolean"
3315
- }
3316
- },
3317
- "required": [
3318
- "success"
3319
- ]
3320
- }
3321
- }
3322
- }
3180
+ "description": "Schedule run triggered"
3181
+ },
3182
+ "400": {
3183
+ "description": "Schedule is disabled"
3323
3184
  },
3324
3185
  "404": {
3325
- "description": "Repo not found",
3326
- "content": {
3327
- "application/json": {
3328
- "schema": {
3329
- "type": "object",
3330
- "properties": {
3331
- "error": {
3332
- "type": "string"
3333
- }
3334
- },
3335
- "required": [
3336
- "error"
3337
- ]
3338
- }
3339
- }
3340
- }
3186
+ "description": "Schedule not found"
3341
3187
  }
3342
3188
  }
3343
3189
  }
3344
3190
  },
3345
- "/api/repos": {
3191
+ "/api/schedules/{id}": {
3346
3192
  "get": {
3347
- "summary": "List repos with optional filters",
3193
+ "summary": "Get a schedule by ID",
3348
3194
  "tags": [
3349
- "Repos"
3195
+ "Schedules"
3350
3196
  ],
3351
3197
  "security": [
3352
3198
  {
@@ -3354,234 +3200,42 @@
3354
3200
  }
3355
3201
  ],
3356
3202
  "parameters": [
3357
- {
3358
- "schema": {
3359
- "type": "string",
3360
- "enum": [
3361
- "true",
3362
- "false"
3363
- ]
3364
- },
3365
- "required": false,
3366
- "name": "autoClone",
3367
- "in": "query"
3368
- },
3369
3203
  {
3370
3204
  "schema": {
3371
3205
  "type": "string"
3372
3206
  },
3373
- "required": false,
3374
- "name": "name",
3375
- "in": "query"
3207
+ "required": true,
3208
+ "name": "id",
3209
+ "in": "path"
3376
3210
  }
3377
3211
  ],
3378
3212
  "responses": {
3379
3213
  "200": {
3380
- "description": "List of repos",
3381
- "content": {
3382
- "application/json": {
3383
- "schema": {
3384
- "type": "object",
3385
- "properties": {
3386
- "repos": {
3387
- "type": "array",
3388
- "items": {
3389
- "type": "object",
3390
- "properties": {
3391
- "id": {
3392
- "type": "string",
3393
- "format": "uuid"
3394
- },
3395
- "url": {
3396
- "type": "string",
3397
- "minLength": 1
3398
- },
3399
- "name": {
3400
- "type": "string",
3401
- "minLength": 1,
3402
- "maxLength": 100
3403
- },
3404
- "clonePath": {
3405
- "type": "string",
3406
- "minLength": 1
3407
- },
3408
- "defaultBranch": {
3409
- "type": "string",
3410
- "default": "main"
3411
- },
3412
- "autoClone": {
3413
- "type": "boolean",
3414
- "default": true
3415
- },
3416
- "createdAt": {
3417
- "type": "string"
3418
- },
3419
- "lastUpdatedAt": {
3420
- "type": "string"
3421
- }
3422
- },
3423
- "required": [
3424
- "id",
3425
- "url",
3426
- "name",
3427
- "clonePath",
3428
- "createdAt",
3429
- "lastUpdatedAt"
3430
- ]
3431
- }
3432
- }
3433
- },
3434
- "required": [
3435
- "repos"
3436
- ]
3437
- }
3438
- }
3439
- }
3214
+ "description": "Schedule details"
3215
+ },
3216
+ "404": {
3217
+ "description": "Schedule not found"
3440
3218
  }
3441
3219
  }
3442
3220
  },
3443
- "post": {
3444
- "summary": "Create a new repo",
3221
+ "put": {
3222
+ "summary": "Update a schedule",
3445
3223
  "tags": [
3446
- "Repos"
3224
+ "Schedules"
3447
3225
  ],
3448
3226
  "security": [
3449
3227
  {
3450
3228
  "bearerAuth": []
3451
3229
  }
3452
3230
  ],
3453
- "requestBody": {
3454
- "content": {
3455
- "application/json": {
3456
- "schema": {
3457
- "type": "object",
3458
- "properties": {
3459
- "url": {
3460
- "type": "string",
3461
- "minLength": 1
3462
- },
3463
- "name": {
3464
- "type": "string",
3465
- "minLength": 1
3466
- },
3467
- "clonePath": {
3468
- "type": "string"
3469
- },
3470
- "defaultBranch": {
3471
- "type": "string"
3472
- },
3473
- "autoClone": {
3474
- "type": "boolean"
3475
- }
3476
- },
3477
- "required": [
3478
- "url",
3479
- "name"
3480
- ]
3481
- }
3482
- }
3483
- }
3484
- },
3485
- "responses": {
3486
- "201": {
3487
- "description": "Repo created",
3488
- "content": {
3489
- "application/json": {
3490
- "schema": {
3491
- "type": "object",
3492
- "properties": {
3493
- "id": {
3494
- "type": "string",
3495
- "format": "uuid"
3496
- },
3497
- "url": {
3498
- "type": "string",
3499
- "minLength": 1
3500
- },
3501
- "name": {
3502
- "type": "string",
3503
- "minLength": 1,
3504
- "maxLength": 100
3505
- },
3506
- "clonePath": {
3507
- "type": "string",
3508
- "minLength": 1
3509
- },
3510
- "defaultBranch": {
3511
- "type": "string",
3512
- "default": "main"
3513
- },
3514
- "autoClone": {
3515
- "type": "boolean",
3516
- "default": true
3517
- },
3518
- "createdAt": {
3519
- "type": "string"
3520
- },
3521
- "lastUpdatedAt": {
3522
- "type": "string"
3523
- }
3524
- },
3525
- "required": [
3526
- "id",
3527
- "url",
3528
- "name",
3529
- "clonePath",
3530
- "createdAt",
3531
- "lastUpdatedAt"
3532
- ]
3533
- }
3534
- }
3535
- }
3536
- },
3537
- "400": {
3538
- "description": "Validation error",
3539
- "content": {
3540
- "application/json": {
3541
- "schema": {
3542
- "type": "object",
3543
- "properties": {
3544
- "error": {
3545
- "type": "string"
3546
- }
3547
- },
3548
- "required": [
3549
- "error"
3550
- ]
3551
- }
3552
- }
3553
- }
3554
- },
3555
- "409": {
3556
- "description": "Duplicate repo",
3557
- "content": {
3558
- "application/json": {
3559
- "schema": {
3560
- "type": "object",
3561
- "properties": {
3562
- "error": {
3563
- "type": "string"
3564
- }
3565
- },
3566
- "required": [
3567
- "error"
3568
- ]
3569
- }
3570
- }
3571
- }
3572
- }
3573
- }
3574
- }
3575
- },
3576
- "/api/schedules": {
3577
- "post": {
3578
- "summary": "Create a new schedule",
3579
- "tags": [
3580
- "Schedules"
3581
- ],
3582
- "security": [
3231
+ "parameters": [
3583
3232
  {
3584
- "bearerAuth": []
3233
+ "schema": {
3234
+ "type": "string"
3235
+ },
3236
+ "required": true,
3237
+ "name": "id",
3238
+ "in": "path"
3585
3239
  }
3586
3240
  ],
3587
3241
  "requestBody": {
@@ -3591,8 +3245,7 @@
3591
3245
  "type": "object",
3592
3246
  "properties": {
3593
3247
  "name": {
3594
- "type": "string",
3595
- "minLength": 1
3248
+ "type": "string"
3596
3249
  },
3597
3250
  "description": {
3598
3251
  "type": "string"
@@ -3604,8 +3257,7 @@
3604
3257
  "type": "integer"
3605
3258
  },
3606
3259
  "taskTemplate": {
3607
- "type": "string",
3608
- "minLength": 1
3260
+ "type": "string"
3609
3261
  },
3610
3262
  "taskType": {
3611
3263
  "type": "string"
@@ -3632,199 +3284,34 @@
3632
3284
  "model": {
3633
3285
  "type": "string"
3634
3286
  },
3635
- "scheduleType": {
3636
- "type": "string",
3637
- "enum": [
3638
- "recurring",
3639
- "one_time"
3287
+ "nextRunAt": {
3288
+ "type": [
3289
+ "string",
3290
+ "null"
3640
3291
  ]
3641
- },
3642
- "delayMs": {
3643
- "type": "integer"
3644
- },
3645
- "runAt": {
3646
- "type": "string"
3647
3292
  }
3648
- },
3649
- "required": [
3650
- "name",
3651
- "taskTemplate"
3652
- ]
3293
+ }
3653
3294
  }
3654
3295
  }
3655
3296
  }
3656
3297
  },
3657
3298
  "responses": {
3658
- "201": {
3659
- "description": "Schedule created"
3299
+ "200": {
3300
+ "description": "Schedule updated"
3660
3301
  },
3661
3302
  "400": {
3662
3303
  "description": "Validation error"
3663
3304
  },
3305
+ "404": {
3306
+ "description": "Schedule not found"
3307
+ },
3664
3308
  "409": {
3665
3309
  "description": "Duplicate name"
3666
3310
  }
3667
3311
  }
3668
- }
3669
- },
3670
- "/api/schedules/{id}/run": {
3671
- "post": {
3672
- "summary": "Run a schedule immediately",
3673
- "tags": [
3674
- "Schedules"
3675
- ],
3676
- "security": [
3677
- {
3678
- "bearerAuth": []
3679
- }
3680
- ],
3681
- "parameters": [
3682
- {
3683
- "schema": {
3684
- "type": "string"
3685
- },
3686
- "required": true,
3687
- "name": "id",
3688
- "in": "path"
3689
- }
3690
- ],
3691
- "responses": {
3692
- "200": {
3693
- "description": "Schedule run triggered"
3694
- },
3695
- "400": {
3696
- "description": "Schedule is disabled"
3697
- },
3698
- "404": {
3699
- "description": "Schedule not found"
3700
- }
3701
- }
3702
- }
3703
- },
3704
- "/api/schedules/{id}": {
3705
- "get": {
3706
- "summary": "Get a schedule by ID",
3707
- "tags": [
3708
- "Schedules"
3709
- ],
3710
- "security": [
3711
- {
3712
- "bearerAuth": []
3713
- }
3714
- ],
3715
- "parameters": [
3716
- {
3717
- "schema": {
3718
- "type": "string"
3719
- },
3720
- "required": true,
3721
- "name": "id",
3722
- "in": "path"
3723
- }
3724
- ],
3725
- "responses": {
3726
- "200": {
3727
- "description": "Schedule details"
3728
- },
3729
- "404": {
3730
- "description": "Schedule not found"
3731
- }
3732
- }
3733
- },
3734
- "put": {
3735
- "summary": "Update a schedule",
3736
- "tags": [
3737
- "Schedules"
3738
- ],
3739
- "security": [
3740
- {
3741
- "bearerAuth": []
3742
- }
3743
- ],
3744
- "parameters": [
3745
- {
3746
- "schema": {
3747
- "type": "string"
3748
- },
3749
- "required": true,
3750
- "name": "id",
3751
- "in": "path"
3752
- }
3753
- ],
3754
- "requestBody": {
3755
- "content": {
3756
- "application/json": {
3757
- "schema": {
3758
- "type": "object",
3759
- "properties": {
3760
- "name": {
3761
- "type": "string"
3762
- },
3763
- "description": {
3764
- "type": "string"
3765
- },
3766
- "cronExpression": {
3767
- "type": "string"
3768
- },
3769
- "intervalMs": {
3770
- "type": "integer"
3771
- },
3772
- "taskTemplate": {
3773
- "type": "string"
3774
- },
3775
- "taskType": {
3776
- "type": "string"
3777
- },
3778
- "tags": {
3779
- "type": "array",
3780
- "items": {
3781
- "type": "string"
3782
- }
3783
- },
3784
- "priority": {
3785
- "type": "integer"
3786
- },
3787
- "targetAgentId": {
3788
- "type": "string",
3789
- "format": "uuid"
3790
- },
3791
- "enabled": {
3792
- "type": "boolean"
3793
- },
3794
- "timezone": {
3795
- "type": "string"
3796
- },
3797
- "model": {
3798
- "type": "string"
3799
- },
3800
- "nextRunAt": {
3801
- "type": [
3802
- "string",
3803
- "null"
3804
- ]
3805
- }
3806
- }
3807
- }
3808
- }
3809
- }
3810
- },
3811
- "responses": {
3812
- "200": {
3813
- "description": "Schedule updated"
3814
- },
3815
- "400": {
3816
- "description": "Validation error"
3817
- },
3818
- "404": {
3819
- "description": "Schedule not found"
3820
- },
3821
- "409": {
3822
- "description": "Duplicate name"
3823
- }
3824
- }
3825
- },
3826
- "delete": {
3827
- "summary": "Delete a schedule",
3312
+ },
3313
+ "delete": {
3314
+ "summary": "Delete a schedule",
3828
3315
  "tags": [
3829
3316
  "Schedules"
3830
3317
  ],
@@ -5133,14 +4620,6 @@
5133
4620
  "name": "agentId",
5134
4621
  "in": "query"
5135
4622
  },
5136
- {
5137
- "schema": {
5138
- "type": "string"
5139
- },
5140
- "required": false,
5141
- "name": "epicId",
5142
- "in": "query"
5143
- },
5144
4623
  {
5145
4624
  "schema": {
5146
4625
  "type": "string"
@@ -5789,31 +5268,347 @@
5789
5268
  "503": {
5790
5269
  "description": "GitLab integration not configured"
5791
5270
  }
5792
- }
5793
- }
5794
- },
5795
- "/api/agentmail/webhook": {
5796
- "post": {
5797
- "summary": "Handle AgentMail webhook events",
5798
- "tags": [
5799
- "Webhooks"
5800
- ],
5271
+ }
5272
+ }
5273
+ },
5274
+ "/api/agentmail/webhook": {
5275
+ "post": {
5276
+ "summary": "Handle AgentMail webhook events",
5277
+ "tags": [
5278
+ "Webhooks"
5279
+ ],
5280
+ "responses": {
5281
+ "200": {
5282
+ "description": "Event received"
5283
+ },
5284
+ "401": {
5285
+ "description": "Invalid signature"
5286
+ },
5287
+ "503": {
5288
+ "description": "AgentMail integration not configured"
5289
+ }
5290
+ }
5291
+ }
5292
+ },
5293
+ "/api/workflows": {
5294
+ "get": {
5295
+ "summary": "List all workflows",
5296
+ "tags": [
5297
+ "Workflows"
5298
+ ],
5299
+ "security": [
5300
+ {
5301
+ "bearerAuth": []
5302
+ }
5303
+ ],
5304
+ "responses": {
5305
+ "200": {
5306
+ "description": "Workflow list"
5307
+ }
5308
+ }
5309
+ },
5310
+ "post": {
5311
+ "summary": "Create a new workflow",
5312
+ "tags": [
5313
+ "Workflows"
5314
+ ],
5315
+ "security": [
5316
+ {
5317
+ "bearerAuth": []
5318
+ }
5319
+ ],
5320
+ "requestBody": {
5321
+ "content": {
5322
+ "application/json": {
5323
+ "schema": {
5324
+ "type": "object",
5325
+ "properties": {
5326
+ "name": {
5327
+ "type": "string",
5328
+ "minLength": 1
5329
+ },
5330
+ "description": {
5331
+ "type": "string"
5332
+ },
5333
+ "definition": {
5334
+ "type": "object",
5335
+ "properties": {
5336
+ "nodes": {
5337
+ "type": "array",
5338
+ "items": {
5339
+ "type": "object",
5340
+ "properties": {
5341
+ "id": {
5342
+ "type": "string",
5343
+ "description": "Unique node identifier, used in 'next' and 'inputs' mappings"
5344
+ },
5345
+ "type": {
5346
+ "type": "string",
5347
+ "description": "Executor type: 'agent-task', 'script', 'raw-llm', 'validate', 'property-match'"
5348
+ },
5349
+ "label": {
5350
+ "type": "string",
5351
+ "description": "Human-readable label for UI display"
5352
+ },
5353
+ "config": {
5354
+ "type": "object",
5355
+ "additionalProperties": {},
5356
+ "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, tags?, priority?, dir?, vcsRepo?, model? }. Values support {{interpolation}} from the node's inputs context. NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
5357
+ },
5358
+ "next": {
5359
+ "anyOf": [
5360
+ {
5361
+ "type": "string"
5362
+ },
5363
+ {
5364
+ "type": "array",
5365
+ "items": {
5366
+ "type": "string"
5367
+ }
5368
+ },
5369
+ {
5370
+ "type": "object",
5371
+ "additionalProperties": {
5372
+ "type": "string"
5373
+ }
5374
+ }
5375
+ ],
5376
+ "description": "Next node(s): string for simple chaining, string[] for fan-out to parallel nodes, or record for port-based routing ({pass: 'a', fail: 'b'})"
5377
+ },
5378
+ "validation": {
5379
+ "type": "object",
5380
+ "properties": {
5381
+ "executor": {
5382
+ "type": "string",
5383
+ "default": "validate"
5384
+ },
5385
+ "config": {
5386
+ "type": "object",
5387
+ "additionalProperties": {}
5388
+ },
5389
+ "mustPass": {
5390
+ "type": "boolean",
5391
+ "default": false
5392
+ },
5393
+ "retry": {
5394
+ "type": "object",
5395
+ "properties": {
5396
+ "maxRetries": {
5397
+ "type": "integer",
5398
+ "minimum": 0,
5399
+ "default": 3
5400
+ },
5401
+ "strategy": {
5402
+ "type": "string",
5403
+ "enum": [
5404
+ "exponential",
5405
+ "static",
5406
+ "linear"
5407
+ ],
5408
+ "default": "exponential"
5409
+ },
5410
+ "baseDelayMs": {
5411
+ "type": "integer",
5412
+ "minimum": 0,
5413
+ "default": 1000
5414
+ },
5415
+ "maxDelayMs": {
5416
+ "type": "integer",
5417
+ "minimum": 0,
5418
+ "default": 60000
5419
+ }
5420
+ }
5421
+ }
5422
+ },
5423
+ "required": [
5424
+ "config"
5425
+ ]
5426
+ },
5427
+ "retry": {
5428
+ "type": "object",
5429
+ "properties": {
5430
+ "maxRetries": {
5431
+ "type": "integer",
5432
+ "minimum": 0,
5433
+ "default": 3
5434
+ },
5435
+ "strategy": {
5436
+ "type": "string",
5437
+ "enum": [
5438
+ "exponential",
5439
+ "static",
5440
+ "linear"
5441
+ ],
5442
+ "default": "exponential"
5443
+ },
5444
+ "baseDelayMs": {
5445
+ "type": "integer",
5446
+ "minimum": 0,
5447
+ "default": 1000
5448
+ },
5449
+ "maxDelayMs": {
5450
+ "type": "integer",
5451
+ "minimum": 0,
5452
+ "default": 60000
5453
+ }
5454
+ }
5455
+ },
5456
+ "inputs": {
5457
+ "type": "object",
5458
+ "additionalProperties": {
5459
+ "type": "string"
5460
+ },
5461
+ "description": "REQUIRED for cross-node data access. Maps local names to context paths. Without this, upstream step outputs are NOT available for interpolation — only 'trigger' and 'input' are. Example: { \"cityData\": \"generate-city\" } → use {{cityData.taskOutput.field}} in config templates. For trigger data: { \"pr\": \"trigger.pullRequest\" }."
5462
+ },
5463
+ "inputSchema": {
5464
+ "type": "object",
5465
+ "additionalProperties": {},
5466
+ "description": "JSON Schema to validate resolved inputs before execution"
5467
+ },
5468
+ "outputSchema": {
5469
+ "type": "object",
5470
+ "additionalProperties": {},
5471
+ "description": "JSON Schema to validate the executor's output (e.g. {taskId, taskOutput} for agent-task). Different from config.outputSchema which validates the agent's raw output."
5472
+ }
5473
+ },
5474
+ "required": [
5475
+ "id",
5476
+ "type",
5477
+ "config"
5478
+ ]
5479
+ },
5480
+ "minItems": 1
5481
+ },
5482
+ "onNodeFailure": {
5483
+ "type": "string",
5484
+ "enum": [
5485
+ "fail",
5486
+ "continue"
5487
+ ],
5488
+ "default": "fail",
5489
+ "description": "Behavior when a node's task fails or is cancelled. 'fail' (default): mark the entire run as failed. 'continue': treat the failed node as completed with error output and proceed — downstream convergence nodes receive '[FAILED: reason]' and can handle partial results."
5490
+ }
5491
+ },
5492
+ "required": [
5493
+ "nodes"
5494
+ ]
5495
+ },
5496
+ "triggers": {
5497
+ "type": "array",
5498
+ "items": {
5499
+ "oneOf": [
5500
+ {
5501
+ "type": "object",
5502
+ "properties": {
5503
+ "type": {
5504
+ "type": "string",
5505
+ "enum": [
5506
+ "webhook"
5507
+ ]
5508
+ },
5509
+ "hmacSecret": {
5510
+ "type": "string"
5511
+ },
5512
+ "hmacHeader": {
5513
+ "type": "string",
5514
+ "default": "X-Hub-Signature-256"
5515
+ }
5516
+ },
5517
+ "required": [
5518
+ "type"
5519
+ ]
5520
+ },
5521
+ {
5522
+ "type": "object",
5523
+ "properties": {
5524
+ "type": {
5525
+ "type": "string",
5526
+ "enum": [
5527
+ "schedule"
5528
+ ]
5529
+ },
5530
+ "scheduleId": {
5531
+ "type": "string",
5532
+ "format": "uuid"
5533
+ }
5534
+ },
5535
+ "required": [
5536
+ "type",
5537
+ "scheduleId"
5538
+ ]
5539
+ }
5540
+ ]
5541
+ }
5542
+ },
5543
+ "cooldown": {
5544
+ "type": "object",
5545
+ "properties": {
5546
+ "hours": {
5547
+ "type": "number",
5548
+ "minimum": 0
5549
+ },
5550
+ "minutes": {
5551
+ "type": "number",
5552
+ "minimum": 0
5553
+ },
5554
+ "seconds": {
5555
+ "type": "number",
5556
+ "minimum": 0
5557
+ }
5558
+ }
5559
+ },
5560
+ "input": {
5561
+ "type": "object",
5562
+ "additionalProperties": {
5563
+ "anyOf": [
5564
+ {
5565
+ "type": "string",
5566
+ "pattern": "^\\$\\{.+\\}$"
5567
+ },
5568
+ {
5569
+ "type": "string",
5570
+ "pattern": "^secret\\..+$"
5571
+ },
5572
+ {
5573
+ "type": "string"
5574
+ }
5575
+ ]
5576
+ }
5577
+ },
5578
+ "triggerSchema": {
5579
+ "type": "object",
5580
+ "additionalProperties": {}
5581
+ },
5582
+ "dir": {
5583
+ "type": "string",
5584
+ "minLength": 1
5585
+ },
5586
+ "vcsRepo": {
5587
+ "type": "string",
5588
+ "minLength": 1
5589
+ }
5590
+ },
5591
+ "required": [
5592
+ "name",
5593
+ "definition"
5594
+ ]
5595
+ }
5596
+ }
5597
+ }
5598
+ },
5801
5599
  "responses": {
5802
- "200": {
5803
- "description": "Event received"
5804
- },
5805
- "401": {
5806
- "description": "Invalid signature"
5600
+ "201": {
5601
+ "description": "Workflow created"
5807
5602
  },
5808
- "503": {
5809
- "description": "AgentMail integration not configured"
5603
+ "400": {
5604
+ "description": "Invalid definition"
5810
5605
  }
5811
5606
  }
5812
5607
  }
5813
5608
  },
5814
- "/api/workflows": {
5609
+ "/api/workflows/{id}": {
5815
5610
  "get": {
5816
- "summary": "List all workflows",
5611
+ "summary": "Get a workflow by ID",
5817
5612
  "tags": [
5818
5613
  "Workflows"
5819
5614
  ],
@@ -5822,14 +5617,27 @@
5822
5617
  "bearerAuth": []
5823
5618
  }
5824
5619
  ],
5620
+ "parameters": [
5621
+ {
5622
+ "schema": {
5623
+ "type": "string"
5624
+ },
5625
+ "required": true,
5626
+ "name": "id",
5627
+ "in": "path"
5628
+ }
5629
+ ],
5825
5630
  "responses": {
5826
5631
  "200": {
5827
- "description": "Workflow list"
5632
+ "description": "Workflow details with auto-generated edges"
5633
+ },
5634
+ "404": {
5635
+ "description": "Workflow not found"
5828
5636
  }
5829
5637
  }
5830
5638
  },
5831
- "post": {
5832
- "summary": "Create a new workflow",
5639
+ "put": {
5640
+ "summary": "Update a workflow",
5833
5641
  "tags": [
5834
5642
  "Workflows"
5835
5643
  ],
@@ -5838,6 +5646,16 @@
5838
5646
  "bearerAuth": []
5839
5647
  }
5840
5648
  ],
5649
+ "parameters": [
5650
+ {
5651
+ "schema": {
5652
+ "type": "string"
5653
+ },
5654
+ "required": true,
5655
+ "name": "id",
5656
+ "in": "path"
5657
+ }
5658
+ ],
5841
5659
  "requestBody": {
5842
5660
  "content": {
5843
5661
  "application/json": {
@@ -5845,8 +5663,7 @@
5845
5663
  "type": "object",
5846
5664
  "properties": {
5847
5665
  "name": {
5848
- "type": "string",
5849
- "minLength": 1
5666
+ "type": "string"
5850
5667
  },
5851
5668
  "description": {
5852
5669
  "type": "string"
@@ -6062,7 +5879,10 @@
6062
5879
  }
6063
5880
  },
6064
5881
  "cooldown": {
6065
- "type": "object",
5882
+ "type": [
5883
+ "object",
5884
+ "null"
5885
+ ],
6066
5886
  "properties": {
6067
5887
  "hours": {
6068
5888
  "type": "number",
@@ -6079,7 +5899,10 @@
6079
5899
  }
6080
5900
  },
6081
5901
  "input": {
6082
- "type": "object",
5902
+ "type": [
5903
+ "object",
5904
+ "null"
5905
+ ],
6083
5906
  "additionalProperties": {
6084
5907
  "anyOf": [
6085
5908
  {
@@ -6097,68 +5920,48 @@
6097
5920
  }
6098
5921
  },
6099
5922
  "triggerSchema": {
6100
- "type": "object",
5923
+ "type": [
5924
+ "object",
5925
+ "null"
5926
+ ],
6101
5927
  "additionalProperties": {}
6102
5928
  },
6103
5929
  "dir": {
6104
- "type": "string",
5930
+ "type": [
5931
+ "string",
5932
+ "null"
5933
+ ],
6105
5934
  "minLength": 1
6106
5935
  },
6107
5936
  "vcsRepo": {
6108
- "type": "string",
5937
+ "type": [
5938
+ "string",
5939
+ "null"
5940
+ ],
6109
5941
  "minLength": 1
5942
+ },
5943
+ "enabled": {
5944
+ "type": "boolean"
6110
5945
  }
6111
- },
6112
- "required": [
6113
- "name",
6114
- "definition"
6115
- ]
5946
+ }
6116
5947
  }
6117
5948
  }
6118
5949
  }
6119
5950
  },
6120
5951
  "responses": {
6121
- "201": {
6122
- "description": "Workflow created"
5952
+ "200": {
5953
+ "description": "Workflow updated (version snapshot created)"
6123
5954
  },
6124
5955
  "400": {
6125
5956
  "description": "Invalid definition"
6126
- }
6127
- }
6128
- }
6129
- },
6130
- "/api/workflows/{id}": {
6131
- "get": {
6132
- "summary": "Get a workflow by ID",
6133
- "tags": [
6134
- "Workflows"
6135
- ],
6136
- "security": [
6137
- {
6138
- "bearerAuth": []
6139
- }
6140
- ],
6141
- "parameters": [
6142
- {
6143
- "schema": {
6144
- "type": "string"
6145
- },
6146
- "required": true,
6147
- "name": "id",
6148
- "in": "path"
6149
- }
6150
- ],
6151
- "responses": {
6152
- "200": {
6153
- "description": "Workflow details with auto-generated edges"
6154
5957
  },
6155
5958
  "404": {
6156
5959
  "description": "Workflow not found"
6157
5960
  }
6158
5961
  }
6159
5962
  },
6160
- "put": {
6161
- "summary": "Update a workflow",
5963
+ "patch": {
5964
+ "summary": "Patch a workflow definition (create/update/delete nodes)",
6162
5965
  "tags": [
6163
5966
  "Workflows"
6164
5967
  ],
@@ -6183,24 +5986,18 @@
6183
5986
  "schema": {
6184
5987
  "type": "object",
6185
5988
  "properties": {
6186
- "name": {
6187
- "type": "string"
6188
- },
6189
- "description": {
6190
- "type": "string"
6191
- },
6192
- "definition": {
6193
- "type": "object",
6194
- "properties": {
6195
- "nodes": {
6196
- "type": "array",
6197
- "items": {
5989
+ "update": {
5990
+ "type": "array",
5991
+ "items": {
5992
+ "type": "object",
5993
+ "properties": {
5994
+ "nodeId": {
5995
+ "type": "string",
5996
+ "description": "ID of the node to update"
5997
+ },
5998
+ "node": {
6198
5999
  "type": "object",
6199
6000
  "properties": {
6200
- "id": {
6201
- "type": "string",
6202
- "description": "Unique node identifier, used in 'next' and 'inputs' mappings"
6203
- },
6204
6001
  "type": {
6205
6002
  "type": "string",
6206
6003
  "description": "Executor type: 'agent-task', 'script', 'raw-llm', 'validate', 'property-match'"
@@ -6330,139 +6127,176 @@
6330
6127
  "description": "JSON Schema to validate the executor's output (e.g. {taskId, taskOutput} for agent-task). Different from config.outputSchema which validates the agent's raw output."
6331
6128
  }
6332
6129
  },
6333
- "required": [
6334
- "id",
6335
- "type",
6336
- "config"
6337
- ]
6338
- },
6339
- "minItems": 1
6130
+ "description": "Partial node data to merge"
6131
+ }
6340
6132
  },
6341
- "onNodeFailure": {
6342
- "type": "string",
6343
- "enum": [
6344
- "fail",
6345
- "continue"
6346
- ],
6347
- "default": "fail",
6348
- "description": "Behavior when a node's task fails or is cancelled. 'fail' (default): mark the entire run as failed. 'continue': treat the failed node as completed with error output and proceed — downstream convergence nodes receive '[FAILED: reason]' and can handle partial results."
6349
- }
6133
+ "required": [
6134
+ "nodeId",
6135
+ "node"
6136
+ ]
6350
6137
  },
6351
- "required": [
6352
- "nodes"
6353
- ]
6138
+ "description": "Nodes to update (partial merge)"
6354
6139
  },
6355
- "triggers": {
6140
+ "delete": {
6356
6141
  "type": "array",
6357
6142
  "items": {
6358
- "oneOf": [
6359
- {
6143
+ "type": "string"
6144
+ },
6145
+ "description": "Node IDs to delete"
6146
+ },
6147
+ "create": {
6148
+ "type": "array",
6149
+ "items": {
6150
+ "type": "object",
6151
+ "properties": {
6152
+ "id": {
6153
+ "type": "string",
6154
+ "description": "Unique node identifier, used in 'next' and 'inputs' mappings"
6155
+ },
6156
+ "type": {
6157
+ "type": "string",
6158
+ "description": "Executor type: 'agent-task', 'script', 'raw-llm', 'validate', 'property-match'"
6159
+ },
6160
+ "label": {
6161
+ "type": "string",
6162
+ "description": "Human-readable label for UI display"
6163
+ },
6164
+ "config": {
6165
+ "type": "object",
6166
+ "additionalProperties": {},
6167
+ "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, tags?, priority?, dir?, vcsRepo?, model? }. Values support {{interpolation}} from the node's inputs context. NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
6168
+ },
6169
+ "next": {
6170
+ "anyOf": [
6171
+ {
6172
+ "type": "string"
6173
+ },
6174
+ {
6175
+ "type": "array",
6176
+ "items": {
6177
+ "type": "string"
6178
+ }
6179
+ },
6180
+ {
6181
+ "type": "object",
6182
+ "additionalProperties": {
6183
+ "type": "string"
6184
+ }
6185
+ }
6186
+ ],
6187
+ "description": "Next node(s): string for simple chaining, string[] for fan-out to parallel nodes, or record for port-based routing ({pass: 'a', fail: 'b'})"
6188
+ },
6189
+ "validation": {
6360
6190
  "type": "object",
6361
6191
  "properties": {
6362
- "type": {
6192
+ "executor": {
6363
6193
  "type": "string",
6364
- "enum": [
6365
- "webhook"
6366
- ]
6194
+ "default": "validate"
6367
6195
  },
6368
- "hmacSecret": {
6369
- "type": "string"
6196
+ "config": {
6197
+ "type": "object",
6198
+ "additionalProperties": {}
6370
6199
  },
6371
- "hmacHeader": {
6372
- "type": "string",
6373
- "default": "X-Hub-Signature-256"
6200
+ "mustPass": {
6201
+ "type": "boolean",
6202
+ "default": false
6203
+ },
6204
+ "retry": {
6205
+ "type": "object",
6206
+ "properties": {
6207
+ "maxRetries": {
6208
+ "type": "integer",
6209
+ "minimum": 0,
6210
+ "default": 3
6211
+ },
6212
+ "strategy": {
6213
+ "type": "string",
6214
+ "enum": [
6215
+ "exponential",
6216
+ "static",
6217
+ "linear"
6218
+ ],
6219
+ "default": "exponential"
6220
+ },
6221
+ "baseDelayMs": {
6222
+ "type": "integer",
6223
+ "minimum": 0,
6224
+ "default": 1000
6225
+ },
6226
+ "maxDelayMs": {
6227
+ "type": "integer",
6228
+ "minimum": 0,
6229
+ "default": 60000
6230
+ }
6231
+ }
6374
6232
  }
6375
6233
  },
6376
6234
  "required": [
6377
- "type"
6235
+ "config"
6378
6236
  ]
6379
6237
  },
6380
- {
6238
+ "retry": {
6381
6239
  "type": "object",
6382
6240
  "properties": {
6383
- "type": {
6241
+ "maxRetries": {
6242
+ "type": "integer",
6243
+ "minimum": 0,
6244
+ "default": 3
6245
+ },
6246
+ "strategy": {
6384
6247
  "type": "string",
6385
6248
  "enum": [
6386
- "schedule"
6387
- ]
6249
+ "exponential",
6250
+ "static",
6251
+ "linear"
6252
+ ],
6253
+ "default": "exponential"
6388
6254
  },
6389
- "scheduleId": {
6390
- "type": "string",
6391
- "format": "uuid"
6255
+ "baseDelayMs": {
6256
+ "type": "integer",
6257
+ "minimum": 0,
6258
+ "default": 1000
6259
+ },
6260
+ "maxDelayMs": {
6261
+ "type": "integer",
6262
+ "minimum": 0,
6263
+ "default": 60000
6392
6264
  }
6265
+ }
6266
+ },
6267
+ "inputs": {
6268
+ "type": "object",
6269
+ "additionalProperties": {
6270
+ "type": "string"
6393
6271
  },
6394
- "required": [
6395
- "type",
6396
- "scheduleId"
6397
- ]
6398
- }
6399
- ]
6400
- }
6401
- },
6402
- "cooldown": {
6403
- "type": [
6404
- "object",
6405
- "null"
6406
- ],
6407
- "properties": {
6408
- "hours": {
6409
- "type": "number",
6410
- "minimum": 0
6411
- },
6412
- "minutes": {
6413
- "type": "number",
6414
- "minimum": 0
6415
- },
6416
- "seconds": {
6417
- "type": "number",
6418
- "minimum": 0
6419
- }
6420
- }
6421
- },
6422
- "input": {
6423
- "type": [
6424
- "object",
6425
- "null"
6426
- ],
6427
- "additionalProperties": {
6428
- "anyOf": [
6429
- {
6430
- "type": "string",
6431
- "pattern": "^\\$\\{.+\\}$"
6272
+ "description": "REQUIRED for cross-node data access. Maps local names to context paths. Without this, upstream step outputs are NOT available for interpolation — only 'trigger' and 'input' are. Example: { \"cityData\": \"generate-city\" } → use {{cityData.taskOutput.field}} in config templates. For trigger data: { \"pr\": \"trigger.pullRequest\" }."
6432
6273
  },
6433
- {
6434
- "type": "string",
6435
- "pattern": "^secret\\..+$"
6274
+ "inputSchema": {
6275
+ "type": "object",
6276
+ "additionalProperties": {},
6277
+ "description": "JSON Schema to validate resolved inputs before execution"
6436
6278
  },
6437
- {
6438
- "type": "string"
6279
+ "outputSchema": {
6280
+ "type": "object",
6281
+ "additionalProperties": {},
6282
+ "description": "JSON Schema to validate the executor's output (e.g. {taskId, taskOutput} for agent-task). Different from config.outputSchema which validates the agent's raw output."
6439
6283
  }
6284
+ },
6285
+ "required": [
6286
+ "id",
6287
+ "type",
6288
+ "config"
6440
6289
  ]
6441
- }
6442
- },
6443
- "triggerSchema": {
6444
- "type": [
6445
- "object",
6446
- "null"
6447
- ],
6448
- "additionalProperties": {}
6449
- },
6450
- "dir": {
6451
- "type": [
6452
- "string",
6453
- "null"
6454
- ],
6455
- "minLength": 1
6290
+ },
6291
+ "description": "New nodes to add"
6456
6292
  },
6457
- "vcsRepo": {
6458
- "type": [
6459
- "string",
6460
- "null"
6293
+ "onNodeFailure": {
6294
+ "type": "string",
6295
+ "enum": [
6296
+ "fail",
6297
+ "continue"
6461
6298
  ],
6462
- "minLength": 1
6463
- },
6464
- "enabled": {
6465
- "type": "boolean"
6299
+ "description": "Update the definition-level onNodeFailure behavior"
6466
6300
  }
6467
6301
  }
6468
6302
  }
@@ -6471,10 +6305,10 @@
6471
6305
  },
6472
6306
  "responses": {
6473
6307
  "200": {
6474
- "description": "Workflow updated (version snapshot created)"
6308
+ "description": "Workflow patched (version snapshot created)"
6475
6309
  },
6476
6310
  "400": {
6477
- "description": "Invalid definition"
6311
+ "description": "Invalid patch or resulting definition"
6478
6312
  },
6479
6313
  "404": {
6480
6314
  "description": "Workflow not found"
@@ -6511,6 +6345,187 @@
6511
6345
  }
6512
6346
  }
6513
6347
  },
6348
+ "/api/workflows/{id}/nodes/{nodeId}": {
6349
+ "patch": {
6350
+ "summary": "Patch a single node in a workflow definition",
6351
+ "tags": [
6352
+ "Workflows"
6353
+ ],
6354
+ "security": [
6355
+ {
6356
+ "bearerAuth": []
6357
+ }
6358
+ ],
6359
+ "parameters": [
6360
+ {
6361
+ "schema": {
6362
+ "type": "string"
6363
+ },
6364
+ "required": true,
6365
+ "name": "id",
6366
+ "in": "path"
6367
+ },
6368
+ {
6369
+ "schema": {
6370
+ "type": "string"
6371
+ },
6372
+ "required": true,
6373
+ "name": "nodeId",
6374
+ "in": "path"
6375
+ }
6376
+ ],
6377
+ "requestBody": {
6378
+ "content": {
6379
+ "application/json": {
6380
+ "schema": {
6381
+ "type": "object",
6382
+ "properties": {
6383
+ "type": {
6384
+ "type": "string",
6385
+ "description": "Executor type: 'agent-task', 'script', 'raw-llm', 'validate', 'property-match'"
6386
+ },
6387
+ "label": {
6388
+ "type": "string",
6389
+ "description": "Human-readable label for UI display"
6390
+ },
6391
+ "config": {
6392
+ "type": "object",
6393
+ "additionalProperties": {},
6394
+ "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, tags?, priority?, dir?, vcsRepo?, model? }. Values support {{interpolation}} from the node's inputs context. NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
6395
+ },
6396
+ "next": {
6397
+ "anyOf": [
6398
+ {
6399
+ "type": "string"
6400
+ },
6401
+ {
6402
+ "type": "array",
6403
+ "items": {
6404
+ "type": "string"
6405
+ }
6406
+ },
6407
+ {
6408
+ "type": "object",
6409
+ "additionalProperties": {
6410
+ "type": "string"
6411
+ }
6412
+ }
6413
+ ],
6414
+ "description": "Next node(s): string for simple chaining, string[] for fan-out to parallel nodes, or record for port-based routing ({pass: 'a', fail: 'b'})"
6415
+ },
6416
+ "validation": {
6417
+ "type": "object",
6418
+ "properties": {
6419
+ "executor": {
6420
+ "type": "string",
6421
+ "default": "validate"
6422
+ },
6423
+ "config": {
6424
+ "type": "object",
6425
+ "additionalProperties": {}
6426
+ },
6427
+ "mustPass": {
6428
+ "type": "boolean",
6429
+ "default": false
6430
+ },
6431
+ "retry": {
6432
+ "type": "object",
6433
+ "properties": {
6434
+ "maxRetries": {
6435
+ "type": "integer",
6436
+ "minimum": 0,
6437
+ "default": 3
6438
+ },
6439
+ "strategy": {
6440
+ "type": "string",
6441
+ "enum": [
6442
+ "exponential",
6443
+ "static",
6444
+ "linear"
6445
+ ],
6446
+ "default": "exponential"
6447
+ },
6448
+ "baseDelayMs": {
6449
+ "type": "integer",
6450
+ "minimum": 0,
6451
+ "default": 1000
6452
+ },
6453
+ "maxDelayMs": {
6454
+ "type": "integer",
6455
+ "minimum": 0,
6456
+ "default": 60000
6457
+ }
6458
+ }
6459
+ }
6460
+ },
6461
+ "required": [
6462
+ "config"
6463
+ ]
6464
+ },
6465
+ "retry": {
6466
+ "type": "object",
6467
+ "properties": {
6468
+ "maxRetries": {
6469
+ "type": "integer",
6470
+ "minimum": 0,
6471
+ "default": 3
6472
+ },
6473
+ "strategy": {
6474
+ "type": "string",
6475
+ "enum": [
6476
+ "exponential",
6477
+ "static",
6478
+ "linear"
6479
+ ],
6480
+ "default": "exponential"
6481
+ },
6482
+ "baseDelayMs": {
6483
+ "type": "integer",
6484
+ "minimum": 0,
6485
+ "default": 1000
6486
+ },
6487
+ "maxDelayMs": {
6488
+ "type": "integer",
6489
+ "minimum": 0,
6490
+ "default": 60000
6491
+ }
6492
+ }
6493
+ },
6494
+ "inputs": {
6495
+ "type": "object",
6496
+ "additionalProperties": {
6497
+ "type": "string"
6498
+ },
6499
+ "description": "REQUIRED for cross-node data access. Maps local names to context paths. Without this, upstream step outputs are NOT available for interpolation — only 'trigger' and 'input' are. Example: { \"cityData\": \"generate-city\" } → use {{cityData.taskOutput.field}} in config templates. For trigger data: { \"pr\": \"trigger.pullRequest\" }."
6500
+ },
6501
+ "inputSchema": {
6502
+ "type": "object",
6503
+ "additionalProperties": {},
6504
+ "description": "JSON Schema to validate resolved inputs before execution"
6505
+ },
6506
+ "outputSchema": {
6507
+ "type": "object",
6508
+ "additionalProperties": {},
6509
+ "description": "JSON Schema to validate the executor's output (e.g. {taskId, taskOutput} for agent-task). Different from config.outputSchema which validates the agent's raw output."
6510
+ }
6511
+ }
6512
+ }
6513
+ }
6514
+ }
6515
+ },
6516
+ "responses": {
6517
+ "200": {
6518
+ "description": "Node patched (version snapshot created)"
6519
+ },
6520
+ "400": {
6521
+ "description": "Invalid patch or resulting definition"
6522
+ },
6523
+ "404": {
6524
+ "description": "Workflow or node not found"
6525
+ }
6526
+ }
6527
+ }
6528
+ },
6514
6529
  "/api/workflows/{id}/trigger": {
6515
6530
  "post": {
6516
6531
  "summary": "Trigger a workflow execution",
@@ -6576,7 +6591,8 @@
6576
6591
  "waiting",
6577
6592
  "completed",
6578
6593
  "failed",
6579
- "skipped"
6594
+ "skipped",
6595
+ "cancelled"
6580
6596
  ]
6581
6597
  },
6582
6598
  "required": false,
@@ -6653,6 +6669,51 @@
6653
6669
  }
6654
6670
  }
6655
6671
  },
6672
+ "/api/workflow-runs/{id}/cancel": {
6673
+ "post": {
6674
+ "summary": "Cancel a running or waiting workflow run",
6675
+ "tags": [
6676
+ "Workflows"
6677
+ ],
6678
+ "security": [
6679
+ {
6680
+ "bearerAuth": []
6681
+ }
6682
+ ],
6683
+ "parameters": [
6684
+ {
6685
+ "schema": {
6686
+ "type": "string"
6687
+ },
6688
+ "required": true,
6689
+ "name": "id",
6690
+ "in": "path"
6691
+ }
6692
+ ],
6693
+ "requestBody": {
6694
+ "content": {
6695
+ "application/json": {
6696
+ "schema": {
6697
+ "type": "object",
6698
+ "properties": {
6699
+ "reason": {
6700
+ "type": "string"
6701
+ }
6702
+ }
6703
+ }
6704
+ }
6705
+ }
6706
+ },
6707
+ "responses": {
6708
+ "200": {
6709
+ "description": "Run cancelled"
6710
+ },
6711
+ "400": {
6712
+ "description": "Cannot cancel"
6713
+ }
6714
+ }
6715
+ }
6716
+ },
6656
6717
  "/api/executor-types": {
6657
6718
  "get": {
6658
6719
  "summary": "List all executor types with their config and output schemas",