@desplega.ai/agent-swarm 1.20.0 → 1.49.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 (810) hide show
  1. package/.claude/settings.json +84 -0
  2. package/.claude/settings.local.json +3 -1
  3. package/.entire/settings.json +4 -0
  4. package/.env.docker.example +40 -23
  5. package/.env.example +39 -1
  6. package/.github/ISSUE_TEMPLATE/bug_report.yml +78 -0
  7. package/.github/ISSUE_TEMPLATE/community-template.yml +77 -0
  8. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  9. package/.github/ISSUE_TEMPLATE/feature_request.yml +60 -0
  10. package/.github/PULL_REQUEST_TEMPLATE/community-template.md +29 -0
  11. package/.github/workflows/ci.yml +3 -27
  12. package/.github/workflows/docker-and-deploy.yml +20 -5
  13. package/.github/workflows/merge-gate.yml +233 -0
  14. package/.opencode/plugins/entire.ts +133 -0
  15. package/.superset/config.json +6 -0
  16. package/.wts-setup.ts +103 -34
  17. package/CHANGELOG.md +447 -0
  18. package/CLAUDE.md +422 -5
  19. package/CONTRIBUTING.md +46 -1
  20. package/DEPLOYMENT.md +26 -9
  21. package/Dockerfile +15 -7
  22. package/Dockerfile.worker +99 -67
  23. package/MCP.md +452 -17
  24. package/README.md +271 -169
  25. package/api-entrypoint.sh +56 -0
  26. package/depot.json +1 -0
  27. package/docker-compose.example.yml +194 -3
  28. package/docker-compose.local.yml +119 -0
  29. package/docker-entrypoint.sh +393 -113
  30. package/docs-site/app/api/search/route.ts +4 -0
  31. package/docs-site/app/docs/[[...slug]]/page.tsx +87 -0
  32. package/docs-site/app/docs/layout.tsx +12 -0
  33. package/docs-site/app/globals.css +24 -0
  34. package/docs-site/app/layout.config.tsx +34 -0
  35. package/docs-site/app/layout.tsx +119 -0
  36. package/docs-site/app/llms-full.txt/route.ts +11 -0
  37. package/docs-site/app/llms.mdx/docs/[[...slug]]/route.ts +24 -0
  38. package/docs-site/app/llms.txt/route.ts +8 -0
  39. package/docs-site/app/page.tsx +5 -0
  40. package/docs-site/app/robots.ts +13 -0
  41. package/docs-site/app/sitemap.ts +37 -0
  42. package/docs-site/components/api-page.client.tsx +4 -0
  43. package/docs-site/components/api-page.tsx +7 -0
  44. package/docs-site/components/mdx/mermaid.tsx +55 -0
  45. package/docs-site/content/docs/(documentation)/architecture/agents.mdx +117 -0
  46. package/docs-site/content/docs/(documentation)/architecture/hooks.mdx +77 -0
  47. package/docs-site/content/docs/(documentation)/architecture/memory.mdx +96 -0
  48. package/docs-site/content/docs/(documentation)/architecture/meta.json +4 -0
  49. package/docs-site/content/docs/(documentation)/architecture/overview.mdx +172 -0
  50. package/docs-site/content/docs/(documentation)/concepts/epics.mdx +98 -0
  51. package/docs-site/content/docs/(documentation)/concepts/meta.json +4 -0
  52. package/docs-site/content/docs/(documentation)/concepts/scheduling.mdx +136 -0
  53. package/docs-site/content/docs/(documentation)/concepts/services.mdx +104 -0
  54. package/docs-site/content/docs/(documentation)/concepts/task-lifecycle.mdx +148 -0
  55. package/docs-site/content/docs/(documentation)/concepts/workflows.mdx +209 -0
  56. package/docs-site/content/docs/(documentation)/contributing.mdx +158 -0
  57. package/docs-site/content/docs/(documentation)/getting-started.mdx +157 -0
  58. package/docs-site/content/docs/(documentation)/guides/agentmail-integration.mdx +79 -0
  59. package/docs-site/content/docs/(documentation)/guides/deployment.mdx +171 -0
  60. package/docs-site/content/docs/(documentation)/guides/github-integration.mdx +81 -0
  61. package/docs-site/content/docs/(documentation)/guides/gitlab-integration.mdx +93 -0
  62. package/docs-site/content/docs/(documentation)/guides/linear-integration.mdx +98 -0
  63. package/docs-site/content/docs/(documentation)/guides/meta.json +13 -0
  64. package/docs-site/content/docs/(documentation)/guides/sentry-integration.mdx +52 -0
  65. package/docs-site/content/docs/(documentation)/guides/slack-integration.mdx +179 -0
  66. package/docs-site/content/docs/(documentation)/guides/x402-payments.mdx +154 -0
  67. package/docs-site/content/docs/(documentation)/index.mdx +65 -0
  68. package/docs-site/content/docs/(documentation)/meta.json +19 -0
  69. package/docs-site/content/docs/(documentation)/reference/cli.mdx +241 -0
  70. package/docs-site/content/docs/(documentation)/reference/environment-variables.mdx +205 -0
  71. package/docs-site/content/docs/(documentation)/reference/mcp-tools.mdx +449 -0
  72. package/docs-site/content/docs/(documentation)/reference/meta.json +4 -0
  73. package/docs-site/content/docs/api-reference/active-sessions.mdx +9 -0
  74. package/docs-site/content/docs/api-reference/agents.mdx +9 -0
  75. package/docs-site/content/docs/api-reference/channels.mdx +9 -0
  76. package/docs-site/content/docs/api-reference/config.mdx +9 -0
  77. package/docs-site/content/docs/api-reference/debug.mdx +9 -0
  78. package/docs-site/content/docs/api-reference/ecosystem.mdx +9 -0
  79. package/docs-site/content/docs/api-reference/epics.mdx +9 -0
  80. package/docs-site/content/docs/api-reference/index.mdx +32 -0
  81. package/docs-site/content/docs/api-reference/memory.mdx +9 -0
  82. package/docs-site/content/docs/api-reference/meta.json +25 -0
  83. package/docs-site/content/docs/api-reference/poll.mdx +9 -0
  84. package/docs-site/content/docs/api-reference/repos.mdx +9 -0
  85. package/docs-site/content/docs/api-reference/schedules.mdx +9 -0
  86. package/docs-site/content/docs/api-reference/session-data.mdx +9 -0
  87. package/docs-site/content/docs/api-reference/stats.mdx +9 -0
  88. package/docs-site/content/docs/api-reference/tasks.mdx +9 -0
  89. package/docs-site/content/docs/api-reference/trackers.mdx +9 -0
  90. package/docs-site/content/docs/api-reference/webhooks.mdx +9 -0
  91. package/docs-site/content/docs/api-reference/workflows.mdx +9 -0
  92. package/docs-site/content/docs/meta.json +3 -0
  93. package/docs-site/lib/get-llm-text.ts +10 -0
  94. package/docs-site/lib/openapi.ts +23 -0
  95. package/docs-site/lib/source.ts +8 -0
  96. package/docs-site/mdx-components.tsx +13 -0
  97. package/docs-site/next.config.mjs +29 -0
  98. package/docs-site/package.json +35 -0
  99. package/docs-site/pnpm-lock.yaml +5407 -0
  100. package/docs-site/postcss.config.mjs +8 -0
  101. package/docs-site/scripts/generate-docs.ts +171 -0
  102. package/docs-site/source.config.ts +17 -0
  103. package/docs-site/tsconfig.json +46 -0
  104. package/ecosystem.config.cjs +4 -4
  105. package/landing/next.config.ts +14 -0
  106. package/landing/package.json +31 -0
  107. package/landing/pnpm-lock.yaml +1091 -0
  108. package/landing/postcss.config.mjs +8 -0
  109. package/landing/public/apple-touch-icon.png +0 -0
  110. package/landing/public/favicon.ico +0 -0
  111. package/landing/public/logo.png +0 -0
  112. package/landing/public/og-image.png +0 -0
  113. package/landing/public/omghost-desplega.svg +30 -0
  114. package/landing/public/omghost-openfort.svg +9 -0
  115. package/landing/src/app/actions/waitlist.ts +25 -0
  116. package/landing/src/app/blog/openfort-hackathon/page.tsx +863 -0
  117. package/landing/src/app/blog/page.tsx +162 -0
  118. package/landing/src/app/blog/swarm-metrics/page.tsx +685 -0
  119. package/landing/src/app/examples/page.tsx +174 -0
  120. package/landing/src/app/examples/x402/page.tsx +456 -0
  121. package/landing/src/app/globals.css +122 -0
  122. package/landing/src/app/layout.tsx +134 -0
  123. package/landing/src/app/page.tsx +27 -0
  124. package/landing/src/app/robots.ts +13 -0
  125. package/landing/src/app/sitemap.ts +44 -0
  126. package/landing/src/components/architecture.tsx +163 -0
  127. package/landing/src/components/cta.tsx +52 -0
  128. package/landing/src/components/features.tsx +160 -0
  129. package/landing/src/components/footer.tsx +100 -0
  130. package/landing/src/components/hero.tsx +217 -0
  131. package/landing/src/components/how-it-works.tsx +165 -0
  132. package/landing/src/components/navbar.tsx +147 -0
  133. package/landing/src/components/waitlist.tsx +110 -0
  134. package/landing/src/components/why-choose.tsx +149 -0
  135. package/landing/src/components/workshops.tsx +328 -0
  136. package/landing/src/lib/utils.ts +6 -0
  137. package/landing/tsconfig.json +41 -0
  138. package/misc/transcripts/2026-03-09-pi-mono-e2e-verification.md +154 -0
  139. package/new-ui/CLAUDE.md +92 -0
  140. package/new-ui/README.md +73 -0
  141. package/new-ui/biome.json +42 -0
  142. package/new-ui/components.json +21 -0
  143. package/new-ui/index.html +25 -0
  144. package/new-ui/package.json +49 -0
  145. package/new-ui/pnpm-lock.yaml +4845 -0
  146. package/new-ui/public/logo.png +0 -0
  147. package/new-ui/src/api/client.ts +814 -0
  148. package/new-ui/src/api/hooks/index.ts +64 -0
  149. package/new-ui/src/api/hooks/use-agents.ts +58 -0
  150. package/new-ui/src/api/hooks/use-channels.ts +115 -0
  151. package/new-ui/src/api/hooks/use-config-api.ts +46 -0
  152. package/new-ui/src/api/hooks/use-costs.ts +122 -0
  153. package/new-ui/src/api/hooks/use-db-query.ts +29 -0
  154. package/new-ui/src/api/hooks/use-epics.ts +75 -0
  155. package/new-ui/src/api/hooks/use-repos.ts +61 -0
  156. package/new-ui/src/api/hooks/use-schedules.ts +81 -0
  157. package/new-ui/src/api/hooks/use-services.ts +16 -0
  158. package/new-ui/src/api/hooks/use-stats.ts +27 -0
  159. package/new-ui/src/api/hooks/use-tasks.ts +89 -0
  160. package/new-ui/src/api/hooks/use-workflows.ts +109 -0
  161. package/{ui/src/types/api.ts → new-ui/src/api/types.ts} +236 -10
  162. package/new-ui/src/app/App.tsx +13 -0
  163. package/new-ui/src/app/providers.tsx +32 -0
  164. package/new-ui/src/app/router.tsx +52 -0
  165. package/new-ui/src/components/layout/app-header.tsx +47 -0
  166. package/new-ui/src/components/layout/app-sidebar.tsx +128 -0
  167. package/new-ui/src/components/layout/breadcrumbs.tsx +57 -0
  168. package/new-ui/src/components/layout/config-guard.tsx +22 -0
  169. package/new-ui/src/components/layout/root-layout.tsx +40 -0
  170. package/new-ui/src/components/layout/swarm-switcher.tsx +85 -0
  171. package/new-ui/src/components/shared/command-menu.tsx +131 -0
  172. package/new-ui/src/components/shared/data-grid.tsx +141 -0
  173. package/new-ui/src/components/shared/empty-state.tsx +24 -0
  174. package/new-ui/src/components/shared/error-boundary.tsx +72 -0
  175. package/new-ui/src/components/shared/json-viewer.tsx +47 -0
  176. package/new-ui/src/components/shared/name-connection-modal.tsx +99 -0
  177. package/new-ui/src/components/shared/page-skeleton.tsx +16 -0
  178. package/new-ui/src/components/shared/session-log-viewer.tsx +364 -0
  179. package/new-ui/src/components/shared/stats-bar.tsx +132 -0
  180. package/new-ui/src/components/shared/status-badge.tsx +131 -0
  181. package/new-ui/src/components/shared/usage-summary.tsx +179 -0
  182. package/new-ui/src/components/ui/alert-dialog.tsx +176 -0
  183. package/new-ui/src/components/ui/alert.tsx +60 -0
  184. package/new-ui/src/components/ui/avatar.tsx +96 -0
  185. package/new-ui/src/components/ui/badge.tsx +46 -0
  186. package/new-ui/src/components/ui/button.tsx +62 -0
  187. package/new-ui/src/components/ui/card.tsx +75 -0
  188. package/new-ui/src/components/ui/command.tsx +160 -0
  189. package/new-ui/src/components/ui/dialog.tsx +143 -0
  190. package/new-ui/src/components/ui/dropdown-menu.tsx +226 -0
  191. package/new-ui/src/components/ui/input.tsx +21 -0
  192. package/new-ui/src/components/ui/label.tsx +19 -0
  193. package/new-ui/src/components/ui/progress.tsx +26 -0
  194. package/new-ui/src/components/ui/scroll-area.tsx +54 -0
  195. package/new-ui/src/components/ui/select.tsx +175 -0
  196. package/new-ui/src/components/ui/separator.tsx +28 -0
  197. package/new-ui/src/components/ui/sheet.tsx +132 -0
  198. package/new-ui/src/components/ui/sidebar.tsx +691 -0
  199. package/new-ui/src/components/ui/skeleton.tsx +13 -0
  200. package/new-ui/src/components/ui/sonner.tsx +35 -0
  201. package/new-ui/src/components/ui/switch.tsx +33 -0
  202. package/new-ui/src/components/ui/table.tsx +92 -0
  203. package/new-ui/src/components/ui/tabs.tsx +79 -0
  204. package/new-ui/src/components/ui/textarea.tsx +18 -0
  205. package/new-ui/src/components/ui/tooltip.tsx +51 -0
  206. package/new-ui/src/components/workflows/action-node.tsx +53 -0
  207. package/new-ui/src/components/workflows/condition-node.tsx +50 -0
  208. package/new-ui/src/components/workflows/graph-utils.ts +124 -0
  209. package/new-ui/src/components/workflows/json-tree.tsx +189 -0
  210. package/new-ui/src/components/workflows/node-styles.ts +10 -0
  211. package/new-ui/src/components/workflows/step-detail-sheet.tsx +87 -0
  212. package/new-ui/src/components/workflows/trigger-node.tsx +41 -0
  213. package/new-ui/src/components/workflows/workflow-graph.tsx +65 -0
  214. package/{ui/src/hooks/useAutoScroll.ts → new-ui/src/hooks/use-auto-scroll.ts} +0 -1
  215. package/new-ui/src/hooks/use-config.ts +203 -0
  216. package/new-ui/src/hooks/use-keyboard-shortcuts.ts +41 -0
  217. package/new-ui/src/hooks/use-mobile.ts +19 -0
  218. package/new-ui/src/hooks/use-theme.ts +60 -0
  219. package/new-ui/src/lib/config.ts +188 -0
  220. package/new-ui/src/lib/slugs.ts +71 -0
  221. package/{ui → new-ui}/src/lib/utils.ts +32 -0
  222. package/new-ui/src/main.tsx +11 -0
  223. package/new-ui/src/pages/agents/[id]/page.tsx +492 -0
  224. package/new-ui/src/pages/agents/page.tsx +134 -0
  225. package/new-ui/src/pages/chat/page.tsx +674 -0
  226. package/new-ui/src/pages/config/page.tsx +1109 -0
  227. package/new-ui/src/pages/dashboard/page.tsx +454 -0
  228. package/new-ui/src/pages/debug/page.tsx +275 -0
  229. package/new-ui/src/pages/epics/[id]/page.tsx +809 -0
  230. package/new-ui/src/pages/epics/page.tsx +321 -0
  231. package/new-ui/src/pages/not-found/page.tsx +18 -0
  232. package/new-ui/src/pages/repos/page.tsx +369 -0
  233. package/new-ui/src/pages/schedules/[id]/page.tsx +664 -0
  234. package/new-ui/src/pages/schedules/page.tsx +477 -0
  235. package/new-ui/src/pages/services/page.tsx +128 -0
  236. package/new-ui/src/pages/tasks/[id]/page.tsx +670 -0
  237. package/new-ui/src/pages/tasks/page.tsx +592 -0
  238. package/new-ui/src/pages/usage/page.tsx +195 -0
  239. package/new-ui/src/pages/workflow-runs/[id]/page.tsx +363 -0
  240. package/new-ui/src/pages/workflows/[id]/page.tsx +417 -0
  241. package/new-ui/src/pages/workflows/page.tsx +266 -0
  242. package/new-ui/src/styles/ag-grid.css +36 -0
  243. package/new-ui/src/styles/globals.css +213 -0
  244. package/new-ui/test-results/.last-run.json +4 -0
  245. package/{ui/tsconfig.json → new-ui/tsconfig.app.json} +7 -4
  246. package/new-ui/tsconfig.json +4 -0
  247. package/new-ui/tsconfig.node.json +26 -0
  248. package/new-ui/vercel.json +4 -0
  249. package/new-ui/vite.config.ts +28 -0
  250. package/openapi.json +4436 -0
  251. package/package.json +31 -7
  252. package/plugin/build-pi-skills.ts +233 -0
  253. package/plugin/commands/close-issue.md +7 -3
  254. package/plugin/commands/create-pr.md +18 -12
  255. package/plugin/commands/implement-issue.md +7 -3
  256. package/plugin/commands/respond-github.md +8 -4
  257. package/plugin/commands/review-pr.md +44 -10
  258. package/plugin/commands/start-leader.md +1 -3
  259. package/plugin/commands/start-worker.md +1 -3
  260. package/plugin/commands/work-on-task.md +22 -3
  261. package/plugin/pi-skills/close-issue/SKILL.md +90 -0
  262. package/plugin/pi-skills/create-pr/SKILL.md +99 -0
  263. package/plugin/pi-skills/implement-issue/SKILL.md +135 -0
  264. package/plugin/pi-skills/investigate-sentry-issue/SKILL.md +138 -0
  265. package/plugin/pi-skills/respond-github/SKILL.md +98 -0
  266. package/plugin/pi-skills/review-offered-task/SKILL.md +45 -0
  267. package/plugin/pi-skills/review-pr/SKILL.md +261 -0
  268. package/plugin/pi-skills/start-leader/SKILL.md +121 -0
  269. package/plugin/pi-skills/start-worker/SKILL.md +60 -0
  270. package/plugin/pi-skills/swarm-chat/SKILL.md +82 -0
  271. package/plugin/pi-skills/todos/SKILL.md +66 -0
  272. package/plugin/pi-skills/work-on-task/SKILL.md +65 -0
  273. package/plugin/skills/artifacts/examples/approval-flow.ts +34 -0
  274. package/plugin/skills/artifacts/examples/hono-dashboard.ts +31 -0
  275. package/plugin/skills/artifacts/examples/multi-artifact.ts +20 -0
  276. package/plugin/skills/artifacts/examples/static-report.sh +17 -0
  277. package/plugin/skills/artifacts/skill.md +71 -0
  278. package/prek.toml +75 -0
  279. package/scripts/check-db-boundary.sh +60 -0
  280. package/scripts/e2e-docker-provider.ts +820 -0
  281. package/scripts/e2e-io-schemas-test.ts +807 -0
  282. package/scripts/e2e-provider-test.ts +220 -0
  283. package/scripts/e2e-workflow-redesign.sh +229 -0
  284. package/scripts/e2e-workflow-test.sh +285 -0
  285. package/scripts/e2e-workflow-test.ts +857 -0
  286. package/scripts/generate-openapi.ts +26 -0
  287. package/scripts/measure-tool-tokens.ts +118 -0
  288. package/scripts/x402-e2e-test.ts +195 -0
  289. package/scripts/x402-test-server.ts +236 -0
  290. package/scripts/x402-testnet-e2e.ts +668 -0
  291. package/slack-manifest.json +17 -0
  292. package/src/agentmail/app.ts +65 -0
  293. package/src/agentmail/handlers.ts +207 -0
  294. package/src/agentmail/index.ts +9 -0
  295. package/src/agentmail/types.ts +51 -0
  296. package/src/artifact-sdk/browser-sdk.ts +30 -0
  297. package/src/artifact-sdk/index.ts +2 -0
  298. package/src/artifact-sdk/localtunnel.d.ts +20 -0
  299. package/src/artifact-sdk/port.ts +12 -0
  300. package/src/artifact-sdk/server.ts +156 -0
  301. package/src/artifact-sdk/tunnel.ts +19 -0
  302. package/src/be/chunking.ts +193 -0
  303. package/src/be/db-queries/oauth.ts +90 -0
  304. package/src/be/db-queries/tracker.ts +182 -0
  305. package/src/be/db.ts +2729 -770
  306. package/src/be/embedding.ts +80 -0
  307. package/src/be/migrations/001_initial.sql +409 -0
  308. package/src/be/migrations/002_one_time_schedules.sql +59 -0
  309. package/src/be/migrations/003_workflows.sql +51 -0
  310. package/src/be/migrations/004_workflow_source.sql +81 -0
  311. package/src/be/migrations/005_epic_next_steps.sql +2 -0
  312. package/src/be/migrations/006_vcs_provider.sql +94 -0
  313. package/src/be/migrations/007_task_dir.sql +2 -0
  314. package/src/be/migrations/008_workflow_redesign.sql +85 -0
  315. package/src/be/migrations/009_tracker_integration.sql +144 -0
  316. package/src/be/migrations/010_step_diagnostics.sql +1 -0
  317. package/src/be/migrations/011_step_next_port.sql +1 -0
  318. package/src/be/migrations/012_trigger_schema.sql +1 -0
  319. package/src/be/migrations/013_task_output_schema.sql +2 -0
  320. package/src/be/migrations/runner.ts +188 -0
  321. package/src/cli.tsx +231 -299
  322. package/src/commands/artifact.ts +241 -0
  323. package/src/commands/onboard/compose-generator.ts +169 -0
  324. package/src/commands/onboard/env-generator.ts +79 -0
  325. package/src/commands/onboard/manifest.ts +37 -0
  326. package/src/commands/onboard/presets.ts +85 -0
  327. package/src/commands/onboard/service-names.ts +47 -0
  328. package/src/commands/onboard/steps/core-credentials.tsx +111 -0
  329. package/src/commands/onboard/steps/custom-templates.tsx +168 -0
  330. package/src/commands/onboard/steps/generate.tsx +154 -0
  331. package/src/commands/onboard/steps/harness-credentials.tsx +195 -0
  332. package/src/commands/onboard/steps/harness.tsx +21 -0
  333. package/src/commands/onboard/steps/health-check.tsx +171 -0
  334. package/src/commands/onboard/steps/integration-github.tsx +105 -0
  335. package/src/commands/onboard/steps/integration-gitlab.tsx +79 -0
  336. package/src/commands/onboard/steps/integration-menu.tsx +58 -0
  337. package/src/commands/onboard/steps/integration-sentry.tsx +79 -0
  338. package/src/commands/onboard/steps/integration-slack.tsx +165 -0
  339. package/src/commands/onboard/steps/post-connect.tsx +145 -0
  340. package/src/commands/onboard/steps/post-dashboard.tsx +34 -0
  341. package/src/commands/onboard/steps/post-task.tsx +103 -0
  342. package/src/commands/onboard/steps/prereq-check.tsx +178 -0
  343. package/src/commands/onboard/steps/review.tsx +82 -0
  344. package/src/commands/onboard/steps/start.tsx +97 -0
  345. package/src/commands/onboard/templates.ts +34 -0
  346. package/src/commands/onboard/types.ts +259 -0
  347. package/src/commands/onboard.tsx +425 -0
  348. package/src/commands/runner.ts +1376 -559
  349. package/src/commands/setup.tsx +23 -38
  350. package/src/commands/shared/client-config.ts +41 -0
  351. package/src/github/app.ts +8 -0
  352. package/src/github/handlers.ts +93 -75
  353. package/src/github/index.ts +1 -0
  354. package/src/github/types.ts +1 -0
  355. package/src/gitlab/auth.ts +63 -0
  356. package/src/gitlab/handlers.ts +327 -0
  357. package/src/gitlab/index.ts +19 -0
  358. package/src/gitlab/reactions.ts +104 -0
  359. package/src/gitlab/types.ts +130 -0
  360. package/src/heartbeat/heartbeat.ts +425 -0
  361. package/src/heartbeat/index.ts +1 -0
  362. package/src/hooks/hook.ts +555 -4
  363. package/src/hooks/tool-loop-detection.test.ts +158 -0
  364. package/src/hooks/tool-loop-detection.ts +167 -0
  365. package/src/http/active-sessions.ts +172 -0
  366. package/src/http/agents.ts +328 -0
  367. package/src/http/config.ts +191 -0
  368. package/src/http/core.ts +309 -0
  369. package/src/http/db-query.ts +91 -0
  370. package/src/http/ecosystem.ts +63 -0
  371. package/src/http/epics.ts +460 -0
  372. package/src/http/index.ts +213 -0
  373. package/src/http/mcp.ts +77 -0
  374. package/src/http/memory.ts +168 -0
  375. package/src/http/openapi.ts +109 -0
  376. package/src/http/poll.ts +178 -0
  377. package/src/http/repos.ts +195 -0
  378. package/src/http/route-def.ts +123 -0
  379. package/src/http/schedules.ts +391 -0
  380. package/src/http/session-data.ts +241 -0
  381. package/src/http/stats.ts +174 -0
  382. package/src/http/tasks.ts +468 -0
  383. package/src/http/trackers/index.ts +10 -0
  384. package/src/http/trackers/linear.ts +187 -0
  385. package/src/http/types.ts +12 -0
  386. package/src/http/utils.ts +87 -0
  387. package/src/http/webhooks.ts +432 -0
  388. package/src/http/workflows.ts +522 -0
  389. package/src/http.ts +1 -1890
  390. package/src/linear/README.md +65 -0
  391. package/src/linear/app.ts +48 -0
  392. package/src/linear/client.ts +18 -0
  393. package/src/linear/index.ts +1 -0
  394. package/src/linear/oauth.ts +35 -0
  395. package/src/linear/outbound.ts +212 -0
  396. package/src/linear/sync.ts +543 -0
  397. package/src/linear/types.ts +7 -0
  398. package/src/linear/webhook.ts +104 -0
  399. package/src/oauth/README.md +66 -0
  400. package/src/oauth/index.ts +6 -0
  401. package/src/oauth/wrapper.ts +204 -0
  402. package/src/prompts/base-prompt.ts +366 -24
  403. package/src/prompts/defaults.ts +196 -0
  404. package/src/providers/claude-adapter.ts +429 -0
  405. package/src/providers/index.ts +24 -0
  406. package/src/providers/pi-mono-adapter.ts +442 -0
  407. package/src/providers/pi-mono-extension.ts +620 -0
  408. package/src/providers/pi-mono-mcp-client.ts +124 -0
  409. package/src/providers/types.ts +75 -0
  410. package/src/scheduler/scheduler.test.ts +2 -0
  411. package/src/scheduler/scheduler.ts +186 -29
  412. package/src/server.ts +82 -6
  413. package/src/slack/HEURISTICS.md +105 -0
  414. package/src/slack/actions.ts +133 -0
  415. package/src/slack/app.ts +7 -0
  416. package/src/slack/assistant.ts +115 -0
  417. package/src/slack/blocks.ts +233 -0
  418. package/src/slack/commands.ts +31 -17
  419. package/src/slack/files.ts +1 -1
  420. package/src/slack/handlers.test.ts +114 -1
  421. package/src/slack/handlers.ts +212 -52
  422. package/src/slack/responses.ts +120 -67
  423. package/src/slack/router.ts +17 -99
  424. package/src/slack/thread-buffer.ts +213 -0
  425. package/src/slack/watcher.ts +119 -4
  426. package/src/tests/agent-activity.test.ts +247 -0
  427. package/src/tests/agentmail-filters.test.ts +97 -0
  428. package/src/tests/artifact-sdk.test.ts +800 -0
  429. package/src/tests/base-prompt.test.ts +264 -0
  430. package/src/tests/build-pi-skills.test.ts +127 -0
  431. package/src/tests/claude-adapter.test.ts +126 -0
  432. package/src/tests/context-versioning.test.ts +425 -0
  433. package/src/tests/db-queries-oauth.test.ts +197 -0
  434. package/src/tests/db-queries-tracker.test.ts +230 -0
  435. package/src/tests/epics.test.ts +3 -3
  436. package/src/tests/error-tracker.test.ts +368 -0
  437. package/src/tests/fetch-resolved-env.test.ts +167 -0
  438. package/src/tests/generate-default-claude-md.test.ts +9 -1
  439. package/src/tests/generate-identity-templates.test.ts +124 -0
  440. package/src/tests/gitlab-auth.test.ts +109 -0
  441. package/src/tests/gitlab-handlers.test.ts +691 -0
  442. package/src/tests/gitlab-vcs-db.test.ts +177 -0
  443. package/src/tests/heartbeat.test.ts +363 -0
  444. package/src/tests/http-api-integration.test.ts +1698 -0
  445. package/src/tests/linear-outbound-sync.test.ts +200 -0
  446. package/src/tests/linear-webhook.test.ts +402 -0
  447. package/src/tests/match-route.test.ts +187 -0
  448. package/src/tests/memory.test.ts +737 -0
  449. package/src/tests/migration-runner-regressions.test.ts +86 -0
  450. package/src/tests/model-control.test.ts +338 -0
  451. package/src/tests/oauth-wrapper.test.ts +147 -0
  452. package/src/tests/onboard-compose.test.ts +138 -0
  453. package/src/tests/onboard-env.test.ts +174 -0
  454. package/src/tests/onboard-manifest.test.ts +137 -0
  455. package/src/tests/pi-mono-adapter.test.ts +234 -0
  456. package/src/tests/progress-dedup.test.ts +98 -0
  457. package/src/tests/provider-adapter.test.ts +122 -0
  458. package/src/tests/provider-command-format.test.ts +98 -0
  459. package/src/tests/reload-config.test.ts +170 -0
  460. package/src/tests/runner-polling-api.test.ts +25 -20
  461. package/src/tests/scheduled-tasks.test.ts +104 -0
  462. package/src/tests/scheduler-backoff.test.ts +166 -0
  463. package/src/tests/self-improvement.test.ts +540 -0
  464. package/src/tests/session-attach.test.ts +536 -0
  465. package/src/tests/session-costs.test.ts +267 -1
  466. package/src/tests/slack-actions.test.ts +133 -0
  467. package/src/tests/slack-assistant.test.ts +136 -0
  468. package/src/tests/slack-blocks.test.ts +246 -0
  469. package/src/tests/slack-metadata-inheritance.test.ts +243 -0
  470. package/src/tests/slack-queue-offline.test.ts +174 -0
  471. package/src/tests/slack-router.test.ts +181 -0
  472. package/src/tests/slack-thread-buffer.test.ts +305 -0
  473. package/src/tests/slack-thread-followups.test.ts +298 -0
  474. package/src/tests/slack-watcher.test.ts +101 -0
  475. package/src/tests/structured-output.test.ts +311 -0
  476. package/src/tests/swarm-repos.test.ts +198 -0
  477. package/src/tests/task-cancellation.test.ts +6 -4
  478. package/src/tests/task-working-dir.test.ts +176 -0
  479. package/src/tests/template-fetch.test.ts +490 -0
  480. package/src/tests/tool-annotations.test.ts +371 -0
  481. package/src/tests/tracker-tools.test.ts +184 -0
  482. package/src/tests/update-profile-api.test.ts +143 -3
  483. package/src/tests/validation-adapters.test.ts +86 -0
  484. package/src/tests/vcs-provider.test.ts +27 -0
  485. package/src/tests/workflow-agent-task.test.ts +196 -0
  486. package/src/tests/workflow-async-v2.test.ts +386 -0
  487. package/src/tests/workflow-convergence.test.ts +541 -0
  488. package/src/tests/workflow-definition-validation.test.ts +290 -0
  489. package/src/tests/workflow-engine-v2.test.ts +691 -0
  490. package/src/tests/workflow-executors.test.ts +736 -0
  491. package/src/tests/workflow-http-v2.test.ts +599 -0
  492. package/src/tests/workflow-integration-io.test.ts +902 -0
  493. package/src/tests/workflow-io-schemas.test.ts +624 -0
  494. package/src/tests/workflow-registry.test.ts +592 -0
  495. package/src/tests/workflow-retry-v2.test.ts +401 -0
  496. package/src/tests/workflow-retry-validation.test.ts +282 -0
  497. package/src/tests/workflow-template.test.ts +288 -0
  498. package/src/tests/workflow-trigger-schema.test.ts +359 -0
  499. package/src/tests/workflow-triggers-v2.test.ts +264 -0
  500. package/src/tests/workflow-versions.test.ts +208 -0
  501. package/src/tests/x402-client.test.ts +117 -0
  502. package/src/tests/x402-config.test.ts +182 -0
  503. package/src/tests/x402-spending-tracker.test.ts +185 -0
  504. package/src/tools/cancel-task.ts +2 -0
  505. package/src/tools/context-diff.ts +171 -0
  506. package/src/tools/context-history.ts +138 -0
  507. package/src/tools/create-channel.ts +1 -0
  508. package/src/tools/db-query.ts +78 -0
  509. package/src/tools/delete-channel.ts +132 -0
  510. package/src/tools/epics/assign-task-to-epic.ts +1 -0
  511. package/src/tools/epics/create-epic.ts +3 -2
  512. package/src/tools/epics/delete-epic.ts +2 -0
  513. package/src/tools/epics/get-epic-details.ts +2 -0
  514. package/src/tools/epics/list-epics.ts +2 -0
  515. package/src/tools/epics/unassign-task-from-epic.ts +1 -0
  516. package/src/tools/epics/update-epic.ts +7 -4
  517. package/src/tools/get-swarm.ts +2 -0
  518. package/src/tools/get-task-details.ts +2 -0
  519. package/src/tools/get-tasks.ts +27 -1
  520. package/src/tools/inject-learning.ts +106 -0
  521. package/src/tools/join-swarm.ts +17 -7
  522. package/src/tools/list-channels.ts +2 -0
  523. package/src/tools/list-services.ts +2 -0
  524. package/src/tools/memory-get.ts +56 -0
  525. package/src/tools/memory-search.ts +131 -0
  526. package/src/tools/my-agent-info.ts +2 -0
  527. package/src/tools/poll-task.ts +2 -20
  528. package/src/tools/post-message.ts +1 -0
  529. package/src/tools/read-messages.ts +2 -0
  530. package/src/tools/register-agentmail-inbox.ts +166 -0
  531. package/src/tools/register-service.ts +2 -0
  532. package/src/tools/schedules/create-schedule.ts +134 -24
  533. package/src/tools/schedules/delete-schedule.ts +2 -0
  534. package/src/tools/schedules/list-schedules.ts +20 -4
  535. package/src/tools/schedules/run-schedule-now.ts +1 -0
  536. package/src/tools/schedules/update-schedule.ts +49 -17
  537. package/src/tools/send-task.ts +132 -10
  538. package/src/tools/slack-download-file.ts +4 -2
  539. package/src/tools/slack-list-channels.ts +2 -0
  540. package/src/tools/slack-post.ts +2 -0
  541. package/src/tools/slack-read.ts +2 -0
  542. package/src/tools/slack-reply.ts +2 -0
  543. package/src/tools/slack-upload-file.ts +2 -0
  544. package/src/tools/store-progress.ts +187 -4
  545. package/src/tools/swarm-config/delete-config.ts +87 -0
  546. package/src/tools/swarm-config/get-config.ts +108 -0
  547. package/src/tools/swarm-config/index.ts +4 -0
  548. package/src/tools/swarm-config/list-config.ts +99 -0
  549. package/src/tools/swarm-config/set-config.ts +118 -0
  550. package/src/tools/task-action.ts +30 -5
  551. package/src/tools/task-dedup.ts +97 -0
  552. package/src/tools/tool-config.ts +117 -0
  553. package/src/tools/tracker/index.ts +6 -0
  554. package/src/tools/tracker/tracker-link-epic.ts +64 -0
  555. package/src/tools/tracker/tracker-link-task.ts +64 -0
  556. package/src/tools/tracker/tracker-map-agent.ts +57 -0
  557. package/src/tools/tracker/tracker-status.ts +56 -0
  558. package/src/tools/tracker/tracker-sync-status.ts +42 -0
  559. package/src/tools/tracker/tracker-unlink.ts +41 -0
  560. package/src/tools/unregister-service.ts +2 -0
  561. package/src/tools/update-profile.ts +93 -10
  562. package/src/tools/update-service-status.ts +2 -0
  563. package/src/tools/utils.ts +10 -1
  564. package/src/tools/workflows/create-workflow.ts +111 -0
  565. package/src/tools/workflows/delete-workflow.ts +42 -0
  566. package/src/tools/workflows/get-workflow-run.ts +59 -0
  567. package/src/tools/workflows/get-workflow.ts +53 -0
  568. package/src/tools/workflows/index.ts +9 -0
  569. package/src/tools/workflows/list-workflow-runs.ts +48 -0
  570. package/src/tools/workflows/list-workflows.ts +42 -0
  571. package/src/tools/workflows/retry-workflow-run.ts +40 -0
  572. package/src/tools/workflows/trigger-workflow.ts +96 -0
  573. package/src/tools/workflows/update-workflow.ts +118 -0
  574. package/src/tracker/types.ts +51 -0
  575. package/src/types.ts +477 -14
  576. package/src/utils/credentials.test.ts +156 -0
  577. package/src/utils/credentials.ts +50 -0
  578. package/src/utils/error-tracker.ts +190 -0
  579. package/src/vcs/index.ts +15 -0
  580. package/src/vcs/types.ts +5 -0
  581. package/src/workflows/checkpoint.ts +121 -0
  582. package/src/workflows/cooldown.ts +28 -0
  583. package/src/workflows/definition.ts +217 -0
  584. package/src/workflows/engine.ts +554 -0
  585. package/src/workflows/event-bus.ts +29 -0
  586. package/src/workflows/executors/agent-task.ts +92 -0
  587. package/src/workflows/executors/base.ts +86 -0
  588. package/src/workflows/executors/code-match.ts +88 -0
  589. package/src/workflows/executors/index.ts +16 -0
  590. package/src/workflows/executors/notify.ts +93 -0
  591. package/src/workflows/executors/property-match.ts +104 -0
  592. package/src/workflows/executors/raw-llm.ts +83 -0
  593. package/src/workflows/executors/registry.ts +76 -0
  594. package/src/workflows/executors/script.ts +103 -0
  595. package/src/workflows/executors/validate.ts +215 -0
  596. package/src/workflows/executors/vcs.ts +58 -0
  597. package/src/workflows/index.ts +61 -0
  598. package/src/workflows/input.ts +46 -0
  599. package/src/workflows/json-schema-validator.ts +118 -0
  600. package/src/workflows/recovery.ts +139 -0
  601. package/src/workflows/resume.ts +143 -0
  602. package/src/workflows/retry-poller.ts +216 -0
  603. package/src/workflows/template.ts +74 -0
  604. package/src/workflows/templates.ts +86 -0
  605. package/src/workflows/triggers.ts +95 -0
  606. package/src/workflows/validation.ts +104 -0
  607. package/src/workflows/version.ts +42 -0
  608. package/src/x402/cli.ts +140 -0
  609. package/src/x402/client.ts +192 -0
  610. package/src/x402/config.ts +131 -0
  611. package/src/x402/index.ts +37 -0
  612. package/src/x402/openfort-signer.ts +83 -0
  613. package/src/x402/spending-tracker.ts +109 -0
  614. package/templates/community/.gitkeep +0 -0
  615. package/templates/official/coder/CLAUDE.md +49 -0
  616. package/templates/official/coder/IDENTITY.md +28 -0
  617. package/templates/official/coder/SOUL.md +43 -0
  618. package/templates/official/coder/TOOLS.md +40 -0
  619. package/templates/official/coder/config.json +23 -0
  620. package/templates/official/coder/start-up.sh +23 -0
  621. package/templates/official/content-reviewer/CLAUDE.md +68 -0
  622. package/templates/official/content-reviewer/IDENTITY.md +28 -0
  623. package/templates/official/content-reviewer/SOUL.md +44 -0
  624. package/templates/official/content-reviewer/TOOLS.md +37 -0
  625. package/templates/official/content-reviewer/config.json +23 -0
  626. package/templates/official/content-reviewer/start-up.sh +23 -0
  627. package/templates/official/content-strategist/CLAUDE.md +63 -0
  628. package/templates/official/content-strategist/IDENTITY.md +33 -0
  629. package/templates/official/content-strategist/SOUL.md +48 -0
  630. package/templates/official/content-strategist/TOOLS.md +47 -0
  631. package/templates/official/content-strategist/config.json +23 -0
  632. package/templates/official/content-strategist/start-up.sh +23 -0
  633. package/templates/official/content-writer/CLAUDE.md +72 -0
  634. package/templates/official/content-writer/IDENTITY.md +30 -0
  635. package/templates/official/content-writer/SOUL.md +46 -0
  636. package/templates/official/content-writer/TOOLS.md +44 -0
  637. package/templates/official/content-writer/config.json +23 -0
  638. package/templates/official/content-writer/start-up.sh +23 -0
  639. package/templates/official/forward-deployed-engineer/CLAUDE.md +54 -0
  640. package/templates/official/forward-deployed-engineer/IDENTITY.md +37 -0
  641. package/templates/official/forward-deployed-engineer/SOUL.md +55 -0
  642. package/templates/official/forward-deployed-engineer/config.json +21 -0
  643. package/templates/official/lead/CLAUDE.md +33 -0
  644. package/templates/official/lead/IDENTITY.md +36 -0
  645. package/templates/official/lead/SOUL.md +51 -0
  646. package/templates/official/lead/config.json +22 -0
  647. package/templates/official/researcher/CLAUDE.md +46 -0
  648. package/templates/official/researcher/IDENTITY.md +28 -0
  649. package/templates/official/researcher/SOUL.md +43 -0
  650. package/templates/official/researcher/config.json +21 -0
  651. package/templates/official/reviewer/CLAUDE.md +63 -0
  652. package/templates/official/reviewer/IDENTITY.md +28 -0
  653. package/templates/official/reviewer/SOUL.md +45 -0
  654. package/templates/official/reviewer/config.json +21 -0
  655. package/templates/official/tester/CLAUDE.md +53 -0
  656. package/templates/official/tester/IDENTITY.md +28 -0
  657. package/templates/official/tester/SOUL.md +55 -0
  658. package/templates/official/tester/config.json +21 -0
  659. package/templates/schema.ts +35 -0
  660. package/templates-ui/README.md +46 -0
  661. package/templates-ui/components.json +17 -0
  662. package/templates-ui/eslint.config.mjs +18 -0
  663. package/templates-ui/next.config.ts +7 -0
  664. package/templates-ui/package.json +35 -0
  665. package/templates-ui/pnpm-lock.yaml +4571 -0
  666. package/templates-ui/postcss.config.mjs +7 -0
  667. package/templates-ui/public/file.svg +1 -0
  668. package/templates-ui/public/globe.svg +1 -0
  669. package/templates-ui/public/logo.png +0 -0
  670. package/templates-ui/public/next.svg +1 -0
  671. package/templates-ui/public/vercel.svg +1 -0
  672. package/templates-ui/public/window.svg +1 -0
  673. package/templates-ui/src/app/[category]/[name]/page.tsx +89 -0
  674. package/templates-ui/src/app/api/templates/[...slug]/route.ts +52 -0
  675. package/templates-ui/src/app/api/templates/route.ts +18 -0
  676. package/templates-ui/src/app/builder/page.tsx +37 -0
  677. package/templates-ui/src/app/globals.css +94 -0
  678. package/templates-ui/src/app/layout.tsx +79 -0
  679. package/templates-ui/src/app/page.tsx +38 -0
  680. package/templates-ui/src/app/robots.ts +11 -0
  681. package/templates-ui/src/app/sitemap.ts +31 -0
  682. package/templates-ui/src/components/compose-builder.tsx +442 -0
  683. package/templates-ui/src/components/compose-preview.tsx +117 -0
  684. package/templates-ui/src/components/file-preview.tsx +77 -0
  685. package/templates-ui/src/components/footer.tsx +40 -0
  686. package/templates-ui/src/components/header.tsx +41 -0
  687. package/templates-ui/src/components/template-card.tsx +87 -0
  688. package/templates-ui/src/components/template-detail.tsx +125 -0
  689. package/templates-ui/src/components/template-gallery.tsx +263 -0
  690. package/templates-ui/src/components/ui/badge.tsx +36 -0
  691. package/templates-ui/src/components/ui/button.tsx +57 -0
  692. package/templates-ui/src/components/ui/card.tsx +76 -0
  693. package/templates-ui/src/components/ui/separator.tsx +31 -0
  694. package/templates-ui/src/components/ui/tooltip.tsx +32 -0
  695. package/templates-ui/src/lib/compose-generator.ts +241 -0
  696. package/templates-ui/src/lib/templates.ts +137 -0
  697. package/templates-ui/src/lib/utils.ts +6 -0
  698. package/templates-ui/tsconfig.json +34 -0
  699. package/thoughts/research/2026-02-28-openfort-viem-x402-research.md +679 -0
  700. package/thoughts/research/2026-02-28-x402-payments-research.md +686 -0
  701. package/thoughts/researcher/plans/2026-02-20-agent-self-improvement-plan.md +282 -0
  702. package/thoughts/researcher/research/2026-02-20-agent-self-improvement.md +492 -0
  703. package/thoughts/shared/plans/2026-02-26-mcp-tool-context-reduction.md +282 -0
  704. package/thoughts/shared/plans/2026-03-02-claude-context-mode-integration.md +328 -0
  705. package/thoughts/shared/plans/2026-03-02-code-level-heartbeat.md +224 -0
  706. package/thoughts/shared/research/2026-02-26-cliffy-mcp-tools.md +159 -0
  707. package/thoughts/shared/research/2026-03-03-database-migration-system-refactor.md +337 -0
  708. package/thoughts/swarm-researcher/plans/2026-02-23-openclaw-improvements-plan.md +778 -0
  709. package/thoughts/swarm-researcher/plans/2026-02-26-artifacts-localtunnel-plan.md +1269 -0
  710. package/thoughts/swarm-researcher/research/2026-02-23-openclaw-vs-agent-swarm-comparison.md +411 -0
  711. package/thoughts/swarm-researcher/research/2026-02-26-artifacts-localtunnel.md +724 -0
  712. package/thoughts/taras/brainstorms/2026-03-20-prompt-template-registry.md +443 -0
  713. package/thoughts/taras/brainstorms/2026-03-20-setup-cli-onboarding.md +307 -0
  714. package/thoughts/taras/plans/2026-02-20-auto-improvement.md +803 -0
  715. package/thoughts/taras/plans/2026-02-20-env-management.md +538 -0
  716. package/thoughts/taras/plans/2026-02-20-memory-system.md +882 -0
  717. package/thoughts/taras/plans/2026-02-20-repos-knowledge.md +806 -0
  718. package/thoughts/taras/plans/2026-02-20-session-attach.md +647 -0
  719. package/thoughts/taras/plans/2026-02-20-worker-identity.md +820 -0
  720. package/thoughts/taras/plans/2026-02-25-feat-new-ui-visual-redesign-plan.md +768 -0
  721. package/thoughts/taras/plans/2026-03-04-fix-buildSystemPrompt-missing-fields.md +77 -0
  722. package/thoughts/taras/plans/2026-03-04-new-ui-missing-actions.md +543 -0
  723. package/thoughts/taras/plans/2026-03-06-one-time-scheduled-tasks.md +373 -0
  724. package/thoughts/taras/plans/2026-03-08-memory-self-improvement-enhancements.md +512 -0
  725. package/thoughts/taras/plans/2026-03-08-pi-mono-provider-implementation.md +919 -0
  726. package/thoughts/taras/plans/2026-03-09-templates-registry.md +723 -0
  727. package/thoughts/taras/plans/2026-03-10-task-working-directory.md +371 -0
  728. package/thoughts/taras/plans/2026-03-11-archil-per-agent-write-strategy.md +621 -0
  729. package/thoughts/taras/plans/2026-03-12-eliminate-inbox-route-to-tasks.md +61 -0
  730. package/thoughts/taras/plans/2026-03-12-slack-thread-followup-additive.md +488 -0
  731. package/thoughts/taras/plans/2026-03-13-slack-ai-improvements.md +644 -0
  732. package/thoughts/taras/plans/2026-03-16-route-wrapper-openapi.md +636 -0
  733. package/thoughts/taras/plans/2026-03-17-multi-api-config.md +444 -0
  734. package/thoughts/taras/plans/2026-03-18-agent-fs-integration.md +591 -0
  735. package/thoughts/taras/plans/2026-03-18-debug-db-explorer.md +446 -0
  736. package/thoughts/taras/plans/2026-03-18-workflow-redesign.md +987 -0
  737. package/thoughts/taras/plans/2026-03-19-compound-learnings.md +403 -0
  738. package/thoughts/taras/plans/2026-03-19-ticket-tracker-linear-integration.md +860 -0
  739. package/thoughts/taras/plans/2026-03-19-workflow-io-schemas-and-bugs.md +899 -0
  740. package/thoughts/taras/plans/2026-03-20-setup-cli-onboarding.md +874 -0
  741. package/thoughts/taras/plans/2026-03-20-workflow-structured-output-validation-workspace.md +723 -0
  742. package/thoughts/taras/research/2026-02-19-agent-native-swarm-architecture.md +390 -0
  743. package/thoughts/taras/research/2026-02-19-swarm-gaps-implementation.md +594 -0
  744. package/thoughts/taras/research/2026-02-25-dashboard-ui-design-best-practices.md +825 -0
  745. package/thoughts/taras/research/2026-02-26-task-detail-page-redesign.md +393 -0
  746. package/thoughts/taras/research/2026-03-03-new-ui-missing-actions.md +168 -0
  747. package/thoughts/taras/research/2026-03-05-pi-mono-provider-research.md +230 -0
  748. package/thoughts/taras/research/2026-03-06-workflow-engine-design.md +445 -0
  749. package/thoughts/taras/research/2026-03-08-drive-loop-concept.md +375 -0
  750. package/thoughts/taras/research/2026-03-08-pi-mono-deep-dive.md +869 -0
  751. package/thoughts/taras/research/2026-03-09-templates-registry.md +373 -0
  752. package/thoughts/taras/research/2026-03-10-agent-working-directory.md +223 -0
  753. package/thoughts/taras/research/2026-03-10-configurable-event-prompts.md +339 -0
  754. package/thoughts/taras/research/2026-03-11-archil-production-setup.md +181 -0
  755. package/thoughts/taras/research/2026-03-11-archil-shared-disk-write-strategies.md +437 -0
  756. package/thoughts/taras/research/2026-03-13-slack-ai-features.md +258 -0
  757. package/thoughts/taras/research/2026-03-16-openapi-docs-generation.md +335 -0
  758. package/thoughts/taras/research/2026-03-16-route-wrapper-openapi.md +670 -0
  759. package/thoughts/taras/research/2026-03-16-slack-thread-followups-e2e.md +54 -0
  760. package/thoughts/taras/research/2026-03-18-agent-fs-integration.md +558 -0
  761. package/thoughts/taras/research/2026-03-18-linear-integration-finalization.md +526 -0
  762. package/thoughts/taras/research/2026-03-18-workflow-redesign.md +797 -0
  763. package/thoughts/taras/research/2026-03-19-workflow-node-io-schemas-and-bugs.md +563 -0
  764. package/thoughts/taras/research/2026-03-19-workflow-structured-output-validation-workspace.md +486 -0
  765. package/thoughts/taras/research/2026-03-20-prompt-template-registry.md +469 -0
  766. package/tsconfig.json +1 -1
  767. package/FAQ.md +0 -19
  768. package/src/tests/get-inbox-message.test.ts +0 -145
  769. package/src/tools/get-inbox-message.ts +0 -89
  770. package/src/tools/inbox-delegate.ts +0 -113
  771. package/ui/CLAUDE.md +0 -49
  772. package/ui/bun.lock +0 -771
  773. package/ui/index.html +0 -22
  774. package/ui/package-lock.json +0 -5290
  775. package/ui/package.json +0 -33
  776. package/ui/pnpm-lock.yaml +0 -3341
  777. package/ui/postcss.config.js +0 -6
  778. package/ui/src/App.tsx +0 -63
  779. package/ui/src/components/ActivityFeed.tsx +0 -440
  780. package/ui/src/components/AgentDetailPanel.tsx +0 -733
  781. package/ui/src/components/AgentsPanel.tsx +0 -815
  782. package/ui/src/components/ChatPanel.tsx +0 -1920
  783. package/ui/src/components/ConfigModal.tsx +0 -253
  784. package/ui/src/components/Dashboard.tsx +0 -832
  785. package/ui/src/components/EditAgentProfileModal.tsx +0 -433
  786. package/ui/src/components/EpicDetailPage.tsx +0 -741
  787. package/ui/src/components/EpicsPanel.tsx +0 -566
  788. package/ui/src/components/Header.tsx +0 -160
  789. package/ui/src/components/JsonViewer.tsx +0 -171
  790. package/ui/src/components/ScheduledTaskDetailPanel.tsx +0 -517
  791. package/ui/src/components/ScheduledTasksPanel.tsx +0 -639
  792. package/ui/src/components/ServicesPanel.tsx +0 -622
  793. package/ui/src/components/SessionLogPanel.tsx +0 -1219
  794. package/ui/src/components/StatsBar.tsx +0 -321
  795. package/ui/src/components/StatusBadge.tsx +0 -168
  796. package/ui/src/components/TaskDetailPanel.tsx +0 -903
  797. package/ui/src/components/TasksPanel.tsx +0 -614
  798. package/ui/src/components/UsageCharts.tsx +0 -216
  799. package/ui/src/components/UsageTab.tsx +0 -394
  800. package/ui/src/hooks/queries.ts +0 -353
  801. package/ui/src/index.css +0 -257
  802. package/ui/src/lib/api.ts +0 -268
  803. package/ui/src/lib/config.ts +0 -35
  804. package/ui/src/lib/contentPreview.ts +0 -208
  805. package/ui/src/lib/theme.ts +0 -214
  806. package/ui/src/main.tsx +0 -28
  807. package/ui/src/vite-env.d.ts +0 -1
  808. package/ui/tailwind.config.js +0 -37
  809. package/ui/vite.config.ts +0 -35
  810. /package/{ui → docs-site}/public/logo.png +0 -0
@@ -0,0 +1,679 @@
1
+ ---
2
+ date: 2026-02-28T10:25:00Z
3
+ researcher: Researcher
4
+ git_commit: n/a
5
+ branch: n/a
6
+ repository: desplega-ai/agent-swarm
7
+ topic: "Openfort viem integration as a robust alternative for x402 payments in agent-swarm"
8
+ tags: [research, x402, openfort, viem, payments, eip-3009, managed-wallets]
9
+ status: complete
10
+ autonomy: autopilot
11
+ last_updated: 2026-02-28T11:25:00Z
12
+ last_updated_by: Researcher (transaction testing update)
13
+ ---
14
+
15
+ # Research: Openfort Viem Integration as a Robust Alternative for x402 Payments
16
+
17
+ **Date**: 2026-02-28
18
+ **Researcher**: Researcher (agent-swarm worker)
19
+ **Context**: PR #108 adds x402 payment capability; feedback that current approach is "too yolo"
20
+
21
+ ## Research Question
22
+
23
+ Can Openfort's viem integration replace the raw `EVM_PRIVATE_KEY` approach in PR #108 for x402 payments, and is it a production-ready improvement?
24
+
25
+ ## Summary
26
+
27
+ **Yes, Openfort's backend wallets are technically compatible with the x402 payment flow.** The x402 SDK's `ClientEvmSigner` interface only requires `address` and `signTypedData` — Openfort's backend wallet provides both. The integration would require ~20 lines of adapter code. However, the trade-off is not straightforward: Openfort adds managed key custody and eliminates raw private keys in env vars, but introduces API latency (~125ms per sign), a vendor dependency on a small startup (7 employees, $3M raised, 658 weekly npm downloads), and per-operation costs.
28
+
29
+ **Recommendation: Implement a provider-agnostic signer abstraction** in `src/x402/` that supports both raw viem accounts (current) and Openfort accounts (new option). This avoids vendor lock-in while giving operators the choice of managed key infrastructure. The current approach should remain as the default for simplicity; Openfort becomes an opt-in upgrade for production deployments that need managed custody.
30
+
31
+ ## Detailed Findings
32
+
33
+ ### 1. What is Openfort?
34
+
35
+ Openfort is a wallet-as-a-service platform providing embedded wallets, backend wallets, account abstraction (ERC-4337/EIP-7702), gas sponsorship, and key management. They position themselves as "Money Movement Infrastructure for AI Agents & Stablecoins."
36
+
37
+ **Company facts:**
38
+ - Founded 2022, CEO Joan Alavedra
39
+ - ~7 employees, $3M raised (Seed, May 2023)
40
+ - Originally gaming-focused, pivoting to AI agents and stablecoins
41
+ - Open-source key management (OpenSigner) using Shamir Secret Sharing (2-of-3 threshold)
42
+ - SOC2 Type II claimed (unverified), Quantstamp audit in progress for OpenSigner
43
+
44
+ **Key products relevant to our use case:**
45
+ | Product | Description |
46
+ |---------|-------------|
47
+ | Backend Wallets | Server-side EOA wallets, keys secured in Google Cloud TEE. Up to 500 write TPS claimed. |
48
+ | OpenSigner | Open-source, self-hostable key management using Shamir Secret Sharing |
49
+ | Gas Sponsorship | Native ERC-4337 paymaster (not needed for x402 — the facilitator pays gas) |
50
+ | Session Keys | Scoped, time-limited signing permissions (potential future feature for agents) |
51
+
52
+ **Pricing:**
53
+ | Plan | Monthly | Included Ops | Overage |
54
+ |------|---------|-------------|---------|
55
+ | Free | $0 | 2,000 | $0.01/op |
56
+ | Growth | $99 | 25,000 | $0.008/op |
57
+ | Pro | $249 | 100,000 | $0.006/op |
58
+ | Scale | $599 | 500,000 | $0.004/op |
59
+
60
+ For our use case (agents making x402 payments), each payment requires one `signTypedData` API call = 1 operation. At the Free tier, that is 2,000 payments/month before charges. At Growth ($99/mo), 25,000 payments/month.
61
+
62
+ **Supported chains:** 25+ EVM chains (Ethereum, Base, Polygon, Arbitrum, etc.) + Solana.
63
+
64
+ ### 2. How the Openfort Viem Integration Works
65
+
66
+ The `@openfort/openfort-node` SDK (v0.9.1) provides a `toEvmAccount()` internal factory that creates an account object with viem-compatible signing methods.
67
+
68
+ **Architecture:**
69
+ ```
70
+ @openfort/openfort-node
71
+ └── src/wallets/evm/
72
+ ├── accounts/evmAccount.ts ← toEvmAccount() factory
73
+ ├── actions/ ← signHash, signMessage, signTransaction, signTypedData
74
+ ├── evmClient.ts ← EvmClient class
75
+ └── types.ts ← Uses viem types (Address, Hex, etc.)
76
+ ```
77
+
78
+ **How it works:**
79
+ 1. You instantiate the SDK with an API key + wallet secret
80
+ 2. `openfort.accounts.evm.backend.create()` creates a backend wallet (EOA secured in TEE)
81
+ 3. The returned account object has `signMessage()`, `signTypedData()`, `signTransaction()`, `sign()`
82
+ 4. Each signing operation makes an HTTP API call to Openfort's backend — the private key never leaves the TEE
83
+
84
+ **The account is NOT a native viem `LocalAccount`** — it has the same method signatures but different TypeScript types (`id`, `custody` fields). To use with viem's `WalletClient`, you wrap it via `toAccount()`:
85
+
86
+ ```typescript
87
+ import { toAccount } from "viem/accounts";
88
+
89
+ const openfortAccount = await openfort.accounts.evm.backend.create();
90
+ const viemAccount = toAccount({
91
+ address: openfortAccount.address,
92
+ async signMessage({ message }) { return openfortAccount.signMessage({ message }); },
93
+ async signTransaction(tx) { return openfortAccount.signTransaction(tx); },
94
+ async signTypedData(data) { return openfortAccount.signTypedData(data); },
95
+ });
96
+ ```
97
+
98
+ **Signing flow per operation:**
99
+ | Operation | Client-side (viem utils) | API call | Latency |
100
+ |-----------|-------------------------|----------|---------|
101
+ | `signMessage` | EIP-191 prefix via `toPrefixedMessage()` | Backend hashes + signs | ~125ms |
102
+ | `signTypedData` | Hash via `hashTypedData()` | Backend signs hash | ~125ms |
103
+ | `signTransaction` | Serialize via `serializeTransaction()` | Backend signs serialized tx | ~125ms |
104
+
105
+ ### 3. Current x402 Implementation (PR #108)
106
+
107
+ PR #108 adds x402 payment capability with this architecture:
108
+
109
+ ```
110
+ src/x402/
111
+ ├── index.ts ← Public API
112
+ ├── client.ts ← Core: privateKeyToAccount + x402 SDK wiring
113
+ ├── config.ts ← Env var loading (EVM_PRIVATE_KEY, limits)
114
+ ├── spending-tracker.ts ← In-memory 24hr spending limits
115
+ └── cli.ts ← Testing CLI
116
+ ```
117
+
118
+ **The "yolo" part — wallet creation in `client.ts`:**
119
+ ```typescript
120
+ const account = privateKeyToAccount(config.evmPrivateKey); // Raw key from env
121
+ const publicClient = createPublicClient({ chain, transport: http() });
122
+ const signer = toClientEvmSigner(account, publicClient); // x402 signer adapter
123
+ ```
124
+
125
+ **Payment flow:**
126
+ 1. Agent calls `paidFetch(url)` (wrapped `fetch`)
127
+ 2. If server returns HTTP 402 with `PAYMENT-REQUIRED` header → x402 SDK intercepts
128
+ 3. SDK constructs EIP-712 typed data for `TransferWithAuthorization` (EIP-3009)
129
+ 4. `signer.signTypedData(...)` signs off-chain (gasless for the agent)
130
+ 5. Signature sent in `PAYMENT-SIGNATURE` header on retry
131
+ 6. Facilitator submits on-chain, moves USDC, returns content
132
+
133
+ **Required env vars:**
134
+ | Variable | Required | Default | Purpose |
135
+ |----------|----------|---------|---------|
136
+ | `EVM_PRIVATE_KEY` | Yes | — | Raw private key (0x-prefixed hex) |
137
+ | `X402_MAX_AUTO_APPROVE` | No | 1.00 | Max USD per request |
138
+ | `X402_DAILY_LIMIT` | No | 10.00 | Max USD per UTC day |
139
+ | `X402_NETWORK` | No | Base Sepolia | CAIP-2 network ID |
140
+
141
+ ### 4. Can Openfort Replace the Current Signer?
142
+
143
+ **Yes.** The x402 SDK's `ClientEvmSigner` interface is minimal:
144
+
145
+ ```typescript
146
+ interface ClientEvmSigner {
147
+ address: `0x${string}`;
148
+ signTypedData: (message: {
149
+ domain: { ... };
150
+ types: Record<string, Array<{ name: string; type: string }>>;
151
+ primaryType: string;
152
+ message: Record<string, unknown>;
153
+ }) => Promise<`0x${string}`>;
154
+ }
155
+ ```
156
+
157
+ It does NOT require a `LocalAccount`, a private key, `signMessage`, or `signTransaction`. Any object with `address` + `signTypedData` works.
158
+
159
+ **Openfort adapter code (complete):**
160
+ ```typescript
161
+ import Openfort from "@openfort/openfort-node";
162
+ import type { ClientEvmSigner } from "@x402/evm";
163
+
164
+ const openfort = new Openfort(process.env.OPENFORT_API_KEY!, {
165
+ walletSecret: process.env.OPENFORT_WALLET_SECRET,
166
+ });
167
+
168
+ const account = await openfort.accounts.evm.backend.create();
169
+
170
+ const signer: ClientEvmSigner = {
171
+ address: account.address,
172
+ signTypedData: async (message) => {
173
+ return account.signTypedData({
174
+ domain: message.domain,
175
+ types: message.types,
176
+ primaryType: message.primaryType,
177
+ message: message.message,
178
+ });
179
+ },
180
+ };
181
+ ```
182
+
183
+ ### 5. EIP-3009 Compatibility — Critical Analysis
184
+
185
+ EIP-3009 (`transferWithAuthorization`) requires:
186
+ 1. An **EIP-712 typed data signature** — Openfort supports this via `signTypedData()`
187
+ 2. A **standard ECDSA signature** verified by `ecrecover` on-chain — Openfort's backend wallets are EOAs that produce standard ECDSA signatures
188
+ 3. The **signer's address must hold the USDC tokens** — must fund the EOA address from `account.address`
189
+
190
+ **Compatibility verdict: COMPATIBLE.** Openfort's backend wallet is an EOA that produces ECDSA signatures. The `signTypedData` method has the right interface. EIP-3009's `ecrecover` will accept the signature.
191
+
192
+ **One critical caveat:** Openfort also pairs accounts with ERC-4337 smart accounts. For x402, you MUST use the EOA address (from `account.address`) and fund USDC there — NOT any paired smart account address. Smart contract signatures (EIP-1271) are NOT compatible with EIP-3009.
193
+
194
+ ### 6. What Changes Are Needed in `src/x402/`
195
+
196
+ The changes would be minimal if we adopt a provider-agnostic approach:
197
+
198
+ **Option A — Minimal (add Openfort as alternative signer):**
199
+ ```
200
+ src/x402/
201
+ ├── config.ts ← Add OPENFORT_API_KEY, OPENFORT_WALLET_SECRET, X402_SIGNER_TYPE
202
+ ├── client.ts ← Add createOpenfortSigner() alongside existing createViemSigner()
203
+ └── (rest unchanged)
204
+ ```
205
+
206
+ Modify `client.ts` to select signer based on config:
207
+ ```typescript
208
+ async function createSigner(config: X402Config): Promise<ClientEvmSigner> {
209
+ if (config.signerType === 'openfort') {
210
+ return createOpenfortSigner(config);
211
+ }
212
+ // Default: current raw key approach
213
+ return createViemSigner(config);
214
+ }
215
+ ```
216
+
217
+ **New env vars:**
218
+ | Variable | Required | Default | Purpose |
219
+ |----------|----------|---------|---------|
220
+ | `X402_SIGNER_TYPE` | No | `viem` | `viem` or `openfort` |
221
+ | `OPENFORT_API_KEY` | If openfort | — | Openfort API key (sk_test_/sk_live_) |
222
+ | `OPENFORT_WALLET_SECRET` | If openfort | — | Openfort wallet encryption secret |
223
+
224
+ **Estimated effort:** ~50-80 lines of new code in `client.ts`, ~20 lines in `config.ts`, tests.
225
+
226
+ **Option B — Openfort-only (replace viem signer entirely):**
227
+ Not recommended. This would make Openfort a hard dependency, add latency to all payments, and remove the simple local-key option for development.
228
+
229
+ ### 7. Security Comparison
230
+
231
+ | Dimension | Current ("yolo") | Openfort |
232
+ |-----------|-----------------|----------|
233
+ | **Key storage** | Raw hex in `EVM_PRIVATE_KEY` env var | TEE-secured on Google Cloud, never exposed |
234
+ | **Key exposure risk** | Env var leak = full wallet compromise | API key leak = can create wallets but not access existing keys without wallet secret |
235
+ | **Key rotation** | Manual — change env var, update address | API call — rotate keys without changing address (with smart accounts) |
236
+ | **Blast radius of compromise** | Immediate full access to all funds | Requires both API key AND wallet secret; Openfort can freeze accounts |
237
+ | **Audit trail** | None — local signing is invisible | Full API audit log of every signing operation |
238
+ | **Compliance** | None | SOC2 Type II (claimed), audit logs |
239
+ | **Multi-agent isolation** | Same key shared across all agents | Each agent can have its own backend wallet with separate permissions |
240
+ | **Recovery** | Lose key = lose funds | 2-of-3 Shamir recovery via OpenSigner |
241
+
242
+ **The security upgrade is real but not transformational.** The biggest win is eliminating raw private keys from env vars — a genuine operational security improvement. The managed audit trail and per-agent wallet isolation are nice-to-haves. But the keys are still ultimately held by a third-party service (Openfort), so it shifts trust rather than eliminating it.
243
+
244
+ ### 8. Limitations and Trade-offs
245
+
246
+ **Concerns:**
247
+
248
+ | Concern | Severity | Detail |
249
+ |---------|----------|--------|
250
+ | **Company risk** | High | 7 employees, $3M raised. Competitors (Privy, Dynamic, Web3Auth, Sequence) have all been acquired. Openfort's independence is uncertain. |
251
+ | **Low adoption** | High | 658 weekly npm downloads on Node SDK. 8 GitHub stars. Very few external users. |
252
+ | **Pre-1.0 SDK** | Medium | Version 0.6.74 — API surface may change without semver guarantees |
253
+ | **Signing latency** | Medium | ~125ms per API call vs <1ms local. Adds latency to every x402 payment. |
254
+ | **Cost** | Low | Free tier covers 2,000 ops/month. Growth at $99/mo covers 25,000. Unlikely to be a budget issue. |
255
+ | **Vendor lock-in** | Medium | Wallets are Openfort-managed — migrating away requires exporting keys or creating new wallets |
256
+ | **Package size** | Low | 3.21 MB (bundled OpenAPI specs). Bloated but functional. |
257
+ | **No 1.0 stability guarantee** | Medium | Breaking changes possible between 0.x versions |
258
+
259
+ **Mitigating factors:**
260
+ - OpenSigner is open-source and self-hostable — reduces lock-in risk
261
+ - The provider-agnostic signer approach (Option A) means we can swap Openfort out without changing the x402 flow
262
+ - Openfort is actively maintained (multiple commits per day as of Feb 2026)
263
+
264
+ ### 9. Alternatives Considered
265
+
266
+ | Alternative | Pros | Cons |
267
+ |-------------|------|------|
268
+ | **Keep raw viem (current)** | Simplest, fastest, zero vendor dependency | Raw private key in env, no audit trail, "yolo" |
269
+ | **Openfort backend wallet** | Managed keys, audit trail, per-agent isolation | Vendor risk, latency, cost |
270
+ | **Coinbase CDP MPC wallet** | Backed by Coinbase (ecosystem alignment with x402) | More complex setup, heavier dependency |
271
+ | **Turnkey** | TEE-based (strong security), backed by Sequoia | Low-level primitives, harder to integrate, no free tier |
272
+ | **Fireblocks** | Enterprise-grade, 150+ chains | Expensive, overkill for our use case |
273
+ | **Vault + local signer** | Keep local signing but store key in HashiCorp Vault / AWS KMS | Same speed as current, better key management, no vendor lock-in | Key still decrypted in memory |
274
+
275
+ ## Recommendation
276
+
277
+ ### Short-term (PR #108): Ship as-is with the raw viem signer
278
+
279
+ The current implementation in PR #108 is functional and well-guarded (spending limits, safe config pattern, testnet default). For an MVP/initial release, it works. The "yolo" concern is about raw private keys in env vars — which is a standard practice for dev/test and acceptable for early production with small balances.
280
+
281
+ ### Medium-term: Implement provider-agnostic signer abstraction
282
+
283
+ Add a `SignerProvider` interface to `src/x402/` that abstracts over the signing backend:
284
+
285
+ ```typescript
286
+ interface SignerProvider {
287
+ type: string;
288
+ createSigner(): Promise<ClientEvmSigner>;
289
+ getWalletAddress(): Promise<`0x${string}`>;
290
+ }
291
+ ```
292
+
293
+ Implement two providers:
294
+ 1. `ViemSignerProvider` — current approach (default)
295
+ 2. `OpenfortSignerProvider` — opt-in via `X402_SIGNER_TYPE=openfort`
296
+
297
+ This keeps the simple path simple while allowing production deployments to upgrade to managed keys.
298
+
299
+ ### Long-term: Evaluate based on Openfort's trajectory
300
+
301
+ Openfort is a small, early-stage startup in a consolidating market. Before making it a primary dependency:
302
+ - Monitor their adoption (npm downloads, GitHub activity)
303
+ - Watch for acquisition or shutdown signals
304
+ - Consider Coinbase CDP as the ecosystem-aligned alternative (same company behind x402)
305
+
306
+ ## Code References
307
+
308
+ | File | Description |
309
+ |------|-------------|
310
+ | `src/x402/client.ts` (PR #108) | Core payment client — where the signer is created |
311
+ | `src/x402/config.ts` (PR #108) | Config loading — where new env vars would be added |
312
+ | `src/x402/spending-tracker.ts` (PR #108) | Spending limits — unchanged by signer swap |
313
+ | `@x402/evm` (npm) | `ClientEvmSigner` interface and `toClientEvmSigner` helper |
314
+ | `@openfort/openfort-node` (npm) | Openfort Node SDK with `accounts.evm.backend.create()` |
315
+
316
+ ## Historical Context
317
+
318
+ - Previous x402 research: `/workspace/shared/thoughts/16990304-76e4-4017-b991-f3e37b34cf73/research/2026-02-28-x402-payments-protocol.md`
319
+ - x402 uses EIP-3009 (gasless USDC transfers via EIP-712 typed data signatures)
320
+ - The x402 SDK is intentionally wallet-agnostic — any object with `address` + `signTypedData` works
321
+
322
+ ## Open Questions
323
+
324
+ - **Wallet persistence:** Does `openfort.accounts.evm.backend.create()` create a new wallet each time, or can you retrieve an existing one by ID? For agent-swarm, we need the same wallet address across restarts.
325
+ - **Coinbase CDP alternative:** Should we also evaluate Coinbase's own MPC wallet as a signer? It would be more ecosystem-aligned with x402.
326
+ - **Multi-agent wallets:** Should each agent have its own wallet (better isolation) or share one (simpler treasury management)?
327
+ - **Key export:** Openfort supports private key export — should we document this as an escape hatch?
328
+
329
+ ## Hands-on Testing Results
330
+
331
+ **Date**: 2026-02-28
332
+ **Tested by**: Researcher (agent-swarm worker)
333
+ **SDK Version**: \`@openfort/openfort-node\` v0.9.1
334
+ **API Key Type**: Test (\`sk_test_...\`)
335
+ **Environment**: Node.js v22.22.0
336
+
337
+ ### Setup
338
+
339
+ Two secrets were configured in the swarm's global config:
340
+ - \`OPENFORT_TEST_SECRET_KEY\` — Test API secret key (\`sk_test_...\`)
341
+ - \`OPENFORT_TEST_WALLET_PRIVATE_KEY\` — ECDSA P-256 private key in base64-encoded DER format
342
+
343
+ **Key discovery:** The \`walletSecret\` parameter in the SDK constructor is NOT a simple string or hex key — it's a **P-256 (ES256) ECDSA private key in PKCS#8 DER format, base64-encoded**. The SDK uses it to generate JWT tokens (with \`ES256\` algorithm) that are sent as the \`X-Wallet-Auth\` HTTP header on backend wallet API calls. This provides request-level authentication: each JWT includes the request method, path, and a hash of the request body.
344
+
345
+ ### Test Results Summary
346
+
347
+ **17 tests executed, 16 passed, 1 expected failure** (error handling test).
348
+
349
+ | # | Test | Result | Duration | Notes |
350
+ |---|------|--------|----------|-------|
351
+ | 1 | SDK Initialization | PASS | 1ms | Instantaneous, no API call |
352
+ | 2 | List Existing Wallets | PASS | 257ms | First API call (cold start) |
353
+ | 3 | Create Backend Wallet | PASS | 696ms | First wallet creation (cold start) |
354
+ | 4 | Get Wallet by ID | PASS | 101ms | Fast lookup |
355
+ | 5 | Get Wallet by Address | PASS | 110ms | Uses list API internally |
356
+ | 6 | Create Second Wallet | PASS | 222ms | Subsequent creates are faster |
357
+ | 7 | Sign Message | PASS | 251ms | Includes get + sign (two API calls) |
358
+ | 8 | **Sign EIP-712 Typed Data** | **PASS** | **251ms** | **x402 critical path — works** |
359
+ | 9 | Sign Raw Hash | PASS | 247ms | Includes get + sign |
360
+ | 10 | signMessage Latency (5x) | PASS | 799ms total | **Avg 140ms** (128-145ms range) |
361
+ | 11 | signTypedData Latency (5x) | PASS | 742ms total | **Avg 130ms** (120-143ms range) |
362
+ | 12 | Export Private Key | PASS | 245ms | Returns 64-char hex (32 bytes) |
363
+ | 13 | List All Wallets | PASS | 101ms | Pagination works |
364
+ | 14 | Delete Wallet | PASS | 122ms | Clean deletion |
365
+ | 15 | V2 Accounts API | PASS | 121ms | Alternative list endpoint |
366
+ | 16 | Error: Bad Wallet ID | FAIL (expected) | 77ms | Clear error message |
367
+ | 17 | Wallet Persistence | PASS | 411ms | Create → Get → Same address |
368
+
369
+ ### x402 Compatibility: Verified
370
+
371
+ **This is the most important finding.** The Openfort backend wallet signature was **verified** using viem's \`verifyTypedData()\` (which internally uses \`ecrecover\`). This proves:
372
+
373
+ 1. Openfort backend wallets produce **standard ECDSA signatures** (not EIP-1271 smart contract signatures)
374
+ 2. The signatures are **65 bytes** (r + s + v), as expected by EIP-3009
375
+ 3. The \`signTypedData()\` method correctly handles EIP-712 structured data
376
+ 4. A minimal \`ClientEvmSigner\` wrapper works perfectly with the x402 interface:
377
+
378
+ \`\`\`typescript
379
+ const clientEvmSigner: ClientEvmSigner = {
380
+ address: account.address,
381
+ signTypedData: async (msg) => {
382
+ return account.signTypedData({
383
+ domain: msg.domain,
384
+ types: msg.types,
385
+ primaryType: msg.primaryType,
386
+ message: msg.message,
387
+ });
388
+ },
389
+ };
390
+ \`\`\`
391
+
392
+ **Verification output:**
393
+ \`\`\`
394
+ Signature: 0xbaf71652df562e10...efd7eb68e01
395
+ Verifying with viem (ecrecover)... ✓ VALID
396
+ ClientEvmSigner wrapper... ✓ VALID
397
+ \`\`\`
398
+
399
+ ### Wallet Secret Deep Dive
400
+
401
+ The SDK's wallet authentication mechanism is more sophisticated than documented:
402
+
403
+ 1. The \`walletSecret\` is a **PKCS#8-encoded ECDSA P-256 private key** (base64 of the DER bytes)
404
+ 2. On every backend wallet mutation (POST/PUT/DELETE to \`/accounts/backend/*\`), the SDK:
405
+ - Generates a JWT with \`ES256\` algorithm
406
+ - Claims include: \`uri\` (method + path), \`iat\`, \`nbf\`, \`jti\` (nonce), and \`reqHash\` (SHA-256 of sorted request body)
407
+ - Signs it with the wallet secret key
408
+ - Attaches it as \`X-Wallet-Auth\` header
409
+ 3. This means **each API request is individually authenticated** — stealing the API key alone is insufficient to perform wallet operations
410
+ 4. The wallet secret can be generated by the Openfort dashboard or via their CLI
411
+
412
+ ### Wallet Persistence: Confirmed
413
+
414
+ **Critical question answered:** Wallets persist indefinitely. \`create()\` always generates a new wallet; you retrieve existing ones via \`get({ id })\` or \`get({ address })\` or \`list()\`. For the agent-swarm use case, the workflow would be:
415
+
416
+ \`\`\`typescript
417
+ // On agent startup:
418
+ const wallets = await openfort.accounts.evm.backend.list({ limit: 1 });
419
+ const account = wallets.accounts.length > 0
420
+ ? wallets.accounts[0]
421
+ : await openfort.accounts.evm.backend.create();
422
+ \`\`\`
423
+
424
+ Or better, store the wallet ID in agent config and use \`get({ id })\` directly.
425
+
426
+ ### Latency Analysis
427
+
428
+ | Operation | Avg Latency | Notes |
429
+ |-----------|------------|-------|
430
+ | \`signMessage\` | **140ms** | 128-145ms range, very consistent |
431
+ | \`signTypedData\` | **130ms** | 120-143ms range — the x402 path |
432
+ | \`create\` wallet | **222-696ms** | First call is cold (~700ms), subsequent ~220ms |
433
+ | \`get\` wallet | **101-110ms** | Fast retrieval |
434
+ | \`list\` wallets | **101ms** | Pagination supported |
435
+ | \`delete\` wallet | **122ms** | Clean cleanup |
436
+ | \`export\` key | **245ms** | RSA encrypt/decrypt overhead |
437
+
438
+ **For x402 payments:** A single \`signTypedData\` call adds ~130ms to each payment. The x402 flow already involves HTTP requests to the facilitator, so this is negligible in practice. Total payment flow: agent → x402 SDK → signTypedData (130ms) → facilitator → blockchain.
439
+
440
+ ### Private Key Export
441
+
442
+ The SDK supports exporting the raw private key from a backend wallet:
443
+ - Returned as a **64-character hex string** (32 bytes, no \`0x\` prefix)
444
+ - Uses RSA-OAEP encryption for transport: SDK generates ephemeral RSA key pair, sends public key to Openfort, Openfort encrypts the private key, SDK decrypts locally
445
+ - This serves as an **escape hatch** if you need to migrate away from Openfort
446
+
447
+ ### Cost Implications
448
+
449
+ With 17 tests executed, each involving 1-6 API calls, we consumed ~35-40 operations. The free tier allows 2,000 operations/month. For the agent-swarm:
450
+ - Each x402 payment = **1 signTypedData call** = 1 operation
451
+ - Agent startup = **1 list or get call** = 1 operation
452
+ - At the free tier: **~2,000 payments/month** before charges
453
+ - At Growth (\$99/mo): **~25,000 payments/month**
454
+
455
+ ### SDK Quirks & Observations
456
+
457
+ 1. **No \`0x\` prefix on exported keys:** The \`export()\` method returns a bare hex string without \`0x\` prefix. When importing or using with viem, you need to add \`0x\` yourself.
458
+
459
+ 2. **\`get()\` by address uses list internally:** The SDK calls \`listBackendWallets({ address, limit: 1 })\` rather than a dedicated endpoint. This is fine but means address lookups are slightly slower than ID lookups.
460
+
461
+ 3. **\`walletSecret\` is required for all mutations:** Without it, any POST/PUT/DELETE to backend wallet endpoints throws \`MissingWalletSecretError\`. Read-only operations (list, get) work without it.
462
+
463
+ 4. **Error messages are clear:** Invalid wallet IDs return descriptive errors like "Request has invalid parameters. Invalid acc: 'acc_nonexistent_12345'."
464
+
465
+ 5. **BigInt support works:** The SDK handles \`BigInt\` values in EIP-712 typed data correctly (via viem's \`hashTypedData\`).
466
+
467
+ 6. **No rate limiting observed:** 17 tests with ~40 API calls in rapid succession — no throttling or 429 responses.
468
+
469
+ 7. **SDK uses global Axios instance:** The \`configure()\` function sets up module-level configuration. This means you cannot have two Openfort instances with different API keys in the same process. Not a problem for our use case (one agent = one key).
470
+
471
+ ### Updated Recommendation
472
+
473
+ Based on hands-on testing, I **strengthen the recommendation** for Openfort integration:
474
+
475
+ 1. **The integration works exactly as designed.** Zero surprises. The \`ClientEvmSigner\` adapter is 7 lines of code.
476
+ 2. **Latency is acceptable.** 130ms for signTypedData is negligible in the context of HTTP-based x402 payments.
477
+ 3. **Wallet persistence is confirmed.** Agents can reliably retrieve the same wallet across restarts.
478
+ 4. **The security model is solid.** Per-request JWT authentication with the wallet secret key means the API key alone cannot sign transactions.
479
+ 5. **Private key export provides an escape hatch.** No vendor lock-in risk.
480
+
481
+ **Revised implementation plan:**
482
+ - Use Openfort as the **default** signer (not opt-in), with raw viem as the fallback for development/testing
483
+ - Store wallet ID in per-agent config (via swarm config system)
484
+ - Add \`OPENFORT_API_KEY\` and \`OPENFORT_WALLET_SECRET\` to the swarm's env vars
485
+ - Use \`X402_SIGNER_TYPE=viem\` as the escape hatch (not the default)
486
+
487
+
488
+ ## Transaction Creation Testing Results
489
+
490
+ **Date**: 2026-02-28
491
+ **Tested by**: Researcher (agent-swarm worker)
492
+ **SDK Version**: \`@openfort/openfort-node\` v0.9.1
493
+ **Chain**: Base Sepolia (chainId: 84532)
494
+
495
+ ### Overview
496
+
497
+ Taras requested testing of actual transaction creation via Openfort. The SDK provides **two distinct mechanisms**:
498
+
499
+ 1. **\`account.signTransaction()\`** — Signs a raw transaction (EIP-1559 or legacy) but does NOT broadcast. The caller must broadcast via a JSON-RPC provider (e.g., viem's \`sendRawTransaction\`).
500
+ 2. **\`transactionIntents.create()\`** — Openfort's high-level API that handles account abstraction (ERC-4337), gas sponsorship, bundling, and broadcasting. Requires a Player + smart account.
501
+
502
+ **There is no \`sendTransaction()\` method in the SDK.**
503
+
504
+ ### Test Results
505
+
506
+ | # | Test | Result | Duration | Notes |
507
+ |---|------|--------|----------|-------|
508
+ | 1a | Sign EIP-1559 Tx (self-transfer) | PASS | 703ms | Signed successfully, ready to broadcast |
509
+ | 1b | Broadcast Self-Transfer | SKIP | — | Wallet has 0 ETH for gas |
510
+ | 2a | Create Player | PASS | 109ms | Players are Openfort's user model |
511
+ | 2b | Create Policy + Fee Sponsorship | PASS | 189ms | Gas sponsorship setup |
512
+ | 2c | Create Sponsored Transaction Intent | PASS | 1280ms | ERC-4337 v6, returns \`nextAction: sign_with_wallet\` |
513
+ | 2d | Sign UserOperation Hash | PASS | 170ms | Backend wallet signs the UserOp hash |
514
+ | 2e | Submit Signature | PASS | 1108ms | Signature accepted by Openfort |
515
+ | 2f | Final Transaction State | PASS | 5186ms | Status 0, tx accepted but not confirmed on-chain |
516
+ | 3 | List Transaction Intents | PASS | 4371ms | All intents listed correctly |
517
+
518
+ **8/9 passed, 1 skipped** (no ETH for gas on the EOA).
519
+
520
+ ### Flow 1: signTransaction (Direct EOA)
521
+
522
+ This is the simpler approach — sign a standard Ethereum transaction and broadcast it yourself.
523
+
524
+ \`\`\`typescript
525
+ // Sign an EIP-1559 transaction
526
+ const tx = {
527
+ to: recipientAddress,
528
+ value: 0n,
529
+ nonce,
530
+ gas: 21000n,
531
+ maxFeePerGas: baseFee * 2n,
532
+ maxPriorityFeePerGas: 1000000n,
533
+ chainId: 84532,
534
+ type: "eip1559",
535
+ };
536
+
537
+ const signedTx = await account.signTransaction(tx);
538
+ // signedTx is a fully serialized signed transaction hex (0x-prefixed)
539
+
540
+ // Broadcast via viem
541
+ const txHash = await publicClient.sendRawTransaction({ serializedTransaction: signedTx });
542
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
543
+ \`\`\`
544
+
545
+ **What works:**
546
+ - EIP-1559 (Type 2) transactions: sign perfectly ✓
547
+ - Contract calldata: sign perfectly ✓ (tested with ERC-20 \`transfer\` calldata)
548
+ - Signed transaction is standard RLP-encoded — compatible with any JSON-RPC provider
549
+
550
+ **What doesn't work:**
551
+ - Legacy transactions with mixed \`number\`/\`BigInt\` nonce from viem's \`getTransactionCount()\` — throws "Cannot mix BigInt and other types". **Workaround:** Use EIP-1559 transactions (always use BigInt for all numeric fields) or explicitly convert nonce to \`BigInt(nonce)\`.
552
+
553
+ **Latency:** ~200-400ms per signTransaction call (includes Openfort API signing + viem serialization).
554
+
555
+ **Limitation:** Requires ETH in the wallet for gas. For testnet, you'd need to use a faucet to fund the wallet. For mainnet, you'd need to transfer ETH to the wallet address.
556
+
557
+ ### Flow 2: transactionIntents (Smart Account + Gas Sponsorship)
558
+
559
+ This is Openfort's managed transaction pipeline — uses ERC-4337 account abstraction.
560
+
561
+ **Prerequisites:**
562
+ 1. Create a **Player** (\`openfort.players.create()\`)
563
+ 2. Create a **Policy** with gas sponsorship rules (\`openfort.policies.create()\`)
564
+ 3. Create a **Fee Sponsorship** linking to the policy (\`openfort.feeSponsorship.create()\`)
565
+
566
+ **Full flow:**
567
+ \`\`\`typescript
568
+ // 1. Create player (auto-creates smart account on first tx)
569
+ const player = await openfort.players.create({ name: "my-agent" });
570
+
571
+ // 2. Create policy + sponsorship (one-time setup)
572
+ const policy = await openfort.policies.create({
573
+ scope: "project",
574
+ rules: [{ action: "accept", operation: "sponsorEvmTransaction",
575
+ criteria: [{ type: "evmNetwork", operator: "in", chainIds: [84532] }] }],
576
+ });
577
+ const sponsorship = await openfort.feeSponsorship.create({
578
+ name: "agent-gas-sponsor",
579
+ strategy: { sponsorSchema: "pay_for_user" },
580
+ policyId: policy.id,
581
+ });
582
+
583
+ // 3. Create transaction intent
584
+ const txIntent = await openfort.transactionIntents.create({
585
+ chainId: 84532,
586
+ player: player.id,
587
+ externalOwnerAddress: backendWallet.address, // backend wallet as owner
588
+ policy: sponsorship.id,
589
+ interactions: [{ to: "0x...", value: "0" }],
590
+ });
591
+
592
+ // 4. If nextAction.type === "sign_with_wallet", sign the UserOp hash
593
+ if (txIntent.nextAction?.payload?.userOperationHash) {
594
+ const signature = await backendWallet.sign({
595
+ hash: txIntent.nextAction.payload.userOperationHash,
596
+ });
597
+
598
+ // 5. Submit signature
599
+ const result = await openfort.transactionIntents.signature(txIntent.id, {
600
+ signature,
601
+ optimistic: true,
602
+ });
603
+ }
604
+ \`\`\`
605
+
606
+ **What works:**
607
+ - Player creation ✓
608
+ - Policy + Fee Sponsorship creation ✓
609
+ - Transaction intent creation with \`abstractionType: "accountAbstractionV6"\` ✓
610
+ - Returns \`nextAction: sign_with_wallet\` with \`userOperationHash\` ✓
611
+ - Backend wallet signs the UserOp hash ✓
612
+ - Signature submission accepted ✓
613
+
614
+ **What didn't fully work:**
615
+ - The transaction stayed at status 0 with no on-chain transaction hash. This likely means:
616
+ - The Openfort paymaster on Base Sepolia testnet may not be funded
617
+ - Or the 0-value transfer to \`address(1)\` may not pass paymaster validation
618
+ - The UserOp was accepted by Openfort but may have been rejected by the bundler
619
+
620
+ **Critical finding: Backend wallets (EOAs) cannot directly use transactionIntents.** The API returns "Account type not supported" when you pass a backend wallet ID. You MUST create a Player, which auto-creates a smart account. The backend wallet serves as the **owner** of the smart account (via \`externalOwnerAddress\`).
621
+
622
+ ### Flow 3: What's NOT relevant for x402
623
+
624
+ **For x402 payments, we don't need transactionIntents at all.** The x402 protocol uses EIP-3009 \`transferWithAuthorization\` — a gasless off-chain signature. The agent just signs EIP-712 typed data using \`signTypedData()\`, and the x402 facilitator handles the on-chain transaction. The agent never submits a transaction.
625
+
626
+ \`signTypedData()\` was already verified in the previous testing round (130ms avg, ecrecover-compatible).
627
+
628
+ ### SDK Architecture: Two Transaction Paths
629
+
630
+ | Feature | \`signTransaction()\` | \`transactionIntents\` |
631
+ |---------|---------------------|----------------------|
632
+ | **What it does** | Signs a raw tx, returns signed hex | Full lifecycle: bundle, sponsor, broadcast |
633
+ | **Account type** | Backend wallet (EOA) ✓ | Smart account (Player) only |
634
+ | **Gas** | Caller pays (needs ETH) | Can be sponsored (Openfort paymaster) |
635
+ | **Broadcasting** | Caller broadcasts via JSON-RPC | Openfort handles via bundler |
636
+ | **Abstraction** | None (standard EVM tx) | ERC-4337 v6 |
637
+ | **Use for x402** | Not needed | Not needed |
638
+ | **Use for funding** | Yes (sign + broadcast) | Possible but complex |
639
+
640
+ ### API Quirks Discovered
641
+
642
+ 1. **\`policies.delete()\` doesn't work with \`ply_\` IDs:** The create API returns IDs like \`ply_...\` but delete seems to expect a different format. Deleting via the fee sponsorship works fine though.
643
+
644
+ 2. **\`transactionIntents.list()\` is slow:** ~4 seconds. This seems to be a backend issue rather than pagination.
645
+
646
+ 3. **EIP-7702 not available on Base Sepolia:** Attempting to upgrade a backend wallet to a "Delegated Account" with \`implementationType: "EIP7702"\` fails with "not available in chainId '84532'".
647
+
648
+ 4. **Contract registration without ABI works:** You can register a contract address without providing an ABI. However, if you then try to use raw \`data\` in an interaction with that contract, Openfort tries to parse it against the (empty) ABI and fails.
649
+
650
+ 5. **Legacy tx BigInt issue:** viem's \`getTransactionCount()\` returns a \`number\`, but \`getGasPrice()\` returns a \`BigInt\`. Mixing them in a legacy transaction object causes "Cannot mix BigInt and other types". EIP-1559 transactions avoid this because all fields accept BigInt natively.
651
+
652
+ ### Relevance to x402 Implementation
653
+
654
+ **Bottom line for PR #108:**
655
+ - **\`signTypedData()\` is all we need for x402 payments** (already verified, 130ms latency)
656
+ - \`signTransaction()\` is available as a bonus for agents that need to send ETH or interact with contracts directly
657
+ - \`transactionIntents\` is the advanced path for gas-sponsored smart account operations — not needed for x402 but could be useful for future agent capabilities
658
+
659
+ **The recommendation stands:** Openfort backend wallets are fully compatible with x402. The \`ClientEvmSigner\` adapter remains 7 lines of code.
660
+
661
+
662
+ ## Sources
663
+
664
+ - [Openfort Homepage](https://www.openfort.io/)
665
+ - [Openfort Pricing](https://www.openfort.io/pricing)
666
+ - [Openfort Viem Integration Docs](https://www.openfort.io/docs/products/server/viem-integration)
667
+ - [Openfort Backend Wallets Blog](https://www.openfort.io/blog/backend-wallets)
668
+ - [Openfort Node SDK (GitHub)](https://github.com/openfort-xyz/openfort-node)
669
+ - [@openfort/openfort-node (npm)](https://www.npmjs.com/package/@openfort/openfort-node)
670
+ - [OpenSigner (GitHub)](https://github.com/openfort-xyz/opensigner)
671
+ - [PR #108 — desplega-ai/agent-swarm](https://github.com/desplega-ai/agent-swarm/pull/108)
672
+ - [x402 Protocol (GitHub)](https://github.com/coinbase/x402)
673
+ - [x402 EVM Exact Scheme Spec](https://github.com/coinbase/x402/blob/main/specs/schemes/exact/scheme_exact_evm.md)
674
+ - [EIP-3009: Transfer With Authorization](https://eips.ethereum.org/EIPS/eip-3009)
675
+ - [EIP-712: Typed Structured Data Hashing](https://eips.ethereum.org/EIPS/eip-712)
676
+ - [x402 Coinbase Developer Docs](https://docs.cdp.coinbase.com/x402/welcome)
677
+ - [@x402/evm (npm)](https://www.npmjs.com/package/@x402/evm)
678
+ - [Openfort AI Agent Solutions](https://www.openfort.io/solutions/ai-agents)
679
+ - [Tiger Research: Openfort Report](https://reports.tiger-research.com/p/openfort-web3-game-eng)