kubiya-control-plane-api 0.9.15__py3-none-any.whl

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 (479) hide show
  1. control_plane_api/LICENSE +676 -0
  2. control_plane_api/README.md +350 -0
  3. control_plane_api/__init__.py +4 -0
  4. control_plane_api/__version__.py +8 -0
  5. control_plane_api/alembic/README +1 -0
  6. control_plane_api/alembic/env.py +121 -0
  7. control_plane_api/alembic/script.py.mako +28 -0
  8. control_plane_api/alembic/versions/2613c65c3dbe_initial_database_setup.py +32 -0
  9. control_plane_api/alembic/versions/2df520d4927d_merge_heads.py +28 -0
  10. control_plane_api/alembic/versions/43abf98d6a01_add_paused_status_to_executions.py +73 -0
  11. control_plane_api/alembic/versions/6289854264cb_merge_multiple_heads.py +28 -0
  12. control_plane_api/alembic/versions/6a4d4dc3d8dc_generate_execution_transitions.py +50 -0
  13. control_plane_api/alembic/versions/87d11cf0a783_add_disconnected_status_to_worker_.py +44 -0
  14. control_plane_api/alembic/versions/add_ephemeral_queue_support.py +85 -0
  15. control_plane_api/alembic/versions/add_model_type_to_llm_models.py +31 -0
  16. control_plane_api/alembic/versions/add_plan_executions_table.py +114 -0
  17. control_plane_api/alembic/versions/add_trace_span_tables.py +154 -0
  18. control_plane_api/alembic/versions/add_user_info_to_traces.py +36 -0
  19. control_plane_api/alembic/versions/adjusting_foreign_keys.py +32 -0
  20. control_plane_api/alembic/versions/b4983d976db2_initial_tables.py +1128 -0
  21. control_plane_api/alembic/versions/d181a3b40e71_rename_custom_metadata_to_metadata_in_.py +50 -0
  22. control_plane_api/alembic/versions/df9117888e82_add_missing_columns.py +82 -0
  23. control_plane_api/alembic/versions/f25de6ad895a_missing_migrations.py +34 -0
  24. control_plane_api/alembic/versions/f71305fb69b9_fix_ephemeral_queue_deletion_foreign_key.py +54 -0
  25. control_plane_api/alembic/versions/mark_local_exec_queues_as_ephemeral.py +68 -0
  26. control_plane_api/alembic.ini +148 -0
  27. control_plane_api/api/index.py +12 -0
  28. control_plane_api/app/__init__.py +11 -0
  29. control_plane_api/app/activities/__init__.py +20 -0
  30. control_plane_api/app/activities/agent_activities.py +384 -0
  31. control_plane_api/app/activities/plan_generation_activities.py +499 -0
  32. control_plane_api/app/activities/team_activities.py +424 -0
  33. control_plane_api/app/activities/temporal_cloud_activities.py +588 -0
  34. control_plane_api/app/config/__init__.py +35 -0
  35. control_plane_api/app/config/api_config.py +469 -0
  36. control_plane_api/app/config/config_loader.py +224 -0
  37. control_plane_api/app/config/model_pricing.py +323 -0
  38. control_plane_api/app/config/storage_config.py +159 -0
  39. control_plane_api/app/config.py +115 -0
  40. control_plane_api/app/controllers/__init__.py +0 -0
  41. control_plane_api/app/controllers/execution_environment_controller.py +1315 -0
  42. control_plane_api/app/database.py +135 -0
  43. control_plane_api/app/exceptions.py +408 -0
  44. control_plane_api/app/lib/__init__.py +11 -0
  45. control_plane_api/app/lib/environment.py +65 -0
  46. control_plane_api/app/lib/event_bus/__init__.py +17 -0
  47. control_plane_api/app/lib/event_bus/base.py +136 -0
  48. control_plane_api/app/lib/event_bus/manager.py +335 -0
  49. control_plane_api/app/lib/event_bus/providers/__init__.py +6 -0
  50. control_plane_api/app/lib/event_bus/providers/http_provider.py +166 -0
  51. control_plane_api/app/lib/event_bus/providers/nats_provider.py +324 -0
  52. control_plane_api/app/lib/event_bus/providers/redis_provider.py +233 -0
  53. control_plane_api/app/lib/event_bus/providers/websocket_provider.py +497 -0
  54. control_plane_api/app/lib/job_executor.py +330 -0
  55. control_plane_api/app/lib/kubiya_client.py +293 -0
  56. control_plane_api/app/lib/litellm_pricing.py +166 -0
  57. control_plane_api/app/lib/mcp_validation.py +163 -0
  58. control_plane_api/app/lib/nats/__init__.py +13 -0
  59. control_plane_api/app/lib/nats/credentials_manager.py +288 -0
  60. control_plane_api/app/lib/nats/listener.py +374 -0
  61. control_plane_api/app/lib/planning_prompt_builder.py +153 -0
  62. control_plane_api/app/lib/planning_tools/__init__.py +41 -0
  63. control_plane_api/app/lib/planning_tools/agents.py +409 -0
  64. control_plane_api/app/lib/planning_tools/agno_toolkit.py +836 -0
  65. control_plane_api/app/lib/planning_tools/base.py +119 -0
  66. control_plane_api/app/lib/planning_tools/cognitive_memory_tools.py +403 -0
  67. control_plane_api/app/lib/planning_tools/context_graph_tools.py +545 -0
  68. control_plane_api/app/lib/planning_tools/environments.py +218 -0
  69. control_plane_api/app/lib/planning_tools/knowledge.py +204 -0
  70. control_plane_api/app/lib/planning_tools/models.py +93 -0
  71. control_plane_api/app/lib/planning_tools/planning_service.py +646 -0
  72. control_plane_api/app/lib/planning_tools/resources.py +242 -0
  73. control_plane_api/app/lib/planning_tools/teams.py +334 -0
  74. control_plane_api/app/lib/policy_enforcer_client.py +1016 -0
  75. control_plane_api/app/lib/redis_client.py +803 -0
  76. control_plane_api/app/lib/sqlalchemy_utils.py +486 -0
  77. control_plane_api/app/lib/state_transition_tools/__init__.py +7 -0
  78. control_plane_api/app/lib/state_transition_tools/execution_context.py +388 -0
  79. control_plane_api/app/lib/storage/__init__.py +20 -0
  80. control_plane_api/app/lib/storage/base_provider.py +274 -0
  81. control_plane_api/app/lib/storage/provider_factory.py +157 -0
  82. control_plane_api/app/lib/storage/vercel_blob_provider.py +468 -0
  83. control_plane_api/app/lib/supabase.py +71 -0
  84. control_plane_api/app/lib/supabase_utils.py +138 -0
  85. control_plane_api/app/lib/task_planning/__init__.py +138 -0
  86. control_plane_api/app/lib/task_planning/agent_factory.py +308 -0
  87. control_plane_api/app/lib/task_planning/agents.py +389 -0
  88. control_plane_api/app/lib/task_planning/cache.py +218 -0
  89. control_plane_api/app/lib/task_planning/entity_resolver.py +273 -0
  90. control_plane_api/app/lib/task_planning/helpers.py +293 -0
  91. control_plane_api/app/lib/task_planning/hooks.py +474 -0
  92. control_plane_api/app/lib/task_planning/models.py +503 -0
  93. control_plane_api/app/lib/task_planning/plan_validator.py +166 -0
  94. control_plane_api/app/lib/task_planning/planning_workflow.py +2911 -0
  95. control_plane_api/app/lib/task_planning/runner.py +656 -0
  96. control_plane_api/app/lib/task_planning/streaming_hook.py +213 -0
  97. control_plane_api/app/lib/task_planning/workflow.py +424 -0
  98. control_plane_api/app/lib/templating/__init__.py +88 -0
  99. control_plane_api/app/lib/templating/compiler.py +278 -0
  100. control_plane_api/app/lib/templating/engine.py +178 -0
  101. control_plane_api/app/lib/templating/parsers/__init__.py +29 -0
  102. control_plane_api/app/lib/templating/parsers/base.py +96 -0
  103. control_plane_api/app/lib/templating/parsers/env.py +85 -0
  104. control_plane_api/app/lib/templating/parsers/graph.py +112 -0
  105. control_plane_api/app/lib/templating/parsers/secret.py +87 -0
  106. control_plane_api/app/lib/templating/parsers/simple.py +81 -0
  107. control_plane_api/app/lib/templating/resolver.py +366 -0
  108. control_plane_api/app/lib/templating/types.py +214 -0
  109. control_plane_api/app/lib/templating/validator.py +201 -0
  110. control_plane_api/app/lib/temporal_client.py +232 -0
  111. control_plane_api/app/lib/temporal_credentials_cache.py +178 -0
  112. control_plane_api/app/lib/temporal_credentials_service.py +203 -0
  113. control_plane_api/app/lib/validation/__init__.py +24 -0
  114. control_plane_api/app/lib/validation/runtime_validation.py +388 -0
  115. control_plane_api/app/main.py +531 -0
  116. control_plane_api/app/middleware/__init__.py +10 -0
  117. control_plane_api/app/middleware/auth.py +645 -0
  118. control_plane_api/app/middleware/exception_handler.py +267 -0
  119. control_plane_api/app/middleware/prometheus_middleware.py +173 -0
  120. control_plane_api/app/middleware/rate_limiting.py +384 -0
  121. control_plane_api/app/middleware/request_id.py +202 -0
  122. control_plane_api/app/models/__init__.py +40 -0
  123. control_plane_api/app/models/agent.py +90 -0
  124. control_plane_api/app/models/analytics.py +206 -0
  125. control_plane_api/app/models/associations.py +107 -0
  126. control_plane_api/app/models/auth_user.py +73 -0
  127. control_plane_api/app/models/context.py +161 -0
  128. control_plane_api/app/models/custom_integration.py +99 -0
  129. control_plane_api/app/models/environment.py +64 -0
  130. control_plane_api/app/models/execution.py +125 -0
  131. control_plane_api/app/models/execution_transition.py +50 -0
  132. control_plane_api/app/models/job.py +159 -0
  133. control_plane_api/app/models/llm_model.py +78 -0
  134. control_plane_api/app/models/orchestration.py +66 -0
  135. control_plane_api/app/models/plan_execution.py +102 -0
  136. control_plane_api/app/models/presence.py +49 -0
  137. control_plane_api/app/models/project.py +61 -0
  138. control_plane_api/app/models/project_management.py +85 -0
  139. control_plane_api/app/models/session.py +29 -0
  140. control_plane_api/app/models/skill.py +155 -0
  141. control_plane_api/app/models/system_tables.py +43 -0
  142. control_plane_api/app/models/task_planning.py +372 -0
  143. control_plane_api/app/models/team.py +86 -0
  144. control_plane_api/app/models/trace.py +257 -0
  145. control_plane_api/app/models/user_profile.py +54 -0
  146. control_plane_api/app/models/worker.py +221 -0
  147. control_plane_api/app/models/workflow.py +161 -0
  148. control_plane_api/app/models/workspace.py +50 -0
  149. control_plane_api/app/observability/__init__.py +177 -0
  150. control_plane_api/app/observability/context_logging.py +475 -0
  151. control_plane_api/app/observability/decorators.py +337 -0
  152. control_plane_api/app/observability/local_span_processor.py +702 -0
  153. control_plane_api/app/observability/metrics.py +303 -0
  154. control_plane_api/app/observability/middleware.py +246 -0
  155. control_plane_api/app/observability/optional.py +115 -0
  156. control_plane_api/app/observability/tracing.py +382 -0
  157. control_plane_api/app/policies/README.md +149 -0
  158. control_plane_api/app/policies/approved_users.rego +62 -0
  159. control_plane_api/app/policies/business_hours.rego +51 -0
  160. control_plane_api/app/policies/rate_limiting.rego +100 -0
  161. control_plane_api/app/policies/tool_enforcement/README.md +336 -0
  162. control_plane_api/app/policies/tool_enforcement/bash_command_validation.rego +71 -0
  163. control_plane_api/app/policies/tool_enforcement/business_hours_enforcement.rego +82 -0
  164. control_plane_api/app/policies/tool_enforcement/mcp_tool_allowlist.rego +58 -0
  165. control_plane_api/app/policies/tool_enforcement/production_safeguards.rego +80 -0
  166. control_plane_api/app/policies/tool_enforcement/role_based_tool_access.rego +44 -0
  167. control_plane_api/app/policies/tool_restrictions.rego +86 -0
  168. control_plane_api/app/routers/__init__.py +4 -0
  169. control_plane_api/app/routers/agents.py +382 -0
  170. control_plane_api/app/routers/agents_v2.py +1598 -0
  171. control_plane_api/app/routers/analytics.py +1310 -0
  172. control_plane_api/app/routers/auth.py +59 -0
  173. control_plane_api/app/routers/client_config.py +57 -0
  174. control_plane_api/app/routers/context_graph.py +561 -0
  175. control_plane_api/app/routers/context_manager.py +577 -0
  176. control_plane_api/app/routers/custom_integrations.py +490 -0
  177. control_plane_api/app/routers/enforcer.py +132 -0
  178. control_plane_api/app/routers/environment_context.py +252 -0
  179. control_plane_api/app/routers/environments.py +761 -0
  180. control_plane_api/app/routers/execution_environment.py +847 -0
  181. control_plane_api/app/routers/executions/__init__.py +28 -0
  182. control_plane_api/app/routers/executions/router.py +286 -0
  183. control_plane_api/app/routers/executions/services/__init__.py +22 -0
  184. control_plane_api/app/routers/executions/services/demo_worker_health.py +156 -0
  185. control_plane_api/app/routers/executions/services/status_service.py +420 -0
  186. control_plane_api/app/routers/executions/services/test_worker_health.py +480 -0
  187. control_plane_api/app/routers/executions/services/worker_health.py +514 -0
  188. control_plane_api/app/routers/executions/streaming/__init__.py +22 -0
  189. control_plane_api/app/routers/executions/streaming/deduplication.py +352 -0
  190. control_plane_api/app/routers/executions/streaming/event_buffer.py +353 -0
  191. control_plane_api/app/routers/executions/streaming/event_formatter.py +964 -0
  192. control_plane_api/app/routers/executions/streaming/history_loader.py +588 -0
  193. control_plane_api/app/routers/executions/streaming/live_source.py +693 -0
  194. control_plane_api/app/routers/executions/streaming/streamer.py +849 -0
  195. control_plane_api/app/routers/executions.py +4888 -0
  196. control_plane_api/app/routers/health.py +165 -0
  197. control_plane_api/app/routers/health_v2.py +394 -0
  198. control_plane_api/app/routers/integration_templates.py +496 -0
  199. control_plane_api/app/routers/integrations.py +287 -0
  200. control_plane_api/app/routers/jobs.py +1809 -0
  201. control_plane_api/app/routers/metrics.py +517 -0
  202. control_plane_api/app/routers/models.py +82 -0
  203. control_plane_api/app/routers/models_v2.py +628 -0
  204. control_plane_api/app/routers/plan_executions.py +1481 -0
  205. control_plane_api/app/routers/plan_generation_async.py +304 -0
  206. control_plane_api/app/routers/policies.py +669 -0
  207. control_plane_api/app/routers/presence.py +234 -0
  208. control_plane_api/app/routers/projects.py +987 -0
  209. control_plane_api/app/routers/runners.py +379 -0
  210. control_plane_api/app/routers/runtimes.py +172 -0
  211. control_plane_api/app/routers/secrets.py +171 -0
  212. control_plane_api/app/routers/skills.py +1010 -0
  213. control_plane_api/app/routers/skills_definitions.py +140 -0
  214. control_plane_api/app/routers/storage.py +456 -0
  215. control_plane_api/app/routers/task_planning.py +611 -0
  216. control_plane_api/app/routers/task_queues.py +650 -0
  217. control_plane_api/app/routers/team_context.py +274 -0
  218. control_plane_api/app/routers/teams.py +1747 -0
  219. control_plane_api/app/routers/templates.py +248 -0
  220. control_plane_api/app/routers/traces.py +571 -0
  221. control_plane_api/app/routers/websocket_client.py +479 -0
  222. control_plane_api/app/routers/websocket_executions_status.py +437 -0
  223. control_plane_api/app/routers/websocket_gateway.py +323 -0
  224. control_plane_api/app/routers/websocket_traces.py +576 -0
  225. control_plane_api/app/routers/worker_queues.py +2555 -0
  226. control_plane_api/app/routers/worker_websocket.py +419 -0
  227. control_plane_api/app/routers/workers.py +1004 -0
  228. control_plane_api/app/routers/workflows.py +204 -0
  229. control_plane_api/app/runtimes/__init__.py +6 -0
  230. control_plane_api/app/runtimes/validation.py +344 -0
  231. control_plane_api/app/schemas/__init__.py +1 -0
  232. control_plane_api/app/schemas/job_schemas.py +302 -0
  233. control_plane_api/app/schemas/mcp_schemas.py +311 -0
  234. control_plane_api/app/schemas/template_schemas.py +133 -0
  235. control_plane_api/app/schemas/trace_schemas.py +168 -0
  236. control_plane_api/app/schemas/worker_queue_observability_schemas.py +165 -0
  237. control_plane_api/app/services/__init__.py +1 -0
  238. control_plane_api/app/services/agno_planning_strategy.py +233 -0
  239. control_plane_api/app/services/agno_service.py +838 -0
  240. control_plane_api/app/services/claude_code_planning_service.py +203 -0
  241. control_plane_api/app/services/context_graph_client.py +224 -0
  242. control_plane_api/app/services/custom_integration_service.py +415 -0
  243. control_plane_api/app/services/integration_resolution_service.py +345 -0
  244. control_plane_api/app/services/litellm_service.py +394 -0
  245. control_plane_api/app/services/plan_generator.py +79 -0
  246. control_plane_api/app/services/planning_strategy.py +66 -0
  247. control_plane_api/app/services/planning_strategy_factory.py +118 -0
  248. control_plane_api/app/services/policy_service.py +615 -0
  249. control_plane_api/app/services/state_transition_service.py +755 -0
  250. control_plane_api/app/services/storage_service.py +593 -0
  251. control_plane_api/app/services/temporal_cloud_provisioning.py +150 -0
  252. control_plane_api/app/services/toolsets/context_graph_skill.py +432 -0
  253. control_plane_api/app/services/trace_retention.py +354 -0
  254. control_plane_api/app/services/worker_queue_metrics_service.py +190 -0
  255. control_plane_api/app/services/workflow_cancellation_manager.py +135 -0
  256. control_plane_api/app/services/workflow_operations_service.py +611 -0
  257. control_plane_api/app/skills/__init__.py +100 -0
  258. control_plane_api/app/skills/base.py +239 -0
  259. control_plane_api/app/skills/builtin/__init__.py +37 -0
  260. control_plane_api/app/skills/builtin/agent_communication/__init__.py +8 -0
  261. control_plane_api/app/skills/builtin/agent_communication/skill.py +246 -0
  262. control_plane_api/app/skills/builtin/code_ingestion/__init__.py +4 -0
  263. control_plane_api/app/skills/builtin/code_ingestion/skill.py +267 -0
  264. control_plane_api/app/skills/builtin/cognitive_memory/__init__.py +4 -0
  265. control_plane_api/app/skills/builtin/cognitive_memory/skill.py +174 -0
  266. control_plane_api/app/skills/builtin/contextual_awareness/__init__.py +4 -0
  267. control_plane_api/app/skills/builtin/contextual_awareness/skill.py +387 -0
  268. control_plane_api/app/skills/builtin/data_visualization/__init__.py +4 -0
  269. control_plane_api/app/skills/builtin/data_visualization/skill.py +154 -0
  270. control_plane_api/app/skills/builtin/docker/__init__.py +4 -0
  271. control_plane_api/app/skills/builtin/docker/skill.py +104 -0
  272. control_plane_api/app/skills/builtin/file_generation/__init__.py +4 -0
  273. control_plane_api/app/skills/builtin/file_generation/skill.py +94 -0
  274. control_plane_api/app/skills/builtin/file_system/__init__.py +4 -0
  275. control_plane_api/app/skills/builtin/file_system/skill.py +110 -0
  276. control_plane_api/app/skills/builtin/knowledge_api/__init__.py +5 -0
  277. control_plane_api/app/skills/builtin/knowledge_api/skill.py +124 -0
  278. control_plane_api/app/skills/builtin/python/__init__.py +4 -0
  279. control_plane_api/app/skills/builtin/python/skill.py +92 -0
  280. control_plane_api/app/skills/builtin/remote_filesystem/__init__.py +5 -0
  281. control_plane_api/app/skills/builtin/remote_filesystem/skill.py +170 -0
  282. control_plane_api/app/skills/builtin/shell/__init__.py +4 -0
  283. control_plane_api/app/skills/builtin/shell/skill.py +161 -0
  284. control_plane_api/app/skills/builtin/slack/__init__.py +3 -0
  285. control_plane_api/app/skills/builtin/slack/skill.py +302 -0
  286. control_plane_api/app/skills/builtin/workflow_executor/__init__.py +4 -0
  287. control_plane_api/app/skills/builtin/workflow_executor/skill.py +469 -0
  288. control_plane_api/app/skills/business_intelligence.py +189 -0
  289. control_plane_api/app/skills/config.py +63 -0
  290. control_plane_api/app/skills/loaders/__init__.py +14 -0
  291. control_plane_api/app/skills/loaders/base.py +73 -0
  292. control_plane_api/app/skills/loaders/filesystem_loader.py +199 -0
  293. control_plane_api/app/skills/registry.py +125 -0
  294. control_plane_api/app/utils/helpers.py +12 -0
  295. control_plane_api/app/utils/workflow_executor.py +354 -0
  296. control_plane_api/app/workflows/__init__.py +11 -0
  297. control_plane_api/app/workflows/agent_execution.py +520 -0
  298. control_plane_api/app/workflows/agent_execution_with_skills.py +223 -0
  299. control_plane_api/app/workflows/namespace_provisioning.py +326 -0
  300. control_plane_api/app/workflows/plan_generation.py +254 -0
  301. control_plane_api/app/workflows/team_execution.py +442 -0
  302. control_plane_api/scripts/seed_models.py +240 -0
  303. control_plane_api/scripts/validate_existing_tool_names.py +492 -0
  304. control_plane_api/shared/__init__.py +8 -0
  305. control_plane_api/shared/version.py +17 -0
  306. control_plane_api/test_deduplication.py +274 -0
  307. control_plane_api/test_executor_deduplication_e2e.py +309 -0
  308. control_plane_api/test_job_execution_e2e.py +283 -0
  309. control_plane_api/test_real_integration.py +193 -0
  310. control_plane_api/version.py +38 -0
  311. control_plane_api/worker/__init__.py +0 -0
  312. control_plane_api/worker/activities/__init__.py +0 -0
  313. control_plane_api/worker/activities/agent_activities.py +1585 -0
  314. control_plane_api/worker/activities/approval_activities.py +234 -0
  315. control_plane_api/worker/activities/job_activities.py +199 -0
  316. control_plane_api/worker/activities/runtime_activities.py +1167 -0
  317. control_plane_api/worker/activities/skill_activities.py +282 -0
  318. control_plane_api/worker/activities/team_activities.py +479 -0
  319. control_plane_api/worker/agent_runtime_server.py +370 -0
  320. control_plane_api/worker/binary_manager.py +333 -0
  321. control_plane_api/worker/config/__init__.py +31 -0
  322. control_plane_api/worker/config/worker_config.py +273 -0
  323. control_plane_api/worker/control_plane_client.py +1491 -0
  324. control_plane_api/worker/examples/analytics_integration_example.py +362 -0
  325. control_plane_api/worker/health_monitor.py +159 -0
  326. control_plane_api/worker/metrics.py +237 -0
  327. control_plane_api/worker/models/__init__.py +1 -0
  328. control_plane_api/worker/models/error_events.py +105 -0
  329. control_plane_api/worker/models/inputs.py +89 -0
  330. control_plane_api/worker/runtimes/__init__.py +35 -0
  331. control_plane_api/worker/runtimes/agent_runtime/runtime.py +485 -0
  332. control_plane_api/worker/runtimes/agno/__init__.py +34 -0
  333. control_plane_api/worker/runtimes/agno/config.py +248 -0
  334. control_plane_api/worker/runtimes/agno/hooks.py +385 -0
  335. control_plane_api/worker/runtimes/agno/mcp_builder.py +195 -0
  336. control_plane_api/worker/runtimes/agno/runtime.py +1063 -0
  337. control_plane_api/worker/runtimes/agno/utils.py +163 -0
  338. control_plane_api/worker/runtimes/base.py +979 -0
  339. control_plane_api/worker/runtimes/claude_code/__init__.py +38 -0
  340. control_plane_api/worker/runtimes/claude_code/cleanup.py +184 -0
  341. control_plane_api/worker/runtimes/claude_code/client_pool.py +529 -0
  342. control_plane_api/worker/runtimes/claude_code/config.py +829 -0
  343. control_plane_api/worker/runtimes/claude_code/hooks.py +482 -0
  344. control_plane_api/worker/runtimes/claude_code/litellm_proxy.py +1702 -0
  345. control_plane_api/worker/runtimes/claude_code/mcp_builder.py +467 -0
  346. control_plane_api/worker/runtimes/claude_code/mcp_discovery.py +558 -0
  347. control_plane_api/worker/runtimes/claude_code/runtime.py +1546 -0
  348. control_plane_api/worker/runtimes/claude_code/tool_mapper.py +403 -0
  349. control_plane_api/worker/runtimes/claude_code/utils.py +149 -0
  350. control_plane_api/worker/runtimes/factory.py +173 -0
  351. control_plane_api/worker/runtimes/model_utils.py +107 -0
  352. control_plane_api/worker/runtimes/validation.py +93 -0
  353. control_plane_api/worker/services/__init__.py +1 -0
  354. control_plane_api/worker/services/agent_communication_tools.py +908 -0
  355. control_plane_api/worker/services/agent_executor.py +485 -0
  356. control_plane_api/worker/services/agent_executor_v2.py +793 -0
  357. control_plane_api/worker/services/analytics_collector.py +457 -0
  358. control_plane_api/worker/services/analytics_service.py +464 -0
  359. control_plane_api/worker/services/approval_tools.py +310 -0
  360. control_plane_api/worker/services/approval_tools_agno.py +207 -0
  361. control_plane_api/worker/services/cancellation_manager.py +177 -0
  362. control_plane_api/worker/services/code_ingestion_tools.py +465 -0
  363. control_plane_api/worker/services/contextual_awareness_tools.py +405 -0
  364. control_plane_api/worker/services/data_visualization.py +834 -0
  365. control_plane_api/worker/services/event_publisher.py +531 -0
  366. control_plane_api/worker/services/jira_tools.py +257 -0
  367. control_plane_api/worker/services/remote_filesystem_tools.py +498 -0
  368. control_plane_api/worker/services/runtime_analytics.py +328 -0
  369. control_plane_api/worker/services/session_service.py +365 -0
  370. control_plane_api/worker/services/skill_context_enhancement.py +181 -0
  371. control_plane_api/worker/services/skill_factory.py +471 -0
  372. control_plane_api/worker/services/system_prompt_enhancement.py +410 -0
  373. control_plane_api/worker/services/team_executor.py +715 -0
  374. control_plane_api/worker/services/team_executor_v2.py +1866 -0
  375. control_plane_api/worker/services/tool_enforcement.py +254 -0
  376. control_plane_api/worker/services/workflow_executor/__init__.py +52 -0
  377. control_plane_api/worker/services/workflow_executor/event_processor.py +287 -0
  378. control_plane_api/worker/services/workflow_executor/event_publisher.py +210 -0
  379. control_plane_api/worker/services/workflow_executor/executors/__init__.py +15 -0
  380. control_plane_api/worker/services/workflow_executor/executors/base.py +270 -0
  381. control_plane_api/worker/services/workflow_executor/executors/json_executor.py +50 -0
  382. control_plane_api/worker/services/workflow_executor/executors/python_executor.py +50 -0
  383. control_plane_api/worker/services/workflow_executor/models.py +142 -0
  384. control_plane_api/worker/services/workflow_executor_tools.py +1748 -0
  385. control_plane_api/worker/skills/__init__.py +12 -0
  386. control_plane_api/worker/skills/builtin/context_graph_search/README.md +213 -0
  387. control_plane_api/worker/skills/builtin/context_graph_search/__init__.py +5 -0
  388. control_plane_api/worker/skills/builtin/context_graph_search/agno_impl.py +808 -0
  389. control_plane_api/worker/skills/builtin/context_graph_search/skill.yaml +67 -0
  390. control_plane_api/worker/skills/builtin/contextual_awareness/__init__.py +4 -0
  391. control_plane_api/worker/skills/builtin/contextual_awareness/agno_impl.py +62 -0
  392. control_plane_api/worker/skills/builtin/data_visualization/agno_impl.py +18 -0
  393. control_plane_api/worker/skills/builtin/data_visualization/skill.yaml +84 -0
  394. control_plane_api/worker/skills/builtin/docker/agno_impl.py +65 -0
  395. control_plane_api/worker/skills/builtin/docker/skill.yaml +60 -0
  396. control_plane_api/worker/skills/builtin/file_generation/agno_impl.py +47 -0
  397. control_plane_api/worker/skills/builtin/file_generation/skill.yaml +64 -0
  398. control_plane_api/worker/skills/builtin/file_system/agno_impl.py +32 -0
  399. control_plane_api/worker/skills/builtin/file_system/skill.yaml +54 -0
  400. control_plane_api/worker/skills/builtin/knowledge_api/__init__.py +4 -0
  401. control_plane_api/worker/skills/builtin/knowledge_api/agno_impl.py +50 -0
  402. control_plane_api/worker/skills/builtin/knowledge_api/skill.yaml +66 -0
  403. control_plane_api/worker/skills/builtin/python/agno_impl.py +25 -0
  404. control_plane_api/worker/skills/builtin/python/skill.yaml +60 -0
  405. control_plane_api/worker/skills/builtin/schema_fix_mixin.py +260 -0
  406. control_plane_api/worker/skills/builtin/shell/agno_impl.py +31 -0
  407. control_plane_api/worker/skills/builtin/shell/skill.yaml +60 -0
  408. control_plane_api/worker/skills/builtin/slack/__init__.py +3 -0
  409. control_plane_api/worker/skills/builtin/slack/agno_impl.py +1282 -0
  410. control_plane_api/worker/skills/builtin/slack/skill.yaml +276 -0
  411. control_plane_api/worker/skills/builtin/workflow_executor/agno_impl.py +62 -0
  412. control_plane_api/worker/skills/builtin/workflow_executor/skill.yaml +79 -0
  413. control_plane_api/worker/skills/loaders/__init__.py +5 -0
  414. control_plane_api/worker/skills/loaders/base.py +23 -0
  415. control_plane_api/worker/skills/loaders/filesystem_loader.py +357 -0
  416. control_plane_api/worker/skills/registry.py +208 -0
  417. control_plane_api/worker/tests/__init__.py +1 -0
  418. control_plane_api/worker/tests/conftest.py +12 -0
  419. control_plane_api/worker/tests/e2e/__init__.py +0 -0
  420. control_plane_api/worker/tests/e2e/test_context_graph_real_api.py +338 -0
  421. control_plane_api/worker/tests/e2e/test_context_graph_templates_e2e.py +523 -0
  422. control_plane_api/worker/tests/e2e/test_enforcement_e2e.py +344 -0
  423. control_plane_api/worker/tests/e2e/test_execution_flow.py +571 -0
  424. control_plane_api/worker/tests/e2e/test_single_execution_mode.py +656 -0
  425. control_plane_api/worker/tests/integration/__init__.py +0 -0
  426. control_plane_api/worker/tests/integration/test_builtin_skills_fixes.py +245 -0
  427. control_plane_api/worker/tests/integration/test_context_graph_search_integration.py +365 -0
  428. control_plane_api/worker/tests/integration/test_control_plane_integration.py +308 -0
  429. control_plane_api/worker/tests/integration/test_hook_enforcement_integration.py +579 -0
  430. control_plane_api/worker/tests/integration/test_scheduled_job_workflow.py +237 -0
  431. control_plane_api/worker/tests/integration/test_system_prompt_enhancement_integration.py +343 -0
  432. control_plane_api/worker/tests/unit/__init__.py +0 -0
  433. control_plane_api/worker/tests/unit/test_builtin_skill_autoload.py +396 -0
  434. control_plane_api/worker/tests/unit/test_context_graph_search.py +450 -0
  435. control_plane_api/worker/tests/unit/test_context_graph_templates.py +403 -0
  436. control_plane_api/worker/tests/unit/test_control_plane_client.py +401 -0
  437. control_plane_api/worker/tests/unit/test_control_plane_client_jobs.py +345 -0
  438. control_plane_api/worker/tests/unit/test_job_activities.py +353 -0
  439. control_plane_api/worker/tests/unit/test_skill_context_enhancement.py +321 -0
  440. control_plane_api/worker/tests/unit/test_system_prompt_enhancement.py +415 -0
  441. control_plane_api/worker/tests/unit/test_tool_enforcement.py +324 -0
  442. control_plane_api/worker/utils/__init__.py +1 -0
  443. control_plane_api/worker/utils/chunk_batcher.py +330 -0
  444. control_plane_api/worker/utils/environment.py +65 -0
  445. control_plane_api/worker/utils/error_publisher.py +260 -0
  446. control_plane_api/worker/utils/event_batcher.py +256 -0
  447. control_plane_api/worker/utils/logging_config.py +335 -0
  448. control_plane_api/worker/utils/logging_helper.py +326 -0
  449. control_plane_api/worker/utils/parameter_validator.py +120 -0
  450. control_plane_api/worker/utils/retry_utils.py +60 -0
  451. control_plane_api/worker/utils/streaming_utils.py +665 -0
  452. control_plane_api/worker/utils/tool_validation.py +332 -0
  453. control_plane_api/worker/utils/workspace_manager.py +163 -0
  454. control_plane_api/worker/websocket_client.py +393 -0
  455. control_plane_api/worker/worker.py +1297 -0
  456. control_plane_api/worker/workflows/__init__.py +0 -0
  457. control_plane_api/worker/workflows/agent_execution.py +909 -0
  458. control_plane_api/worker/workflows/scheduled_job_wrapper.py +332 -0
  459. control_plane_api/worker/workflows/team_execution.py +611 -0
  460. kubiya_control_plane_api-0.9.15.dist-info/METADATA +354 -0
  461. kubiya_control_plane_api-0.9.15.dist-info/RECORD +479 -0
  462. kubiya_control_plane_api-0.9.15.dist-info/WHEEL +5 -0
  463. kubiya_control_plane_api-0.9.15.dist-info/entry_points.txt +5 -0
  464. kubiya_control_plane_api-0.9.15.dist-info/licenses/LICENSE +676 -0
  465. kubiya_control_plane_api-0.9.15.dist-info/top_level.txt +3 -0
  466. scripts/__init__.py +1 -0
  467. scripts/migrations.py +39 -0
  468. scripts/seed_worker_queues.py +128 -0
  469. scripts/setup_agent_runtime.py +142 -0
  470. worker_internal/__init__.py +1 -0
  471. worker_internal/planner/__init__.py +1 -0
  472. worker_internal/planner/activities.py +1499 -0
  473. worker_internal/planner/agent_tools.py +197 -0
  474. worker_internal/planner/event_models.py +148 -0
  475. worker_internal/planner/event_publisher.py +67 -0
  476. worker_internal/planner/models.py +199 -0
  477. worker_internal/planner/retry_logic.py +134 -0
  478. worker_internal/planner/worker.py +300 -0
  479. worker_internal/planner/workflows.py +970 -0
@@ -0,0 +1,379 @@
1
+ """Runners endpoint - proxies to Kubiya API"""
2
+
3
+ from fastapi import APIRouter, Depends, Request, HTTPException, Query
4
+ from typing import List, Dict, Any, Optional
5
+ import structlog
6
+ import httpx
7
+ import asyncio
8
+
9
+ from control_plane_api.app.middleware.auth import get_current_organization
10
+ from control_plane_api.app.lib.kubiya_client import get_kubiya_client
11
+ from control_plane_api.app.config import settings
12
+
13
+ logger = structlog.get_logger()
14
+
15
+ router = APIRouter()
16
+
17
+ # Valid component names for filtering
18
+ VALID_COMPONENTS = [
19
+ "workflow_engine",
20
+ "workflow-engine",
21
+ "workflowEngine",
22
+ "tool-manager",
23
+ "tool_manager",
24
+ "toolManager",
25
+ "agent-manager",
26
+ "agent_manager",
27
+ "agentManager",
28
+ ]
29
+
30
+
31
+ @router.get("")
32
+ async def list_runners(
33
+ request: Request,
34
+ organization: dict = Depends(get_current_organization),
35
+ component: Optional[str] = Query(
36
+ None,
37
+ description="Filter runners by healthy component (e.g., 'workflow_engine', 'tool-manager'). If not specified, returns all runners with health data.",
38
+ ),
39
+ ):
40
+ """
41
+ List available runners for the organization.
42
+ Fetches health data for each runner and optionally filters by component health.
43
+
44
+ Query Parameters:
45
+ - component: Optional component name to filter by (workflow_engine, tool-manager, etc.)
46
+
47
+ Returns only runners with the specified healthy component, or all runners if no filter specified.
48
+ """
49
+ # Validate component parameter if provided
50
+ if component and component not in VALID_COMPONENTS:
51
+ raise HTTPException(
52
+ status_code=400,
53
+ detail={
54
+ "error": f"Invalid component '{component}'",
55
+ "valid_components": VALID_COMPONENTS,
56
+ "message": f"Valid choices are: {', '.join(VALID_COMPONENTS)}",
57
+ },
58
+ )
59
+
60
+ try:
61
+ kubiya_client = get_kubiya_client()
62
+ token = request.state.kubiya_token
63
+
64
+ runners = await kubiya_client.get_runners(token, organization["id"])
65
+
66
+ # Fetch health for each runner in parallel
67
+ kubiya_api_base = settings.kubiya_api_base
68
+
69
+ async with httpx.AsyncClient(timeout=30.0) as client:
70
+ # Create health check tasks for all runners
71
+ health_tasks = []
72
+ for runner in runners:
73
+ runner_name = runner.get("name")
74
+ if runner_name:
75
+ health_tasks.append(_fetch_runner_health(client, kubiya_api_base, token, runner_name))
76
+ else:
77
+ health_tasks.append(None)
78
+
79
+ # Execute all health checks in parallel
80
+ health_results = await asyncio.gather(*health_tasks, return_exceptions=True)
81
+
82
+ # Combine runners with their health data and optionally filter by component
83
+ filtered_runners = []
84
+ for runner, health_data in zip(runners, health_results):
85
+ runner_name = runner.get("name")
86
+
87
+ # Determine if we should include this runner
88
+ should_include = False
89
+ status = "unknown"
90
+
91
+ # If no component filter specified, include all runners
92
+ if not component:
93
+ should_include = True
94
+ # Determine status from health data if available
95
+ if health_data and not isinstance(health_data, Exception):
96
+ runner["health_data"] = health_data
97
+ status = _determine_runner_status_from_health(runner, health_data)
98
+ else:
99
+ # No health data or error - mark as unknown or active
100
+ status = "unknown" if isinstance(health_data, Exception) else "active"
101
+ else:
102
+ # Component filter specified - only include if component is healthy
103
+ if health_data and not isinstance(health_data, Exception):
104
+ runner["health_data"] = health_data
105
+ should_include = _has_healthy_component(health_data, component)
106
+ if should_include:
107
+ status = _determine_runner_status_from_health(runner, health_data)
108
+ else:
109
+ should_include = False
110
+ logger.debug(
111
+ "runner_health_check_failed",
112
+ runner_name=runner_name,
113
+ component=component,
114
+ error=str(health_data) if isinstance(health_data, Exception) else "No health data",
115
+ )
116
+
117
+ # Add runner to filtered list if it should be included
118
+ if should_include:
119
+ normalized_runner = {
120
+ **runner, # Keep all original fields
121
+ "id": runner.get("name") or runner.get("id"),
122
+ "status": status,
123
+ }
124
+ filtered_runners.append(normalized_runner)
125
+
126
+ logger.debug(
127
+ "runner_included",
128
+ runner_name=runner_name,
129
+ status=status,
130
+ component_filter=component,
131
+ )
132
+ elif component:
133
+ logger.debug(
134
+ "runner_filtered_out",
135
+ runner_name=runner_name,
136
+ component=component,
137
+ reason="component_not_healthy",
138
+ )
139
+
140
+ logger.info(
141
+ "runners_listed",
142
+ org_id=organization["id"],
143
+ total_runners=len(runners),
144
+ filtered_runners=len(filtered_runners),
145
+ component_filter=component,
146
+ )
147
+
148
+ return {
149
+ "runners": filtered_runners,
150
+ "count": len(filtered_runners),
151
+ }
152
+
153
+ except Exception as e:
154
+ logger.error("runners_list_failed", error=str(e), org_id=organization["id"])
155
+ # Return empty list if Kubiya API fails
156
+ return {
157
+ "runners": [],
158
+ "count": 0,
159
+ "error": "Failed to fetch runners from Kubiya API"
160
+ }
161
+
162
+
163
+ @router.get("/{runner_name}/health")
164
+ async def get_runner_health(
165
+ runner_name: str,
166
+ request: Request,
167
+ organization: dict = Depends(get_current_organization),
168
+ ):
169
+ """
170
+ Get health status for a specific runner.
171
+
172
+ Proxies to Kubiya API /api/v3/runners/{runner_name}/health
173
+ Checks workflow_engine component health specifically.
174
+ """
175
+ try:
176
+ token = request.state.kubiya_token
177
+ kubiya_api_base = settings.kubiya_api_base
178
+
179
+ # Determine auth method from request state
180
+ auth_type = getattr(request.state, "kubiya_auth_type", "Bearer")
181
+ auth_header = f"{auth_type} {token}"
182
+
183
+ # Call Kubiya API health endpoint
184
+ async with httpx.AsyncClient(timeout=10.0) as client:
185
+ # Try Bearer first, fallback to UserKey
186
+ response = await client.get(
187
+ f"{kubiya_api_base}/api/v3/runners/{runner_name}/health",
188
+ headers={"Authorization": f"Bearer {token}"},
189
+ )
190
+
191
+ if response.status_code == 401:
192
+ # Try UserKey if Bearer fails
193
+ response = await client.get(
194
+ f"{kubiya_api_base}/api/v3/runners/{runner_name}/health",
195
+ headers={"Authorization": f"UserKey {token}"},
196
+ )
197
+
198
+ if response.status_code == 200:
199
+ health_data = response.json()
200
+
201
+ logger.info(
202
+ "runner_health_fetched",
203
+ runner_name=runner_name,
204
+ status=health_data.get("status"),
205
+ org_id=organization["id"],
206
+ )
207
+
208
+ return health_data
209
+ else:
210
+ logger.warning(
211
+ "runner_health_failed",
212
+ runner_name=runner_name,
213
+ status_code=response.status_code,
214
+ )
215
+ raise HTTPException(
216
+ status_code=response.status_code,
217
+ detail=f"Failed to fetch runner health: {response.status_code}"
218
+ )
219
+
220
+ except httpx.TimeoutException:
221
+ logger.error("runner_health_timeout", runner_name=runner_name)
222
+ raise HTTPException(status_code=504, detail="Health check timeout")
223
+ except Exception as e:
224
+ logger.error("runner_health_error", runner_name=runner_name, error=str(e))
225
+ raise HTTPException(status_code=500, detail=str(e))
226
+
227
+
228
+ async def _fetch_runner_health(
229
+ client: httpx.AsyncClient,
230
+ kubiya_api_base: str,
231
+ token: str,
232
+ runner_name: str,
233
+ ) -> Optional[Dict[str, Any]]:
234
+ """
235
+ Fetch health data for a specific runner from Kubiya API.
236
+ Tries Bearer auth first, then UserKey.
237
+ """
238
+ try:
239
+ # Try Bearer first
240
+ response = await client.get(
241
+ f"{kubiya_api_base}/api/v3/runners/{runner_name}/health",
242
+ headers={"Authorization": f"Bearer {token}"},
243
+ )
244
+
245
+ # Fallback to UserKey if Bearer fails
246
+ if response.status_code == 401:
247
+ response = await client.get(
248
+ f"{kubiya_api_base}/api/v3/runners/{runner_name}/health",
249
+ headers={"Authorization": f"UserKey {token}"},
250
+ )
251
+
252
+ if response.status_code == 200:
253
+ return response.json()
254
+
255
+ return None
256
+
257
+ except Exception as e:
258
+ logger.debug(
259
+ "runner_health_fetch_error",
260
+ runner_name=runner_name,
261
+ error=str(e),
262
+ )
263
+ return None
264
+
265
+
266
+ def _has_healthy_component(health_data: Dict[str, Any], component_name: str) -> bool:
267
+ """
268
+ Check if the runner has a healthy component with the specified name.
269
+
270
+ Health data structure:
271
+ {
272
+ "checks": [
273
+ {"name": "workflow-engine", "status": "ok", ...},
274
+ {"name": "tool-manager", "status": "ok", ...},
275
+ ...
276
+ ]
277
+ }
278
+
279
+ Args:
280
+ health_data: Health data from Kubiya API
281
+ component_name: Component name to check (supports multiple naming conventions)
282
+
283
+ Returns:
284
+ True if component is found and healthy, False otherwise
285
+ """
286
+ checks = health_data.get("checks", [])
287
+
288
+ # Normalize component name to check against multiple naming conventions
289
+ component_variants = _get_component_name_variants(component_name)
290
+
291
+ for check in checks:
292
+ check_name = check.get("name", "")
293
+ if check_name in component_variants:
294
+ status = check.get("status", "")
295
+ # Consider "ok" or "healthy" as valid
296
+ if status in ["ok", "healthy"]:
297
+ return True
298
+
299
+ return False
300
+
301
+
302
+ def _get_component_name_variants(component_name: str) -> List[str]:
303
+ """
304
+ Get all possible naming variants for a component name.
305
+
306
+ Examples:
307
+ - "workflow_engine" → ["workflow_engine", "workflow-engine", "workflowEngine"]
308
+ - "tool-manager" → ["tool-manager", "tool_manager", "toolManager"]
309
+ - "workflowEngine" → ["workflow_engine", "workflow-engine", "workflowEngine"]
310
+
311
+ Args:
312
+ component_name: Component name in any format
313
+
314
+ Returns:
315
+ List of possible naming variants
316
+ """
317
+ import re
318
+
319
+ # Detect if input is camelCase and split it
320
+ # Insert underscore before uppercase letters (except first char)
321
+ snake_from_camel = re.sub(r"(?<!^)(?=[A-Z])", "_", component_name)
322
+
323
+ # Convert to lowercase base
324
+ base = snake_from_camel.lower().replace("-", "_").replace(" ", "_")
325
+
326
+ # Generate camelCase: first word lowercase, rest capitalized
327
+ words = base.split("_")
328
+ if len(words) > 1:
329
+ camel_case = words[0] + "".join(word.capitalize() for word in words[1:])
330
+ else:
331
+ camel_case = words[0]
332
+
333
+ # Generate variants
334
+ variants = [
335
+ base, # workflow_engine
336
+ base.replace("_", "-"), # workflow-engine
337
+ camel_case, # workflowEngine
338
+ ]
339
+
340
+ # Also include the original input
341
+ variants.append(component_name)
342
+
343
+ return list(set(variants))
344
+
345
+
346
+ def _determine_runner_status_from_health(runner: Dict[str, Any], health_data: Dict[str, Any]) -> str:
347
+ """
348
+ Determine runner status based on health check data.
349
+
350
+ Returns: "active", "degraded", "unhealthy"
351
+ """
352
+ # Check if managed cloud (always active)
353
+ if runner.get("runner_type") == "managed_cloud" or runner.get("isManagedCloud"):
354
+ return "active"
355
+
356
+ # Check overall health status
357
+ overall_status = health_data.get("status", "")
358
+ if overall_status == "ok":
359
+ return "active"
360
+
361
+ # Check individual component health
362
+ checks = health_data.get("checks", [])
363
+ healthy_count = 0
364
+ total_count = len(checks)
365
+
366
+ for check in checks:
367
+ if check.get("status") == "ok":
368
+ healthy_count += 1
369
+
370
+ # All components healthy
371
+ if total_count > 0 and healthy_count == total_count:
372
+ return "active"
373
+
374
+ # Some components healthy
375
+ if healthy_count > 0:
376
+ return "degraded"
377
+
378
+ # No healthy components
379
+ return "unhealthy"
@@ -0,0 +1,172 @@
1
+ """Runtime types endpoint for agent execution frameworks"""
2
+ from fastapi import APIRouter, HTTPException
3
+ from pydantic import BaseModel, Field
4
+ from typing import List, Dict, Any, Optional
5
+
6
+ from control_plane_api.app.lib.validation import (
7
+ validate_agent_for_runtime,
8
+ get_runtime_requirements_info,
9
+ )
10
+
11
+ router = APIRouter()
12
+
13
+
14
+ class ModelRequirementInfo(BaseModel):
15
+ """Model requirements for a runtime"""
16
+ description: str = Field(..., description="Human-readable description")
17
+ supported_providers: List[str] = Field(..., description="Supported model providers")
18
+ supported_families: List[str] = Field(..., description="Supported model families")
19
+ examples: List[str] = Field(..., description="Example valid model IDs")
20
+
21
+
22
+ class RuntimeRequirementsInfo(BaseModel):
23
+ """Requirements specification for a runtime"""
24
+ model_requirement: ModelRequirementInfo
25
+ required_config_fields: List[str] = Field(default_factory=list)
26
+ recommended_config_fields: List[str] = Field(default_factory=list)
27
+ max_history_length: Optional[int] = None
28
+ requires_system_prompt: bool = False
29
+ requires_tools: bool = False
30
+
31
+
32
+ class RuntimeInfo(BaseModel):
33
+ """Information about an agent runtime"""
34
+ id: str = Field(..., description="Runtime identifier")
35
+ name: str = Field(..., description="Display name")
36
+ description: str = Field(..., description="Description of the runtime")
37
+ icon: str = Field(..., description="Icon identifier for UI")
38
+ features: List[str] = Field(..., description="Key features of this runtime")
39
+ status: str = Field(..., description="Status: available, beta, coming_soon")
40
+ requirements: Optional[RuntimeRequirementsInfo] = Field(None, description="Runtime requirements and validation rules")
41
+
42
+
43
+ class ValidationRequest(BaseModel):
44
+ """Request to validate agent configuration for a runtime"""
45
+ runtime_type: str = Field(..., description="Runtime type to validate for")
46
+ model_id: Optional[str] = Field(None, description="Model ID to validate")
47
+ agent_config: Optional[Dict[str, Any]] = Field(None, description="Agent configuration")
48
+ system_prompt: Optional[str] = Field(None, description="System prompt")
49
+
50
+
51
+ class ValidationResponse(BaseModel):
52
+ """Response from validation"""
53
+ valid: bool = Field(..., description="Whether configuration is valid")
54
+ errors: List[str] = Field(default_factory=list, description="Validation errors if any")
55
+
56
+
57
+ def _get_runtime_requirements(runtime_id: str) -> Optional[RuntimeRequirementsInfo]:
58
+ """Helper to get requirements for a runtime from shared validation module."""
59
+ try:
60
+ req_info = get_runtime_requirements_info(runtime_id)
61
+ if "error" in req_info:
62
+ return None
63
+
64
+ model_req = req_info.get("model_requirement", {})
65
+ return RuntimeRequirementsInfo(
66
+ model_requirement=ModelRequirementInfo(
67
+ description=model_req.get("description", ""),
68
+ supported_providers=model_req.get("supported_providers", []),
69
+ supported_families=model_req.get("supported_families", []),
70
+ examples=model_req.get("examples", []),
71
+ ),
72
+ required_config_fields=req_info.get("required_config_fields", []),
73
+ recommended_config_fields=req_info.get("recommended_config_fields", []),
74
+ max_history_length=req_info.get("max_history_length"),
75
+ requires_system_prompt=req_info.get("requires_system_prompt", False),
76
+ requires_tools=req_info.get("requires_tools", False),
77
+ )
78
+ except Exception as e:
79
+ print(f"Error loading requirements for {runtime_id}: {e}")
80
+ return None
81
+
82
+
83
+ @router.get("/runtimes", response_model=List[RuntimeInfo], tags=["Runtimes"])
84
+ def list_runtimes():
85
+ """
86
+ List available agent runtime types with requirements.
87
+
88
+ Returns information about different agent execution frameworks
89
+ that can be used when creating or configuring agents, including
90
+ model compatibility requirements and validation rules.
91
+ """
92
+ return [
93
+ RuntimeInfo(
94
+ id="default",
95
+ name="Agno Runtime",
96
+ description="Production-ready agent framework with advanced reasoning and tool execution capabilities. Best for complex workflows and multi-step tasks. Supports most LiteLLM-compatible models.",
97
+ icon="agno",
98
+ features=[
99
+ "Advanced reasoning capabilities",
100
+ "Multi-step task execution",
101
+ "Built-in tool integration",
102
+ "Session management",
103
+ "Production-tested reliability",
104
+ "Supports GPT, Claude, Gemini, Mistral, and more"
105
+ ],
106
+ status="available",
107
+ requirements=_get_runtime_requirements("default")
108
+ ),
109
+ RuntimeInfo(
110
+ id="claude_code",
111
+ name="Claude Code SDK",
112
+ description="Specialized runtime for code generation and software development tasks. Requires Anthropic Claude models for optimal performance with extended context and advanced code understanding.",
113
+ icon="code",
114
+ features=[
115
+ "Code-first design",
116
+ "Advanced code generation",
117
+ "Built-in code review",
118
+ "Repository awareness",
119
+ "Development workflow optimization",
120
+ "Requires Claude models (claude-3-opus, claude-3-sonnet, etc.)"
121
+ ],
122
+ status="beta",
123
+ requirements=_get_runtime_requirements("claude_code")
124
+ )
125
+ ]
126
+
127
+
128
+ @router.post("/runtimes/validate", response_model=ValidationResponse, tags=["Runtimes"])
129
+ def validate_runtime_config(request: ValidationRequest):
130
+ """
131
+ Validate agent/team configuration for a specific runtime.
132
+
133
+ This endpoint checks if the provided configuration is compatible with
134
+ the selected runtime, including model validation and required fields.
135
+
136
+ Use this before creating or updating agents to ensure compatibility.
137
+ """
138
+ try:
139
+ is_valid, errors = validate_agent_for_runtime(
140
+ runtime_type=request.runtime_type,
141
+ model_id=request.model_id,
142
+ agent_config=request.agent_config,
143
+ system_prompt=request.system_prompt,
144
+ )
145
+
146
+ return ValidationResponse(
147
+ valid=is_valid,
148
+ errors=errors
149
+ )
150
+
151
+ except Exception as e:
152
+ raise HTTPException(
153
+ status_code=500,
154
+ detail=f"Validation error: {str(e)}"
155
+ )
156
+
157
+
158
+ @router.get("/runtimes/{runtime_id}/requirements", response_model=RuntimeRequirementsInfo, tags=["Runtimes"])
159
+ def get_runtime_requirements(runtime_id: str):
160
+ """
161
+ Get detailed requirements for a specific runtime.
162
+
163
+ Returns model compatibility requirements, required configuration fields,
164
+ and other validation rules for the specified runtime.
165
+ """
166
+ requirements = _get_runtime_requirements(runtime_id)
167
+ if not requirements:
168
+ raise HTTPException(
169
+ status_code=404,
170
+ detail=f"Runtime '{runtime_id}' not found or has no requirements"
171
+ )
172
+ return requirements