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,80 @@
1
+ # Production Safeguards Policy
2
+ # Block high-risk and critical operations in production environment
3
+
4
+ package kubiya.tool_enforcement
5
+
6
+ import future.keywords.if
7
+
8
+ # Default deny
9
+ default allow = false
10
+
11
+ # Block high-risk tools in production
12
+ deny if {
13
+ input.execution.environment == "production"
14
+ input.tool.risk_level == "critical"
15
+ }
16
+
17
+ deny if {
18
+ input.execution.environment == "production"
19
+ input.tool.risk_level == "high"
20
+ input.tool.category == "command_execution"
21
+ contains(lower(input.tool.arguments.command), "delete")
22
+ }
23
+
24
+ deny if {
25
+ input.execution.environment == "production"
26
+ input.tool.category == "file_operation"
27
+ input.tool.name == "Write"
28
+ contains(input.tool.arguments.file_path, "/etc/")
29
+ }
30
+
31
+ # Allow everything in non-production
32
+ allow if {
33
+ input.execution.environment != "production"
34
+ input.user.email != ""
35
+ }
36
+
37
+ # Allow safe operations in production
38
+ allow if {
39
+ input.execution.environment == "production"
40
+ input.tool.risk_level == "low"
41
+ }
42
+
43
+ allow if {
44
+ input.execution.environment == "production"
45
+ input.tool.risk_level == "medium"
46
+ not deny
47
+ }
48
+
49
+ # Allow with admin override
50
+ allow if {
51
+ input.user.roles[_] == "admin"
52
+ }
53
+
54
+ # Violation messages
55
+ violation[msg] if {
56
+ deny
57
+ input.tool.risk_level == "critical"
58
+ msg := sprintf("Critical tool '%s' is blocked in production. Use dev/staging for testing.", [input.tool.name])
59
+ }
60
+
61
+ violation[msg] if {
62
+ deny
63
+ input.tool.risk_level == "high"
64
+ not input.tool.risk_level == "critical"
65
+ msg := sprintf("High-risk tool '%s' is restricted in production. Contact admin for approval.", [input.tool.name])
66
+ }
67
+
68
+ # Helper function
69
+ lower(s) := lower_s {
70
+ lower_s := lower(s)
71
+ }
72
+
73
+ # Metadata
74
+ metadata := {
75
+ "name": "production_safeguards",
76
+ "description": "Block high-risk operations in production environment",
77
+ "version": "1.0.0",
78
+ "author": "Kubiya",
79
+ "tags": ["production", "security", "risk_management"]
80
+ }
@@ -0,0 +1,44 @@
1
+ # Role-Based Tool Access Policy
2
+ # Only admin and devops roles can execute command execution tools
3
+
4
+ package kubiya.tool_enforcement
5
+
6
+ import future.keywords.if
7
+ import future.keywords.in
8
+
9
+ # Default deny
10
+ default allow = false
11
+
12
+ # Allow if user has required role for command execution
13
+ allow if {
14
+ input.tool.category == "command_execution"
15
+ input.user.roles[_] == "admin"
16
+ }
17
+
18
+ allow if {
19
+ input.tool.category == "command_execution"
20
+ input.user.roles[_] == "devops"
21
+ }
22
+
23
+ # Allow all other tool categories for any authenticated user
24
+ allow if {
25
+ input.tool.category != "command_execution"
26
+ input.user.email != ""
27
+ }
28
+
29
+ # Violation message
30
+ violation[msg] if {
31
+ input.tool.category == "command_execution"
32
+ not input.user.roles[_] == "admin"
33
+ not input.user.roles[_] == "devops"
34
+ msg := sprintf("Command execution tools require 'admin' or 'devops' role. User %s has roles: %v", [input.user.email, input.user.roles])
35
+ }
36
+
37
+ # Metadata
38
+ metadata := {
39
+ "name": "role_based_tool_access",
40
+ "description": "Only admin and devops roles can execute command tools",
41
+ "version": "1.0.0",
42
+ "author": "Kubiya",
43
+ "tags": ["rbac", "security", "command_execution"]
44
+ }
@@ -0,0 +1,86 @@
1
+ # Tool Restrictions Policy
2
+ # Controls which tools agents can use, with different restrictions per environment
3
+
4
+ package tool_restrictions
5
+
6
+ import future.keywords.if
7
+ import future.keywords.in
8
+
9
+ # Default deny
10
+ default allow = false
11
+
12
+ # Dangerous tools that require explicit approval
13
+ dangerous_tools := {
14
+ "docker",
15
+ "shell",
16
+ "file_system"
17
+ }
18
+
19
+ # Production-safe tools
20
+ production_safe_tools := {
21
+ "python",
22
+ "sleep",
23
+ "file_generation"
24
+ }
25
+
26
+ # Development environment - allow all tools
27
+ allow if {
28
+ input.environment == "development"
29
+ }
30
+
31
+ # Staging environment - allow non-dangerous tools
32
+ allow if {
33
+ input.environment == "staging"
34
+ input.tool
35
+ not input.tool in dangerous_tools
36
+ }
37
+
38
+ # Production environment - only allow production-safe tools
39
+ allow if {
40
+ input.environment == "production"
41
+ input.tool in production_safe_tools
42
+ }
43
+
44
+ # Allow dangerous tools in production with explicit approval
45
+ allow if {
46
+ input.environment == "production"
47
+ input.tool in dangerous_tools
48
+ input.approved_by
49
+ input.approval_id
50
+ }
51
+
52
+ # Violations
53
+ violations[msg] if {
54
+ input.environment == "production"
55
+ input.tool in dangerous_tools
56
+ not input.approved_by
57
+ msg := sprintf("Tool '%v' requires approval in production environment", [input.tool])
58
+ }
59
+
60
+ violations[msg] if {
61
+ input.environment == "staging"
62
+ input.tool in dangerous_tools
63
+ msg := sprintf("Dangerous tool '%v' not allowed in staging environment", [input.tool])
64
+ }
65
+
66
+ violations[msg] if {
67
+ input.environment == "production"
68
+ input.tool
69
+ not input.tool in production_safe_tools
70
+ not input.approved_by
71
+ msg := sprintf("Tool '%v' not allowed in production without approval", [input.tool])
72
+ }
73
+
74
+ violations[msg] if {
75
+ not input.tool
76
+ msg := "No tool specified in the request"
77
+ }
78
+
79
+ # Metadata
80
+ metadata := {
81
+ "name": "tool-restrictions",
82
+ "description": "Control which tools agents can use based on environment and approval status",
83
+ "version": "1.0.0",
84
+ "author": "Kubiya",
85
+ "tags": ["security", "tools", "environment"]
86
+ }
@@ -0,0 +1,4 @@
1
+ # API Routers
2
+ from . import agents, teams, workflows, health, executions, presence
3
+
4
+ __all__ = ["agents", "teams", "workflows", "health", "executions", "presence"]
@@ -0,0 +1,382 @@
1
+ from fastapi import APIRouter, Depends, HTTPException, status
2
+ from fastapi.responses import StreamingResponse
3
+ from sqlalchemy.orm import Session
4
+ from typing import List, Optional
5
+ from datetime import datetime
6
+
7
+ from control_plane_api.app.database import get_db
8
+ from control_plane_api.app.middleware.auth import get_current_organization
9
+ from control_plane_api.app.models.agent import Agent, AgentStatus
10
+ from control_plane_api.app.models.execution import Execution, ExecutionStatus, ExecutionType
11
+ from control_plane_api.app.services.litellm_service import litellm_service
12
+ from control_plane_api.app.observability import (
13
+ create_span_with_context,
14
+ add_span_event,
15
+ add_span_error,
16
+ instrument_endpoint,
17
+ )
18
+ from pydantic import BaseModel, Field
19
+
20
+ router = APIRouter()
21
+
22
+
23
+ def agent_to_response(agent: Agent) -> dict:
24
+ """Convert Agent model to response dict, mapping model_config to llm_config"""
25
+ return {
26
+ "id": agent.id,
27
+ "name": agent.name,
28
+ "description": agent.description,
29
+ "status": agent.status,
30
+ "capabilities": agent.capabilities,
31
+ "configuration": agent.configuration,
32
+ "model_id": agent.model_id,
33
+ "llm_config": agent.model_config,
34
+ "team_id": agent.team_id,
35
+ "created_at": agent.created_at,
36
+ "updated_at": agent.updated_at,
37
+ "last_active_at": agent.last_active_at,
38
+ "state": agent.state,
39
+ "error_message": agent.error_message,
40
+ }
41
+
42
+
43
+ # Pydantic schemas
44
+ class AgentCreate(BaseModel):
45
+ name: str = Field(..., description="Agent name")
46
+ description: str | None = Field(None, description="Agent description")
47
+ capabilities: list = Field(default_factory=list, description="Agent capabilities")
48
+ configuration: dict = Field(default_factory=dict, description="Agent configuration")
49
+ model_id: str | None = Field(None, description="LiteLLM model identifier")
50
+ llm_config: dict = Field(default_factory=dict, description="Model-specific configuration")
51
+ team_id: str | None = Field(None, description="Team ID to assign this agent to")
52
+
53
+
54
+ class AgentUpdate(BaseModel):
55
+ name: str | None = None
56
+ description: str | None = None
57
+ status: AgentStatus | None = None
58
+ capabilities: list | None = None
59
+ configuration: dict | None = None
60
+ state: dict | None = None
61
+ model_id: str | None = None
62
+ llm_config: dict | None = None
63
+ team_id: str | None = None
64
+
65
+
66
+ class AgentResponse(BaseModel):
67
+ id: str
68
+ name: str
69
+ description: str | None
70
+ status: AgentStatus
71
+ capabilities: list
72
+ configuration: dict
73
+ model_id: str | None
74
+ llm_config: dict
75
+ team_id: str | None
76
+ created_at: datetime
77
+ updated_at: datetime
78
+ last_active_at: datetime | None
79
+ state: dict
80
+ error_message: str | None
81
+
82
+ class Config:
83
+ from_attributes = True
84
+
85
+
86
+ class AgentExecutionRequest(BaseModel):
87
+ prompt: str = Field(..., description="The prompt to execute")
88
+ system_prompt: str | None = Field(None, description="Optional system prompt")
89
+ stream: bool = Field(False, description="Whether to stream the response")
90
+ config: dict | None = Field(None, description="Optional configuration including user metadata")
91
+
92
+
93
+ class AgentExecutionResponse(BaseModel):
94
+ execution_id: str
95
+ success: bool
96
+ response: str | None = None
97
+ error: str | None = None
98
+ model: str
99
+ usage: dict | None = None
100
+ finish_reason: str | None = None
101
+
102
+
103
+ @router.post("", response_model=AgentResponse, status_code=status.HTTP_201_CREATED)
104
+ @instrument_endpoint("agents.create")
105
+ def create_agent(agent_data: AgentCreate, organization: dict = Depends(get_current_organization), db: Session = Depends(get_db)):
106
+ """Create a new agent"""
107
+ agent = Agent(
108
+ name=agent_data.name,
109
+ description=agent_data.description,
110
+ capabilities=agent_data.capabilities,
111
+ configuration=agent_data.configuration,
112
+ model_id=agent_data.model_id,
113
+ model_config=agent_data.llm_config,
114
+ team_id=agent_data.team_id,
115
+ )
116
+ db.add(agent)
117
+ db.commit()
118
+ db.refresh(agent)
119
+ return agent_to_response(agent)
120
+
121
+
122
+ @router.get("", response_model=List[AgentResponse])
123
+ @instrument_endpoint("agents.list_agents")
124
+ def list_agents(
125
+ skip: int = 0,
126
+ limit: int = 100,
127
+ status_filter: AgentStatus | None = None,
128
+ db: Session = Depends(get_db),
129
+ ):
130
+ """List all agents"""
131
+ query = db.query(Agent)
132
+ if status_filter:
133
+ query = query.filter(Agent.status == status_filter)
134
+ agents = query.offset(skip).limit(limit).all()
135
+ return [agent_to_response(agent) for agent in agents]
136
+
137
+
138
+ @router.get("/{agent_id}", response_model=AgentResponse)
139
+ @instrument_endpoint("agents.get_agent")
140
+ def get_agent(agent_id: str, db: Session = Depends(get_db)):
141
+ """Get a specific agent by ID"""
142
+ agent = db.query(Agent).filter(Agent.id == agent_id).first()
143
+ if not agent:
144
+ raise HTTPException(status_code=404, detail="Agent not found")
145
+ return agent_to_response(agent)
146
+
147
+
148
+ @router.patch("/{agent_id}", response_model=AgentResponse)
149
+ @instrument_endpoint("agents.update_agent")
150
+ def update_agent(agent_id: str, agent_data: AgentUpdate, db: Session = Depends(get_db)):
151
+ """Update an agent"""
152
+ agent = db.query(Agent).filter(Agent.id == agent_id).first()
153
+ if not agent:
154
+ raise HTTPException(status_code=404, detail="Agent not found")
155
+
156
+ update_data = agent_data.model_dump(exclude_unset=True)
157
+ for field, value in update_data.items():
158
+ setattr(agent, field, value)
159
+
160
+ agent.updated_at = datetime.utcnow()
161
+ db.commit()
162
+ db.refresh(agent)
163
+ return agent_to_response(agent)
164
+
165
+
166
+ @router.delete("/{agent_id}", status_code=status.HTTP_204_NO_CONTENT)
167
+ @instrument_endpoint("agents.delete_agent")
168
+ def delete_agent(agent_id: str, db: Session = Depends(get_db)):
169
+ """Delete an agent"""
170
+ agent = db.query(Agent).filter(Agent.id == agent_id).first()
171
+ if not agent:
172
+ raise HTTPException(status_code=404, detail="Agent not found")
173
+
174
+ db.delete(agent)
175
+ db.commit()
176
+ return None
177
+
178
+
179
+ @router.post("/{agent_id}/start", response_model=AgentResponse)
180
+ @instrument_endpoint("agents.start_agent")
181
+ def start_agent(agent_id: str, db: Session = Depends(get_db)):
182
+ """Start an agent"""
183
+ agent = db.query(Agent).filter(Agent.id == agent_id).first()
184
+ if not agent:
185
+ raise HTTPException(status_code=404, detail="Agent not found")
186
+
187
+ if agent.status == AgentStatus.RUNNING:
188
+ raise HTTPException(status_code=400, detail="Agent is already running")
189
+
190
+ agent.status = AgentStatus.RUNNING
191
+ agent.last_active_at = datetime.utcnow()
192
+ agent.error_message = None
193
+ db.commit()
194
+ db.refresh(agent)
195
+ return agent_to_response(agent)
196
+
197
+
198
+ @router.post("/{agent_id}/stop", response_model=AgentResponse)
199
+ @instrument_endpoint("agents.stop_agent")
200
+ def stop_agent(agent_id: str, db: Session = Depends(get_db)):
201
+ """Stop an agent"""
202
+ agent = db.query(Agent).filter(Agent.id == agent_id).first()
203
+ if not agent:
204
+ raise HTTPException(status_code=404, detail="Agent not found")
205
+
206
+ agent.status = AgentStatus.STOPPED
207
+ agent.last_active_at = datetime.utcnow()
208
+ db.commit()
209
+ db.refresh(agent)
210
+ return agent_to_response(agent)
211
+
212
+
213
+ @router.post("/{agent_id}/pause", response_model=AgentResponse)
214
+ @instrument_endpoint("agents.pause_agent")
215
+ def pause_agent(agent_id: str, db: Session = Depends(get_db)):
216
+ """Pause an agent"""
217
+ agent = db.query(Agent).filter(Agent.id == agent_id).first()
218
+ if not agent:
219
+ raise HTTPException(status_code=404, detail="Agent not found")
220
+
221
+ if agent.status != AgentStatus.RUNNING:
222
+ raise HTTPException(status_code=400, detail="Can only pause running agents")
223
+
224
+ agent.status = AgentStatus.PAUSED
225
+ agent.last_active_at = datetime.utcnow()
226
+ db.commit()
227
+ db.refresh(agent)
228
+ return agent_to_response(agent)
229
+
230
+
231
+ @router.post("/{agent_id}/resume", response_model=AgentResponse)
232
+ @instrument_endpoint("agents.resume_agent")
233
+ def resume_agent(agent_id: str, db: Session = Depends(get_db)):
234
+ """Resume a paused agent"""
235
+ agent = db.query(Agent).filter(Agent.id == agent_id).first()
236
+ if not agent:
237
+ raise HTTPException(status_code=404, detail="Agent not found")
238
+
239
+ if agent.status != AgentStatus.PAUSED:
240
+ raise HTTPException(status_code=400, detail="Can only resume paused agents")
241
+
242
+ agent.status = AgentStatus.RUNNING
243
+ agent.last_active_at = datetime.utcnow()
244
+ db.commit()
245
+ db.refresh(agent)
246
+ return agent_to_response(agent)
247
+
248
+
249
+ @router.post("/{agent_id}/execute", response_model=AgentExecutionResponse)
250
+ @instrument_endpoint("agents.execute_agent")
251
+ def execute_agent(
252
+ agent_id: str,
253
+ execution_request: AgentExecutionRequest,
254
+ db: Session = Depends(get_db),
255
+ ):
256
+ """Execute an agent with a prompt using LiteLLM"""
257
+ agent = db.query(Agent).filter(Agent.id == agent_id).first()
258
+ if not agent:
259
+ raise HTTPException(status_code=404, detail="Agent not found")
260
+
261
+ # Extract user metadata from config if provided
262
+ user_metadata = {}
263
+ if execution_request.config and "user_metadata" in execution_request.config:
264
+ user_metadata = execution_request.config["user_metadata"]
265
+
266
+ # Create execution record
267
+ execution = Execution(
268
+ execution_type=ExecutionType.AGENT,
269
+ entity_id=agent.id,
270
+ entity_name=agent.name,
271
+ prompt=execution_request.prompt,
272
+ system_prompt=execution_request.system_prompt,
273
+ status=ExecutionStatus.RUNNING,
274
+ execution_metadata={
275
+ "user_id": user_metadata.get("user_id"),
276
+ "user_name": user_metadata.get("user_name"),
277
+ "user_email": user_metadata.get("user_email"),
278
+ "user_avatar": user_metadata.get("user_avatar"),
279
+ },
280
+ )
281
+ db.add(execution)
282
+ db.flush() # Get execution ID without committing
283
+ execution.started_at = datetime.utcnow()
284
+
285
+ # Extract model configuration
286
+ model = agent.model_id
287
+ model_config = agent.model_config or {}
288
+
289
+ # Get system prompt from configuration if not provided
290
+ system_prompt = execution_request.system_prompt
291
+ if not system_prompt and "system_prompt" in agent.configuration:
292
+ system_prompt = agent.configuration["system_prompt"]
293
+
294
+ try:
295
+ # Execute using LiteLLM service
296
+ result = litellm_service.execute_agent(
297
+ prompt=execution_request.prompt,
298
+ model=model,
299
+ system_prompt=system_prompt,
300
+ **model_config,
301
+ )
302
+
303
+ # Update execution record with results
304
+ execution.response = result.get("response")
305
+ execution.usage = result.get("usage", {})
306
+ execution.execution_metadata = {
307
+ "model": result.get("model"),
308
+ "finish_reason": result.get("finish_reason"),
309
+ }
310
+
311
+ if result.get("success"):
312
+ execution.status = ExecutionStatus.COMPLETED
313
+ agent.status = AgentStatus.COMPLETED
314
+ else:
315
+ execution.status = ExecutionStatus.FAILED
316
+ execution.error_message = result.get("error")
317
+ agent.status = AgentStatus.FAILED
318
+ agent.error_message = result.get("error")
319
+
320
+ execution.completed_at = datetime.utcnow()
321
+
322
+ except Exception as e:
323
+ # Handle execution errors
324
+ execution.status = ExecutionStatus.FAILED
325
+ execution.error_message = str(e)
326
+ execution.completed_at = datetime.utcnow()
327
+ agent.status = AgentStatus.FAILED
328
+ agent.error_message = str(e)
329
+ result = {
330
+ "success": False,
331
+ "error": str(e),
332
+ "model": model,
333
+ "usage": None,
334
+ "finish_reason": None,
335
+ }
336
+
337
+ # Update agent state
338
+ agent.last_active_at = datetime.utcnow()
339
+ db.commit()
340
+
341
+ return AgentExecutionResponse(
342
+ execution_id=execution.id,
343
+ **result
344
+ )
345
+
346
+
347
+ @router.post("/{agent_id}/execute/stream")
348
+ @instrument_endpoint("agents.execute_agent_stream")
349
+ def execute_agent_stream(
350
+ agent_id: str,
351
+ execution_request: AgentExecutionRequest,
352
+ db: Session = Depends(get_db),
353
+ ):
354
+ """Execute an agent with a prompt using LiteLLM (streaming response)"""
355
+ agent = db.query(Agent).filter(Agent.id == agent_id).first()
356
+ if not agent:
357
+ raise HTTPException(status_code=404, detail="Agent not found")
358
+
359
+ # Extract model configuration
360
+ model = agent.model_id
361
+ model_config = agent.model_config or {}
362
+
363
+ # Get system prompt from configuration if not provided
364
+ system_prompt = execution_request.system_prompt
365
+ if not system_prompt and "system_prompt" in agent.configuration:
366
+ system_prompt = agent.configuration["system_prompt"]
367
+
368
+ # Update agent state
369
+ agent.last_active_at = datetime.utcnow()
370
+ agent.status = AgentStatus.RUNNING
371
+ db.commit()
372
+
373
+ # Execute using LiteLLM service (streaming)
374
+ return StreamingResponse(
375
+ litellm_service.execute_agent_stream(
376
+ prompt=execution_request.prompt,
377
+ model=model,
378
+ system_prompt=system_prompt,
379
+ **model_config,
380
+ ),
381
+ media_type="text/event-stream",
382
+ )