@openhands/agent-canvas 1.18.0 → 1.20.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 (420) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/acp-providers-DOKcGeaV.js +1 -0
  4. package/build/assets/active-backend-context-BETEdaJl.js +2 -0
  5. package/build/assets/{agent-context-settings-D3peZkjX.js → agent-context-settings-Dir0loAn.js} +1 -1
  6. package/build/assets/{agent-profiles-service.api-DkeZaqIl.js → agent-profiles-service.api-CiMVQAIT.js} +1 -1
  7. package/build/assets/{agent-profiles-settings-7yMWYjGF.js → agent-profiles-settings-CT5owzRT.js} +1 -1
  8. package/build/assets/agent-server-conversation-service.api-BtOlitCD.js +88 -0
  9. package/build/assets/agent-settings-BnzyTgCb.js +2 -0
  10. package/build/assets/agent-settings-CeXj3xK-.js +1 -0
  11. package/build/assets/{alert-banner-eYyqvHL3.js → alert-banner-Ccx1Du6n.js} +1 -1
  12. package/build/assets/{api-key-entry-screen-CCBvBD8u.js → api-key-entry-screen-DXIuzBjY.js} +1 -1
  13. package/build/assets/{app-settings-BtYDs-Be.js → app-settings-DkIJVTKL.js} +1 -1
  14. package/build/assets/automation-detail-CF2SweVs.js +3 -0
  15. package/build/assets/automation-disabled-reason-QFtMrdOr.js +1 -0
  16. package/build/assets/{automation-export-BJsfi7n2.js → automation-export-CkvehhPF.js} +1 -1
  17. package/build/assets/{automation-git-sync-B7o_Nbl-.js → automation-git-sync-di4tBAyZ.js} +1 -1
  18. package/build/assets/automation-setup-route-FERj7WEe.js +3 -0
  19. package/build/assets/{automation-templates-Bb98r-kx.js → automation-templates-DlaCRvD-.js} +1 -1
  20. package/build/assets/automations-list-yK7ETmYP.js +1 -0
  21. package/build/assets/{back-nav-button-B2yBiVMB.js → back-nav-button-oDvIxpQ5.js} +1 -1
  22. package/build/assets/backend-form-modal-DzYf_arO.js +1 -0
  23. package/build/assets/{backend-synced-settings-badge-DLEp6cq7.js → backend-synced-settings-badge-DXDDHWX4.js} +1 -1
  24. package/build/assets/{badge-ehL-kgeO.js → badge-CDHZEVeN.js} +1 -1
  25. package/build/assets/{base-modal-C1a0TsSx.js → base-modal-CZq4kB_H.js} +1 -1
  26. package/build/assets/{brand-button-CUMfjb99.js → brand-button-CGUwj6zK.js} +1 -1
  27. package/build/assets/{browser-SE24Tk8g.js → browser-kY6jN61T.js} +2 -2
  28. package/build/assets/{browser-tab-HjJxHA0V.js → browser-tab-DFyZXsnB.js} +1 -1
  29. package/build/assets/{canvas-extension-page-BsUGBb1T.js → canvas-extension-page-DsGq1DtT.js} +1 -1
  30. package/build/assets/{canvas-extensions-C9Tm6s_E.js → canvas-extensions-Cb2Z0Hdc.js} +1 -1
  31. package/build/assets/{canvas-extensions-runtime-B8kxM4rO.js → canvas-extensions-runtime-DS6eT4nK.js} +1 -1
  32. package/build/assets/{chat-send-button-CGvc2wpE.js → chat-send-button-B6aVaD9V.js} +1 -1
  33. package/build/assets/{circle-plus-check-toggle-BDX_ctNs.js → circle-plus-check-toggle-ZOXpJ3I2.js} +1 -1
  34. package/build/assets/{cloud-funnel-analytics-D5uJ_4JE.js → cloud-funnel-analytics-BH_zxjiO.js} +1 -1
  35. package/build/assets/{cog-CAEugqtV.js → cog-DVZT1f0s.js} +1 -1
  36. package/build/assets/{command-menu-CQxs4mtX.js → command-menu-ImeHQ6c2.js} +1 -1
  37. package/build/assets/{commits-tab-D0xgjipP.js → commits-tab-B5SUF66c.js} +1 -1
  38. package/build/assets/{condenser-settings-D63NJRBT.js → condenser-settings-BlGOXEXM.js} +1 -1
  39. package/build/assets/{confirmation-modal-78sd9Vny.js → confirmation-modal-oN1EId79.js} +1 -1
  40. package/build/assets/{context-menu-list-item-Cm7-7Y-7.js → context-menu-list-item-DIm5xQg6.js} +1 -1
  41. package/build/assets/{conversation-B_nweu5p.js → conversation-9a53tdbO.js} +4 -4
  42. package/build/assets/conversation-XRsI28ZM.js +1 -0
  43. package/build/assets/conversation-panel-XRsI28ZM.js +1 -0
  44. package/build/assets/{conversation-state-store-9D_3P7q4.js → conversation-state-store-Br-eE-gg.js} +1 -1
  45. package/build/assets/{conversation-tab-empty-state-B3dpJXX0.js → conversation-tab-empty-state-BT1GrnKP.js} +1 -1
  46. package/build/assets/{copy-to-clipboard-button-B1ljgNxO.js → copy-to-clipboard-button-CvTHqY13.js} +1 -1
  47. package/build/assets/{device-verify-D5QRIS_x.js → device-verify-DX0xdNjo.js} +1 -1
  48. package/build/assets/{dropdown-classes-BGvOvW2_.js → dropdown-classes-DyyMaaXl.js} +1 -1
  49. package/build/assets/edit-automation-modal-bfD-5NIc.js +1 -0
  50. package/build/assets/empty-state-B5advKVW.js +1 -0
  51. package/build/assets/{entry.client-BMafTpjO.js → entry.client-D_2gnSyB.js} +2 -2
  52. package/build/assets/{enum-filter-dropdown-UNaom12H.js → enum-filter-dropdown-VAJp5mqh.js} +1 -1
  53. package/build/assets/{environment-switch-overlay-COibRUA-.js → environment-switch-overlay-C7x_yhEs.js} +1 -1
  54. package/build/assets/{error-state-Cf8LRuuY.js → error-state-BgYl7YeB.js} +1 -1
  55. package/build/assets/{extensions-hub-C_6ahIua.js → extensions-hub-DjhOed1I.js} +1 -1
  56. package/build/assets/{extensions-navigation-C5GfpzFe.js → extensions-navigation-Di-J2KUR.js} +1 -1
  57. package/build/assets/{files-tab-D5PPIWI1.js → files-tab-BNDp3e_x.js} +1 -1
  58. package/build/assets/{form-control-classes-Dbq-7YP_.js → form-control-classes-BVI_szaj.js} +1 -1
  59. package/build/assets/{get-git-path-jU2zjqIB.js → get-git-path-DOe6PM_a.js} +1 -1
  60. package/build/assets/git-repo-dropdown-1fZGYtYm.js +1 -0
  61. package/build/assets/{git-repo-dropdown-uxlFw2gn.js → git-repo-dropdown-DNlinQ7r.js} +1 -1
  62. package/build/assets/{highlighted-source-view-C7pAXrT0.js → highlighted-source-view-DPerL6tF.js} +1 -1
  63. package/build/assets/home-4lyLzYjG.js +1 -0
  64. package/build/assets/home-BGaB0EeK.js +1 -0
  65. package/build/assets/home-automation-run-tooltip-v5n7zXR0.js +1 -0
  66. package/build/assets/{home-store-DCbei3DX.js → home-store-roz1x6D5.js} +1 -1
  67. package/build/assets/{hooks-service-Dnmhqc0Z.js → hooks-service-tzRqtAlm.js} +1 -1
  68. package/build/assets/index-home-6Y_Y7kOo.js +1 -0
  69. package/build/assets/{install-server-modal-B81I-5OE.js → install-server-modal-DkMCfj0J.js} +1 -1
  70. package/build/assets/{key-O84CMFHb.js → key-DpfBWQbk.js} +1 -1
  71. package/build/assets/{launch-ZLxI4opd.js → launch-TrnYlJe6.js} +1 -1
  72. package/build/assets/link-external-B4gx3EeM.js +1 -0
  73. package/build/assets/llm-not-configured-banner-BdjItKQR.js +27 -0
  74. package/build/assets/{llm-settings-CODhjQzy.js → llm-settings-CUgt39uu.js} +1 -1
  75. package/build/assets/llm-settings-DEfw-fUJ.js +1 -0
  76. package/build/assets/{llm-subscription-service-CgIDc38n.js → llm-subscription-service-LGYVzyAc.js} +1 -1
  77. package/build/assets/{loading-spinner-BeLV0IXf.js → loading-spinner-BJc2J0Dw.js} +1 -1
  78. package/build/assets/{manage-backends-modal-cMXqCb-B.js → manage-backends-modal-CIjk0B2H.js} +1 -1
  79. package/build/assets/manifest-23d79467.js +1 -0
  80. package/build/assets/{manifest-subpage-layout-CVZgVKoY.js → manifest-subpage-layout-DGYRoP_8.js} +1 -1
  81. package/build/assets/{markdown-renderer-DyFl9-mL.js → markdown-renderer-DRpwRlNm.js} +1 -1
  82. package/build/assets/mcp-CoUOIGBF.js +1 -0
  83. package/build/assets/mcp-installed-servers-BW51n6PC.js +1 -0
  84. package/build/assets/mcp-marketplace-utils-BwEnDYqm.js +1 -0
  85. package/build/assets/mcp-page-hZ4aJjj_.js +9 -0
  86. package/build/assets/{messages-Bk1xhbU2.js → messages-WUb9Yh-p.js} +4 -4
  87. package/build/assets/{modal-body-C24WsdFb.js → modal-body-B_95ci1c.js} +1 -1
  88. package/build/assets/{modal-classes-B0b9eiL8.js → modal-classes-BPcBCWVj.js} +1 -1
  89. package/build/assets/{modal-close-button-DfqfB2Nj.js → modal-close-button-Cq3dma5u.js} +1 -1
  90. package/build/assets/onboarding-Cc4Av7bi.js +1 -0
  91. package/build/assets/{onboarding-modal-BT3Gx_sZ.js → onboarding-modal-DCFD4Dsa.js} +1 -1
  92. package/build/assets/{organization-service.api-B5CvmnYQ.js → organization-service.api-zhHpQU0t.js} +1 -1
  93. package/build/assets/parse-git-remote-url-BG8pcKL8.js +1 -0
  94. package/build/assets/{planner-tab-CstoOlAB.js → planner-tab-yISBVUKu.js} +1 -1
  95. package/build/assets/{plugins-management-service-5rqVPEGN.js → plugins-management-service-2oP6_tWr.js} +1 -1
  96. package/build/assets/{profiles-service.api-D1XKMgr0.js → profiles-service.api-B5thiTI3.js} +1 -1
  97. package/build/assets/{providers-XmZ9HM4Q.js → providers-Co9PsD0s.js} +1 -1
  98. package/build/assets/{proxy-XP6U1Dhv.js → proxy-BCCQUna8.js} +1 -1
  99. package/build/assets/recommended-automations-launcher-D1Do753p.js +1 -0
  100. package/build/assets/root-D1y82Lhg.js +2 -0
  101. package/build/assets/{root-layout-DUquNZTU.js → root-layout-cQTYEG2w.js} +2 -2
  102. package/build/assets/root-sEWn3ha1.css +1 -0
  103. package/build/assets/{schema-field-Y3F8JvXd.js → schema-field-DSi0d7a8.js} +1 -1
  104. package/build/assets/{sdk-section-page-CNZTLwH9.js → sdk-section-page-DCoI2dtd.js} +1 -1
  105. package/build/assets/{secret-form-9-BoGA40.js → secret-form-BDvzojzN.js} +1 -1
  106. package/build/assets/{secrets-service-BOIsfD9j.js → secrets-service-C3CNNEpY.js} +1 -1
  107. package/build/assets/{secrets-settings-CBJgFr42.js → secrets-settings-BKqfYQt5.js} +1 -1
  108. package/build/assets/{settings-D4hdToD4.js → settings-C8ZLONyx.js} +1 -1
  109. package/build/assets/{settings-dropdown-input-DBvsZ7-Q.js → settings-dropdown-input-Df_HXRk4.js} +1 -1
  110. package/build/assets/{settings-index-DeQphyBK.js → settings-index-BWvlGHg3.js} +1 -1
  111. package/build/assets/{settings-input-dVuzapBA.js → settings-input-B3i5U9GL.js} +1 -1
  112. package/build/assets/{settings-list-classes-DhAPuXm6.js → settings-list-classes-DbqcSiVW.js} +1 -1
  113. package/build/assets/{settings-modal-tHiJ8iYV.js → settings-modal-DHKJSBPL.js} +1 -1
  114. package/build/assets/{settings-nav-GAQjW1a-.js → settings-nav-BThjwLWD.js} +1 -1
  115. package/build/assets/{settings-service.api-C1vZH9Vh.js → settings-service.api-CYBTLGOd.js} +1 -1
  116. package/build/assets/{settings-switch-DDd1cQ8t.js → settings-switch-CI93Iozg.js} +1 -1
  117. package/build/assets/{shared-conversation-Cyg7m7ns.js → shared-conversation-C7OILS-U.js} +1 -1
  118. package/build/assets/{sidebar-layout-DH0E-5KW.js → sidebar-layout-Csb6Geq0.js} +1 -1
  119. package/build/assets/{sidebar-mobile-menu-toggle-CQ4iky__.js → sidebar-mobile-menu-toggle-B2xwXm4s.js} +1 -1
  120. package/build/assets/{sidebar-nav-link-oLQiKUBu.js → sidebar-nav-link-Xv7QEMVS.js} +1 -1
  121. package/build/assets/{sidebar-onboarding-checklist-storage-TfvNNnnr.js → sidebar-onboarding-checklist-storage-_zxMqHS0.js} +1 -1
  122. package/build/assets/{skill-card-pill-row-DfjIfj0K.js → skill-card-pill-row-CxOFySng.js} +1 -1
  123. package/build/assets/{skill-enablement-DXeaImBz.js → skill-enablement-BBKya60C.js} +1 -1
  124. package/build/assets/{skill-filter-DsNLmn76.js → skill-filter-BvtbD--b.js} +1 -1
  125. package/build/assets/{skill-icon-badge-0MK_68Nc.js → skill-icon-badge-CVxE42yg.js} +1 -1
  126. package/build/assets/{skill-scope-BE-H9TSZ.js → skill-scope-C0NxJnpT.js} +1 -1
  127. package/build/assets/{skills-plugins-vzSdxSk_.js → skills-plugins-BGjX4jve.js} +1 -1
  128. package/build/assets/{skills-settings-BiPOH9H9.js → skills-settings-d3ZwIjSP.js} +1 -1
  129. package/build/assets/{styled-tooltip-CejG0rqv.js → styled-tooltip-CknPQH4Y.js} +1 -1
  130. package/build/assets/{task-list-tab-OkZSqnTp.js → task-list-tab-CQisRcPh.js} +1 -1
  131. package/build/assets/{terminal-Dph60VFZ.js → terminal-Bs50gJPC.js} +1 -1
  132. package/build/assets/{toggle-switch-B2uXaAUS.js → toggle-switch-D3TBxlsc.js} +1 -1
  133. package/build/assets/trash-D1QMHInX.js +1 -0
  134. package/build/assets/{typography-DgcLGdHk.js → typography-BdAApXGl.js} +1 -1
  135. package/build/assets/{usage-tab-MCmNRAnR.js → usage-tab-ClVHAFJy.js} +1 -1
  136. package/build/assets/{use-acp-credential-form-ychoGqjC.js → use-acp-credential-form-GfqcTJl5.js} +1 -1
  137. package/build/assets/{use-activate-agent-profile-8L8Xdghy.js → use-activate-agent-profile-DO6SNPkK.js} +1 -1
  138. package/build/assets/{use-agent-profiles-Bi8hSkze.js → use-agent-profiles-YsBlt3tT.js} +1 -1
  139. package/build/assets/{use-automation-health-U99vvHxx.js → use-automation-health-CbQ9n-k7.js} +1 -1
  140. package/build/assets/{use-automation-permissions-Buus0R6h.js → use-automation-permissions-gFy-2VD0.js} +1 -1
  141. package/build/assets/{use-automations-Bq5hVuv0.js → use-automations-7_XBXHQK.js} +1 -1
  142. package/build/assets/{use-can-manage-org-profiles-MzIeEV8F.js → use-can-manage-org-profiles-Dt4YkPO7.js} +1 -1
  143. package/build/assets/{use-canvas-extensions-Ca9KoVEm.js → use-canvas-extensions-BhYQrtMK.js} +1 -1
  144. package/build/assets/{use-cloud-current-user-id-B4ZLUZSa.js → use-cloud-current-user-id-Dqw6qQUg.js} +1 -1
  145. package/build/assets/{use-config-l5tkDHyD.js → use-config-BJ_FJCjV.js} +1 -1
  146. package/build/assets/use-create-conversation-D15Px574.js +1 -0
  147. package/build/assets/use-create-secret-D_qPU88t.js +1 -0
  148. package/build/assets/{use-free-models-gCsJ5BV0.js → use-free-models-FAk2nngq.js} +1 -1
  149. package/build/assets/{use-get-secrets-CMTuWEp_.js → use-get-secrets-Pbo9jh2A.js} +1 -1
  150. package/build/assets/{use-llm-configured-Dl4zg8ht.js → use-llm-configured-DF9BYmIe.js} +1 -1
  151. package/build/assets/{use-llm-profiles-SWsuFmFu.js → use-llm-profiles-U4u1gzuk.js} +1 -1
  152. package/build/assets/use-manifest-capabilities-D81_YdAF.js +1 -0
  153. package/build/assets/{use-onboarding-completion-Xl63ZvzQ.js → use-onboarding-completion-C4W-m2Jk.js} +1 -1
  154. package/build/assets/{use-pinned-home-route-BXDIUaxQ.js → use-pinned-home-route-DByWTojw.js} +1 -1
  155. package/build/assets/{use-plugins-marketplace-BIIaPiaB.js → use-plugins-marketplace-CTRoukH0.js} +1 -1
  156. package/build/assets/{use-save-agent-profile-D-ZHHE94.js → use-save-agent-profile-xpHBxMZM.js} +1 -1
  157. package/build/assets/{use-save-settings-Dapkf4cC.js → use-save-settings-CmX41wlf.js} +1 -1
  158. package/build/assets/{use-settings-C2KKQKVC.js → use-settings-D69cw06D.js} +1 -1
  159. package/build/assets/{use-settings-nav-items-TOc0Rsfd.js → use-settings-nav-items-CVz0SnDr.js} +1 -1
  160. package/build/assets/use-tracking-BAFpgpgq.js +3 -0
  161. package/build/assets/{use-user-conversation-5UFqMoO4.js → use-user-conversation-BBDXUbOc.js} +1 -1
  162. package/build/assets/utils-CbjwNcR-.js +1 -0
  163. package/build/assets/{vendor~browser-hbU4u2Ag.js → vendor~browser-BZ-zIfb6.js} +1 -1
  164. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0x1wrp2-DvZtOcoT.js +2 -0
  165. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-CxhwKuAd.js → vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-BIjRfQ4u.js} +1 -1
  166. package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~inibp4qe-BBfdJIV9.js +48 -0
  167. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-3eJ4ExtV.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-fgzdgvrL.js} +3579 -165
  168. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~jz4f6vo2-C7HiY4Ae.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~jz4f6vo2-BqdU447s.js} +794 -227
  169. package/build/assets/{verification-settings-DdBpaVPz.js → verification-settings-BXspn27q.js} +1 -1
  170. package/build/index.html +4 -4
  171. package/build/locales/ar/openhands.json +18 -1
  172. package/build/locales/ca/openhands.json +18 -1
  173. package/build/locales/de/openhands.json +18 -1
  174. package/build/locales/en/openhands.json +18 -1
  175. package/build/locales/es/openhands.json +18 -1
  176. package/build/locales/fr/openhands.json +18 -1
  177. package/build/locales/it/openhands.json +18 -1
  178. package/build/locales/ja/openhands.json +18 -1
  179. package/build/locales/ko-KR/openhands.json +18 -1
  180. package/build/locales/no/openhands.json +18 -1
  181. package/build/locales/pt/openhands.json +18 -1
  182. package/build/locales/tr/openhands.json +18 -1
  183. package/build/locales/uk/openhands.json +18 -1
  184. package/build/locales/zh-CN/openhands.json +18 -1
  185. package/build/locales/zh-TW/openhands.json +18 -1
  186. package/config/defaults.json +3 -3
  187. package/dist/api/agent-profiles-service/profile-field-support.d.ts +2 -0
  188. package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.cjs +3 -3
  189. package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.cjs.map +1 -1
  190. package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.js +12 -16
  191. package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.js.map +1 -1
  192. package/dist/components/features/automations/agent-profile-selector.d.ts +7 -0
  193. package/dist/components/features/automations/detail/disabled-reason-banner.d.ts +16 -0
  194. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs +1 -1
  195. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs.map +1 -1
  196. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js +38 -29
  197. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js.map +1 -1
  198. package/dist/components/features/settings/agent-profiles/profile-scope-list.d.ts +20 -0
  199. package/dist/config/defaults.cjs +1 -1
  200. package/dist/config/defaults.cjs.map +1 -1
  201. package/dist/config/defaults.js +3 -3
  202. package/dist/config/defaults.js.map +1 -1
  203. package/dist/constants/acp-providers.cjs +1 -1
  204. package/dist/constants/acp-providers.cjs.map +1 -1
  205. package/dist/constants/acp-providers.d.ts +0 -5
  206. package/dist/constants/acp-providers.js +20 -16
  207. package/dist/constants/acp-providers.js.map +1 -1
  208. package/dist/constants/profile-scope.d.ts +21 -0
  209. package/dist/hooks/mutation/use-create-conversation.cjs +1 -1
  210. package/dist/hooks/mutation/use-create-conversation.cjs.map +1 -1
  211. package/dist/hooks/mutation/use-create-conversation.js +30 -19
  212. package/dist/hooks/mutation/use-create-conversation.js.map +1 -1
  213. package/dist/hooks/mutation/use-switch-acp-model.cjs +1 -1
  214. package/dist/hooks/mutation/use-switch-acp-model.cjs.map +1 -1
  215. package/dist/hooks/mutation/use-switch-acp-model.js +11 -12
  216. package/dist/hooks/mutation/use-switch-acp-model.js.map +1 -1
  217. package/dist/hooks/query/query-keys.cjs +1 -1
  218. package/dist/hooks/query/query-keys.cjs.map +1 -1
  219. package/dist/hooks/query/query-keys.d.ts +1 -0
  220. package/dist/hooks/query/query-keys.js +10 -1
  221. package/dist/hooks/query/query-keys.js.map +1 -1
  222. package/dist/hooks/query/use-active-acp-profile-detail.cjs +1 -1
  223. package/dist/hooks/query/use-active-acp-profile-detail.cjs.map +1 -1
  224. package/dist/hooks/query/use-active-acp-profile-detail.d.ts +0 -9
  225. package/dist/hooks/query/use-active-acp-profile-detail.js +4 -13
  226. package/dist/hooks/query/use-active-acp-profile-detail.js.map +1 -1
  227. package/dist/hooks/query/use-automation-sdk-version.cjs +1 -1
  228. package/dist/hooks/query/use-automation-sdk-version.cjs.map +1 -1
  229. package/dist/hooks/query/use-automation-sdk-version.js +3 -1
  230. package/dist/hooks/query/use-automation-sdk-version.js.map +1 -1
  231. package/dist/hooks/use-drag-resize.cjs +1 -1
  232. package/dist/hooks/use-drag-resize.cjs.map +1 -1
  233. package/dist/hooks/use-drag-resize.js +8 -9
  234. package/dist/hooks/use-drag-resize.js.map +1 -1
  235. package/dist/i18n/declaration.cjs +1 -1
  236. package/dist/i18n/declaration.cjs.map +1 -1
  237. package/dist/i18n/declaration.d.ts +18 -1
  238. package/dist/i18n/declaration.js +1 -1
  239. package/dist/i18n/declaration.js.map +1 -1
  240. package/dist/i18n/translation.cjs +3 -3
  241. package/dist/i18n/translation.cjs.map +1 -1
  242. package/dist/i18n/translation.js +289 -0
  243. package/dist/i18n/translation.js.map +1 -1
  244. package/dist/locales/ar/openhands.json +18 -1
  245. package/dist/locales/ca/openhands.json +18 -1
  246. package/dist/locales/de/openhands.json +18 -1
  247. package/dist/locales/en/openhands.json +18 -1
  248. package/dist/locales/es/openhands.json +18 -1
  249. package/dist/locales/fr/openhands.json +18 -1
  250. package/dist/locales/it/openhands.json +18 -1
  251. package/dist/locales/ja/openhands.json +18 -1
  252. package/dist/locales/ko-KR/openhands.json +18 -1
  253. package/dist/locales/no/openhands.json +18 -1
  254. package/dist/locales/pt/openhands.json +18 -1
  255. package/dist/locales/tr/openhands.json +18 -1
  256. package/dist/locales/uk/openhands.json +18 -1
  257. package/dist/locales/zh-CN/openhands.json +18 -1
  258. package/dist/locales/zh-TW/openhands.json +18 -1
  259. package/dist/manifests/automation-setup.cjs.map +1 -1
  260. package/dist/manifests/automation-setup.js.map +1 -1
  261. package/dist/manifests/manifest-local-validation.cjs.map +1 -1
  262. package/dist/manifests/manifest-local-validation.js.map +1 -1
  263. package/dist/manifests/manifest-validation.cjs +1 -1
  264. package/dist/manifests/manifest-validation.cjs.map +1 -1
  265. package/dist/manifests/manifest-validation.js +2 -2
  266. package/dist/manifests/manifest-validation.js.map +1 -1
  267. package/dist/node_modules/@openhands/extensions/automations/bundle-index.cjs +3670 -247
  268. package/dist/node_modules/@openhands/extensions/automations/bundle-index.cjs.map +1 -1
  269. package/dist/node_modules/@openhands/extensions/automations/bundle-index.js +26 -3
  270. package/dist/node_modules/@openhands/extensions/automations/bundle-index.js.map +1 -1
  271. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.cjs +1 -1
  272. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.cjs.map +1 -1
  273. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.js +4 -1
  274. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.js.map +1 -1
  275. package/dist/node_modules/@openhands/extensions/automations/catalog/github-delivery-watchdog/manifest.cjs +2 -0
  276. package/dist/node_modules/@openhands/extensions/automations/catalog/github-delivery-watchdog/manifest.cjs.map +1 -0
  277. package/dist/node_modules/@openhands/extensions/automations/catalog/github-delivery-watchdog/manifest.js +79 -0
  278. package/dist/node_modules/@openhands/extensions/automations/catalog/github-delivery-watchdog/manifest.js.map +1 -0
  279. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs +1 -11
  280. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs.map +1 -1
  281. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js +25 -11
  282. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js.map +1 -1
  283. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-triage/manifest.cjs +2 -0
  284. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-triage/manifest.cjs.map +1 -0
  285. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-triage/manifest.js +72 -0
  286. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-triage/manifest.js.map +1 -0
  287. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs +1 -10
  288. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs.map +1 -1
  289. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js +24 -11
  290. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js.map +1 -1
  291. package/dist/node_modules/@openhands/extensions/automations/catalog/gitlab-issue-to-mr/manifest.cjs +12 -0
  292. package/dist/node_modules/@openhands/extensions/automations/catalog/gitlab-issue-to-mr/manifest.cjs.map +1 -0
  293. package/dist/node_modules/@openhands/extensions/automations/catalog/gitlab-issue-to-mr/manifest.js +115 -0
  294. package/dist/node_modules/@openhands/extensions/automations/catalog/gitlab-issue-to-mr/manifest.js.map +1 -0
  295. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs +1 -1
  296. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs.map +1 -1
  297. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js +20 -14
  298. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js.map +1 -1
  299. package/dist/node_modules/@openhands/extensions/integrations/catalog/reportportal.cjs +2 -0
  300. package/dist/node_modules/@openhands/extensions/integrations/catalog/reportportal.cjs.map +1 -0
  301. package/dist/node_modules/@openhands/extensions/integrations/catalog/reportportal.js +73 -0
  302. package/dist/node_modules/@openhands/extensions/integrations/catalog/reportportal.js.map +1 -0
  303. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs +1 -1
  304. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs.map +1 -1
  305. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js +9 -7
  306. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js.map +1 -1
  307. package/dist/node_modules/@openhands/extensions/skills/index.cjs +794 -227
  308. package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
  309. package/dist/node_modules/@openhands/extensions/skills/index.js +46 -6
  310. package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
  311. package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.cjs +1 -1
  312. package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.cjs.map +1 -1
  313. package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.js +15 -8
  314. package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.js.map +1 -1
  315. package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.cjs +1 -1
  316. package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.cjs.map +1 -1
  317. package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.js +11 -13
  318. package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.js.map +1 -1
  319. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs +1 -1
  320. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs.map +1 -1
  321. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js +6 -0
  322. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js.map +1 -1
  323. package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.cjs +1 -1
  324. package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.cjs.map +1 -1
  325. package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.js +9 -12
  326. package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.js.map +1 -1
  327. package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.cjs +1 -1
  328. package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.cjs.map +1 -1
  329. package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.js +9 -10
  330. package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.js.map +1 -1
  331. package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.cjs +2 -0
  332. package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.cjs.map +1 -0
  333. package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.js +41 -0
  334. package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.js.map +1 -0
  335. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs +1 -1
  336. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs.map +1 -1
  337. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js +2 -2
  338. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js.map +1 -1
  339. package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.cjs +1 -1
  340. package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.cjs.map +1 -1
  341. package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.js +3 -6
  342. package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.js.map +1 -1
  343. package/dist/node_modules/@openhands/typescript-client/dist/clients.cjs +1 -1
  344. package/dist/node_modules/@openhands/typescript-client/dist/clients.js +1 -2
  345. package/dist/node_modules/@openhands/typescript-client/dist/conversation/conversation-manager.cjs +1 -1
  346. package/dist/node_modules/@openhands/typescript-client/dist/conversation/conversation-manager.js +0 -1
  347. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs +1 -1
  348. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs.map +1 -1
  349. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js +199 -61
  350. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js.map +1 -1
  351. package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.cjs +1 -1
  352. package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.cjs.map +1 -1
  353. package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.js +9 -8
  354. package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.js.map +1 -1
  355. package/dist/package.cjs +1 -1
  356. package/dist/package.cjs.map +1 -1
  357. package/dist/package.js +3 -3
  358. package/dist/package.js.map +1 -1
  359. package/dist/routes/agent-settings.d.ts +11 -0
  360. package/dist/types/automation.cjs.map +1 -1
  361. package/dist/types/automation.d.ts +26 -2
  362. package/dist/types/automation.js.map +1 -1
  363. package/dist/utils/automation-disabled-reason.cjs +2 -0
  364. package/dist/utils/automation-disabled-reason.cjs.map +1 -0
  365. package/dist/utils/automation-disabled-reason.d.ts +32 -0
  366. package/dist/utils/automation-disabled-reason.js +19 -0
  367. package/dist/utils/automation-disabled-reason.js.map +1 -0
  368. package/dist/utils/parse-git-remote-url.cjs +1 -1
  369. package/dist/utils/parse-git-remote-url.cjs.map +1 -1
  370. package/dist/utils/parse-git-remote-url.d.ts +5 -1
  371. package/dist/utils/parse-git-remote-url.js +20 -13
  372. package/dist/utils/parse-git-remote-url.js.map +1 -1
  373. package/package.json +3 -3
  374. package/scripts/check-sdk-version-sync.mjs +79 -8
  375. package/scripts/dev-safe.mjs +14 -1
  376. package/scripts/docker-build.mjs +3 -0
  377. package/scripts/static-server.mjs +24 -7
  378. package/build/assets/acp-providers-DcY_mKYa.js +0 -1
  379. package/build/assets/active-backend-context-BnH4-L8h.js +0 -2
  380. package/build/assets/agent-server-conversation-service.api-jiCopc2E.js +0 -88
  381. package/build/assets/agent-settings-BF8hM6wb.js +0 -2
  382. package/build/assets/agent-settings-YPutBAeR.js +0 -1
  383. package/build/assets/automation-detail-BxXhb_m2.js +0 -3
  384. package/build/assets/automation-setup-route-qaJ6lLCf.js +0 -3
  385. package/build/assets/automations-list-DEPVNud3.js +0 -1
  386. package/build/assets/backend-form-modal-DxisQV_6.js +0 -1
  387. package/build/assets/conversation-edjzrv5w.js +0 -1
  388. package/build/assets/conversation-panel-edjzrv5w.js +0 -1
  389. package/build/assets/edit-automation-modal-D_JWSmxT.js +0 -1
  390. package/build/assets/empty-state-FK_s1B60.js +0 -1
  391. package/build/assets/git-repo-dropdown-BoDDWXfX.js +0 -1
  392. package/build/assets/home-BM5_Wz_R.js +0 -1
  393. package/build/assets/home-Ivfm7KC4.js +0 -1
  394. package/build/assets/home-automation-run-tooltip-B1N2uO9p.js +0 -1
  395. package/build/assets/index-home-td9BN2T3.js +0 -1
  396. package/build/assets/kebab-menu-item-content-SCJBwZnp.js +0 -1
  397. package/build/assets/link-external-BNZzCM1I.js +0 -1
  398. package/build/assets/llm-not-configured-banner-Dh_ajcM8.js +0 -27
  399. package/build/assets/llm-settings-CZaXYgtw.js +0 -1
  400. package/build/assets/manifest-bfeccb98.js +0 -1
  401. package/build/assets/mcp-CraxoXQv.js +0 -1
  402. package/build/assets/mcp-marketplace-utils-C7PYr293.js +0 -1
  403. package/build/assets/mcp-page-CteH_K0N.js +0 -9
  404. package/build/assets/onboarding-DXFBRqEy.js +0 -1
  405. package/build/assets/parse-git-remote-url-DpDM9bK6.js +0 -1
  406. package/build/assets/recommended-automations-launcher-DEHRKIAg.js +0 -1
  407. package/build/assets/root-CM6IZHlg.css +0 -1
  408. package/build/assets/root-DdFkodKW.js +0 -2
  409. package/build/assets/trash-Ckh7yCaB.js +0 -1
  410. package/build/assets/use-create-conversation-i_PdFdIs.js +0 -1
  411. package/build/assets/use-create-secret-CjWq0J4O.js +0 -1
  412. package/build/assets/use-manifest-capabilities-CdqYfUAC.js +0 -1
  413. package/build/assets/use-tracking-j4uo9VEW.js +0 -3
  414. package/build/assets/utils-BgLSZdyy.js +0 -1
  415. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0x1wrp2-Z0lly3FE.js +0 -2
  416. package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~inibp4qe-CnsDDzeE.js +0 -48
  417. package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.cjs +0 -2
  418. package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.cjs.map +0 -1
  419. package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.js +0 -21
  420. package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.js.map +0 -1
@@ -1437,6 +1437,10 @@ reviewing it would tell you nothing the first did not.
1437
1437
 
1438
1438
  ---
1439
1439
 
1440
+ The script imports shared GitHub transport from
1441
+ \`scripts/github_client.py\`, installed with this skill. Include it beside
1442
+ \`main.py\` when packaging manually, as shown below.
1443
+
1440
1444
  ## Prerequisites
1441
1445
 
1442
1446
  ### Required secret
@@ -1560,9 +1564,11 @@ substitutions near the top of the file:
1560
1564
  Use a safe string writer such as \`json.dumps(value)\` when inserting user-provided
1561
1565
  repository names or prefixes into Python string literals.
1562
1566
 
1563
- Write the customized script to a temporary build directory and validate it:
1567
+ Run these commands from this skill's directory, write the customized script
1568
+ to a temporary build directory, and validate it:
1564
1569
  \`\`\`bash
1565
1570
  mkdir -p /tmp/agents-md-build
1571
+ cp -L scripts/github_client.py /tmp/agents-md-build/github_client.py
1566
1572
  # write the customized main.py to /tmp/agents-md-build/main.py
1567
1573
  python3 -m py_compile /tmp/agents-md-build/main.py && echo "Syntax OK"
1568
1574
  \`\`\`
@@ -1676,7 +1682,14 @@ For each repository:
1676
1682
  | \`git is not available in the automation runtime\` | The runtime image has no git | Use a runtime image that ships git |
1677
1683
  | Pull request says nothing changed | The agent judged AGENTS.md accurate but still committed | Read its summary in the pull request body; tighten the prompt if it keeps making cosmetic edits |
1678
1684
  | Every run reports \`no-changes\` | AGENTS.md is accurate, or the agent cannot read the repository | Open the conversation from the run log and check what it saw |
1679
- | Clones remain under \`agents-md/\` | Their conversations had not stopped yet | They are removed by a later run once the conversation is terminal |`,category:`automations`},{name:`github-issue-to-pr`,description:`Create an automation that implements GitHub issues when a configurable trigger label is applied. Polls one or more repositories deterministically, clones the default branch, starts one OpenHands conversation per label event, then commits, pushes, and opens the pull request itself.`,triggers:[`/issue-to-pr:setup`],content:`# GitHub Issue to PR Automation
1685
+ | Clones remain under \`agents-md/\` | Their conversations had not stopped yet | They are removed by a later run once the conversation is terminal |`,category:`automations`},{name:`github-delivery-watchdog`,description:`Periodically check pull requests and merge only current heads with independent review, tests, and passing CI.`,triggers:[`/github-delivery-watchdog`],content:"# GitHub delivery watchdog\n\nThis is a deterministic scheduled host command. It creates no agent or\nconversation and needs no agent profile. Configure a repository-scoped\nfine-grained PAT with Contents and Issues read/write plus Pull requests, Actions,\nCommit statuses, and Metadata read. Contents write permits merge; Issues write\nretains the review label when the branch is updated. Never put the token value in\nthe automation definition.\n\nPackage `scripts/worker.py` as `worker.py` and the shared\n`scripts/github_client.py` as `github_client.py`.\nThe catalog bundle declares these exact files. Its `config.json` supplies\n`repos`, `branch_prefix`, and the saved secret name. The shared GitHub client\nresolves only that named secret. Automation owns scheduling and cancellation.\n\nSet `branch_prefix` (default `openhands/issue`), `base_branch` (defaults to the repository's default branch),\nand `required_workflow_ids` when particular Actions workflows must run. The\nwatchdog requires `software-factory/tests` and `software-factory/review` success\nstatuses on the exact head, all other statuses and Actions passing, a current\nbase, a non-draft PR, and GitHub reporting it mergeable. Missing, pending, failed,\nor inaccessible evidence does not permit merge. A changed head requires fresh\nreview and tests. When an accepted branch is behind the base, the watchdog asks\nGitHub to update it and retains the review trigger label; it considers the new\nhead only on a later run. The merge request includes the expected head SHA.\n\nActions are optional when `required_workflow_ids` is empty; the two acceptance\nstatuses remain mandatory. Configure workflow IDs when GitHub Actions must also\nsupply evidence. Branch protection remains GitHub's final merge gate.",category:`automations`},{name:`github-issue-to-pr`,description:`Create an automation that implements GitHub issues when a configurable trigger label is applied. Polls one or more repositories deterministically, clones the default branch, starts one OpenHands conversation per label event, then commits, pushes, and opens the pull request itself.`,triggers:[`/issue-to-pr:setup`],content:`# GitHub Issue to PR Automation
1686
+
1687
+ ## Agent Canvas catalog
1688
+
1689
+ For new Agent Canvas installations, use the **GitHub issue to PR** catalog
1690
+ entry. Its deterministic \`worker.py\` scanner delegates each eligible issue to a
1691
+ stable conversation using the selected agent profile. The manual upload flow
1692
+ below remains for existing deployments and is deprecated for new installations.
1680
1693
 
1681
1694
  Create a cron automation that watches one or more GitHub repositories for issues
1682
1695
  with a trigger label, starts an OpenHands conversation once per label event with
@@ -1707,6 +1720,11 @@ environment of a command that mentions it, and masks it in the output.
1707
1720
 
1708
1721
  ---
1709
1722
 
1723
+ The script imports shared GitHub transport from
1724
+ \`scripts/github_client.py\`, installed with this skill. Include it beside
1725
+ \`main.py\` when packaging manually, as shown below; catalog bundles include it
1726
+ automatically.
1727
+
1710
1728
  ## Prerequisites
1711
1729
 
1712
1730
  ### Required secret
@@ -1872,9 +1890,11 @@ Use a safe string writer such as \`json.dumps(value)\` when inserting user-provi
1872
1890
  repository names, labels, or prefixes into Python string literals.
1873
1891
  \`json.dumps(list_of_repos)\` produces the whole \`REPOS\` list safely in one step.
1874
1892
 
1875
- Write the customized script to a temporary build directory:
1893
+ Run these commands from this skill's directory and write the customized script
1894
+ to a temporary build directory:
1876
1895
  \`\`\`bash
1877
1896
  mkdir -p /tmp/issue-to-pr-build
1897
+ cp -L scripts/github_client.py /tmp/issue-to-pr-build/github_client.py
1878
1898
  # write the customized main.py to /tmp/issue-to-pr-build/main.py
1879
1899
  \`\`\`
1880
1900
 
@@ -2037,7 +2057,33 @@ The completion callback fires once for the whole run.
2037
2057
  | Same issue not picked up again after new comments | Its label event was already processed | Remove and re-apply the trigger label |
2038
2058
  | Agent reports it cannot push or open a PR | By design - it has no credentials | No action; the automation pushes and opens the pull request after the agent stops |
2039
2059
  | A backlog of labelled issues starts slowly | \`MAX_NEW_PER_RUN\` caps how many conversations one poll starts | Wait for the next polls, or raise the cap in the script |
2040
- | Clones remain under \`issue-to-pr/\` | Their conversations had not stopped yet | They are removed by a later poll once the conversation is terminal |`,category:`automations`},{name:`github-pr-review`,description:`Post PR review comments using the GitHub API with inline comments, suggestions, and priority labels.`,triggers:[`/github-pr-review`],content:`# GitHub PR Review
2060
+ | Clones remain under \`issue-to-pr/\` | Their conversations had not stopped yet | They are removed by a later poll once the conversation is terminal |`,category:`automations`},{name:`github-issue-triage`,description:`Prioritize open issues and establish acceptance criteria before marking them ready for development.`,triggers:[`/github-issue-triage`],content:`# GitHub issue triage
2061
+
2062
+ Prioritize open issues and establish acceptance criteria before marking them ready for development.
2063
+
2064
+ Create this automation separately from implementation and review. Use a
2065
+ fine-grained GitHub PAT limited to the selected repositories with Issues: read and
2066
+ write. Never put the token value in the automation definition or prompt.
2067
+
2068
+ Package \`worker.py\` with the shared \`github_client.py\` and
2069
+ \`agent_conversation.py\` helpers. Supply \`config.json\` with \`repos\` and the saved
2070
+ GitHub secret name; the entrypoint is \`python3 worker.py\`. Include that secret in
2071
+ the selected profile so the delegated agent can use GitHub. Naming it in the
2072
+ automation does not grant it to the agent.
2073
+
2074
+ The scanner is an ordinary Automation host command. It submits selected issues
2075
+ through the shared KV-backed conversation dispatcher, which creates or resumes
2076
+ one stable conversation per issue through the Software Agent SDK. Only that
2077
+ agent workspace is local or Docker. Automation owns scheduling, cancellation,
2078
+ and cleanup.
2079
+
2080
+ Honor \`Depends on: #12, #13\` lines. A dependency must be closed as completed.
2081
+ Post readable acceptance criteria and rationale. Add \`ready-for-dev\` only when
2082
+ criteria are actionable; preserve existing issue labels. Unclear issues stay open
2083
+ for clarification. Do not implement code or accept pull requests.
2084
+
2085
+ Each scheduled run submits every changed eligible issue. A failure on one issue is
2086
+ reported and does not prevent the remaining issues from being submitted.`,category:`automations`},{name:`github-pr-review`,description:`Post PR review comments using the GitHub API with inline comments, suggestions, and priority labels.`,triggers:[`/github-pr-review`],content:`# GitHub PR Review
2041
2087
 
2042
2088
  Post structured code review feedback using the GitHub API with inline comments on specific lines.
2043
2089
  Windows PowerShell equivalents for JSON file creation, temp paths, line lookup, and fallback \`curl\` are in \`references/windows.md\`.
@@ -2218,6 +2264,13 @@ curl -X POST \\
2218
2264
  7. Keep the review body brief (details go in inline comments)
2219
2265
  8. If no issues: post a short approval message with no inline comments`,category:`code-hosting`},{name:`github-pr-reviewer`,description:`Create an automation that reviews GitHub pull requests when a configurable trigger label is applied. Polls one or more repositories deterministically, starts one OpenHands review conversation per label event with the pull request's head commit already checked out, and publishes the review to GitHub.`,triggers:[`/pr-reviewer:setup`],content:`# GitHub PR Reviewer Automation
2220
2266
 
2267
+ ## Agent Canvas catalog
2268
+
2269
+ For new Agent Canvas installations, use the **GitHub code review** catalog
2270
+ entry. Its deterministic \`worker.py\` scanner delegates each labeled exact head
2271
+ to a stable conversation using the selected agent profile. The manual upload
2272
+ flow below remains for existing deployments and is deprecated for new installations.
2273
+
2221
2274
  Create a cron automation that watches one or more GitHub repositories for pull
2222
2275
  requests with a review trigger label, starts an OpenHands review conversation
2223
2276
  once per label event, and publishes the AI review to GitHub.
@@ -2236,6 +2289,11 @@ checkout once the conversation has stopped. Nothing accumulates between runs.
2236
2289
 
2237
2290
  ---
2238
2291
 
2292
+ The script imports shared GitHub transport from
2293
+ \`scripts/github_client.py\`, installed with this skill. Include it beside
2294
+ \`main.py\` when packaging manually, as shown below; catalog bundles include it
2295
+ automatically.
2296
+
2239
2297
  ## Prerequisites
2240
2298
 
2241
2299
  ### Required secret
@@ -2368,9 +2426,11 @@ Use a safe string writer such as \`json.dumps(value)\` when inserting user-provi
2368
2426
  repository names, labels, or style instructions into Python string literals.
2369
2427
  \`json.dumps(list_of_repos)\` produces the whole \`REPOS\` list safely in one step.
2370
2428
 
2371
- Write the customized script to a temporary build directory:
2429
+ Run these commands from this skill's directory and write the customized script
2430
+ to a temporary build directory:
2372
2431
  \`\`\`bash
2373
2432
  mkdir -p /tmp/pr-reviewer-build
2433
+ cp -L scripts/github_client.py /tmp/pr-reviewer-build/github_client.py
2374
2434
  # write the customized main.py to /tmp/pr-reviewer-build/main.py
2375
2435
  \`\`\`
2376
2436
 
@@ -2544,6 +2604,10 @@ On every subsequent run:
2544
2604
 
2545
2605
  ---
2546
2606
 
2607
+ The script imports shared GitHub transport from
2608
+ \`scripts/github_client.py\`, installed with this skill. Include it beside
2609
+ \`main.py\` when packaging manually, as shown below.
2610
+
2547
2611
  ## Prerequisites
2548
2612
 
2549
2613
  ### Required secret
@@ -2688,9 +2752,11 @@ constant substitutions near the top of the file:
2688
2752
  | \`ALLOWED_GITHUB_LOGINS = ["<TOKEN_OWNER>"]\` | \`ALLOWED_GITHUB_LOGINS = {allowed_logins_list}\` |
2689
2753
  | \`DEFAULT_OPENHANDS_URL = "http://localhost:8000"\` | \`DEFAULT_OPENHANDS_URL = "{url}"\` (keep default if the user has no preference) |
2690
2754
 
2691
- Write the customised script to a temporary build directory:
2755
+ Run these commands from this skill's directory and write the customised script
2756
+ to a temporary build directory:
2692
2757
  \`\`\`bash
2693
2758
  mkdir -p /tmp/github-monitor-build
2759
+ cp -L scripts/github_client.py /tmp/github-monitor-build/github_client.py
2694
2760
  # (write the customised main.py to /tmp/github-monitor-build/main.py)
2695
2761
  \`\`\`
2696
2762
 
@@ -2821,7 +2887,403 @@ Each cron run executes \`main.py\`, which:
2821
2887
  | Comments posted but no conversation created | Agent server URL wrong | Check \`OPENHANDS_URL\` secret and \`AGENT_SERVER_URL\` env var |
2822
2888
  | Same comment processed twice | \`processed_comment_ids\` cleared | State file was deleted; harmless but duplicate comment may appear |
2823
2889
  | Summary never posted | Conversation stuck in \`running\` | Open the conversation in the OpenHands UI; agent may need input |
2824
- | No events detected after first run | \`last_poll\` in the future | Delete the state file to reset; it will be recreated on next run |`,category:`automations`},{name:`gitlab`,description:`Interact with GitLab repositories, merge requests, and APIs using the GITLAB_TOKEN environment variable. Use when working with code hosted on GitLab or managing GitLab resources.`,triggers:[`gitlab`],content:"You have access to an environment variable, `GITLAB_TOKEN`, which allows you to interact with\nthe GitLab API.\n\n<IMPORTANT>\nYou can use `curl` with the `GITLAB_TOKEN` to interact with GitLab's API.\nALWAYS use the GitLab API for operations instead of a web browser.\nALWAYS use the `create_mr` tool to open a merge request\n</IMPORTANT>\n\nIf you encounter authentication issues when pushing to GitLab (such as password prompts or permission errors), the old token may have expired. In such case, update the remote URL to include the current token: `git remote set-url origin https://oauth2:${GITLAB_TOKEN}@gitlab.com/username/repo.git`\n\nHere are some instructions for pushing, but ONLY do this if the user asks you to:\n* NEVER push directly to the `main` or `master` branch\n* Git config (username and email) is pre-set. Do not modify.\n* You may already be on a branch starting with `openhands-workspace`. Create a new branch with a better name before pushing.\n* Use the `create_mr` tool to create a merge request, if you haven't already\n* Once you've created your own branch or a merge request, continue to update it. Do NOT create a new one unless you are explicitly asked to. Update the PR title and description as necessary, but don't change the branch name.\n* Use the main branch as the base branch, unless the user requests otherwise\n* After opening or updating a merge request, send the user a short message with a link to the merge request.\n* Do all of the above in as few steps as possible. E.g. you could push changes with one step by running the following bash commands:\n```bash\ngit remote -v && git branch # to find the current org, repo and branch\ngit checkout -b create-widget && git add . && git commit -m \"Create widget\" && git push -u origin create-widget\n```\n\nOn Windows PowerShell, use `$env:GITLAB_TOKEN` in remote URLs and run the `git` commands as separate commands if `&&` is not supported by the installed shell.",category:`code-hosting`},{name:`incident-retrospective`,description:`Create an automation that drafts incident retrospectives. Gathers incident-channel messages from Slack, collects linked tickets and follow-ups from Linear, and publishes a retrospective draft to Notion with a timeline, impact summary, root-cause hypotheses, and action items.`,triggers:[`/incident-retro:setup`],content:`# Incident Retrospective Drafter Automation
2890
+ | No events detected after first run | \`last_poll\` in the future | Delete the state file to reset; it will be recreated on next run |`,category:`automations`},{name:`gitlab`,description:`Interact with GitLab repositories, merge requests, and APIs using the GITLAB_TOKEN environment variable. Use when working with code hosted on GitLab or managing GitLab resources.`,triggers:[`gitlab`],content:"You have access to an environment variable, `GITLAB_TOKEN`, which allows you to interact with\nthe GitLab API.\n\n<IMPORTANT>\nYou can use `curl` with the `GITLAB_TOKEN` to interact with GitLab's API.\nALWAYS use the GitLab API for operations instead of a web browser.\nALWAYS use the `create_mr` tool to open a merge request\n</IMPORTANT>\n\nIf you encounter authentication issues when pushing to GitLab (such as password prompts or permission errors), the old token may have expired. In such case, update the remote URL to include the current token: `git remote set-url origin https://oauth2:${GITLAB_TOKEN}@gitlab.com/username/repo.git`\n\nHere are some instructions for pushing, but ONLY do this if the user asks you to:\n* NEVER push directly to the `main` or `master` branch\n* Git config (username and email) is pre-set. Do not modify.\n* You may already be on a branch starting with `openhands-workspace`. Create a new branch with a better name before pushing.\n* Use the `create_mr` tool to create a merge request, if you haven't already\n* Once you've created your own branch or a merge request, continue to update it. Do NOT create a new one unless you are explicitly asked to. Update the PR title and description as necessary, but don't change the branch name.\n* Use the main branch as the base branch, unless the user requests otherwise\n* After opening or updating a merge request, send the user a short message with a link to the merge request.\n* Do all of the above in as few steps as possible. E.g. you could push changes with one step by running the following bash commands:\n```bash\ngit remote -v && git branch # to find the current org, repo and branch\ngit checkout -b create-widget && git add . && git commit -m \"Create widget\" && git push -u origin create-widget\n```\n\nOn Windows PowerShell, use `$env:GITLAB_TOKEN` in remote URLs and run the `git` commands as separate commands if `&&` is not supported by the installed shell.",category:`code-hosting`},{name:`gitlab-issue-to-mr`,description:`Create an automation that implements GitLab issues when a configurable trigger label is applied. Polls one or more projects deterministically, clones the default branch, starts one OpenHands conversation per label event, then commits, pushes, and opens the merge request itself.`,triggers:[`/issue-to-mr:setup`],content:`# GitLab Issue to MR Automation
2891
+
2892
+ Create a cron automation that watches one or more GitLab projects for issues
2893
+ with a trigger label, starts an OpenHands conversation once per label event with
2894
+ the project's default branch already checked out, and opens a merge request with
2895
+ whatever the agent produced.
2896
+
2897
+ The automation script is deterministic: issue discovery, label-event tracking,
2898
+ state persistence, the clone, the branch, the commit, the push, the merge
2899
+ request, the issue comments, and the clone's removal are all handled in Python.
2900
+ The LLM is invoked only to write the code.
2901
+
2902
+ The agent is told **which** issue to implement, not what it says. It fetches the
2903
+ description, the discussion, and whatever they link to itself, so nothing in the
2904
+ prompt goes stale between dispatch and the moment the agent reads it.
2905
+
2906
+ That needs read access, so the conversation is handed one secret, \`GITLAB_TOKEN\`.
2907
+ \`AGENT_SECRET_NAMES\` stays an allow-list: the rest of the deployment's secret
2908
+ store is not reachable from a conversation whose instructions came from an issue.
2909
+
2910
+ The deployment's MCP servers are forwarded whole, matching \`github-pr-reviewer\`,
2911
+ so a connected GitLab server gives the agent typed tools rather than curl. What
2912
+ those servers reach is reachable from an issue-authored prompt, so connect only
2913
+ servers that may be driven by untrusted text.
2914
+
2915
+ The agent also finishes the job: it commits, pushes its branch, and opens the
2916
+ merge request, so the merge request appears when the agent stops rather than on
2917
+ the next poll. The script does not trust that it happened - when the conversation
2918
+ ends it asks GitLab whether the merge request exists, and opens it itself when it
2919
+ does not. \`origin\` still carries no credential, so every GitLab command the agent
2920
+ runs has to name \`GITLAB_TOKEN\`; the SDK only puts a secret in the environment of
2921
+ a command that mentions it, and masks it in the output.
2922
+
2923
+ ---
2924
+
2925
+ ## Prerequisites
2926
+
2927
+ ### Required secret
2928
+
2929
+ Verify that the following secret is set in **OpenHands Settings -> Secrets**:
2930
+
2931
+ | Secret name | Token type | Minimum requirements |
2932
+ |---|---|---|
2933
+ | \`GITLAB_TOKEN\` | Personal access token | \`api\` scope, and at least the **Developer** role on every watched project |
2934
+ | \`GITLAB_TOKEN\` | Project or group access token | \`api\` scope, role **Developer** or above |
2935
+
2936
+ The \`api\` scope is what GitLab grants read and write on issues, notes, branches,
2937
+ and merge requests through one scope; \`read_api\` polls happily and then fails at
2938
+ the point of pushing. Developer is the lowest role that can push a branch and
2939
+ open a merge request.
2940
+
2941
+ Two things the role does not cover, and which fail the push rather than the poll:
2942
+
2943
+ - **Protected branches.** The default branch is usually protected, but the
2944
+ automation never pushes to it. Protect the branch prefix as well and the push
2945
+ is rejected; leave \`openhands/issue-*\` unprotected.
2946
+ - **CI/CD files.** An issue asking for a pipeline change makes the agent touch
2947
+ \`.gitlab-ci.yml\`. That needs no extra scope, but a project with a protected
2948
+ CI/CD configuration path rejects the push.
2949
+
2950
+ When several projects are monitored, the token must cover all of them.
2951
+
2952
+ Check with:
2953
+ \`\`\`bash
2954
+ curl -s "https://gitlab.com/api/v4/user" \\
2955
+ -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \\
2956
+ | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('username') or d.get('message'))"
2957
+ \`\`\`
2958
+
2959
+ If the token is missing or invalid, inform the user and stop.
2960
+
2961
+ ---
2962
+
2963
+ ## Setup Workflow
2964
+
2965
+ Follow these steps in order.
2966
+
2967
+ ### Step 1 - Verify \`GITLAB_TOKEN\`
2968
+
2969
+ Run the \`curl\` check above, against the user's instance if it is not
2970
+ \`gitlab.com\`.
2971
+
2972
+ - If absent: *"GITLAB_TOKEN is not set. Please add it in OpenHands Settings ->
2973
+ Secrets."* Stop.
2974
+ - If the API returns \`{"message": "401 Unauthorized"}\`: tell the user the token
2975
+ is invalid and ask them to update it. Stop.
2976
+
2977
+ ### Step 2 - Collect the GitLab API URL
2978
+
2979
+ Ask: *"Which GitLab instance? (Press Enter for gitlab.com. For a self-managed
2980
+ instance give its API root, e.g. \`https://gitlab.example.com/api/v4\`.)"*
2981
+
2982
+ Record as \`GITLAB_API_URL\`. Default: \`https://gitlab.com/api/v4\`. Use this URL in
2983
+ every check below.
2984
+
2985
+ ### Step 3 - Collect projects
2986
+
2987
+ Ask: *"Which GitLab projects should be watched?
2988
+ (Format: \`group/project\`, e.g. \`myorg/backend\`. Subgroups are fine -
2989
+ \`myorg/team/service\`. List several separated by commas to serve them all from one
2990
+ automation.)"*
2991
+
2992
+ Validate access to **each** project, and confirm the token's role:
2993
+ \`\`\`bash
2994
+ PROJECT_ID=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "{group}/{project}")
2995
+ curl -s "\${GITLAB_API_URL}/projects/\${PROJECT_ID}" \\
2996
+ -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \\
2997
+ | python3 -c "
2998
+ import json, sys
2999
+ d = json.load(sys.stdin)
3000
+ if 'message' in d or 'error' in d:
3001
+ print('ERROR:', d.get('message') or d.get('error'))
3002
+ else:
3003
+ perms = d.get('permissions') or {}
3004
+ levels = [(perms.get(k) or {}).get('access_level') for k in ('project_access', 'group_access')]
3005
+ levels = [n for n in levels if isinstance(n, int)]
3006
+ role = max(levels) if levels else 'unknown'
3007
+ print(f\\"Accessible. Default branch: {d.get('default_branch')}. Access level: {role}\\")
3008
+ "
3009
+ \`\`\`
3010
+
3011
+ Record every accepted project into \`PROJECTS = ["{group}/{project}", ...]\`. If
3012
+ one project fails the check, say which and ask whether to continue without it.
3013
+ An access level below \`30\` (Developer) means the automation cannot open merge
3014
+ requests there; ask for a token with a higher role.
3015
+
3016
+ Each project is polled independently and keeps its own state, so issue numbers
3017
+ never collide between them. The trigger label, branch prefix, and schedule are
3018
+ shared; a project needing different settings wants its own automation.
3019
+
3020
+ ### Step 4 - Collect trigger label
3021
+
3022
+ Ask: *"Which issue label should trigger an implementation?
3023
+ (Press Enter for the default: \`openhands\`.)"*
3024
+
3025
+ Record the answer as \`TRIGGER_LABEL\`. If the label does not exist yet, tell the
3026
+ user that GitLab will still record the event once the label is created and
3027
+ applied to an issue.
3028
+
3029
+ The automation works an issue when it sees the latest matching label event for
3030
+ that label. To ask for another attempt later, remove and re-apply the label -
3031
+ that opens a second branch and a second merge request rather than overwriting the
3032
+ first.
3033
+
3034
+ ### Step 5 - Collect the merge request mode
3035
+
3036
+ Ask: *"Should the merge requests be opened as drafts?
3037
+ 1. Draft (default) - title prefixed \`Draft:\`, ready for a human to mark ready
3038
+ 2. Ready for review - opened as a normal merge request
3039
+ (Press Enter for Draft)"*
3040
+
3041
+ Map the choice to \`DRAFT_MERGE_REQUEST\` (\`True\` or \`False\`). GitLab has no draft
3042
+ flag on the merge request API; a draft is a title carrying the \`Draft: \` prefix,
3043
+ which the script adds.
3044
+
3045
+ ### Step 6 - Collect the branch prefix
3046
+
3047
+ Ask: *"What branch prefix should the automation use?
3048
+ (Press Enter for the default: \`openhands/issue\`, which produces
3049
+ \`openhands/issue-42\`.)"*
3050
+
3051
+ Record as \`BRANCH_PREFIX\`. Keep it free of spaces and of characters git rejects
3052
+ in a ref name, and make sure the prefix is not covered by a protected-branch
3053
+ rule.
3054
+
3055
+ ### Step 7 - Collect cron schedule
3056
+
3057
+ Ask: *"How often should the automation poll for labelled issues?
3058
+ (Press Enter for the default: every 5 minutes.
3059
+ Use a cron expression for a different interval, e.g. \`0 * * * *\` = hourly)"*
3060
+
3061
+ Default: \`*/5 * * * *\`.
3062
+
3063
+ Record as \`CRON_SCHEDULE\`.
3064
+
3065
+ ### Step 8 - Confirm the secret scope
3066
+
3067
+ The agent is handed \`GITLAB_TOKEN\`, because it reads the issue and its discussion
3068
+ itself. Ask: *"Beyond the GitLab token, does the project's build need a secret of
3069
+ its own - a package registry token, for example? (Press Enter for none.)"*
3070
+
3071
+ Record the answers appended to the default, as
3072
+ \`AGENT_SECRET_NAMES = ["GITLAB_TOKEN", "NAME", ...]\`.
3073
+
3074
+ Keep it an allow-list. Forwarding the whole secret store would put every
3075
+ credential in the deployment behind a prompt written by whoever opened the issue.
3076
+ If the projects are public and you would rather the conversation held no
3077
+ credential at all, set the list to \`[]\` - the agent can still read a public issue
3078
+ unauthenticated, and private projects then stop working.
3079
+
3080
+ The deployment's MCP servers are a separate matter: they are forwarded whole, so
3081
+ the conversation can reach everything they expose. Say so, and check the user is
3082
+ willing to have those servers driven by text written by whoever opened an issue.
3083
+ Removing a server from the deployment's MCP settings is the only way to keep it
3084
+ out of these conversations.
3085
+
3086
+ ### Step 9 - Generate the automation script
3087
+
3088
+ Read \`scripts/main.py\` from this skill's directory. Apply exactly six constant
3089
+ substitutions near the top of the file:
3090
+
3091
+ > The script also reads a \`config.json\` shipped beside it, if there is one, over
3092
+ > these constants. That is how the catalog entry
3093
+ > (\`automations/catalog/gitlab-issue-to-mr/\`) configures an unmodified copy,
3094
+ > since a declarative host cannot rewrite Python. This setup path substitutes the
3095
+ > constants and ships no \`config.json\`, so the two never collide.
3096
+
3097
+ | Placeholder | Replace with |
3098
+ |---|---|
3099
+ | \`PROJECTS = ["group/project"]\` | \`PROJECTS = ["{group_project}", ...]\` - one entry per project collected in Step 3 |
3100
+ | \`TRIGGER_LABEL = "openhands"\` | \`TRIGGER_LABEL = "{trigger_label}"\` |
3101
+ | \`BRANCH_PREFIX = "openhands/issue"\` | \`BRANCH_PREFIX = "{branch_prefix}"\` |
3102
+ | \`DRAFT_MERGE_REQUEST = True\` | \`DRAFT_MERGE_REQUEST = {True or False}\` |
3103
+ | \`GITLAB_API_URL = "https://gitlab.com/api/v4"\` | \`GITLAB_API_URL = "{gitlab_api_url}"\` |
3104
+ | \`AGENT_SECRET_NAMES: list[str] = ["GITLAB_TOKEN"]\` | \`AGENT_SECRET_NAMES: list[str] = ["{name}", ...]\` |
3105
+
3106
+ Leave \`MAX_NEW_PER_RUN\` and \`DEFAULT_OPENHANDS_URL\` alone unless the user asks
3107
+ for a different cap or a non-default OpenHands URL.
3108
+
3109
+ A project may be given as \`group/project\`, as a clone URL, or as an SSH remote;
3110
+ the script normalizes each one at startup and names the value it could not read
3111
+ rather than blaming the token. Subgroups are preserved.
3112
+
3113
+ Use a safe string writer such as \`json.dumps(value)\` when inserting user-provided
3114
+ project paths, labels, or prefixes into Python string literals.
3115
+ \`json.dumps(list_of_projects)\` produces the whole \`PROJECTS\` list safely in one
3116
+ step.
3117
+
3118
+ Write the customized script to a temporary build directory:
3119
+ \`\`\`bash
3120
+ mkdir -p /tmp/issue-to-mr-build
3121
+ # write the customized main.py to /tmp/issue-to-mr-build/main.py
3122
+ \`\`\`
3123
+
3124
+ Validate syntax before packaging:
3125
+ \`\`\`bash
3126
+ python3 -m py_compile /tmp/issue-to-mr-build/main.py && echo "Syntax OK"
3127
+ \`\`\`
3128
+
3129
+ Fix any syntax errors before proceeding.
3130
+
3131
+ ### Step 10 - Package and upload
3132
+
3133
+ Determine the Automation backend URL and auth from the \`<RUNTIME_SERVICES>\`
3134
+ block in your system context:
3135
+ - **OPENHANDS_HOST**: the Automation backend \`url_from_agent\`
3136
+ - **Auth**: \`X-Session-API-Key: $OPENHANDS_AUTOMATION_API_KEY\`
3137
+
3138
+ \`\`\`bash
3139
+ tar -czf /tmp/issue-to-mr.tar.gz -C /tmp/issue-to-mr-build .
3140
+
3141
+ TARBALL_PATH=$(curl -s -X POST \\
3142
+ "\${OPENHANDS_HOST}/api/automation/v1/uploads?name=gitlab-issue-to-mr" \\
3143
+ -H "X-Session-API-Key: $OPENHANDS_AUTOMATION_API_KEY" \\
3144
+ -H "Content-Type: application/gzip" \\
3145
+ --data-binary @/tmp/issue-to-mr.tar.gz \\
3146
+ | python3 -c "import json,sys; print(json.load(sys.stdin)['tarball_path'])")
3147
+
3148
+ echo "Uploaded: $TARBALL_PATH"
3149
+ \`\`\`
3150
+
3151
+ ### Step 11 - Register the automation
3152
+
3153
+ \`\`\`bash
3154
+ curl -s -X POST "\${OPENHANDS_HOST}/api/automation/v1" \\
3155
+ -H "X-Session-API-Key: $OPENHANDS_AUTOMATION_API_KEY" \\
3156
+ -H "Content-Type: application/json" \\
3157
+ -d "{
3158
+ \\"name\\": \\"GitLab Issue to MR: {project_summary} label {trigger_label}\\",
3159
+ \\"trigger\\": {\\"type\\": \\"cron\\", \\"schedule\\": \\"{cron_schedule}\\"},
3160
+ \\"tarball_path\\": \\"$TARBALL_PATH\\",
3161
+ \\"entrypoint\\": \\"python3 main.py\\",
3162
+ \\"timeout\\": 900
3163
+ }" | python3 -m json.tool
3164
+ \`\`\`
3165
+
3166
+ Use the single project as \`{project_summary}\` when there is one, and something
3167
+ like \`3 projects\` when there are several. A poll clones a project per queued
3168
+ issue and pushes finished branches, so the timeout allows for that; a run never
3169
+ waits for an agent to finish, only for it to be started.
3170
+
3171
+ Record the returned \`id\`.
3172
+
3173
+ ### Step 12 - Confirm
3174
+
3175
+ Tell the user:
3176
+
3177
+ > ✅ **GitLab Issue to MR** is running!
3178
+ >
3179
+ > - Automation ID: \`{id}\`
3180
+ > - Projects: \`{group}/{project}\`, ... (one line each)
3181
+ > - GitLab API: \`{gitlab_api_url}\`
3182
+ > - Trigger label: \`{trigger_label}\`
3183
+ > - Branch prefix: \`{branch_prefix}\`
3184
+ > - Merge requests: \`{draft or ready for review}\`
3185
+ > - Polling schedule: \`{cron_schedule}\`
3186
+ > - State file per project:
3187
+ > \`~/.openhands/workspaces/automation-state/gitlab_issue_to_mr_{id}_{group}__{project}.json\`
3188
+ >
3189
+ > Apply the \`{trigger_label}\` label to an issue to queue an implementation. Each
3190
+ > label event is processed once. To ask for another attempt, remove and re-apply
3191
+ > the label - that opens a second branch and merge request.
3192
+ >
3193
+ > The agent runs without a checkout credential; the automation pushes the branch
3194
+ > and opens the merge request once the agent has stopped.
3195
+
3196
+ ---
3197
+
3198
+ ## Runtime Behaviour (per poll)
3199
+
3200
+ Each cron run executes \`main.py\`, which loads \`config.json\` if the catalog
3201
+ shipped one, checks that \`git\` is available, resolves and validates \`GITLAB_TOKEN\`
3202
+ once, then processes every project in \`PROJECTS\` independently. One project
3203
+ failing does not stop the others; the run fails only if every project fails.
3204
+
3205
+ For each project:
3206
+
3207
+ 1. Loads that project's state (see \`references/state-schema.md\`) and reads its
3208
+ default branch and clone URL.
3209
+ 2. Lists open issues carrying \`TRIGGER_LABEL\`, newest-updated first. GitLab keeps
3210
+ merge requests on their own endpoint, so labelling a merge request never
3211
+ queues an implementation.
3212
+ 3. For each labelled issue, up to \`MAX_NEW_PER_RUN\` new ones per run:
3213
+ - Refetches the issue so a label removed since the listing does not start work.
3214
+ - Finds the latest matching resource label event with \`action: "add"\`, and
3215
+ skips it if that event has already been tracked.
3216
+ - Picks the first free branch name, \`{BRANCH_PREFIX}-{iid}\` or a numbered
3217
+ variant of it.
3218
+ - Clones the default branch, shallow and single-branch, into
3219
+ \`{WORKSPACE_BASE}/issue-to-mr/{group}__{project}/issue-{iid}-{event_id}\`,
3220
+ sets the commit identity, and creates the branch. \`origin\` keeps its plain
3221
+ HTTPS URL, so the workspace holds no credential.
3222
+ - Starts an OpenHands conversation **whose working directory is that clone**,
3223
+ told which issue to read, with the secrets named in \`AGENT_SECRET_NAMES\`
3224
+ and the deployment's MCP servers attached.
3225
+ - Comments on the issue with the branch, the label event, and the conversation
3226
+ link.
3227
+ - Records the task with \`status: "active"\`.
3228
+ - If the clone or the conversation cannot be created, the clone is removed and
3229
+ nothing is recorded, so the next poll retries the label event.
3230
+ 4. For each active task:
3231
+ - Abandons a conversation that has not reached a terminal status within two
3232
+ hours, comments on the issue, and reclaims its clone.
3233
+ - When the conversation reaches \`idle\`, \`finished\`, \`error\`, or \`stuck\`:
3234
+ - Adopts the merge request the agent opened, if GitLab says one exists for
3235
+ the branch, and comments its link on the issue. Everything below is the
3236
+ path taken when it does not.
3237
+ - Skips the merge request if the issue was closed meanwhile.
3238
+ - Reports the problem on the issue if the conversation ended in \`error\` or
3239
+ \`stuck\`.
3240
+ - Commits whatever the agent left uncommitted, on top of any commits it made
3241
+ itself.
3242
+ - Posts the agent's answer on the issue, and opens no merge request, when
3243
+ there are no commits at all - that is how an agent reports an issue too
3244
+ ambiguous to implement.
3245
+ - Otherwise pushes the branch, opens the merge request (draft by default,
3246
+ titled \`Draft: [#42] <issue title>\`, with the agent's summary and
3247
+ \`Closes #42\` in the description), and comments the link on the issue.
3248
+ - A push or merge request that fails is retried on the next two polls before
3249
+ the task is reported as failed, so a transient GitLab error does not throw
3250
+ the work away.
3251
+ 5. Removes the clone of every finished task, but only after confirming the
3252
+ conversation has stopped - deleting it under a running agent would remove its
3253
+ working directory. When that cannot be confirmed the directory is left alone
3254
+ and the next poll tries again.
3255
+ 6. Saves that project's state atomically.
3256
+
3257
+ The completion callback fires once for the whole run.
3258
+
3259
+ ---
3260
+
3261
+ ## Additional Resources
3262
+
3263
+ - **\`references/state-schema.md\`** - State JSON schema, field definitions, and the
3264
+ task lifecycle.
3265
+ - **\`scripts/main.py\`** - The complete automation script. Customize the six
3266
+ constants at the top before packaging.
3267
+
3268
+ ---
3269
+
3270
+ ## Troubleshooting
3271
+
3272
+ | Symptom | Likely cause | Fix |
3273
+ |---|---|---|
3274
+ | Nothing is ever queued | Trigger label not present, or applied to a merge request rather than an issue | Apply the configured label to an issue |
3275
+ | "401 Unauthorized" in run logs | Token expired | Rotate and update \`GITLAB_TOKEN\` |
3276
+ | "The token's role on ... is below Developer" | The token has Reporter or Guest on that project | Grant Developer or above, or drop the project from \`PROJECTS\` |
3277
+ | Push rejected: "You are not allowed to push code to protected branches" | The branch prefix is covered by a protected-branch rule | Leave \`{BRANCH_PREFIX}-*\` unprotected |
3278
+ | Push rejected on \`.gitlab-ci.yml\` | The project protects its CI/CD configuration path | Allow the token's role to update it, or exclude such issues |
3279
+ | 404 on project access | Project path wrong, or no access | Re-check the entry in \`PROJECTS\` and the token's role. Subgroups must be included in full |
3280
+ | \`git is not available in the automation runtime\` | The runtime image has no git | Use a runtime image that ships git; the script clones, commits, and pushes with it |
3281
+ | Issue commented "did not change any code" | The agent judged the issue too ambiguous, or made no edits | Read its answer in the comment, add the missing detail to the issue, then re-apply the label |
3282
+ | Same issue not picked up again after new comments | Its label event was already processed | Remove and re-apply the trigger label |
3283
+ | Agent reports it cannot push or open an MR | By design - it has no push credentials in \`origin\` | No action; the automation pushes and opens the merge request after the agent stops |
3284
+ | \`Warning: could not fetch MCP config\` in run logs | The settings endpoint was unreachable | Non-fatal; the agent falls back to the REST calls in the prompt |
3285
+ | A backlog of labelled issues starts slowly | \`MAX_NEW_PER_RUN\` caps how many conversations one poll starts | Wait for the next polls, or raise the cap in the script |
3286
+ | Clones remain under \`issue-to-mr/\` | Their conversations had not stopped yet | They are removed by a later poll once the conversation is terminal |`,category:`automations`},{name:`incident-retrospective`,description:`Create an automation that drafts incident retrospectives. Gathers incident-channel messages from Slack, collects linked tickets and follow-ups from Linear, and publishes a retrospective draft to Notion with a timeline, impact summary, root-cause hypotheses, and action items.`,triggers:[`/incident-retro:setup`],content:`# Incident Retrospective Drafter Automation
2825
3287
 
2826
3288
  Set up an automation that drafts incident retrospectives by pulling data from
2827
3289
  Slack, Linear, and Notion.
@@ -4928,7 +5390,7 @@ The agent server typically runs inside a **sandbox** (a Docker or Kubernetes con
4928
5390
  |---|---|---|
4929
5391
  | \`RUNTIME_URL\` | Ambient in cloud environments | Public-facing URL of the **agent server** sandbox. Use this to determine whether external webhook delivery is possible — if unset or local, webhooks cannot be received. The automation service may run at a separate URL (see Determining the API Host). |
4930
5392
  | \`AGENT_SERVER_URL\` | Injected into scripts at run time only | Internal URL of the agent server. Available inside script execution context; **not** an ambient environment variable outside of a running script. |
4931
- | \`OPENHANDS_HOST\` | Shell convention only — set manually | Base URL for the automation service API. **Not a real environment variable.** Set it from the \`<HOST>\` system-prompt value, or default to \`https://app.all-hands.dev\`. Used in all \`curl\` examples throughout this skill. |
5393
+ | \`OPENHANDS_HOST\` | Shell convention only — set manually | Base URL for the automation service API. **Not a real environment variable.** Set it from an explicit host, a detected local Agent Canvas server, or the cloud default. Used in all \`curl\` examples throughout this skill. |
4932
5394
 
4933
5395
  > **⚠️ CRITICAL — Agent behavior rules:**
4934
5396
  >
@@ -4993,11 +5455,17 @@ Entrypoint must be \`python3 main.py\` (no \`setup.sh\` needed). Wrap your main
4993
5455
 
4994
5456
  ## Authentication
4995
5457
 
4996
- All requests require Bearer authentication:
5458
+ All requests require authentication:
4997
5459
 
4998
- \`\`\`bash
4999
- -H "Authorization: Bearer \${OPENHANDS_API_KEY}"
5000
- \`\`\`
5460
+ - Cloud (default \`https://app.all-hands.dev\`): Bearer token:
5461
+
5462
+ \`-H "Authorization: Bearer \${OPENHANDS_API_KEY}"\`
5463
+
5464
+ - Local Agent Canvas (\`http://localhost:8001\`): session API key through \`X-Session-API-Key\`:
5465
+
5466
+ \`-H "X-Session-API-Key: \${OPENHANDS_AUTOMATION_API_KEY:-\${SESSION_API_KEY}}"\`
5467
+
5468
+ The curl examples below show cloud Bearer authentication. For local Agent Canvas, replace that header with the \`X-Session-API-Key\` header above.
5001
5469
 
5002
5470
  ## API Endpoints
5003
5471
 
@@ -5007,14 +5475,18 @@ All requests require Bearer authentication:
5007
5475
 
5008
5476
  The automation service may run at a different URL from the agent server. In the examples throughout this skill, \`\${OPENHANDS_HOST}\` is a shell-variable convention for the automation service base URL — it is **not** a real environment variable. Set it from context before running any curl command:
5009
5477
 
5010
- - Look for a \`<HOST>\` value in the system prompt. If present, use that URL.
5478
+ - Look for a \`<HOST>\` value in the system prompt or runtime-services block. If present, use that URL.
5479
+ - If running inside a local Agent Canvas stack and no explicit host is provided, use \`http://localhost:8001\` for the local automation/agent-server API.
5011
5480
  - Otherwise default to \`https://app.all-hands.dev\`.
5012
5481
 
5482
+ For a local Agent Canvas server, validate the endpoint before making a mutating request and authenticate with the session key through \`X-Session-API-Key\` when that API requires it. Do not use the cloud default merely because no \`<HOST>\` value is present.
5483
+
5013
5484
  \`\`\`bash
5014
- OPENHANDS_HOST="https://app.all-hands.dev" # replace with <HOST> if provided
5485
+ # Choose the host that matches the detected environment:
5486
+ OPENHANDS_HOST="http://localhost:8001" # local Agent Canvas
5487
+ # OPENHANDS_HOST="https://app.all-hands.dev" # OpenHands Cloud
5015
5488
  \`\`\`
5016
5489
 
5017
-
5018
5490
  ### Automation Endpoints
5019
5491
 
5020
5492
  | Endpoint | Method | Description |
@@ -5766,233 +6238,328 @@ See \`references/security.md\` — also covers narrowing triggers and sender-lev
5766
6238
  - **\`references/custom-automation.md\`** — Detailed guide for custom automations: tarball uploads, code structure (SDK and no-LLM), state persistence via the KV store, environment variables, validation rules, and complete examples. Consult this whenever you need to evaluate or recommend the custom path (including for deterministic / cost-sensitive tasks per rule 0). Only *implement* a custom automation after the user agrees to that path.
5767
6239
  - **\`references/ab-testing.md\`** — A/B testing for plugin automations: defining variants with weights, experiment configuration, variant selection logic, observability via conversation tags, and complete examples. Consult this when a user wants to compare plugin versions or configurations.
5768
6240
  - **\`references/security.md\`** — Trust boundaries: untrusted content vs. verified sender, least-privilege secrets, trigger scoping, sender authorization, pre-deploy verification. Consult whenever an automation handles external input or forwards secrets to a spawned conversation.
5769
- - **\`references/security.md\`** — Trust boundaries for automations: untrusted event content vs. verified sender, least-privilege secret scoping for spawned conversations, narrowing triggers, sender-level authorization, and verifying a script actually runs before deploying it. Consult this whenever an automation handles external/untrusted input (GitHub issues/PRs, Slack messages, any public-facing webhook) or forwards secrets to a spawned conversation.`,category:`automations`,defaultEnabled:!0},{name:`openhands-sdk`,description:`Reference skill for the OpenHands Software Agent SDK - the Python framework for building AI agents that write software. Use when you need to build agents with the SDK, create custom tools, configure LLMs, manage conversations, delegate to sub-agents, or deploy agents locally or remotely.`,triggers:[`openhands-sdk`,`openhands sdk`,`software-agent-sdk`,`agent-sdk`,`/sdk`],content:`# OpenHands Software Agent SDK
6241
+ - **\`references/security.md\`** — Trust boundaries for automations: untrusted event content vs. verified sender, least-privilege secret scoping for spawned conversations, narrowing triggers, sender-level authorization, and verifying a script actually runs before deploying it. Consult this whenever an automation handles external/untrusted input (GitHub issues/PRs, Slack messages, any public-facing webhook) or forwards secrets to a spawned conversation.`,category:`automations`,defaultEnabled:!0},{name:`openhands-enterprise-troubleshooting`,description:`This skill should be used when a user reports an issue with OpenHands Enterprise (OHE) on a self-hosted (Replicated VM-based) installation. Use for diagnosing sandbox startup failures, auth issues, certificate errors, LLM connectivity problems, Keycloak login issues, Replicated Admin Console access, upgrade failures, or resource exhaustion. Helps triage symptoms, run diagnostic commands, guide through recovery steps, generate and analyze Replicated support bundles offline, and produce escalation handoffs.`,triggers:[`openhands enterprise`,`OHE troubleshooting`,`openhands not working`,`sandbox failed`,`replicated admin console`,`keycloak login`,`certificate error`,`LLM connectivity`,`upgrade failed`,`support bundle`,`openhands install`],content:`# OpenHands Enterprise Troubleshooting
5770
6242
 
5771
- All SDK documentation lives at <https://docs.openhands.dev/sdk>.
6243
+ This skill helps diagnose and resolve common issues on OpenHands Enterprise (OHE) self-hosted installations using Replicated. It covers triage, guided recovery, support bundle generation, and escalation handoffs.
5772
6244
 
5773
- For the full topic index, fetch <https://docs.openhands.dev/llms.txt> and read
5774
- the "OpenHands Software Agent SDK" section.
6245
+ ## Diagnostic Workflow
5775
6246
 
5776
- ## Quick reference
6247
+ When a user reports an OHE issue:
5777
6248
 
5778
- Install: \`pip install openhands-sdk openhands-tools\`
6249
+ 1. **Collect symptoms** - Ask user to describe what they see, error messages, when it started
6250
+ 2. **Identify failure mode** - Match symptoms to one of the common issues below
6251
+ 3. **Run targeted diagnostics** - Use commands in \`references/diagnostics.md\`
6252
+ 4. **Guide recovery** - Follow resolution steps for the identified issue, one at a time
6253
+ 5. **Verify fix** - Confirm the original symptom is gone, not just that the last command succeeded
6254
+ 6. **Generate handoff** - If unresolved, produce a clear summary for the OpenHands team
5779
6255
 
5780
- \`\`\`python
5781
- import os
6256
+ Take recovery one step at a time. Before each step, state what it will change and what you expect to
6257
+ see afterwards; after it, run the check that confirms it before moving on. If the check fails or
6258
+ shows something unexpected, stop and re-diagnose — a step applied on top of a failed one buries the
6259
+ evidence, and several applied blind can leave the install worse than the fault you started with.
6260
+ Destructive steps (restarts, rollbacks, config changes) need the user's agreement first, and are
6261
+ worth recording as you go so the handoff can say exactly what was changed.
5782
6262
 
5783
- from openhands.sdk import LLM, Agent, Conversation, Tool
5784
- from openhands.tools.file_editor import FileEditorTool
5785
- from openhands.tools.task_tracker import TaskTrackerTool
5786
- from openhands.tools.terminal import TerminalTool
6263
+ Work from whatever the user has. A described symptom starts at step 1; a support bundle goes to
6264
+ [Analyzing the Support Bundle](#analyzing-the-support-bundle). If they paste raw log output, the
6265
+ triage method in
6266
+ [\`references/support-bundle-analysis.md\`](references/support-bundle-analysis.md#triaging-a-log-file)
6267
+ applies to pasted text as well as to files, and notes what a hand-picked excerpt can hide.
5787
6268
 
6269
+ ## Common Failure Modes
5788
6270
 
5789
- llm = LLM(
5790
- model=os.getenv("LLM_MODEL", "gpt-5.5"),
5791
- api_key=os.getenv("LLM_API_KEY"),
5792
- base_url=os.getenv("LLM_BASE_URL", None),
5793
- )
6271
+ ### 1. Sandbox Fails to Start / Timeout
5794
6272
 
5795
- agent = Agent(
5796
- llm=llm,
5797
- tools=[
5798
- Tool(name=TerminalTool.name),
5799
- Tool(name=FileEditorTool.name),
5800
- Tool(name=TaskTrackerTool.name),
5801
- ],
5802
- )
6273
+ **Symptoms:**
6274
+ - Conversation hangs then times out
6275
+ - "Sandbox failed to start" error
6276
+ - A timeout in the logs. Read the actual value rather than assuming one: the timeouts in
6277
+ \`runtime-api\` are configurable and differ between the Kubernetes client and the app, so quoting a
6278
+ fixed number back to a customer is how you end up chasing the wrong one.
6279
+
6280
+ **Diagnosis:** Check sandbox service status, the \`sysbox-runc\` RuntimeClass and its containerd
6281
+ runtime, resource availability
5803
6282
 
5804
- cwd = os.getcwd()
5805
- conversation = Conversation(agent=agent, workspace=cwd)
6283
+ **Reference:** See \`references/diagnostics.md\` - Section "Sandbox Startup"
5806
6284
 
5807
- conversation.send_message("Write 3 facts about the current project into FACTS.txt.")
5808
- conversation.run()
5809
- print("All done!")
6285
+ ### 2. Git Provider Auth Broken
6286
+
6287
+ **Symptoms:**
6288
+ - "Authentication failed" for the configured provider
6289
+ - Can't clone or push repos
6290
+ - The provider shows as disconnected
6291
+
6292
+ **Diagnosis:** Check the provider's secret in Kubernetes and that the provider is enabled. GitHub,
6293
+ GitLab, Bitbucket Data Center, and Azure DevOps are each configured separately — confirm which one
6294
+ the user is actually on before diagnosing
6295
+
6296
+ **Reference:** See \`references/diagnostics.md\` - Section "Git Provider Auth"
6297
+
6298
+ ### 3. Certificate Errors
6299
+
6300
+ **Symptoms:**
6301
+ - "certificate expired" or "self-signed certificate" errors
6302
+ - TLS handshake failures
6303
+ - Browser shows insecure connection warning
6304
+
6305
+ **Diagnosis:** Check cert expiry, certificate chain, ingress configuration
6306
+
6307
+ **Reference:** See \`references/diagnostics.md\` - Section "Certificate Issues"
6308
+
6309
+ ### 4. LLM Connectivity Failures
6310
+
6311
+ **Symptoms:**
6312
+ - "LLM endpoint unreachable"
6313
+ - "Authentication failed" for LLM API
6314
+ - Conversations fail to start
6315
+
6316
+ **Diagnosis:** Check LLM endpoint URL, API key secrets, network policies
6317
+
6318
+ **Reference:** See \`references/diagnostics.md\` - Section "LLM Connectivity"
6319
+
6320
+ ### 5. Keycloak Login Issues
6321
+
6322
+ **Symptoms:**
6323
+ - Can't access admin console
6324
+ - Login loop or "invalid credentials"
6325
+ - Keycloak pod showing errors
6326
+
6327
+ **Diagnosis:** Check Keycloak pod status, database connectivity, realm configuration
6328
+
6329
+ **Reference:** See \`references/diagnostics.md\` - Section "Keycloak"
6330
+
6331
+ ### 6. Replicated Admin Console Unreachable
6332
+
6333
+ **Symptoms:**
6334
+ - Can't access admin console URL
6335
+ - Connection refused or timeout
6336
+ - Browser shows "site cannot be reached"
6337
+
6338
+ **Diagnosis:** Check Replicated operator pod, ingress, service endpoints
6339
+
6340
+ **Reference:** See \`references/diagnostics.md\` - Section "Replicated Admin Console"
6341
+
6342
+ ### 7. Upgrade Stuck or Failed
6343
+
6344
+ **Symptoms:**
6345
+ - Replicated shows upgrade as "failed"
6346
+ - Pods in crash loop after upgrade
6347
+ - Migration jobs failing
6348
+
6349
+ **Diagnosis:** Check failed job logs, resource availability, pre-flight failures
6350
+
6351
+ **Reference:** See \`references/diagnostics.md\` - Section "Upgrade Issues"
6352
+
6353
+ ### 8. OOM / Resource Exhaustion
6354
+
6355
+ **Symptoms:**
6356
+ - Pods being OOMKilled
6357
+ - "Too many open files" errors
6358
+ - Services becoming unresponsive
6359
+
6360
+ **Diagnosis:** Check node resources (memory, disk, file descriptors)
6361
+
6362
+ **Reference:** See \`references/diagnostics.md\` - Section "Resource Exhaustion"
6363
+
6364
+ ## Diagnostic Commands Quick Reference
6365
+
6366
+ Access the VM and run these common commands.
6367
+
6368
+ **An empty result never means "healthy".** \`kubectl get pods -l <selector>\` prints \`No resources
6369
+ found\` and exits 0 both when a component is down and when the selector is wrong, so the two are
6370
+ indistinguishable. When you need to know whether something is running, ask its Deployment or
6371
+ StatefulSet for a READY count instead — that object exists either way, and \`0/1\` means down while a
6372
+ \`NotFound\` error means you had the name wrong.
6373
+
6374
+ \`\`\`bash
6375
+ # Is it up? READY answers this; an empty pod list does not.
6376
+ kubectl get deploy,statefulset -n openhands
6377
+
6378
+ # Check overall pod status
6379
+ kubectl get pods -n openhands
6380
+
6381
+ # View pod logs (replace POD_NAME)
6382
+ kubectl logs -n openhands POD_NAME
6383
+ kubectl logs -n openhands POD_NAME --previous
6384
+
6385
+ # Describe a pod for events
6386
+ kubectl describe pod -n openhands POD_NAME
6387
+
6388
+ # Check resource usage
6389
+ kubectl top nodes
6390
+ kubectl top pods -n openhands
6391
+
6392
+ # Check certificate expiry
6393
+ echo | openssl s_client -connect HOST:443 2>/dev/null | openssl x509 -noout -dates
6394
+
6395
+ # Check the Replicated components. On Embedded Cluster these are the Admin
6396
+ # Console in \`kotsadm\`, the operator in \`embedded-cluster\`, and the Replicated
6397
+ # SDK in \`openhands\` under app.kubernetes.io/name=replicated. A \`replicated\`
6398
+ # namespace belongs to the older kURL topology and is absent here.
6399
+ kubectl get pods -n kotsadm
6400
+ kubectl get pods -n embedded-cluster
6401
+ kubectl get pods -n openhands -l app.kubernetes.io/name=replicated
5810
6402
  \`\`\`
5811
6403
 
5812
- ## Core classes (\`openhands.sdk\`)
6404
+ ## Support Bundle Generation
6405
+
6406
+ When the issue requires deeper investigation — or before escalating — generate a support bundle. It
6407
+ captures both host- and cluster-level state in one archive.
6408
+
6409
+ ### Generating the Support Bundle
6410
+
6411
+ SSH to the VM, then from the directory containing the installer binary:
6412
+
6413
+ \`\`\`bash
6414
+ sudo ./openhands support-bundle
6415
+ \`\`\`
5813
6416
 
5814
- | Class | Purpose |
6417
+ This uses the default Embedded Cluster spec to collect cluster- *and* host-level information, and
6418
+ automatically includes the OpenHands application-specific collectors. Run it on a **controller
6419
+ node** — on a non-controller node it cannot capture cluster-wide information.
6420
+
6421
+ For Embedded Cluster versions earlier than 1.17.0, use the support-bundle plugin from within the
6422
+ cluster shell instead:
6423
+
6424
+ \`\`\`bash
6425
+ sudo ./openhands shell
6426
+ kubectl support-bundle --load-cluster-specs /var/lib/embedded-cluster/support/host-support-bundle.yaml
6427
+ \`\`\`
6428
+
6429
+ The bundle is written to the working directory as \`support-bundle-<UTC timestamp>.tar.gz\`. Share it
6430
+ with the OpenHands team, or analyze it directly with the steps below.
6431
+
6432
+ Support bundles carry potentially sensitive data. Replicated's redactor masks common secret patterns
6433
+ as \`***HIDDEN***\`, but it is not a guarantee — hostnames, user and installation identifiers, and
6434
+ config values routinely survive it. Treat a bundle as confidential, send it only through the channel
6435
+ the OpenHands team gives you, and avoid pasting raw excerpts into public issues or chats.
6436
+
6437
+ ### Analyzing the Support Bundle
6438
+
6439
+ **Full guide: [\`references/support-bundle-analysis.md\`](references/support-bundle-analysis.md).**
6440
+ Read it before drawing conclusions — the bundle's layout is not what you would guess from \`kubectl\`,
6441
+ and several of its gaps produce convincing false negatives.
6442
+
6443
+ Fast path — the bundled triage script reconstructs the standard first pass (cluster meta, analyzer
6444
+ results, pod table, OOM and restart scan, \`top\` equivalent, allocatable headroom, events) in one
6445
+ command. It reports; the ranking and the diagnosis are yours to make:
6446
+
6447
+ \`\`\`bash
6448
+ tar -xzf support-bundle-2026-07-28T06_54_18.tar.gz
6449
+ python3 scripts/bundle_triage.py support-bundle-2026-07-28T06_54_18
6450
+ \`\`\`
6451
+
6452
+ You are reading this bundle because something is broken, so treat a clean run as "not here" rather
6453
+ than "nothing wrong" — the script sees pod objects, analyzer verdicts, node conditions and resource
6454
+ totals, and reads no application logs at all. \`references/support-bundle-analysis.md\` has a section
6455
+ on where to look next when the objects come back clean.
6456
+
6457
+ Then the four things that most often answer the question outright:
6458
+
6459
+ | Question | Where to look |
5815
6460
  |---|---|
5816
- | [\`Agent\`](https://docs.openhands.dev/sdk/arch/agent.md) | Reasoning-action loop |
5817
- | [\`Condenser\`](https://docs.openhands.dev/sdk/arch/condenser.md) | Conversation history compression system |
5818
- | [\`Conversation\`](https://docs.openhands.dev/sdk/arch/conversation.md) | Conversation orchestration system |
5819
- | [\`Event\`](https://docs.openhands.dev/sdk/arch/events.md) | Typed event framework |
5820
- | [\`LLM\`](https://docs.openhands.dev/sdk/arch/llm.md) | Provider-agnostic language model interface |
5821
- | [\`SecurityAnalyzer\`](https://docs.openhands.dev/sdk/arch/security.md) | Action security analysis and validation |
5822
- | [\`Skill\`](https://docs.openhands.dev/sdk/arch/skill.md) | Reusable prompt system |
5823
- | [\`Tool / ToolDefinition\`](https://docs.openhands.dev/sdk/arch/tool-system.md) | Action-observation tool framework |
5824
- | [\`Workspace\`](https://docs.openhands.dev/sdk/arch/workspace.md) | Execution environment abstraction |
5825
-
5826
- ## API reference
5827
-
5828
- [\`openhands.sdk.agent\`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.agent.md), [\`openhands.sdk.conversation\`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.conversation.md), [\`openhands.sdk.event\`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.event.md), [\`openhands.sdk.llm\`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.llm.md), [\`openhands.sdk.security\`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.security.md), [\`openhands.sdk.tool\`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.tool.md), [\`openhands.sdk.utils\`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.utils.md), [\`openhands.sdk.workspace\`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.workspace.md)
5829
-
5830
- ## Guides
5831
-
5832
- - [ACP Agent](https://docs.openhands.dev/sdk/guides/agent-acp.md): Delegate to an ACP-compatible server (Claude Code, Gemini CLI, etc.) instead of calling an LLM directly.
5833
- - [Agent Settings](https://docs.openhands.dev/sdk/guides/agent-settings.md): Configure, serialize, and recreate agents from structured settings.
5834
- - [Agent Skills & Context](https://docs.openhands.dev/sdk/guides/skill.md): Skills add specialized behaviors, domain knowledge, and context-aware triggers to your agent through structured prompts.
5835
- - [API-based Sandbox](https://docs.openhands.dev/sdk/guides/agent-server/api-sandbox.md): Connect to hosted API-based agent server for fully managed infrastructure.
5836
- - [Apptainer Sandbox](https://docs.openhands.dev/sdk/guides/agent-server/apptainer-sandbox.md): Run agent server in rootless Apptainer containers for HPC and shared computing environments.
5837
- - [Ask Agent Questions](https://docs.openhands.dev/sdk/guides/convo-ask-agent.md): Get sidebar replies from the agent during conversation execution without interrupting the main flow.
5838
- - [Assign Reviews](https://docs.openhands.dev/sdk/guides/github-workflows/assign-reviews.md): Automate PR management with intelligent reviewer assignment and workflow notifications using OpenHands Agent
5839
- - [Browser Session Recording](https://docs.openhands.dev/sdk/guides/browser-session-recording.md): Record and replay your agent's browser sessions using rrweb.
5840
- - [Browser Use](https://docs.openhands.dev/sdk/guides/agent-browser-use.md): Enable web browsing and interaction capabilities for your agent.
5841
- - [Context Condenser](https://docs.openhands.dev/sdk/guides/context-condenser.md): Manage agent memory by condensing conversation history to save tokens.
5842
- - [Conversation Goals](https://docs.openhands.dev/sdk/guides/agent-server/conversation-goals.md): Add a resumable goal strategy to a normal agent-server conversation.
5843
- - [Conversation with Async](https://docs.openhands.dev/sdk/guides/convo-async.md): Use async/await for concurrent agent operations and non-blocking execution.
5844
- - [Creating Custom Agent](https://docs.openhands.dev/sdk/guides/agent-custom.md): Learn how to design specialized agents with custom tool sets
5845
- - [Critic (Experimental)](https://docs.openhands.dev/sdk/guides/critic.md): Real-time evaluation of agent actions using an LLM-based critic model, with built-in iterative refinement.
5846
- - [Custom Tools](https://docs.openhands.dev/sdk/guides/custom-tools.md): Tools define what agents can do. The SDK includes built-in tools for common operations and supports creating custom tools for specialized needs.
5847
- - [Custom Tools with Remote Agent Server](https://docs.openhands.dev/sdk/guides/agent-server/custom-tools.md): Learn how to use custom tools with a remote agent server by building a custom base image that includes your tool implementations.
5848
- - [Custom Visualizer](https://docs.openhands.dev/sdk/guides/convo-custom-visualizer.md): Customize conversation visualization by creating custom visualizers or configuring the default visualizer.
5849
- - [Deferred Init (Warm-Pool)](https://docs.openhands.dev/sdk/guides/agent-server/deferred-init.md): Pre-warm agent-server pods before a user is matched, then activate them at runtime with POST /api/init.
5850
- - [Docker Sandbox](https://docs.openhands.dev/sdk/guides/agent-server/docker-sandbox.md): Run agent server in isolated Docker containers for security and reproducibility.
5851
- - [Exception Handling](https://docs.openhands.dev/sdk/guides/llm-error-handling.md): Provider‑agnostic exceptions raised by the SDK and recommended patterns for handling them.
5852
- - [FAQ](https://docs.openhands.dev/sdk/faq.md): Frequently asked questions about the OpenHands SDK
5853
- - [File-Based Agents](https://docs.openhands.dev/sdk/guides/agent-file-based.md): Define specialized sub-agents as simple Markdown files with YAML frontmatter no Python code required.
5854
- - [Fork a Conversation](https://docs.openhands.dev/sdk/guides/convo-fork.md): Branch off an existing conversation for follow-up exploration without contaminating the original.
5855
- - [Getting Started](https://docs.openhands.dev/sdk/getting-started.md): Install the OpenHands SDK and build AI agents that write software.
5856
- - [Goal Completion Loop](https://docs.openhands.dev/sdk/guides/convo-goal.md): Drive a conversation toward a verifiable objective with a judge-driven, self-continuing completion loop.
5857
- - [GPT-5 Preset (ApplyPatchTool)](https://docs.openhands.dev/sdk/guides/llm-gpt5-preset.md): Use the GPT-5 preset to build an agent that swaps the standard FileEditorTool for ApplyPatchTool.
5858
- - [Hello World](https://docs.openhands.dev/sdk/guides/hello-world.md): The simplest possible OpenHands agent - configure an LLM, create an agent, and complete a task.
5859
- - [Hooks](https://docs.openhands.dev/sdk/guides/hooks.md): Use lifecycle hooks to observe, log, and customize agent execution.
5860
- - [Image Input](https://docs.openhands.dev/sdk/guides/llm-image-input.md): Send images to multimodal agents for vision-based tasks and analysis.
5861
- - [Interactive Terminal](https://docs.openhands.dev/sdk/guides/agent-interactive-terminal.md): Enable agents to interact with terminal applications like ipython, python REPL, and other interactive CLI tools.
5862
- - [Iterative Refinement](https://docs.openhands.dev/sdk/guides/iterative-refinement.md): Implement iterative refinement workflows where agents refine their work based on critique feedback until quality thresholds are met.
5863
- - [LLM Fallback Strategy](https://docs.openhands.dev/sdk/guides/llm-fallback.md): Automatically try alternate LLMs when the primary model fails with a transient error.
5864
- - [LLM Profile Store](https://docs.openhands.dev/sdk/guides/llm-profile-store.md): Save, load, and manage reusable LLM configurations so you never repeat setup code again.
5865
- - [LLM Registry](https://docs.openhands.dev/sdk/guides/llm-registry.md): Dynamically select and configure language models using the LLM registry.
5866
- - [LLM Streaming](https://docs.openhands.dev/sdk/guides/llm-streaming.md): Stream LLM responses token-by-token for real-time display and interactive user experiences.
5867
- - [LLM Subscriptions](https://docs.openhands.dev/sdk/guides/llm-subscriptions.md): Use your ChatGPT Plus/Pro subscription to access Codex models without consuming API credits.
5868
- - [Local Agent Server](https://docs.openhands.dev/sdk/guides/agent-server/local-server.md): Install and run an OpenHands Agent Server on your machine, then connect to it from the SDK.
5869
- - [Metrics Tracking](https://docs.openhands.dev/sdk/guides/metrics.md): Track token usage, costs, and latency metrics for your agents.
5870
- - [Model Context Protocol](https://docs.openhands.dev/sdk/guides/mcp.md): Model Context Protocol (MCP) enables dynamic tool integration from external servers. Agents can discover and use MCP-provided tools automatically.
5871
- - [Model Routing](https://docs.openhands.dev/sdk/guides/llm-routing.md): Route agent's LLM requests to different models.
5872
- - [Observability & Tracing](https://docs.openhands.dev/sdk/guides/observability.md): Enable OpenTelemetry tracing to monitor and debug your agent's execution with tools like Laminar, MLflow, Honeycomb, or any OTLP-compatible backend.
5873
- - [OpenAI-Compatible Endpoint](https://docs.openhands.dev/sdk/guides/agent-server/openai-gateway.md): Call an OpenHands agent-server through the OpenAI Chat Completions protocol.
5874
- - [OpenHands Cloud Workspace](https://docs.openhands.dev/sdk/guides/agent-server/cloud-workspace.md): Connect to OpenHands Cloud for fully managed sandbox environments with optional SaaS credential inheritance.
5875
- - [Overview](https://docs.openhands.dev/sdk/guides/agent-server/overview.md): Run agents on remote servers with isolated workspaces for production deployments.
5876
- - [Parallel Tool Execution](https://docs.openhands.dev/sdk/guides/parallel-tool-execution.md): Execute multiple tools concurrently within a single LLM response to improve throughput for independent operations.
5877
- - [Pause and Resume](https://docs.openhands.dev/sdk/guides/convo-pause-and-resume.md): Pause agent execution, perform operations, and resume without losing state.
5878
- - [Persistence](https://docs.openhands.dev/sdk/guides/convo-persistence.md): Save and restore conversation state for multi-session workflows.
5879
- - [Persistent Memory](https://docs.openhands.dev/sdk/guides/persistent-memory.md): Give agents opt-in, two-tier memory that survives across conversations.
5880
- - [Plugins](https://docs.openhands.dev/sdk/guides/plugins.md): Plugins bundle skills, hooks, MCP servers, agents, and commands into reusable packages that extend agent capabilities.
5881
- - [PR Review](https://docs.openhands.dev/sdk/guides/github-workflows/pr-review.md): Use OpenHands Agent to generate meaningful pull request review
5882
- - [Reasoning](https://docs.openhands.dev/sdk/guides/llm-reasoning.md): Access model reasoning traces from Anthropic extended thinking and OpenAI responses API.
5883
- - [Secret Registry](https://docs.openhands.dev/sdk/guides/secrets.md): Provide environment variables and secrets to agent workspace securely.
5884
- - [Security & Action Confirmation](https://docs.openhands.dev/sdk/guides/security.md): Control agent action execution through confirmation policy and security analyzer.
5885
- - [Send Message While Running](https://docs.openhands.dev/sdk/guides/convo-send-message-while-running.md): Interrupt running agents to provide additional context or corrections.
5886
- - [Software Agent SDK](https://docs.openhands.dev/sdk.md): Build AI agents that write software. A clean, modular SDK with production-ready tools.
5887
- - [Stuck Detector](https://docs.openhands.dev/sdk/guides/agent-stuck-detector.md): Detect and handle stuck agents automatically with timeout mechanisms.
5888
- - [Task Tool Set](https://docs.openhands.dev/sdk/guides/task-tool-set.md): Delegate complex work to specialized sub-agents that run synchronously and return results to the parent agent.
5889
- - [Theory of Mind (TOM) Agent](https://docs.openhands.dev/sdk/guides/agent-tom-agent.md): Enable your agent to understand user intent and preferences through Theory of Mind capabilities, providing personalized guidance based on user modeling.
5890
- - [TODO Management](https://docs.openhands.dev/sdk/guides/github-workflows/todo-management.md): Implement TODOs using OpenHands Agent
5891
-
5892
- ## Examples
5893
-
5894
- Source: [\`examples/\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples)
5895
-
5896
- ### [\`01_standalone_sdk/\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk)
5897
-
5898
- - [\`01_hello_world.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/01_hello_world.py)
5899
- - [\`02_custom_tools.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/02_custom_tools.py)
5900
- - [\`03_activate_skill.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/03_activate_skill.py)
5901
- - [\`04_confirmation_mode_example.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/04_confirmation_mode_example.py)
5902
- - [\`05_use_llm_registry.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/05_use_llm_registry.py)
5903
- - [\`06_interactive_terminal_w_reasoning.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/06_interactive_terminal_w_reasoning.py)
5904
- - [\`07_mcp_integration.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/07_mcp_integration.py)
5905
- - [\`08_mcp_with_oauth.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/08_mcp_with_oauth.py)
5906
- - [\`09_pause_example.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/09_pause_example.py)
5907
- - [\`10_persistence.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/10_persistence.py)
5908
- - [\`11_async.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/11_async.py)
5909
- - [\`12_custom_secrets.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/12_custom_secrets.py)
5910
- - [\`13_get_llm_metrics.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/13_get_llm_metrics.py)
5911
- - [\`14_context_condenser.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/14_context_condenser.py)
5912
- - [\`15_browser_use.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/15_browser_use.py)
5913
- - [\`16_llm_security_analyzer.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/16_llm_security_analyzer.py)
5914
- - [\`17_image_input.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/17_image_input.py)
5915
- - [\`18_send_message_while_processing.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/18_send_message_while_processing.py)
5916
- - [\`19_llm_routing.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/19_llm_routing.py)
5917
- - [\`20_stuck_detector.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/20_stuck_detector.py)
5918
- - [\`21_generate_extraneous_conversation_costs.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/21_generate_extraneous_conversation_costs.py)
5919
- - [\`22_anthropic_thinking.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/22_anthropic_thinking.py)
5920
- - [\`23_responses_reasoning.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/23_responses_reasoning.py)
5921
- - [\`24_planning_agent_workflow.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/24_planning_agent_workflow.py)
5922
- - [\`25_agent_delegation.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/25_agent_delegation.py)
5923
- - [\`26_custom_visualizer.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/26_custom_visualizer.py)
5924
- - [\`27_observability_laminar.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/27_observability_laminar.py)
5925
- - [\`28_ask_agent_example.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/28_ask_agent_example.py)
5926
- - [\`29_llm_streaming.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/29_llm_streaming.py)
5927
- - [\`30_tom_agent.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/30_tom_agent.py)
5928
- - [\`31_iterative_refinement.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/31_iterative_refinement.py)
5929
- - [\`32_configurable_security_policy.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/32_configurable_security_policy.py)
5930
- - [\`33_hooks\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/33_hooks)
5931
- - [\`34_critic_example.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/34_critic_example.py)
5932
- - [\`35_subscription_login.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/35_subscription_login.py)
5933
- - [\`36_event_json_to_openai_messages.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/36_event_json_to_openai_messages.py)
5934
- - [\`37_llm_profile_store\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/37_llm_profile_store)
5935
- - [\`38_browser_session_recording.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/38_browser_session_recording.py)
5936
- - [\`39_llm_fallback.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/39_llm_fallback.py)
5937
- - [\`40_acp_agent_example.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/40_acp_agent_example.py)
5938
- - [\`41_task_tool_set.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/41_task_tool_set.py)
5939
- - [\`42_file_based_subagents.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/42_file_based_subagents.py)
5940
- - [\`44_model_switching_in_convo.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/44_model_switching_in_convo.py)
5941
- - [\`45_parallel_tool_execution.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/45_parallel_tool_execution.py)
5942
- - [\`46_agent_settings.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/46_agent_settings.py)
5943
- - [\`47_defense_in_depth_security.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/47_defense_in_depth_security.py)
5944
- - [\`48_conversation_fork.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/48_conversation_fork.py)
5945
- - [\`49_switch_llm_tool.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/49_switch_llm_tool.py)
5946
- - [\`50_async_cancellation.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/50_async_cancellation.py)
5947
- - [\`51_agent_hooks\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/51_agent_hooks)
5948
- - [\`52_dynamic_workflow.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/52_dynamic_workflow.py)
5949
- - [\`53_client_defined_tools.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/53_client_defined_tools.py)
5950
- - [\`54_goal_completion_loop.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/54_goal_completion_loop.py)
5951
- - [\`55_persistent_memory.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/55_persistent_memory.py)
5952
- - [\`56_structured_output.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/56_structured_output.py)
5953
- - [\`57_prompt_hooks\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/57_prompt_hooks)
5954
- - [\`58_ask_oracle_tool\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/58_ask_oracle_tool)
5955
-
5956
- ### [\`02_remote_agent_server/\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server)
5957
-
5958
- - [\`01_convo_with_local_agent_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/01_convo_with_local_agent_server.py)
5959
- - [\`02_convo_with_docker_sandboxed_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/02_convo_with_docker_sandboxed_server.py)
5960
- - [\`03_browser_use_with_docker_sandboxed_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/03_browser_use_with_docker_sandboxed_server.py)
5961
- - [\`04_convo_with_api_sandboxed_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/04_convo_with_api_sandboxed_server.py)
5962
- - [\`05_vscode_with_docker_sandboxed_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/05_vscode_with_docker_sandboxed_server.py)
5963
- - [\`06_custom_tool\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/06_custom_tool)
5964
- - [\`07_convo_with_cloud_workspace.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/07_convo_with_cloud_workspace.py)
5965
- - [\`08_convo_with_apptainer_sandboxed_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/08_convo_with_apptainer_sandboxed_server.py)
5966
- - [\`09_acp_agent_with_remote_runtime.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py)
5967
- - [\`10_cloud_workspace_share_credentials.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/10_cloud_workspace_share_credentials.py)
5968
- - [\`11_conversation_fork.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/11_conversation_fork.py)
5969
- - [\`12_settings_and_secrets_api.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/12_settings_and_secrets_api.py)
5970
- - [\`13_workspace_get_llm.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/13_workspace_get_llm.py)
5971
- - [\`14_client_defined_tools.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/14_client_defined_tools.py)
5972
- - [\`15_openai_compatible_gateway.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/15_openai_compatible_gateway.py)
5973
- - [\`16_deferred_init.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/16_deferred_init.py)
5974
- - [\`hook_scripts\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/hook_scripts)
5975
- - [\`scripts\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/scripts)
5976
-
5977
- ### [\`03_github_workflows/\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows)
5978
-
5979
- - [\`01_basic_action\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/01_basic_action)
5980
- - [\`02_pr_review\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/02_pr_review)
5981
- - [\`03_todo_management\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/03_todo_management)
5982
- - [\`04_datadog_debugging\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/04_datadog_debugging)
5983
- - [\`05_posthog_debugging\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/05_posthog_debugging)
5984
-
5985
- ### [\`04_llm_specific_tools/\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/04_llm_specific_tools)
5986
-
5987
- - [\`01_gpt5_apply_patch_preset.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/04_llm_specific_tools/01_gpt5_apply_patch_preset.py)
5988
- - [\`02_gemini_file_tools.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/04_llm_specific_tools/02_gemini_file_tools.py)
5989
-
5990
- ### [\`05_skills_and_plugins/\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins)
5991
-
5992
- - [\`01_loading_agentskills\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/01_loading_agentskills)
5993
- - [\`02_loading_plugins\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/02_loading_plugins)
5994
- - [\`03_managing_installed_skills\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/03_managing_installed_skills)
5995
- - [\`04_mixed_marketplace_skills\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/04_mixed_marketplace_skills)`,category:`agent-authoring`,defaultEnabled:!0},{name:`pdflatex`,description:`Install and use pdflatex to compile LaTeX documents into PDFs on Linux. Use when generating academic papers, research publications, or any documents written in LaTeX.`,triggers:[`pdflatex`],content:`PdfLatex is a tool that converts Latex sources into PDF. This is specifically very important for researchers, as they use it to publish their findings. It could be installed very easily using Linux terminal, though this seems an annoying task on Windows. Installation commands are given below.
6461
+ | What did the collector already conclude? | \`analysis.json\` pre-computed verdicts, highest-value file in the bundle |
6462
+ | What is each pod actually doing? | \`cluster-resources/pods/<namespace>.json\` |
6463
+ | What did a container log? | \`cluster-resources/pods/logs/<ns>/<pod>/<container>.log\` |
6464
+ | What is the install running? | \`kots/admin_console/app-info.json\` version, channel, sequence |
6465
+
6466
+ Four traps worth knowing before you start:
6467
+
6468
+ - **Never use file mtimes for timing.** They record when you extracted the archive. Take the capture
6469
+ time from the bundle directory name, which is UTC.
6470
+ - **Log filenames are container names, not pod names.** Init-container failures (\`migrate-db\`,
6471
+ \`wait-for-db\`) are invisible to \`kubectl logs <pod>\` and are the easiest real failure to miss.
6472
+ - **\`***HIDDEN***\` means "redacted", not "unset".** The redactor over-redacts, including non-secrets.
6473
+ - **Check a log's format before filtering it.** Most bundle logs are plain text, not JSON, and \`jq\`
6474
+ aborts on the first non-JSON line — so a severity filter can print nothing on a file full of
6475
+ errors. Prefix with \`grep '^{'\`, and read the non-JSON lines separately.
6476
+
6477
+ Once triage points at a failure mode, use \`references/diagnostics.md\` for that mode's specific
6478
+ commands and error patterns.
6479
+
6480
+ ### Summarizing the Bundle: Most Likely Root Cause
6481
+
6482
+ The script reports; deciding which of its observations explains the user's symptom is your job. Work
6483
+ through its output in this order, because it is roughly the order in which a finding is likely to be
6484
+ the actual cause rather than a side effect.
6485
+
6486
+ **1. Start from the symptom and the clock, not from the output.** Get the capture time from the
6487
+ bundle directory name (UTC) and establish when the user says it broke. A finding that predates the
6488
+ symptom by weeks is background; one that starts within the window is a candidate. Ages in the pod
6489
+ table are the cheapest way to place an event in time.
6490
+
6491
+ **2. Read \`analysis.json\` first but not literally.** The collector's own verdicts are the
6492
+ highest-value content in the bundle. Two cautions when reading them through the script: everything
6493
+ non-passing prints under a \`FAIL\` heading, including \`warn\`-severity entries that may be advisory,
6494
+ so check the severity in \`analysis.json\` before calling one a failure; and per-object analyzers are
6495
+ collapsed into families with one example each, so \`[x12]\` means twelve objects affected and the
6496
+ example shown is arbitrary. Open the file directly before quoting an analyzer verdict to a customer.
6497
+
6498
+ **3. Rank what remains by how directly it explains the symptom.** In descending order of
6499
+ usefulness a container in \`CrashLoopBackOff\` or actively OOM-killed right now; a pod that never
6500
+ started (\`Pending\`, \`CreateContainerConfigError\`, an init container that never completed); a pod
6501
+ that is \`Running\` but not \`Ready\`, which fails a health check and takes traffic out of rotation; a
6502
+ node condition that is genuinely bad; and resource pressure, which is usually a consequence rather
6503
+ than a cause. A recovered termination visible only as \`lastState\` with an older age explains a
6504
+ past blip, not a live outage; do not lead with one.
6505
+
6506
+ **4. Prefer the cause nearest the symptom.** A failed \`migrate-db\` init container and an app pod
6507
+ stuck \`Pending\` are one finding, not two, and the init container is the one to report. When several
6508
+ findings share a timestamp, look for the common dependency rather than listing all of them.
6509
+
6510
+ **5. Say what you ruled out.** The script reads pod objects, analyzer verdicts, node conditions and
6511
+ resource totals — and no application logs. If nothing in the objects explains the symptom, that is
6512
+ itself a result: it puts the cause in the application logs, in the network path, or outside the
6513
+ cluster. Name which, rather than reporting that the bundle looked healthy.
6514
+
6515
+ State the conclusion with its evidence and its confidence the object or analyzer it rests on, and
6516
+ whether it explains the reported symptom or merely coincides with it. A ranked shortlist of two or
6517
+ three candidates is more useful than a single confident guess, and it drops straight into the
6518
+ **Likely Root Cause** field of the handoff template below.
6519
+
6520
+ ## Escalation Handoff Template
6521
+
6522
+ When an issue cannot be resolved, produce this summary:
6523
+
6524
+ \`\`\`
6525
+ ## Issue Summary
6526
+ **Problem:** [One-line description]
6527
+ **Duration:** [When it started]
6528
+ **Impact:** [Who is affected]
6529
+
6530
+ ## Symptoms Observed
6531
+ - [Symptom 1]
6532
+ - [Symptom 2]
6533
+
6534
+ ## Diagnostic Steps Taken
6535
+ 1. [Step 1]
6536
+ 2. [Step 2]
6537
+
6538
+ ## Logs / Evidence
6539
+ \`\`\`
6540
+ [Relevant log excerpts]
6541
+ \`\`\`
6542
+
6543
+ ## Resolution Attempts
6544
+ - [Attempt 1] - [Result]
6545
+ - [Attempt 2] - [Result]
6546
+
6547
+ ## Likely Root Cause
6548
+ [Analysis]
6549
+ \`\`\`
6550
+
6551
+ ## Additional Resources
6552
+
6553
+ - **Diagnostic Reference:** [\`references/diagnostics.md\`](references/diagnostics.md) — detailed commands and log interpretation for each failure mode
6554
+ - **Support Bundle Analysis:** [\`references/support-bundle-analysis.md\`](references/support-bundle-analysis.md) — reading a bundle offline: file map, interpretation traps, known gaps
6555
+ - **Triage Script:** \`scripts/bundle_triage.py\` — offline first-pass triage, standard library only
6556
+ - **Replicated Docs:** [Generating support bundles for Embedded Cluster](https://docs.replicated.com/vendor/support-bundle-embedded)
6557
+
6558
+ ## Maintenance
6559
+
6560
+ As new failure modes are discovered in the field, add them to this skill. Update
6561
+ \`references/diagnostics.md\` with new patterns and resolution steps, and add the offline equivalent to
6562
+ \`references/support-bundle-analysis.md\` when the failure is diagnosable from a bundle.`,category:`integrations`},{name:`openhands-sdk`,description:`Reference skill for the OpenHands Software Agent SDK - the Python framework for building AI agents that write software. Use when you need to build agents with the SDK, create custom tools, configure LLMs, manage conversations, delegate to sub-agents, or deploy agents locally or remotely.`,triggers:[`openhands-sdk`,`openhands sdk`,`software-agent-sdk`,`agent-sdk`,`/sdk`],content:'# OpenHands Software Agent SDK\n\nAll SDK documentation lives at <https://docs.openhands.dev/sdk>.\n\nFor the full topic index, fetch <https://docs.openhands.dev/llms.txt> and read\nthe "OpenHands Software Agent SDK" section.\n\n## Quick reference\n\nInstall: `pip install openhands-sdk openhands-tools`\n\n```python\nimport os\n\nfrom openhands.sdk import LLM, Agent, Conversation, Tool\nfrom openhands.tools.file_editor import FileEditorTool\nfrom openhands.tools.task_tracker import TaskTrackerTool\nfrom openhands.tools.terminal import TerminalTool\n\n\nllm = LLM(\n model=os.getenv("LLM_MODEL", "gpt-5.5"),\n api_key=os.getenv("LLM_API_KEY"),\n base_url=os.getenv("LLM_BASE_URL", None),\n)\n\nagent = Agent(\n llm=llm,\n tools=[\n Tool(name=TerminalTool.name),\n Tool(name=FileEditorTool.name),\n Tool(name=TaskTrackerTool.name),\n ],\n)\n\ncwd = os.getcwd()\nconversation = Conversation(agent=agent, workspace=cwd)\n\nconversation.send_message("Write 3 facts about the current project into FACTS.txt.")\nconversation.run()\nprint("All done!")\n```\n\n## Core classes (`openhands.sdk`)\n\n| Class | Purpose |\n|---|---|\n| [`Agent`](https://docs.openhands.dev/sdk/arch/agent.md) | Reasoning-action loop |\n| [`Condenser`](https://docs.openhands.dev/sdk/arch/condenser.md) | Conversation history compression system |\n| [`Conversation`](https://docs.openhands.dev/sdk/arch/conversation.md) | Conversation orchestration system |\n| [`Event`](https://docs.openhands.dev/sdk/arch/events.md) | Typed event framework |\n| [`LLM`](https://docs.openhands.dev/sdk/arch/llm.md) | Provider-agnostic language model interface |\n| [`SecurityAnalyzer`](https://docs.openhands.dev/sdk/arch/security.md) | Action security analysis and validation |\n| [`Skill`](https://docs.openhands.dev/sdk/arch/skill.md) | Reusable prompt system |\n| [`Tool / ToolDefinition`](https://docs.openhands.dev/sdk/arch/tool-system.md) | Action-observation tool framework |\n| [`Workspace`](https://docs.openhands.dev/sdk/arch/workspace.md) | Execution environment abstraction |\n\n## API reference\n\n[`openhands.sdk.agent`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.agent.md), [`openhands.sdk.conversation`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.conversation.md), [`openhands.sdk.event`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.event.md), [`openhands.sdk.llm`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.llm.md), [`openhands.sdk.security`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.security.md), [`openhands.sdk.tool`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.tool.md), [`openhands.sdk.utils`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.utils.md), [`openhands.sdk.workspace`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.workspace.md)\n\n## Guides\n\n- [ACP Agent](https://docs.openhands.dev/sdk/guides/agent-acp.md): Delegate to an ACP-compatible server (Claude Code, Gemini CLI, etc.) instead of calling an LLM directly.\n- [Agent Settings](https://docs.openhands.dev/sdk/guides/agent-settings.md): Configure, serialize, and recreate agents from structured settings.\n- [Agent Skills & Context](https://docs.openhands.dev/sdk/guides/skill.md): Skills add specialized behaviors, domain knowledge, and context-aware triggers to your agent through structured prompts.\n- [API-based Sandbox](https://docs.openhands.dev/sdk/guides/agent-server/api-sandbox.md): Connect to hosted API-based agent server for fully managed infrastructure.\n- [Apptainer Sandbox](https://docs.openhands.dev/sdk/guides/agent-server/apptainer-sandbox.md): Run agent server in rootless Apptainer containers for HPC and shared computing environments.\n- [Ask Agent Questions](https://docs.openhands.dev/sdk/guides/convo-ask-agent.md): Get sidebar replies from the agent during conversation execution without interrupting the main flow.\n- [Assign Reviews](https://docs.openhands.dev/sdk/guides/github-workflows/assign-reviews.md): Automate PR management with intelligent reviewer assignment and workflow notifications using OpenHands Agent\n- [Browser Session Recording](https://docs.openhands.dev/sdk/guides/browser-session-recording.md): Record and replay your agent\'s browser sessions using rrweb.\n- [Browser Use](https://docs.openhands.dev/sdk/guides/agent-browser-use.md): Enable web browsing and interaction capabilities for your agent.\n- [Context Condenser](https://docs.openhands.dev/sdk/guides/context-condenser.md): Manage agent memory by condensing conversation history to save tokens.\n- [Conversation Goals](https://docs.openhands.dev/sdk/guides/agent-server/conversation-goals.md): Add a resumable goal strategy to a normal agent-server conversation.\n- [Conversation with Async](https://docs.openhands.dev/sdk/guides/convo-async.md): Use async/await for concurrent agent operations and non-blocking execution.\n- [Creating Custom Agent](https://docs.openhands.dev/sdk/guides/agent-custom.md): Learn how to design specialized agents with custom tool sets\n- [Critic (Experimental)](https://docs.openhands.dev/sdk/guides/critic.md): Real-time evaluation of agent actions using an LLM-based critic model, with built-in iterative refinement.\n- [Custom Tools](https://docs.openhands.dev/sdk/guides/custom-tools.md): Tools define what agents can do. The SDK includes built-in tools for common operations and supports creating custom tools for specialized needs.\n- [Custom Tools with Remote Agent Server](https://docs.openhands.dev/sdk/guides/agent-server/custom-tools.md): Learn how to use custom tools with a remote agent server by building a custom base image that includes your tool implementations.\n- [Custom Visualizer](https://docs.openhands.dev/sdk/guides/convo-custom-visualizer.md): Customize conversation visualization by creating custom visualizers or configuring the default visualizer.\n- [Deferred Init (Warm-Pool)](https://docs.openhands.dev/sdk/guides/agent-server/deferred-init.md): Pre-warm agent-server pods before a user is matched, then activate them at runtime with POST /api/init.\n- [Docker Sandbox](https://docs.openhands.dev/sdk/guides/agent-server/docker-sandbox.md): Run agent server in isolated Docker containers for security and reproducibility.\n- [Exception Handling](https://docs.openhands.dev/sdk/guides/llm-error-handling.md): Provider‑agnostic exceptions raised by the SDK and recommended patterns for handling them.\n- [FAQ](https://docs.openhands.dev/sdk/faq.md): Frequently asked questions about the OpenHands SDK\n- [File-Based Agents](https://docs.openhands.dev/sdk/guides/agent-file-based.md): Define specialized sub-agents as simple Markdown files with YAML frontmatter — no Python code required.\n- [Fork a Conversation](https://docs.openhands.dev/sdk/guides/convo-fork.md): Branch off an existing conversation for follow-up exploration without contaminating the original.\n- [Getting Started](https://docs.openhands.dev/sdk/getting-started.md): Install the OpenHands SDK and build AI agents that write software.\n- [Goal Completion Loop](https://docs.openhands.dev/sdk/guides/convo-goal.md): Drive a conversation toward a verifiable objective with a judge-driven, self-continuing completion loop.\n- [GPT-5 Preset (ApplyPatchTool)](https://docs.openhands.dev/sdk/guides/llm-gpt5-preset.md): Use the GPT-5 preset to build an agent that swaps the standard FileEditorTool for ApplyPatchTool.\n- [Hello World](https://docs.openhands.dev/sdk/guides/hello-world.md): The simplest possible OpenHands agent - configure an LLM, create an agent, and complete a task.\n- [Hooks](https://docs.openhands.dev/sdk/guides/hooks.md): Use lifecycle hooks to observe, log, and customize agent execution.\n- [Image Input](https://docs.openhands.dev/sdk/guides/llm-image-input.md): Send images to multimodal agents for vision-based tasks and analysis.\n- [Interactive Terminal](https://docs.openhands.dev/sdk/guides/agent-interactive-terminal.md): Enable agents to interact with terminal applications like ipython, python REPL, and other interactive CLI tools.\n- [Iterative Refinement](https://docs.openhands.dev/sdk/guides/iterative-refinement.md): Implement iterative refinement workflows where agents refine their work based on critique feedback until quality thresholds are met.\n- [LLM Fallback Strategy](https://docs.openhands.dev/sdk/guides/llm-fallback.md): Automatically try alternate LLMs when the primary model fails with a transient error.\n- [LLM Profile Store](https://docs.openhands.dev/sdk/guides/llm-profile-store.md): Save, load, and manage reusable LLM configurations so you never repeat setup code again.\n- [LLM Registry](https://docs.openhands.dev/sdk/guides/llm-registry.md): Dynamically select and configure language models using the LLM registry.\n- [LLM Streaming](https://docs.openhands.dev/sdk/guides/llm-streaming.md): Stream LLM responses token-by-token for real-time display and interactive user experiences.\n- [LLM Subscriptions](https://docs.openhands.dev/sdk/guides/llm-subscriptions.md): Use your ChatGPT Plus/Pro subscription to access Codex models without consuming API credits.\n- [Local Agent Server](https://docs.openhands.dev/sdk/guides/agent-server/local-server.md): Install and run an OpenHands Agent Server on your machine, then connect to it from the SDK.\n- [Metrics Tracking](https://docs.openhands.dev/sdk/guides/metrics.md): Track token usage, costs, and latency metrics for your agents.\n- [Model Context Protocol](https://docs.openhands.dev/sdk/guides/mcp.md): Model Context Protocol (MCP) enables dynamic tool integration from external servers. Agents can discover and use MCP-provided tools automatically.\n- [Model Routing](https://docs.openhands.dev/sdk/guides/llm-routing.md): Route agent\'s LLM requests to different models.\n- [Observability & Tracing](https://docs.openhands.dev/sdk/guides/observability.md): Enable OpenTelemetry tracing to monitor and debug your agent\'s execution with tools like Laminar, MLflow, Honeycomb, or any OTLP-compatible backend.\n- [OpenAI-Compatible Endpoint](https://docs.openhands.dev/sdk/guides/agent-server/openai-gateway.md): Call an OpenHands agent-server through the OpenAI Chat Completions protocol.\n- [OpenHands Cloud Workspace](https://docs.openhands.dev/sdk/guides/agent-server/cloud-workspace.md): Connect to OpenHands Cloud for fully managed sandbox environments with optional SaaS credential inheritance.\n- [Overview](https://docs.openhands.dev/sdk/guides/agent-server/overview.md): Run agents on remote servers with isolated workspaces for production deployments.\n- [Parallel Tool Execution](https://docs.openhands.dev/sdk/guides/parallel-tool-execution.md): Execute multiple tools concurrently within a single LLM response to improve throughput for independent operations.\n- [Pause and Resume](https://docs.openhands.dev/sdk/guides/convo-pause-and-resume.md): Pause agent execution, perform operations, and resume without losing state.\n- [Persistence](https://docs.openhands.dev/sdk/guides/convo-persistence.md): Save and restore conversation state for multi-session workflows.\n- [Persistent Memory](https://docs.openhands.dev/sdk/guides/persistent-memory.md): Give agents opt-in, two-tier memory that survives across conversations.\n- [Plugins](https://docs.openhands.dev/sdk/guides/plugins.md): Plugins bundle skills, hooks, MCP servers, agents, and commands into reusable packages that extend agent capabilities.\n- [PR Review](https://docs.openhands.dev/sdk/guides/github-workflows/pr-review.md): Use OpenHands Agent to generate meaningful pull request review\n- [Reasoning](https://docs.openhands.dev/sdk/guides/llm-reasoning.md): Access model reasoning traces from Anthropic extended thinking and OpenAI responses API.\n- [Secret Registry](https://docs.openhands.dev/sdk/guides/secrets.md): Provide environment variables and secrets to agent workspace securely.\n- [Security & Action Confirmation](https://docs.openhands.dev/sdk/guides/security.md): Control agent action execution through confirmation policy and security analyzer.\n- [Send Message While Running](https://docs.openhands.dev/sdk/guides/convo-send-message-while-running.md): Interrupt running agents to provide additional context or corrections.\n- [Software Agent SDK](https://docs.openhands.dev/sdk.md): Build AI agents that write software. A clean, modular SDK with production-ready tools.\n- [Stuck Detector](https://docs.openhands.dev/sdk/guides/agent-stuck-detector.md): Detect and handle stuck agents automatically with timeout mechanisms.\n- [Task Tool Set](https://docs.openhands.dev/sdk/guides/task-tool-set.md): Delegate complex work to specialized sub-agents that run synchronously and return results to the parent agent.\n- [Theory of Mind (TOM) Agent](https://docs.openhands.dev/sdk/guides/agent-tom-agent.md): Enable your agent to understand user intent and preferences through Theory of Mind capabilities, providing personalized guidance based on user modeling.\n- [TODO Management](https://docs.openhands.dev/sdk/guides/github-workflows/todo-management.md): Implement TODOs using OpenHands Agent\n\n## Examples\n\nSource: [`examples/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples)\n\n### [`01_standalone_sdk/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk)\n\n- [`01_hello_world.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/01_hello_world.py)\n- [`02_custom_tools.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/02_custom_tools.py)\n- [`03_activate_skill.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/03_activate_skill.py)\n- [`04_confirmation_mode_example.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/04_confirmation_mode_example.py)\n- [`05_use_llm_registry.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/05_use_llm_registry.py)\n- [`06_interactive_terminal_w_reasoning.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/06_interactive_terminal_w_reasoning.py)\n- [`07_mcp_integration.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/07_mcp_integration.py)\n- [`08_mcp_with_oauth.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/08_mcp_with_oauth.py)\n- [`09_pause_example.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/09_pause_example.py)\n- [`10_persistence.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/10_persistence.py)\n- [`11_async.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/11_async.py)\n- [`12_custom_secrets.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/12_custom_secrets.py)\n- [`13_get_llm_metrics.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/13_get_llm_metrics.py)\n- [`14_context_condenser.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/14_context_condenser.py)\n- [`15_browser_use.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/15_browser_use.py)\n- [`16_llm_security_analyzer.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/16_llm_security_analyzer.py)\n- [`17_image_input.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/17_image_input.py)\n- [`18_send_message_while_processing.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/18_send_message_while_processing.py)\n- [`19_llm_routing.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/19_llm_routing.py)\n- [`20_stuck_detector.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/20_stuck_detector.py)\n- [`21_generate_extraneous_conversation_costs.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/21_generate_extraneous_conversation_costs.py)\n- [`22_anthropic_thinking.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/22_anthropic_thinking.py)\n- [`23_responses_reasoning.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/23_responses_reasoning.py)\n- [`24_planning_agent_workflow.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/24_planning_agent_workflow.py)\n- [`25_agent_delegation.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/25_agent_delegation.py)\n- [`26_custom_visualizer.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/26_custom_visualizer.py)\n- [`27_observability_laminar.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/27_observability_laminar.py)\n- [`28_ask_agent_example.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/28_ask_agent_example.py)\n- [`29_llm_streaming.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/29_llm_streaming.py)\n- [`30_tom_agent.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/30_tom_agent.py)\n- [`31_iterative_refinement.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/31_iterative_refinement.py)\n- [`32_configurable_security_policy.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/32_configurable_security_policy.py)\n- [`33_hooks`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/33_hooks)\n- [`34_critic_example.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/34_critic_example.py)\n- [`35_subscription_login.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/35_subscription_login.py)\n- [`36_event_json_to_openai_messages.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/36_event_json_to_openai_messages.py)\n- [`37_llm_profile_store`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/37_llm_profile_store)\n- [`38_browser_session_recording.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/38_browser_session_recording.py)\n- [`39_llm_fallback.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/39_llm_fallback.py)\n- [`40_acp_agent_example.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/40_acp_agent_example.py)\n- [`41_task_tool_set.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/41_task_tool_set.py)\n- [`42_file_based_subagents.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/42_file_based_subagents.py)\n- [`44_model_switching_in_convo.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/44_model_switching_in_convo.py)\n- [`45_parallel_tool_execution.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/45_parallel_tool_execution.py)\n- [`46_agent_settings.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/46_agent_settings.py)\n- [`47_defense_in_depth_security.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/47_defense_in_depth_security.py)\n- [`48_conversation_fork.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/48_conversation_fork.py)\n- [`49_switch_llm_tool.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/49_switch_llm_tool.py)\n- [`50_async_cancellation.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/50_async_cancellation.py)\n- [`51_agent_hooks`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/51_agent_hooks)\n- [`52_dynamic_workflow.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/52_dynamic_workflow.py)\n- [`53_client_defined_tools.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/53_client_defined_tools.py)\n- [`54_goal_completion_loop.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/54_goal_completion_loop.py)\n- [`55_persistent_memory.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/55_persistent_memory.py)\n- [`56_structured_output.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/56_structured_output.py)\n- [`57_prompt_hooks`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/57_prompt_hooks)\n- [`58_ask_oracle_tool`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/58_ask_oracle_tool)\n\n### [`02_remote_agent_server/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server)\n\n- [`01_convo_with_local_agent_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/01_convo_with_local_agent_server.py)\n- [`02_convo_with_docker_sandboxed_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/02_convo_with_docker_sandboxed_server.py)\n- [`03_browser_use_with_docker_sandboxed_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/03_browser_use_with_docker_sandboxed_server.py)\n- [`04_convo_with_api_sandboxed_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/04_convo_with_api_sandboxed_server.py)\n- [`05_vscode_with_docker_sandboxed_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/05_vscode_with_docker_sandboxed_server.py)\n- [`06_custom_tool`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/06_custom_tool)\n- [`07_convo_with_cloud_workspace.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/07_convo_with_cloud_workspace.py)\n- [`08_convo_with_apptainer_sandboxed_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/08_convo_with_apptainer_sandboxed_server.py)\n- [`09_acp_agent_with_remote_runtime.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py)\n- [`10_cloud_workspace_share_credentials.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/10_cloud_workspace_share_credentials.py)\n- [`11_conversation_fork.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/11_conversation_fork.py)\n- [`12_settings_and_secrets_api.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/12_settings_and_secrets_api.py)\n- [`13_workspace_get_llm.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/13_workspace_get_llm.py)\n- [`14_client_defined_tools.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/14_client_defined_tools.py)\n- [`15_openai_compatible_gateway.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/15_openai_compatible_gateway.py)\n- [`16_deferred_init.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/16_deferred_init.py)\n- [`17_convo_with_agent_sandbox_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/17_convo_with_agent_sandbox_server.py)\n- [`agent_sandbox_deploy`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/agent_sandbox_deploy)\n- [`hook_scripts`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/hook_scripts)\n- [`scripts`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/scripts)\n\n### [`03_github_workflows/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows)\n\n- [`01_basic_action`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/01_basic_action)\n- [`02_pr_review`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/02_pr_review)\n- [`03_todo_management`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/03_todo_management)\n- [`04_datadog_debugging`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/04_datadog_debugging)\n- [`05_posthog_debugging`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/05_posthog_debugging)\n\n### [`04_llm_specific_tools/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/04_llm_specific_tools)\n\n- [`01_gpt5_apply_patch_preset.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/04_llm_specific_tools/01_gpt5_apply_patch_preset.py)\n- [`02_gemini_file_tools.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/04_llm_specific_tools/02_gemini_file_tools.py)\n\n### [`05_skills_and_plugins/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins)\n\n- [`01_loading_agentskills`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/01_loading_agentskills)\n- [`02_loading_plugins`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/02_loading_plugins)\n- [`03_managing_installed_skills`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/03_managing_installed_skills)\n- [`04_mixed_marketplace_skills`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/04_mixed_marketplace_skills)',category:`agent-authoring`,defaultEnabled:!0},{name:`pdflatex`,description:`Install and use pdflatex to compile LaTeX documents into PDFs on Linux. Use when generating academic papers, research publications, or any documents written in LaTeX.`,triggers:[`pdflatex`],content:`PdfLatex is a tool that converts Latex sources into PDF. This is specifically very important for researchers, as they use it to publish their findings. It could be installed very easily using Linux terminal, though this seems an annoying task on Windows. Installation commands are given below.
5996
6563
 
5997
6564
  * Install the TexLive base
5998
6565