agentcore-cli 0.31.1__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 (655) hide show
  1. agentcore/__init__.py +1 -0
  2. agentcore/agent_inspector/NOTICE +9 -0
  3. agentcore/agent_inspector/favicon.svg +60 -0
  4. agentcore/agent_inspector/index.css +1 -0
  5. agentcore/agent_inspector/index.html +14 -0
  6. agentcore/agent_inspector/index.js +289 -0
  7. agentcore/assets/AGENTS.md +60 -0
  8. agentcore/assets/README.md +108 -0
  9. agentcore/assets/agents/AGENTS.md +218 -0
  10. agentcore/assets/cdk/.prettierrc +8 -0
  11. agentcore/assets/cdk/README.md +26 -0
  12. agentcore/assets/cdk/bin/cdk.ts +216 -0
  13. agentcore/assets/cdk/cdk.json +88 -0
  14. agentcore/assets/cdk/gitignore.template +9 -0
  15. agentcore/assets/cdk/jest.config.js +9 -0
  16. agentcore/assets/cdk/lib/cdk-stack.ts +291 -0
  17. agentcore/assets/cdk/npmignore.template +6 -0
  18. agentcore/assets/cdk/package.json +30 -0
  19. agentcore/assets/cdk/test/cdk.test.ts +31 -0
  20. agentcore/assets/cdk/tsconfig.json +28 -0
  21. agentcore/assets/container/python/Dockerfile +47 -0
  22. agentcore/assets/container/python/dockerignore.template +27 -0
  23. agentcore/assets/container/typescript/Dockerfile +25 -0
  24. agentcore/assets/container/typescript/dockerignore.template +24 -0
  25. agentcore/assets/datasets/predefined-v1.jsonl +3 -0
  26. agentcore/assets/datasets/simulated-v1.jsonl +3 -0
  27. agentcore/assets/evaluators/autoevals-lambda/execution-role-policy.json +15 -0
  28. agentcore/assets/evaluators/autoevals-lambda/lambda_function.py +37 -0
  29. agentcore/assets/evaluators/autoevals-lambda/pyproject.toml +22 -0
  30. agentcore/assets/evaluators/deepeval-lambda/execution-role-policy.json +15 -0
  31. agentcore/assets/evaluators/deepeval-lambda/lambda_function.py +29 -0
  32. agentcore/assets/evaluators/deepeval-lambda/pyproject.toml +19 -0
  33. agentcore/assets/evaluators/python-lambda/execution-role-policy.json +10 -0
  34. agentcore/assets/evaluators/python-lambda/lambda_function.py +19 -0
  35. agentcore/assets/evaluators/python-lambda/pyproject.toml +15 -0
  36. agentcore/assets/harness/invoke.py.template +74 -0
  37. agentcore/assets/mcp/python/README.md +27 -0
  38. agentcore/assets/mcp/python/pyproject.toml +22 -0
  39. agentcore/assets/mcp/python/server.py +117 -0
  40. agentcore/assets/mcp/python-lambda/README.md +22 -0
  41. agentcore/assets/mcp/python-lambda/handler.py +144 -0
  42. agentcore/assets/mcp/python-lambda/pyproject.toml +15 -0
  43. agentcore/assets/python/a2a/googleadk/base/README.md +22 -0
  44. agentcore/assets/python/a2a/googleadk/base/gitignore.template +41 -0
  45. agentcore/assets/python/a2a/googleadk/base/main.py +124 -0
  46. agentcore/assets/python/a2a/googleadk/base/model/__init__.py +1 -0
  47. agentcore/assets/python/a2a/googleadk/base/model/load.py +41 -0
  48. agentcore/assets/python/a2a/googleadk/base/pyproject.toml +22 -0
  49. agentcore/assets/python/a2a/langchain_langgraph/base/README.md +22 -0
  50. agentcore/assets/python/a2a/langchain_langgraph/base/gitignore.template +41 -0
  51. agentcore/assets/python/a2a/langchain_langgraph/base/main.py +144 -0
  52. agentcore/assets/python/a2a/langchain_langgraph/base/model/__init__.py +1 -0
  53. agentcore/assets/python/a2a/langchain_langgraph/base/model/load.py +123 -0
  54. agentcore/assets/python/a2a/langchain_langgraph/base/pyproject.toml +26 -0
  55. agentcore/assets/python/a2a/strands/base/README.md +22 -0
  56. agentcore/assets/python/a2a/strands/base/gitignore.template +41 -0
  57. agentcore/assets/python/a2a/strands/base/main.py +113 -0
  58. agentcore/assets/python/a2a/strands/base/model/__init__.py +1 -0
  59. agentcore/assets/python/a2a/strands/base/model/load.py +123 -0
  60. agentcore/assets/python/a2a/strands/base/pyproject.toml +23 -0
  61. agentcore/assets/python/a2a/strands/capabilities/memory/__init__.py +1 -0
  62. agentcore/assets/python/a2a/strands/capabilities/memory/session.py +46 -0
  63. agentcore/assets/python/agui/googleadk/base/README.md +30 -0
  64. agentcore/assets/python/agui/googleadk/base/gitignore.template +41 -0
  65. agentcore/assets/python/agui/googleadk/base/main.py +91 -0
  66. agentcore/assets/python/agui/googleadk/base/model/__init__.py +1 -0
  67. agentcore/assets/python/agui/googleadk/base/model/load.py +41 -0
  68. agentcore/assets/python/agui/googleadk/base/pyproject.toml +25 -0
  69. agentcore/assets/python/agui/langchain_langgraph/base/README.md +22 -0
  70. agentcore/assets/python/agui/langchain_langgraph/base/gitignore.template +41 -0
  71. agentcore/assets/python/agui/langchain_langgraph/base/main.py +130 -0
  72. agentcore/assets/python/agui/langchain_langgraph/base/model/__init__.py +1 -0
  73. agentcore/assets/python/agui/langchain_langgraph/base/model/load.py +123 -0
  74. agentcore/assets/python/agui/langchain_langgraph/base/pyproject.toml +31 -0
  75. agentcore/assets/python/agui/strands/base/README.md +22 -0
  76. agentcore/assets/python/agui/strands/base/gitignore.template +41 -0
  77. agentcore/assets/python/agui/strands/base/main.py +105 -0
  78. agentcore/assets/python/agui/strands/base/model/__init__.py +1 -0
  79. agentcore/assets/python/agui/strands/base/model/load.py +123 -0
  80. agentcore/assets/python/agui/strands/base/pyproject.toml +27 -0
  81. agentcore/assets/python/agui/strands/capabilities/memory/__init__.py +1 -0
  82. agentcore/assets/python/agui/strands/capabilities/memory/session.py +46 -0
  83. agentcore/assets/python/http/autogen/base/README.md +45 -0
  84. agentcore/assets/python/http/autogen/base/gitignore.template +41 -0
  85. agentcore/assets/python/http/autogen/base/main.py +145 -0
  86. agentcore/assets/python/http/autogen/base/mcp_client/__init__.py +1 -0
  87. agentcore/assets/python/http/autogen/base/mcp_client/client.py +28 -0
  88. agentcore/assets/python/http/autogen/base/model/__init__.py +1 -0
  89. agentcore/assets/python/http/autogen/base/model/load.py +136 -0
  90. agentcore/assets/python/http/autogen/base/pyproject.toml +34 -0
  91. agentcore/assets/python/http/bma/base/Dockerfile +41 -0
  92. agentcore/assets/python/http/bma/base/README.md +178 -0
  93. agentcore/assets/python/http/bma/base/client.py +200 -0
  94. agentcore/assets/python/http/bma/base/lifecycle/server.py +641 -0
  95. agentcore/assets/python/http/bma/base/otel/collector.yaml +69 -0
  96. agentcore/assets/python/http/bma/base/plugins/acr-report/.codex-plugin/plugin.json +6 -0
  97. agentcore/assets/python/http/bma/base/plugins/acr-report/skills/acr-report/SKILL.md +16 -0
  98. agentcore/assets/python/http/bma/base/policies/bma-acr-policy.json +11 -0
  99. agentcore/assets/python/http/bma/base/policies/bma-session-policy.json +35 -0
  100. agentcore/assets/python/http/bma/base/policies/bma-session-trust.json +20 -0
  101. agentcore/assets/python/http/bma/base/pyproject.toml +21 -0
  102. agentcore/assets/python/http/googleadk/base/README.md +45 -0
  103. agentcore/assets/python/http/googleadk/base/gitignore.template +41 -0
  104. agentcore/assets/python/http/googleadk/base/main.py +207 -0
  105. agentcore/assets/python/http/googleadk/base/mcp_client/__init__.py +1 -0
  106. agentcore/assets/python/http/googleadk/base/mcp_client/client.py +75 -0
  107. agentcore/assets/python/http/googleadk/base/model/__init__.py +1 -0
  108. agentcore/assets/python/http/googleadk/base/model/load.py +41 -0
  109. agentcore/assets/python/http/googleadk/base/pyproject.toml +24 -0
  110. agentcore/assets/python/http/langchain_langgraph/base/README.md +45 -0
  111. agentcore/assets/python/http/langchain_langgraph/base/gitignore.template +41 -0
  112. agentcore/assets/python/http/langchain_langgraph/base/main.py +227 -0
  113. agentcore/assets/python/http/langchain_langgraph/base/mcp_client/__init__.py +1 -0
  114. agentcore/assets/python/http/langchain_langgraph/base/mcp_client/client.py +79 -0
  115. agentcore/assets/python/http/langchain_langgraph/base/model/__init__.py +1 -0
  116. agentcore/assets/python/http/langchain_langgraph/base/model/load.py +123 -0
  117. agentcore/assets/python/http/langchain_langgraph/base/pyproject.toml +38 -0
  118. agentcore/assets/python/http/openaiagents/base/README.md +45 -0
  119. agentcore/assets/python/http/openaiagents/base/gitignore.template +41 -0
  120. agentcore/assets/python/http/openaiagents/base/main.py +200 -0
  121. agentcore/assets/python/http/openaiagents/base/mcp_client/__init__.py +1 -0
  122. agentcore/assets/python/http/openaiagents/base/mcp_client/client.py +74 -0
  123. agentcore/assets/python/http/openaiagents/base/model/__init__.py +1 -0
  124. agentcore/assets/python/http/openaiagents/base/model/load.py +37 -0
  125. agentcore/assets/python/http/openaiagents/base/pyproject.toml +21 -0
  126. agentcore/assets/python/http/strands/base/README.md +46 -0
  127. agentcore/assets/python/http/strands/base/gitignore.template +41 -0
  128. agentcore/assets/python/http/strands/base/main.py +714 -0
  129. agentcore/assets/python/http/strands/base/mcp_client/__init__.py +1 -0
  130. agentcore/assets/python/http/strands/base/mcp_client/client.py +116 -0
  131. agentcore/assets/python/http/strands/base/model/__init__.py +1 -0
  132. agentcore/assets/python/http/strands/base/model/load.py +239 -0
  133. agentcore/assets/python/http/strands/base/model/mantle_compat.py +21 -0
  134. agentcore/assets/python/http/strands/base/pyproject.toml +31 -0
  135. agentcore/assets/python/http/strands/base/skills/fetcher.py +279 -0
  136. agentcore/assets/python/http/strands/capabilities/execution-limits/hooks/execution_limits.py +54 -0
  137. agentcore/assets/python/http/strands/capabilities/memory/__init__.py +1 -0
  138. agentcore/assets/python/http/strands/capabilities/memory/session.py +47 -0
  139. agentcore/assets/python/http/strands/capabilities/payments/__init__.py +4 -0
  140. agentcore/assets/python/http/strands/capabilities/payments/payments.py +142 -0
  141. agentcore/assets/python/mcp/standalone/base/README.md +36 -0
  142. agentcore/assets/python/mcp/standalone/base/gitignore.template +41 -0
  143. agentcore/assets/python/mcp/standalone/base/main.py +83 -0
  144. agentcore/assets/python/mcp/standalone/base/pyproject.toml +16 -0
  145. agentcore/assets/typescript/.gitkeep +0 -0
  146. agentcore/assets/typescript/http/strands/base/README.md +42 -0
  147. agentcore/assets/typescript/http/strands/base/gitignore.template +22 -0
  148. agentcore/assets/typescript/http/strands/base/main.ts +149 -0
  149. agentcore/assets/typescript/http/strands/base/mcp_client/client.ts +11 -0
  150. agentcore/assets/typescript/http/strands/base/model/load.ts +102 -0
  151. agentcore/assets/typescript/http/strands/base/package.json +38 -0
  152. agentcore/assets/typescript/http/strands/base/tsconfig.json +19 -0
  153. agentcore/assets/typescript/http/strands/capabilities/memory/memory.ts +52 -0
  154. agentcore/assets/typescript/http/vercelai/base/README.md +42 -0
  155. agentcore/assets/typescript/http/vercelai/base/gitignore.template +22 -0
  156. agentcore/assets/typescript/http/vercelai/base/main.ts +70 -0
  157. agentcore/assets/typescript/http/vercelai/base/model/load.ts +121 -0
  158. agentcore/assets/typescript/http/vercelai/base/package.json +35 -0
  159. agentcore/assets/typescript/http/vercelai/base/tsconfig.json +19 -0
  160. agentcore/aws/__init__.py +263 -0
  161. agentcore/aws/_aws_errors.py +72 -0
  162. agentcore/aws/_http.py +176 -0
  163. agentcore/aws/_util.py +37 -0
  164. agentcore/aws/account.py +165 -0
  165. agentcore/aws/agentcore.py +971 -0
  166. agentcore/aws/agentcore_ab_tests.py +230 -0
  167. agentcore/aws/agentcore_batch_evaluation.py +227 -0
  168. agentcore/aws/agentcore_config_bundles.py +220 -0
  169. agentcore/aws/agentcore_control.py +994 -0
  170. agentcore/aws/agentcore_datasets.py +222 -0
  171. agentcore/aws/agentcore_harness.py +330 -0
  172. agentcore/aws/agentcore_payments.py +430 -0
  173. agentcore/aws/agentcore_recommendation.py +140 -0
  174. agentcore/aws/agui_parser.py +131 -0
  175. agentcore/aws/agui_types.py +342 -0
  176. agentcore/aws/api_client.py +87 -0
  177. agentcore/aws/arn.py +18 -0
  178. agentcore/aws/aws_context.py +23 -0
  179. agentcore/aws/bedrock.py +44 -0
  180. agentcore/aws/bedrock_agent.py +129 -0
  181. agentcore/aws/bedrock_import.py +252 -0
  182. agentcore/aws/bedrock_import_types.py +111 -0
  183. agentcore/aws/cloudwatch.py +136 -0
  184. agentcore/aws/connect_shell.py +266 -0
  185. agentcore/aws/iam.py +41 -0
  186. agentcore/aws/partition.py +58 -0
  187. agentcore/aws/policy_generation.py +116 -0
  188. agentcore/aws/region.py +54 -0
  189. agentcore/aws/retry.py +27 -0
  190. agentcore/aws/shell_framer.py +136 -0
  191. agentcore/aws/stage_endpoint.py +39 -0
  192. agentcore/aws/target_region.py +54 -0
  193. agentcore/aws/transaction_search.py +97 -0
  194. agentcore/cdk/__init__.py +10 -0
  195. agentcore/cdk/constants.py +13 -0
  196. agentcore/cdk/local_cdk_project.py +48 -0
  197. agentcore/cdk/toolkit.py +706 -0
  198. agentcore/cli/__init__.py +0 -0
  199. agentcore/cli/commands/__init__.py +0 -0
  200. agentcore/cli/commands/_jobs_common.py +39 -0
  201. agentcore/cli/commands/_run_wizards.py +639 -0
  202. agentcore/cli/commands/add/__init__.py +37 -0
  203. agentcore/cli/commands/add/_commander.py +52 -0
  204. agentcore/cli/commands/add/_common.py +47 -0
  205. agentcore/cli/commands/add/agent_wizard.py +528 -0
  206. agentcore/cli/commands/add/auth_options.py +154 -0
  207. agentcore/cli/commands/add/skill_action.py +105 -0
  208. agentcore/cli/commands/add/skill_command.py +87 -0
  209. agentcore/cli/commands/add/tool_action.py +160 -0
  210. agentcore/cli/commands/add/tool_command.py +117 -0
  211. agentcore/cli/commands/add/validate.py +333 -0
  212. agentcore/cli/commands/capacity_provider/__init__.py +86 -0
  213. agentcore/cli/commands/capacity_provider/action.py +114 -0
  214. agentcore/cli/commands/capacity_provider/constants.py +22 -0
  215. agentcore/cli/commands/config.py +91 -0
  216. agentcore/cli/commands/config_bundle.py +251 -0
  217. agentcore/cli/commands/create/__init__.py +643 -0
  218. agentcore/cli/commands/create/action.py +406 -0
  219. agentcore/cli/commands/create/dependencies.py +91 -0
  220. agentcore/cli/commands/create/harness_validate.py +82 -0
  221. agentcore/cli/commands/create/validate.py +195 -0
  222. agentcore/cli/commands/create/wizard.py +127 -0
  223. agentcore/cli/commands/dataset.py +119 -0
  224. agentcore/cli/commands/deploy/__init__.py +31 -0
  225. agentcore/cli/commands/deploy/_guards.py +25 -0
  226. agentcore/cli/commands/deploy/actions.py +840 -0
  227. agentcore/cli/commands/deploy/command.py +349 -0
  228. agentcore/cli/commands/deploy/progress.py +115 -0
  229. agentcore/cli/commands/deploy/types.py +68 -0
  230. agentcore/cli/commands/deploy/utils.py +43 -0
  231. agentcore/cli/commands/deploy/validate.py +21 -0
  232. agentcore/cli/commands/dev/__init__.py +5 -0
  233. agentcore/cli/commands/dev/_deps.py +50 -0
  234. agentcore/cli/commands/dev/browser_mode.py +270 -0
  235. agentcore/cli/commands/dev/command.py +450 -0
  236. agentcore/cli/commands/dev/terminal_mode.py +379 -0
  237. agentcore/cli/commands/exec/__init__.py +29 -0
  238. agentcore/cli/commands/exec/action.py +442 -0
  239. agentcore/cli/commands/exec/command.py +206 -0
  240. agentcore/cli/commands/exec/types.py +35 -0
  241. agentcore/cli/commands/export/__init__.py +114 -0
  242. agentcore/cli/commands/export/constants.py +21 -0
  243. agentcore/cli/commands/export/fetch_harness_spec.py +234 -0
  244. agentcore/cli/commands/export/harness_action.py +385 -0
  245. agentcore/cli/commands/export/harness_mapper.py +868 -0
  246. agentcore/cli/commands/export/harness_resolver.py +95 -0
  247. agentcore/cli/commands/export/types.py +90 -0
  248. agentcore/cli/commands/export/wizard.py +97 -0
  249. agentcore/cli/commands/feedback/__init__.py +69 -0
  250. agentcore/cli/commands/feedback/action.py +30 -0
  251. agentcore/cli/commands/feedback/consent_prompt.py +35 -0
  252. agentcore/cli/commands/feedback/wizard.py +49 -0
  253. agentcore/cli/commands/fetch/__init__.py +69 -0
  254. agentcore/cli/commands/fetch/action.py +62 -0
  255. agentcore/cli/commands/help.py +65 -0
  256. agentcore/cli/commands/import_/__init__.py +167 -0
  257. agentcore/cli/commands/import_/_js.py +72 -0
  258. agentcore/cli/commands/import_/actions.py +457 -0
  259. agentcore/cli/commands/import_/constants.py +45 -0
  260. agentcore/cli/commands/import_/import_evaluator.py +140 -0
  261. agentcore/cli/commands/import_/import_gateway.py +520 -0
  262. agentcore/cli/commands/import_/import_memory.py +128 -0
  263. agentcore/cli/commands/import_/import_online_eval.py +165 -0
  264. agentcore/cli/commands/import_/import_pipeline.py +145 -0
  265. agentcore/cli/commands/import_/import_runtime.py +214 -0
  266. agentcore/cli/commands/import_/import_utils.py +410 -0
  267. agentcore/cli/commands/import_/phase1_update.py +110 -0
  268. agentcore/cli/commands/import_/phase2_import.py +206 -0
  269. agentcore/cli/commands/import_/resource_import.py +228 -0
  270. agentcore/cli/commands/import_/template_utils.py +148 -0
  271. agentcore/cli/commands/import_/types.py +150 -0
  272. agentcore/cli/commands/import_/yaml_parser.py +265 -0
  273. agentcore/cli/commands/init.py +196 -0
  274. agentcore/cli/commands/invoke/__init__.py +32 -0
  275. agentcore/cli/commands/invoke/_deps.py +73 -0
  276. agentcore/cli/commands/invoke/action.py +840 -0
  277. agentcore/cli/commands/invoke/command.py +490 -0
  278. agentcore/cli/commands/invoke/constants.py +40 -0
  279. agentcore/cli/commands/invoke/guards.py +23 -0
  280. agentcore/cli/commands/invoke/interactive.py +604 -0
  281. agentcore/cli/commands/invoke/resolve.py +149 -0
  282. agentcore/cli/commands/invoke/resolve_prompt.py +60 -0
  283. agentcore/cli/commands/invoke/types.py +61 -0
  284. agentcore/cli/commands/invoke/validate.py +33 -0
  285. agentcore/cli/commands/job_actions.py +239 -0
  286. agentcore/cli/commands/job_history.py +380 -0
  287. agentcore/cli/commands/logs/__init__.py +53 -0
  288. agentcore/cli/commands/logs/action.py +159 -0
  289. agentcore/cli/commands/logs/filter_pattern.py +17 -0
  290. agentcore/cli/commands/logs/guards.py +51 -0
  291. agentcore/cli/commands/logs_evals.py +42 -0
  292. agentcore/cli/commands/package.py +118 -0
  293. agentcore/cli/commands/remove/__init__.py +172 -0
  294. agentcore/cli/commands/remove/skill_command.py +131 -0
  295. agentcore/cli/commands/remove/tool_command.py +59 -0
  296. agentcore/cli/commands/run.py +808 -0
  297. agentcore/cli/commands/run_ingest.py +97 -0
  298. agentcore/cli/commands/shared/__init__.py +0 -0
  299. agentcore/cli/commands/shared/arn_utils.py +9 -0
  300. agentcore/cli/commands/shared/filesystem_utils.py +421 -0
  301. agentcore/cli/commands/shared/header_utils.py +87 -0
  302. agentcore/cli/commands/shared/indexed_key_parser.py +76 -0
  303. agentcore/cli/commands/shared/lifecycle_utils.py +72 -0
  304. agentcore/cli/commands/shared/region_utils.py +20 -0
  305. agentcore/cli/commands/shared/vpc_utils.py +99 -0
  306. agentcore/cli/commands/status/__init__.py +30 -0
  307. agentcore/cli/commands/status/_guards.py +25 -0
  308. agentcore/cli/commands/status/action.py +741 -0
  309. agentcore/cli/commands/status/command.py +321 -0
  310. agentcore/cli/commands/status/constants.py +36 -0
  311. agentcore/cli/commands/status/format_knowledge_base.py +111 -0
  312. agentcore/cli/commands/telemetry.py +79 -0
  313. agentcore/cli/commands/traces/__init__.py +155 -0
  314. agentcore/cli/commands/traces/action.py +123 -0
  315. agentcore/cli/commands/update/__init__.py +63 -0
  316. agentcore/cli/commands/update/action.py +164 -0
  317. agentcore/cli/commands/validate.py +165 -0
  318. agentcore/cli/constants.py +96 -0
  319. agentcore/cli/errors.py +118 -0
  320. agentcore/cli/external_requirements/__init__.py +67 -0
  321. agentcore/cli/external_requirements/checks.py +280 -0
  322. agentcore/cli/external_requirements/detect.py +55 -0
  323. agentcore/cli/external_requirements/versions.py +57 -0
  324. agentcore/cli/groups.py +23 -0
  325. agentcore/cli/interactive.py +85 -0
  326. agentcore/cli/main.py +137 -0
  327. agentcore/cli/naming.py +11 -0
  328. agentcore/cli/notices.py +42 -0
  329. agentcore/cli/project.py +34 -0
  330. agentcore/cli/run_command.py +27 -0
  331. agentcore/cli/tree.py +135 -0
  332. agentcore/cli/update_notifier.py +123 -0
  333. agentcore/cli/variadic.py +50 -0
  334. agentcore/cloudformation/__init__.py +84 -0
  335. agentcore/cloudformation/bootstrap.py +64 -0
  336. agentcore/cloudformation/logical_ids.py +37 -0
  337. agentcore/cloudformation/outputs.py +566 -0
  338. agentcore/cloudformation/stack_discovery.py +75 -0
  339. agentcore/cloudformation/stack_events.py +107 -0
  340. agentcore/cloudformation/stack_status.py +98 -0
  341. agentcore/cloudformation/types.py +44 -0
  342. agentcore/lib/__init__.py +68 -0
  343. agentcore/lib/constants.py +77 -0
  344. agentcore/lib/dependency_management/__init__.py +23 -0
  345. agentcore/lib/dependency_management/messages.py +92 -0
  346. agentcore/lib/dependency_management/plan.py +98 -0
  347. agentcore/lib/dependency_management/semver.py +137 -0
  348. agentcore/lib/dependency_management/sync.py +139 -0
  349. agentcore/lib/dependency_management/types.py +56 -0
  350. agentcore/lib/errors/__init__.py +5 -0
  351. agentcore/lib/errors/types.py +352 -0
  352. agentcore/lib/errors/validation.py +121 -0
  353. agentcore/lib/packaging/__init__.py +81 -0
  354. agentcore/lib/packaging/build_args.py +23 -0
  355. agentcore/lib/packaging/build_context.py +26 -0
  356. agentcore/lib/packaging/build_context_dockerignore.py +45 -0
  357. agentcore/lib/packaging/container.py +95 -0
  358. agentcore/lib/packaging/helpers.py +289 -0
  359. agentcore/lib/packaging/node.py +153 -0
  360. agentcore/lib/packaging/python.py +135 -0
  361. agentcore/lib/packaging/types.py +69 -0
  362. agentcore/lib/packaging/uv.py +45 -0
  363. agentcore/lib/result.py +104 -0
  364. agentcore/lib/schemas/__init__.py +1 -0
  365. agentcore/lib/schemas/io/__init__.py +27 -0
  366. agentcore/lib/schemas/io/config_io.py +458 -0
  367. agentcore/lib/schemas/io/global_config.py +239 -0
  368. agentcore/lib/schemas/io/path_resolver.py +132 -0
  369. agentcore/lib/secrets/__init__.py +18 -0
  370. agentcore/lib/secrets/cipher.py +70 -0
  371. agentcore/lib/secrets/key_provider.py +163 -0
  372. agentcore/lib/secrets/sensitive_keys.py +55 -0
  373. agentcore/lib/time_constants.py +4 -0
  374. agentcore/lib/utils/__init__.py +47 -0
  375. agentcore/lib/utils/aws_account.py +15 -0
  376. agentcore/lib/utils/credentials.py +68 -0
  377. agentcore/lib/utils/dotenv.py +32 -0
  378. agentcore/lib/utils/env.py +105 -0
  379. agentcore/lib/utils/json_format.py +29 -0
  380. agentcore/lib/utils/json_rpc.py +22 -0
  381. agentcore/lib/utils/platform.py +33 -0
  382. agentcore/lib/utils/polling.py +86 -0
  383. agentcore/lib/utils/subprocess.py +135 -0
  384. agentcore/lib/utils/time_parser.py +48 -0
  385. agentcore/lib/utils/validation.py +106 -0
  386. agentcore/logging/__init__.py +10 -0
  387. agentcore/logging/_common.py +77 -0
  388. agentcore/logging/cdk_io_host.py +36 -0
  389. agentcore/logging/create_logger.py +107 -0
  390. agentcore/logging/dev_logger.py +63 -0
  391. agentcore/logging/exec_logger.py +159 -0
  392. agentcore/logging/invoke_logger.py +154 -0
  393. agentcore/logging/remove_logger.py +95 -0
  394. agentcore/operations/__init__.py +0 -0
  395. agentcore/operations/agent/__init__.py +0 -0
  396. agentcore/operations/agent/config_bundle_defaults.py +31 -0
  397. agentcore/operations/agent/generate/__init__.py +28 -0
  398. agentcore/operations/agent/generate/schema_mapper.py +319 -0
  399. agentcore/operations/agent/generate/types.py +172 -0
  400. agentcore/operations/agent/generate/write_agent_to_project.py +67 -0
  401. agentcore/operations/agent/import_/__init__.py +31 -0
  402. agentcore/operations/agent/import_/base_translator.py +449 -0
  403. agentcore/operations/agent/import_/constants.py +23 -0
  404. agentcore/operations/agent/import_/execute.py +127 -0
  405. agentcore/operations/agent/import_/langgraph_translator.py +294 -0
  406. agentcore/operations/agent/import_/pyproject_generator.py +73 -0
  407. agentcore/operations/agent/import_/strands_translator.py +289 -0
  408. agentcore/operations/config_bundle/__init__.py +1 -0
  409. agentcore/operations/config_bundle/bundle_name_variants.py +9 -0
  410. agentcore/operations/config_bundle/diff_versions.py +52 -0
  411. agentcore/operations/config_bundle/resolve_bundle.py +65 -0
  412. agentcore/operations/connectors/__init__.py +3 -0
  413. agentcore/operations/connectors/translators.py +63 -0
  414. agentcore/operations/dataset/__init__.py +21 -0
  415. agentcore/operations/dataset/delete.py +7 -0
  416. agentcore/operations/dataset/publish.py +16 -0
  417. agentcore/operations/dataset/pull.py +21 -0
  418. agentcore/operations/dataset/push.py +201 -0
  419. agentcore/operations/dataset/resolve_dataset.py +65 -0
  420. agentcore/operations/dataset/status.py +18 -0
  421. agentcore/operations/dataset/wait.py +25 -0
  422. agentcore/operations/deploy/__init__.py +152 -0
  423. agentcore/operations/deploy/backfill_vpc_id.py +90 -0
  424. agentcore/operations/deploy/change_detection.py +84 -0
  425. agentcore/operations/deploy/constants.py +58 -0
  426. agentcore/operations/deploy/dependency_sync.py +105 -0
  427. agentcore/operations/deploy/ensure_target.py +30 -0
  428. agentcore/operations/deploy/gateway_status.py +44 -0
  429. agentcore/operations/deploy/managed_memory_notice.py +36 -0
  430. agentcore/operations/deploy/payment_connector_authorization.py +106 -0
  431. agentcore/operations/deploy/post_deploy_datasets.py +96 -0
  432. agentcore/operations/deploy/post_deploy_knowledge_bases.py +104 -0
  433. agentcore/operations/deploy/post_deploy_observability.py +28 -0
  434. agentcore/operations/deploy/post_deploy_online_evals.py +60 -0
  435. agentcore/operations/deploy/pre_deploy_identity.py +505 -0
  436. agentcore/operations/deploy/preflight.py +385 -0
  437. agentcore/operations/deploy/region_override.py +45 -0
  438. agentcore/operations/deploy/teardown.py +153 -0
  439. agentcore/operations/dev/__init__.py +61 -0
  440. agentcore/operations/dev/_http.py +79 -0
  441. agentcore/operations/dev/_server.py +165 -0
  442. agentcore/operations/dev/codezip_dev_server.py +151 -0
  443. agentcore/operations/dev/config.py +128 -0
  444. agentcore/operations/dev/constants.py +9 -0
  445. agentcore/operations/dev/container_dev_server.py +237 -0
  446. agentcore/operations/dev/container_runtime.py +37 -0
  447. agentcore/operations/dev/dev_server.py +244 -0
  448. agentcore/operations/dev/gateway_env.py +25 -0
  449. agentcore/operations/dev/invoke.py +214 -0
  450. agentcore/operations/dev/invoke_a2a.py +204 -0
  451. agentcore/operations/dev/invoke_agui.py +88 -0
  452. agentcore/operations/dev/invoke_mcp.py +145 -0
  453. agentcore/operations/dev/invoke_types.py +30 -0
  454. agentcore/operations/dev/load_dev_env.py +26 -0
  455. agentcore/operations/dev/memory_env.py +19 -0
  456. agentcore/operations/dev/otel/__init__.py +5 -0
  457. agentcore/operations/dev/otel/collector.py +234 -0
  458. agentcore/operations/dev/otel/transforms.py +331 -0
  459. agentcore/operations/dev/payment_env.py +50 -0
  460. agentcore/operations/dev/server.py +28 -0
  461. agentcore/operations/dev/sse_transform.py +30 -0
  462. agentcore/operations/dev/utils.py +152 -0
  463. agentcore/operations/dev/web_ui/__init__.py +31 -0
  464. agentcore/operations/dev/web_ui/constants.py +25 -0
  465. agentcore/operations/dev/web_ui/handlers/__init__.py +36 -0
  466. agentcore/operations/dev/web_ui/handlers/_common.py +36 -0
  467. agentcore/operations/dev/web_ui/handlers/_deployed.py +37 -0
  468. agentcore/operations/dev/web_ui/handlers/a2a_proxy.py +37 -0
  469. agentcore/operations/dev/web_ui/handlers/cloudwatch_traces.py +71 -0
  470. agentcore/operations/dev/web_ui/handlers/harness_invocation.py +89 -0
  471. agentcore/operations/dev/web_ui/handlers/harness_utils.py +95 -0
  472. agentcore/operations/dev/web_ui/handlers/invocations.py +327 -0
  473. agentcore/operations/dev/web_ui/handlers/mcp_proxy.py +119 -0
  474. agentcore/operations/dev/web_ui/handlers/memory.py +84 -0
  475. agentcore/operations/dev/web_ui/handlers/resources.py +351 -0
  476. agentcore/operations/dev/web_ui/handlers/start.py +182 -0
  477. agentcore/operations/dev/web_ui/handlers/status.py +25 -0
  478. agentcore/operations/dev/web_ui/handlers/traces.py +50 -0
  479. agentcore/operations/dev/web_ui/run_web_ui.py +60 -0
  480. agentcore/operations/dev/web_ui/web_server.py +297 -0
  481. agentcore/operations/eval/__init__.py +8 -0
  482. agentcore/operations/eval/list_eval_runs.py +18 -0
  483. agentcore/operations/eval/logs_eval.py +119 -0
  484. agentcore/operations/eval/pause_resume.py +90 -0
  485. agentcore/operations/eval/run_eval.py +354 -0
  486. agentcore/operations/eval/shared/__init__.py +0 -0
  487. agentcore/operations/eval/shared/dataset_loader.py +68 -0
  488. agentcore/operations/eval/shared/dataset_session_provider.py +122 -0
  489. agentcore/operations/eval/shared/evaluator_runner.py +89 -0
  490. agentcore/operations/eval/shared/scenario_executor.py +71 -0
  491. agentcore/operations/eval/shared/span_collector.py +255 -0
  492. agentcore/operations/eval/storage.py +67 -0
  493. agentcore/operations/feedback/__init__.py +21 -0
  494. agentcore/operations/feedback/aperture_client.py +98 -0
  495. agentcore/operations/feedback/build_payload.py +97 -0
  496. agentcore/operations/feedback/constants.py +26 -0
  497. agentcore/operations/feedback/submit_feedback.py +150 -0
  498. agentcore/operations/fetch_access/__init__.py +36 -0
  499. agentcore/operations/fetch_access/_target.py +17 -0
  500. agentcore/operations/fetch_access/fetch_gateway_token.py +75 -0
  501. agentcore/operations/fetch_access/fetch_harness_token.py +72 -0
  502. agentcore/operations/fetch_access/fetch_runtime_token.py +76 -0
  503. agentcore/operations/fetch_access/list_agents.py +18 -0
  504. agentcore/operations/fetch_access/list_gateways.py +26 -0
  505. agentcore/operations/fetch_access/list_harnesses.py +23 -0
  506. agentcore/operations/fetch_access/oauth_token.py +162 -0
  507. agentcore/operations/fetch_access/types.py +34 -0
  508. agentcore/operations/harness/__init__.py +1 -0
  509. agentcore/operations/harness/orphan.py +84 -0
  510. agentcore/operations/harness/skill_utils.py +56 -0
  511. agentcore/operations/identity/__init__.py +33 -0
  512. agentcore/operations/identity/api_key_credential_provider.py +68 -0
  513. agentcore/operations/identity/oauth2_credential_provider.py +95 -0
  514. agentcore/operations/ingest/__init__.py +184 -0
  515. agentcore/operations/init/__init__.py +3 -0
  516. agentcore/operations/init/files.py +59 -0
  517. agentcore/operations/insights/__init__.py +21 -0
  518. agentcore/operations/insights/insights_storage.py +67 -0
  519. agentcore/operations/insights/run_insights.py +148 -0
  520. agentcore/operations/invoke/__init__.py +5 -0
  521. agentcore/operations/invoke/resolve_agent_context.py +85 -0
  522. agentcore/operations/jobs/__init__.py +38 -0
  523. agentcore/operations/jobs/ab_test/__init__.py +0 -0
  524. agentcore/operations/jobs/ab_test/build_options.py +126 -0
  525. agentcore/operations/jobs/ab_test/format.py +121 -0
  526. agentcore/operations/jobs/ab_test/handler.py +412 -0
  527. agentcore/operations/jobs/ab_test/promote.py +142 -0
  528. agentcore/operations/jobs/ab_test/resolve.py +221 -0
  529. agentcore/operations/jobs/batch_evaluation/__init__.py +0 -0
  530. agentcore/operations/jobs/batch_evaluation/build_source.py +68 -0
  531. agentcore/operations/jobs/batch_evaluation/dataset_phase1.py +95 -0
  532. agentcore/operations/jobs/batch_evaluation/format.py +58 -0
  533. agentcore/operations/jobs/batch_evaluation/handler.py +203 -0
  534. agentcore/operations/jobs/insights/__init__.py +0 -0
  535. agentcore/operations/jobs/insights/format.py +65 -0
  536. agentcore/operations/jobs/insights/handler.py +178 -0
  537. agentcore/operations/jobs/recommendation/__init__.py +0 -0
  538. agentcore/operations/jobs/recommendation/apply_to_bundle.py +76 -0
  539. agentcore/operations/jobs/recommendation/build_config.py +271 -0
  540. agentcore/operations/jobs/recommendation/fetch_session_spans.py +93 -0
  541. agentcore/operations/jobs/recommendation/format.py +77 -0
  542. agentcore/operations/jobs/recommendation/handler.py +331 -0
  543. agentcore/operations/jobs/shared/__init__.py +0 -0
  544. agentcore/operations/jobs/shared/constants.py +85 -0
  545. agentcore/operations/jobs/shared/engine.py +187 -0
  546. agentcore/operations/jobs/shared/format.py +104 -0
  547. agentcore/operations/jobs/shared/region.py +34 -0
  548. agentcore/operations/jobs/shared/resolve_agent_state.py +30 -0
  549. agentcore/operations/jobs/shared/storage.py +117 -0
  550. agentcore/operations/jobs/shared/wait.py +30 -0
  551. agentcore/operations/knowledge_base/__init__.py +33 -0
  552. agentcore/operations/knowledge_base/connector_config.py +105 -0
  553. agentcore/operations/knowledge_base/hydrate_data_sources.py +59 -0
  554. agentcore/operations/mcp/__init__.py +4 -0
  555. agentcore/operations/memory/__init__.py +13 -0
  556. agentcore/operations/memory/_records.py +72 -0
  557. agentcore/operations/memory/list_memory_records.py +45 -0
  558. agentcore/operations/memory/retrieve_memory_records.py +52 -0
  559. agentcore/operations/node/__init__.py +15 -0
  560. agentcore/operations/node/setup.py +36 -0
  561. agentcore/operations/python/__init__.py +17 -0
  562. agentcore/operations/python/setup.py +47 -0
  563. agentcore/operations/resolve_agent.py +159 -0
  564. agentcore/operations/session/__init__.py +86 -0
  565. agentcore/operations/traces/__init__.py +29 -0
  566. agentcore/operations/traces/get_trace.py +202 -0
  567. agentcore/operations/traces/insights_query.py +74 -0
  568. agentcore/operations/traces/list_traces.py +46 -0
  569. agentcore/operations/traces/trace_url.py +25 -0
  570. agentcore/operations/traces/types.py +55 -0
  571. agentcore/primitives/__init__.py +0 -0
  572. agentcore/primitives/_gateway_target_wizard.py +293 -0
  573. agentcore/primitives/_gateway_validation.py +442 -0
  574. agentcore/primitives/_harness_cli.py +557 -0
  575. agentcore/primitives/_harness_validation.py +163 -0
  576. agentcore/primitives/_harness_wizard.py +726 -0
  577. agentcore/primitives/_knowledge_base_wizard.py +259 -0
  578. agentcore/primitives/_payment_wizard.py +331 -0
  579. agentcore/primitives/_policy_form.py +160 -0
  580. agentcore/primitives/agent.py +817 -0
  581. agentcore/primitives/auth_utils.py +77 -0
  582. agentcore/primitives/base.py +178 -0
  583. agentcore/primitives/capacity_provider.py +501 -0
  584. agentcore/primitives/config_bundle.py +329 -0
  585. agentcore/primitives/credential.py +387 -0
  586. agentcore/primitives/credential_utils.py +45 -0
  587. agentcore/primitives/dataset.py +211 -0
  588. agentcore/primitives/deployed_gateways.py +34 -0
  589. agentcore/primitives/evaluator.py +909 -0
  590. agentcore/primitives/gateway.py +496 -0
  591. agentcore/primitives/gateway_target.py +988 -0
  592. agentcore/primitives/harness.py +706 -0
  593. agentcore/primitives/knowledge_base.py +477 -0
  594. agentcore/primitives/memory.py +387 -0
  595. agentcore/primitives/online_eval_config.py +365 -0
  596. agentcore/primitives/online_insights.py +275 -0
  597. agentcore/primitives/payment_connector.py +427 -0
  598. agentcore/primitives/payment_eligible.py +20 -0
  599. agentcore/primitives/payment_manager.py +605 -0
  600. agentcore/primitives/payment_validation.py +68 -0
  601. agentcore/primitives/policy.py +622 -0
  602. agentcore/primitives/policy_engine.py +358 -0
  603. agentcore/primitives/registry.py +56 -0
  604. agentcore/primitives/runtime_endpoint.py +361 -0
  605. agentcore/primitives/secret_flag_warning.py +17 -0
  606. agentcore/schema/__init__.py +14 -0
  607. agentcore/schema/_zod.py +395 -0
  608. agentcore/schema/constants.py +306 -0
  609. agentcore/schema/schemas/__init__.py +40 -0
  610. agentcore/schema/schemas/agent_env.py +545 -0
  611. agentcore/schema/schemas/agentcore_project.py +530 -0
  612. agentcore/schema/schemas/auth.py +286 -0
  613. agentcore/schema/schemas/aws_targets.py +72 -0
  614. agentcore/schema/schemas/connections.py +187 -0
  615. agentcore/schema/schemas/deployed_state.py +322 -0
  616. agentcore/schema/schemas/mcp.py +650 -0
  617. agentcore/schema/schemas/mcp_defs.py +54 -0
  618. agentcore/schema/schemas/primitives/__init__.py +52 -0
  619. agentcore/schema/schemas/primitives/ab_test.py +162 -0
  620. agentcore/schema/schemas/primitives/capacity_provider.py +214 -0
  621. agentcore/schema/schemas/primitives/config_bundle.py +48 -0
  622. agentcore/schema/schemas/primitives/dataset.py +55 -0
  623. agentcore/schema/schemas/primitives/evaluator.py +171 -0
  624. agentcore/schema/schemas/primitives/harness.py +710 -0
  625. agentcore/schema/schemas/primitives/knowledge_base.py +90 -0
  626. agentcore/schema/schemas/primitives/memory.py +113 -0
  627. agentcore/schema/schemas/primitives/online_eval_config.py +77 -0
  628. agentcore/schema/schemas/primitives/payment.py +114 -0
  629. agentcore/schema/schemas/primitives/policy.py +83 -0
  630. agentcore/schema/schemas/primitives/tags.py +50 -0
  631. agentcore/schema/schemas/zod_util.py +5 -0
  632. agentcore/schema/types/__init__.py +3 -0
  633. agentcore/schema/types/path.py +16 -0
  634. agentcore/templates/__init__.py +115 -0
  635. agentcore/templates/_handlebars.py +782 -0
  636. agentcore/templates/_js.py +164 -0
  637. agentcore/templates/base_renderer.py +107 -0
  638. agentcore/templates/cdk_renderer.py +129 -0
  639. agentcore/templates/evaluator_renderer.py +39 -0
  640. agentcore/templates/gateway_target_renderer.py +69 -0
  641. agentcore/templates/llm_context/README.md +16 -0
  642. agentcore/templates/llm_context/agentcore.ts +685 -0
  643. agentcore/templates/llm_context/aws-targets.ts +51 -0
  644. agentcore/templates/profiles.py +151 -0
  645. agentcore/templates/render.py +92 -0
  646. agentcore/templates/renderers.py +83 -0
  647. agentcore/templates/schema_assets.py +23 -0
  648. agentcore/templates/template_root.py +28 -0
  649. agentcore/templates/types.py +192 -0
  650. agentcore_cli-0.31.1.dist-info/METADATA +84 -0
  651. agentcore_cli-0.31.1.dist-info/RECORD +655 -0
  652. agentcore_cli-0.31.1.dist-info/WHEEL +4 -0
  653. agentcore_cli-0.31.1.dist-info/entry_points.txt +2 -0
  654. agentcore_cli-0.31.1.dist-info/licenses/LICENSE +175 -0
  655. agentcore_cli-0.31.1.dist-info/licenses/NOTICE +88 -0
@@ -0,0 +1,808 @@
1
+ """`agentcore run eval|batch-evaluation|insights|recommendation|ab-test` (port of commands/run/command.tsx).
2
+
3
+ `run ingest` belongs to the knowledge-base area (cli/commands/run_ingest.py).
4
+ """
5
+
6
+ import json
7
+ from typing import Any
8
+
9
+ import typer
10
+
11
+ from agentcore.cli.commands._jobs_common import fail_early, print_json, red, require_project
12
+ from agentcore.cli.errors import get_error_message
13
+ from agentcore.cli.groups import group
14
+ from agentcore.cli.run_command import run_cli_command
15
+ from agentcore.cli.variadic import variadic
16
+ from agentcore.lib import ConfigIO, ValidationError, serialize_result
17
+ from agentcore.operations.eval.run_eval import handle_run_eval
18
+ from agentcore.operations.jobs import create_job_engine, run_dataset_phase1, wait_for_terminal
19
+ from agentcore.operations.jobs.ab_test.format import print_ab_test_detail
20
+ from agentcore.operations.jobs.recommendation.format import failure_text
21
+ from agentcore.operations.jobs.shared.format import parse_int, to_fixed, to_locale_string
22
+ from agentcore.schema import is_valid_kms_key_arn
23
+
24
+ RECOMMENDATION_TYPE_MAP = {
25
+ "system-prompt": "SYSTEM_PROMPT_RECOMMENDATION",
26
+ "tool-description": "TOOL_DESCRIPTION_RECOMMENDATION",
27
+ }
28
+ _DATASET_VERSION_ERROR = "--dataset-version requires --dataset (the version selects a version of that dataset)"
29
+ _ENDPOINT_HELP = "Runtime endpoint name (e.g. PROMPT_V1). Defaults to AGENTCORE_RUNTIME_ENDPOINT env var, then DEFAULT"
30
+ _KMS_HELP_ERROR = (
31
+ "--kms-key must be a valid KMS key ARN "
32
+ "(e.g. arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012)"
33
+ )
34
+
35
+ run_app = group("run")
36
+
37
+
38
+ def _job_json(record: dict[str, Any], extra: dict[str, Any] | None = None) -> None:
39
+ print_json(serialize_result({"success": True, **record, **(extra or {})}))
40
+
41
+
42
+ # ──────────────────────────────────────────────────────────────────────────────
43
+ # run eval
44
+ # ──────────────────────────────────────────────────────────────────────────────
45
+
46
+
47
+ def format_run_output(value: dict[str, Any]) -> None:
48
+ run = value["run"]
49
+ lookback = "" if run.get("source") == "dataset" else f" | Lookback: {run.get('lookbackDays')}d"
50
+ dataset = run.get("dataset")
51
+ dataset_str = (
52
+ f" | Dataset: {dataset['id']}@{dataset['version']}" if run.get("source") == "dataset" and dataset else ""
53
+ )
54
+ typer.echo(
55
+ f"\nAgent: {run['agent']} | {to_locale_string(run['timestamp'])} | Sessions: {run['sessionCount']}"
56
+ f"{lookback}{dataset_str}"
57
+ )
58
+ refs = run.get("referenceInputs")
59
+ if refs:
60
+ parts = []
61
+ if refs.get("assertions"):
62
+ parts.append(f"{len(refs['assertions'])} assertion(s)")
63
+ if refs.get("expectedResponse"):
64
+ parts.append("expected response")
65
+ if refs.get("expectedTrajectory"):
66
+ parts.append(f"{len(refs['expectedTrajectory'])} trajectory step(s)")
67
+ if parts:
68
+ typer.echo(f"Reference inputs: {', '.join(parts)}")
69
+ typer.echo("")
70
+ for r in run["results"]:
71
+ errors = sum(1 for s in r["sessionScores"] if s.get("errorMessage"))
72
+ suffix = f" ({errors} errors)" if errors else ""
73
+ typer.echo(f" {r['evaluator']}: {to_fixed(r['aggregateScore'], 2)}{suffix}")
74
+ if value.get("filePath"):
75
+ typer.echo(f"\nResults saved to: {value['filePath']}")
76
+
77
+
78
+ @run_app.command(
79
+ "eval",
80
+ help="Run on-demand evaluation of runtime traces. Use --runtime-arn to evaluate runtimes outside the project.",
81
+ cls=variadic("-e", "--evaluator", "--evaluator-arn", "-A", "--assertion"),
82
+ )
83
+ def run_eval(
84
+ runtime: str | None = typer.Option(None, "-r", "--runtime", help="Runtime name from project config"),
85
+ runtime_arn: str | None = typer.Option(None, "--runtime-arn", help="Runtime ARN — run outside a project directory"),
86
+ evaluator: list[str] | None = typer.Option(
87
+ None, "-e", "--evaluator", help="Evaluator name(s) — project evaluators or Builtin.* IDs"
88
+ ),
89
+ evaluator_arn: list[str] | None = typer.Option(
90
+ None, "--evaluator-arn", help="Evaluator ARN(s) — use with --runtime-arn for standalone mode"
91
+ ),
92
+ region: str | None = typer.Option(
93
+ None, "--region", help="AWS region (required with --runtime-arn, auto-detected otherwise)"
94
+ ),
95
+ session_id: str | None = typer.Option(None, "-s", "--session-id", help="Evaluate a specific session only"),
96
+ trace_id: str | None = typer.Option(None, "-t", "--trace-id", help="Evaluate a specific trace only"),
97
+ endpoint: str | None = typer.Option(None, "--endpoint", help=_ENDPOINT_HELP),
98
+ days: str = typer.Option("7", "--days", help="Lookback window in days"),
99
+ assertion: list[str] | None = typer.Option(
100
+ None, "-A", "--assertion", help="Ground truth assertion the agent response must satisfy (repeatable)"
101
+ ),
102
+ expected_trajectory: str | None = typer.Option(
103
+ None, "--expected-trajectory", help="Ground truth: expected tool call names in order (comma-separated)"
104
+ ),
105
+ expected_response: str | None = typer.Option(
106
+ None, "--expected-response", help="Ground truth: expected agent response text to compare against"
107
+ ),
108
+ output: str | None = typer.Option(None, "--output", help="Custom output file path for results"),
109
+ dataset: str | None = typer.Option(
110
+ None, "--dataset", help="Dataset name — invoke agent with dataset scenarios instead of historical traces"
111
+ ),
112
+ dataset_version: str | None = typer.Option(
113
+ None, "--dataset-version", help="Dataset version to use (omit for local file, or N/DRAFT)"
114
+ ),
115
+ as_json: bool = typer.Option(False, "--json", help="Output as JSON"),
116
+ ) -> None:
117
+ if not (runtime_arn and evaluator_arn):
118
+ require_project()
119
+ if not evaluator and not evaluator_arn:
120
+ fail_early(as_json, "At least one --evaluator or --evaluator-arn is required")
121
+ if dataset_version and not dataset:
122
+ fail_early(as_json, _DATASET_VERSION_ERROR)
123
+
124
+ options = {
125
+ "agent": runtime,
126
+ "agentArn": runtime_arn,
127
+ "evaluator": evaluator or [],
128
+ "evaluatorArn": evaluator_arn or None,
129
+ "region": region,
130
+ "sessionId": session_id,
131
+ "traceId": trace_id,
132
+ "endpoint": endpoint,
133
+ "assertions": assertion or None,
134
+ "expectedTrajectory": [s.strip() for s in expected_trajectory.split(",")] if expected_trajectory else None,
135
+ "expectedResponse": expected_response,
136
+ "days": parse_int(days),
137
+ "output": output,
138
+ "dataset": dataset,
139
+ "datasetVersion": dataset_version,
140
+ "onProgress": None if as_json else (lambda _phase, message: typer.echo(message)),
141
+ }
142
+ try:
143
+ result = handle_run_eval(options)
144
+ if as_json:
145
+ print_json(serialize_result(result))
146
+ elif result.success:
147
+ format_run_output(result.value)
148
+ else:
149
+ red(str(result.error))
150
+ raise typer.Exit(0 if result.success else 1)
151
+ except typer.Exit:
152
+ raise
153
+ except Exception as exc: # noqa: BLE001
154
+ if as_json:
155
+ print_json({"success": False, "error": get_error_message(exc)})
156
+ else:
157
+ red(f"Error: {get_error_message(exc)}")
158
+ raise typer.Exit(1) from None
159
+
160
+
161
+ # ──────────────────────────────────────────────────────────────────────────────
162
+ # run batch-evaluation
163
+ # ──────────────────────────────────────────────────────────────────────────────
164
+
165
+
166
+ def print_batch_eval_result(record: dict[str, Any]) -> None:
167
+ results = record.get("evaluationResults")
168
+ if results:
169
+ parts = []
170
+ if results.get("totalNumberOfSessions") is not None:
171
+ parts.append(f"{results['totalNumberOfSessions']} sessions")
172
+ if results.get("numberOfSessionsCompleted") is not None:
173
+ parts.append(f"{results['numberOfSessionsCompleted']} completed")
174
+ if results.get("numberOfSessionsFailed"):
175
+ parts.append(f"{results['numberOfSessionsFailed']} failed")
176
+ if parts:
177
+ typer.echo(f"Sessions: {', '.join(parts)}")
178
+ summaries = (results or {}).get("evaluatorSummaries")
179
+ if summaries:
180
+ typer.echo("\nResults:")
181
+ for s in summaries:
182
+ avg = (s.get("statistics") or {}).get("averageScore")
183
+ fail = f" ({s['totalFailed']} failed)" if s.get("totalFailed") else ""
184
+ count = f" [{s['totalEvaluated']} evaluated]" if s.get("totalEvaluated") is not None else ""
185
+ typer.echo(f" {s.get('evaluatorId')}: {to_fixed(avg, 2) if avg is not None else 'N/A'} avg{fail}{count}")
186
+ elif record.get("results"):
187
+ typer.echo("\nResults:")
188
+ groups: dict[str, list[dict[str, Any]]] = {}
189
+ for r in record["results"]:
190
+ groups.setdefault(r.get("evaluatorId"), []).append(r)
191
+ for evaluator_id, entries in groups.items():
192
+ scores = [r["score"] for r in entries if not r.get("error") and r.get("score") is not None]
193
+ avg = sum(scores) / len(scores) if scores else 0
194
+ errors = sum(1 for r in entries if r.get("error"))
195
+ typer.echo(f" {evaluator_id}: {to_fixed(avg, 2)} avg{f' ({errors} errors)' if errors else ''}")
196
+
197
+
198
+ @run_app.command(
199
+ "batch-evaluation",
200
+ help="Run evaluators in batch across all agent sessions in CloudWatch",
201
+ cls=variadic("-e", "--evaluator", "--evaluator-arn", "-s", "--session-ids"),
202
+ )
203
+ def run_batch_evaluation(
204
+ runtime: str | None = typer.Option(
205
+ None, "-r", "--runtime", help="Runtime name from project config [non-interactive]"
206
+ ),
207
+ evaluator: list[str] | None = typer.Option(
208
+ None, "-e", "--evaluator", help="Evaluator name(s) — Builtin.* IDs [non-interactive]"
209
+ ),
210
+ evaluator_arn: list[str] | None = typer.Option(
211
+ None, "--evaluator-arn", help="Evaluator ARN(s) — use instead of -e when referencing evaluators by ARN"
212
+ ),
213
+ name: str | None = typer.Option(
214
+ None, "-n", "--name", help="Name for the batch evaluation (auto-generated if omitted)"
215
+ ),
216
+ lookback_days: str | None = typer.Option(
217
+ None, "-d", "--lookback-days", help="Lookback window in days (filters sessions by time range)"
218
+ ),
219
+ session_ids: list[str] | None = typer.Option(None, "-s", "--session-ids", help="Specific session IDs to evaluate"),
220
+ ground_truth: str | None = typer.Option(
221
+ None,
222
+ "-g",
223
+ "--ground-truth",
224
+ help="JSON file with session metadata and ground truth (assertions, expected trajectory, turns)",
225
+ ),
226
+ region: str | None = typer.Option(None, "--region", help="AWS region (auto-detected if omitted)"),
227
+ endpoint: str | None = typer.Option(None, "--endpoint", help=_ENDPOINT_HELP),
228
+ dataset: str | None = typer.Option(
229
+ None, "--dataset", help="Dataset name — invoke agent with dataset scenarios before batch evaluation"
230
+ ),
231
+ dataset_version: str | None = typer.Option(
232
+ None, "--dataset-version", help="Dataset version to use (omit for local file, or N/DRAFT)"
233
+ ),
234
+ kms_key: str | None = typer.Option(None, "--kms-key", help="KMS key ARN for encrypting batch evaluation results"),
235
+ wait: bool = typer.Option(False, "--wait", help="Block until the batch evaluation reaches a terminal state"),
236
+ as_json: bool = typer.Option(False, "--json", help="Output as JSON"),
237
+ ) -> None:
238
+ require_project()
239
+ if not runtime and not as_json:
240
+ from agentcore.cli import interactive
241
+ from agentcore.cli.commands._run_wizards import run_batch_eval_wizard
242
+
243
+ interactive.require_tty()
244
+ run_batch_eval_wizard()
245
+ raise typer.Exit(0)
246
+ if not runtime or (not evaluator and not evaluator_arn):
247
+ fail_early(
248
+ as_json, "--runtime and at least one --evaluator or --evaluator-arn are required in non-interactive mode"
249
+ )
250
+ if dataset_version and not dataset:
251
+ fail_early(as_json, _DATASET_VERSION_ERROR)
252
+
253
+ def log(message: str) -> None:
254
+ if not as_json:
255
+ typer.echo(message)
256
+
257
+ def run() -> None:
258
+ engine = create_job_engine(ConfigIO())
259
+ session_metadata = None
260
+ if ground_truth:
261
+ with open(ground_truth, encoding="utf-8") as fh:
262
+ data = json.load(fh)
263
+ parsed = (
264
+ data if isinstance(data, list) else (data.get("sessionMetadata") if isinstance(data, dict) else None)
265
+ )
266
+ if not isinstance(parsed, list):
267
+ raise Exception(
268
+ "Ground truth file must be a JSON array of session metadata entries, or an object with a "
269
+ '"sessionMetadata" key'
270
+ )
271
+ session_metadata = parsed
272
+ days = parse_int(lookback_days) if lookback_days else None
273
+ if lookback_days and (days is None or days < 1 or days > 90):
274
+ raise Exception("--lookback-days must be between 1 and 90")
275
+ ids = list(session_ids) if session_ids else None
276
+ dataset_info = {"id": dataset, "version": dataset_version or "LOCAL"} if dataset else None
277
+ if dataset:
278
+ phase1 = run_dataset_phase1(
279
+ agent=runtime or "",
280
+ dataset_name=dataset,
281
+ dataset_version=dataset_version,
282
+ endpoint=endpoint,
283
+ on_progress=lambda _p, m: log(m),
284
+ )
285
+ if not phase1.success:
286
+ raise phase1.error
287
+ ids = [*(ids or []), *phase1.value["sessionIds"]]
288
+ session_metadata = [*(session_metadata or []), *phase1.value["sessionMetadata"]]
289
+ start = engine.start(
290
+ "batch-evaluation",
291
+ {
292
+ "agent": runtime,
293
+ "evaluators": [*(evaluator or []), *(evaluator_arn or [])],
294
+ "name": name,
295
+ "region": region,
296
+ "endpoint": endpoint,
297
+ "sessionIds": ids,
298
+ "lookbackDays": days or None,
299
+ "sessionMetadata": session_metadata,
300
+ "source": "dataset" if dataset else "traces",
301
+ "dataset": dataset_info,
302
+ "kmsKeyArn": kms_key,
303
+ "onProgress": None if as_json else (lambda _s, m: typer.echo(m)),
304
+ },
305
+ )
306
+ if not start.success:
307
+ raise start.error
308
+ record = start.value
309
+ if wait:
310
+ final = wait_for_terminal(engine, "batch-evaluation", record["id"], on_tick=lambda s: log(f"Status: {s}"))
311
+ if final:
312
+ record = final
313
+ if as_json:
314
+ _job_json(record)
315
+ else:
316
+ typer.echo(f"\n✓ Batch evaluation started: {record['id']} ({record['status']})")
317
+ print_batch_eval_result(record)
318
+ if not wait:
319
+ typer.echo(f"\nNext: agentcore view batch-evaluation {record['id']}")
320
+ typer.echo("")
321
+
322
+ run_cli_command(as_json, run)
323
+
324
+
325
+ # ──────────────────────────────────────────────────────────────────────────────
326
+ # run insights
327
+ # ──────────────────────────────────────────────────────────────────────────────
328
+
329
+
330
+ def print_insights_result(record: dict[str, Any]) -> None:
331
+ categories = (record.get("failureAnalysisResult") or {}).get("failureCategories")
332
+ summaries = (record.get("evaluationResults") or {}).get("evaluatorSummaries")
333
+ if categories:
334
+ typer.echo("\nFailure Analysis:")
335
+ for cat in categories:
336
+ typer.echo(
337
+ f" {cat.get('failureCategoryName') or 'Unknown'}: {cat.get('failureCategoryDescription') or ''}"
338
+ )
339
+ for rc in cat.get("rootCauses") or []:
340
+ typer.echo(f" - {rc.get('rootCauseCategory') or ''}: {rc.get('rootCauseDescription') or ''}")
341
+ if rc.get("recommendation"):
342
+ typer.echo(f" Recommendation: {rc['recommendation']}")
343
+ elif summaries:
344
+ typer.echo("\nEvaluation Results:")
345
+ for s in summaries:
346
+ avg = (s.get("statistics") or {}).get("averageScore")
347
+ typer.echo(f" {s.get('evaluatorId')}: {to_fixed(avg, 2) if avg is not None else 'N/A'}")
348
+
349
+
350
+ @run_app.command(
351
+ "insights",
352
+ help="[preview] Run failure analysis across agent sessions",
353
+ cls=variadic("--insights", "-e", "--evaluator", "-s", "--session-ids"),
354
+ )
355
+ def run_insights(
356
+ runtime: str | None = typer.Option(None, "-r", "--runtime", help="Runtime name from project config"),
357
+ insights: list[str] | None = typer.Option(
358
+ None, "--insights", help="Insight type(s) (default: Builtin.Insight.FailureAnalysis)"
359
+ ),
360
+ evaluator: list[str] | None = typer.Option(
361
+ None, "-e", "--evaluator", help="Evaluator(s) to include (needed for chaining into recommendations)"
362
+ ),
363
+ online_eval_config_arn: str | None = typer.Option(
364
+ None, "--online-eval-config-arn", help="Use an existing OnlineEvaluationConfig as session source"
365
+ ),
366
+ lookback_days: str | None = typer.Option(
367
+ None, "-d", "--lookback-days", help="Lookback window in days (default: 7)"
368
+ ),
369
+ start_time: str | None = typer.Option(None, "--start-time", help="Session filter start time"),
370
+ end_time: str | None = typer.Option(None, "--end-time", help="Session filter end time"),
371
+ session_ids: list[str] | None = typer.Option(None, "-s", "--session-ids", help="Limit to specific session IDs"),
372
+ name: str | None = typer.Option(None, "-n", "--name", help="Job name (auto-generated if omitted)"),
373
+ kms_key: str | None = typer.Option(None, "--kms-key", help="KMS key ARN for encrypting insights job results"),
374
+ wait: bool = typer.Option(False, "--wait", help="Block until the job reaches a terminal state"),
375
+ region: str | None = typer.Option(None, "--region", help="AWS region (auto-detected if omitted)"),
376
+ endpoint: str | None = typer.Option(None, "--endpoint", help="Runtime endpoint name (e.g. PROMPT_V1)"),
377
+ as_json: bool = typer.Option(False, "--json", help="Output as JSON"),
378
+ ) -> None:
379
+ require_project()
380
+
381
+ def log(message: str) -> None:
382
+ if not as_json:
383
+ typer.echo(message)
384
+
385
+ def run() -> None:
386
+ if name is not None and name.strip() == "":
387
+ raise ValidationError("--name must not be empty. Omit the flag to auto-generate a name.")
388
+ if kms_key and not is_valid_kms_key_arn(kms_key):
389
+ raise ValidationError(_KMS_HELP_ERROR)
390
+ engine = create_job_engine(ConfigIO())
391
+ days = parse_int(lookback_days) if lookback_days else None
392
+ if lookback_days and (days is None or days < 1 or days > 90):
393
+ raise ValidationError("--lookback-days must be a positive integer between 1 and 90.")
394
+ start = engine.start(
395
+ "insights",
396
+ {
397
+ "agent": runtime,
398
+ "insights": list(insights) if insights else ["Builtin.Insight.FailureAnalysis"],
399
+ "evaluators": list(evaluator) if evaluator else None,
400
+ "onlineEvalConfigArn": online_eval_config_arn,
401
+ "lookbackDays": days or None,
402
+ "startTime": start_time,
403
+ "endTime": end_time,
404
+ "sessionIds": list(session_ids) if session_ids else None,
405
+ "name": name,
406
+ "kmsKeyArn": kms_key,
407
+ "region": region,
408
+ "endpoint": endpoint,
409
+ "onProgress": None if as_json else (lambda _s, m: typer.echo(m)),
410
+ },
411
+ )
412
+ if not start.success:
413
+ raise start.error
414
+ record = start.value
415
+ if wait:
416
+ final = wait_for_terminal(engine, "insights", record["id"], on_tick=lambda s: log(f"Status: {s}"))
417
+ if final:
418
+ record = final
419
+ if as_json:
420
+ _job_json(record)
421
+ else:
422
+ typer.echo(f"\n✓ Insights job started: {record['id']} ({record['status']})")
423
+ print_insights_result(record)
424
+ if not wait:
425
+ typer.echo(f"\nNext: agentcore insights results --id {record['id']}")
426
+ typer.echo("")
427
+
428
+ run_cli_command(as_json, run)
429
+
430
+
431
+ # ──────────────────────────────────────────────────────────────────────────────
432
+ # run recommendation
433
+ # ──────────────────────────────────────────────────────────────────────────────
434
+
435
+
436
+ def print_recommendation_result(record: dict[str, Any]) -> None:
437
+ result = record.get("result") or {}
438
+ sys_result = result.get("systemPromptRecommendationResult") or {}
439
+ tool_result = result.get("toolDescriptionRecommendationResult") or {}
440
+ if sys_result.get("recommendedSystemPrompt"):
441
+ if sys_result.get("explanation"):
442
+ typer.echo("\n--- Explanation ---")
443
+ typer.echo(sys_result["explanation"])
444
+ typer.echo("\n+++ Recommended System Prompt +++")
445
+ typer.echo(sys_result["recommendedSystemPrompt"])
446
+ elif tool_result.get("tools"):
447
+ for t in tool_result["tools"]:
448
+ typer.echo(f"\nTool: {t.get('toolName')}")
449
+ if t.get("explanation"):
450
+ typer.echo(f"Explanation: {t['explanation']}")
451
+ typer.echo(f"Recommended: {t.get('recommendedToolDescription')}")
452
+ elif record.get("status") == "FAILED":
453
+ typer.echo(f"\nError: {failure_text(record)}")
454
+ if record.get("syncedVersionId"):
455
+ typer.echo(f"\nNew config bundle version {record['syncedVersionId']} applied to agentcore.json.")
456
+
457
+
458
+ @run_app.command(
459
+ "recommendation",
460
+ help="Optimize a system prompt or tool descriptions using agent traces as signal",
461
+ cls=variadic("--tool-desc-json-path", "--tools", "-s", "--session-id"),
462
+ )
463
+ def run_recommendation(
464
+ type_: str | None = typer.Option(
465
+ None, "-t", "--type", help="What to optimize: system-prompt or tool-description (default: system-prompt)"
466
+ ),
467
+ runtime: str | None = typer.Option(None, "-r", "--runtime", help="Runtime name from project config"),
468
+ evaluator: str | None = typer.Option(
469
+ None,
470
+ "-e",
471
+ "--evaluator",
472
+ help="Evaluator name (exactly one). Required for system-prompt unless the trace source is a batch or online "
473
+ "evaluation, which inherits its evaluator",
474
+ ),
475
+ prompt_file: str | None = typer.Option(None, "--prompt-file", help="Load the current system prompt from a file"),
476
+ inline: str | None = typer.Option(
477
+ None, "--inline", help="Provide the current system prompt or tool descriptions inline"
478
+ ),
479
+ bundle_name: str | None = typer.Option(
480
+ None, "--bundle-name", help="Read current content from a deployed config bundle"
481
+ ),
482
+ bundle_version: str | None = typer.Option(
483
+ None, "--bundle-version", help="Config bundle version (used with --bundle-name)"
484
+ ),
485
+ system_prompt_json_path: str | None = typer.Option(
486
+ None,
487
+ "--system-prompt-json-path",
488
+ help='Field name under "configuration" in the bundle (e.g. "systemPrompt"). The CLI resolves it to the '
489
+ "full path automatically. Do not use bracket notation — use dot notation only.",
490
+ ),
491
+ tool_desc_json_path: list[str] | None = typer.Option(
492
+ None,
493
+ "--tool-desc-json-path",
494
+ help="Tool name:field pairs for tool descriptions in a config bundle (e.g. --tool-desc-json-path "
495
+ '"search:searchDesc"). The CLI resolves each to the full path automatically.',
496
+ ),
497
+ tools: list[str] | None = typer.Option(
498
+ None,
499
+ "--tools",
500
+ help='Tool name:description pairs (repeatable, e.g. --tools "search:Searches the web" --tools "calc:Does '
501
+ 'math")',
502
+ ),
503
+ spans_file: str | None = typer.Option(
504
+ None, "--spans-file", help="JSON file with OTEL session spans (use instead of CloudWatch traces)"
505
+ ),
506
+ lookback: str = typer.Option(
507
+ "7",
508
+ "--lookback",
509
+ help="How far back to collect traces (days). Also bounds the online-evaluation reuse window: startTime = "
510
+ "now − lookback, endTime = now",
511
+ ),
512
+ session_id: list[str] | None = typer.Option(
513
+ None, "-s", "--session-id", help="Limit trace collection to specific session IDs"
514
+ ),
515
+ run_name: str | None = typer.Option(None, "-n", "--run", help="Run name prefix for the recommendation"),
516
+ region: str | None = typer.Option(None, "--region", help="AWS region"),
517
+ kms_key: str | None = typer.Option(None, "--kms-key", help="KMS key ARN for encrypting recommendation results"),
518
+ from_insights: str | None = typer.Option(
519
+ None, "--from-insights", help="Use a local insights run as trace source (resolves batch eval ARN)"
520
+ ),
521
+ batch_evaluation_arn: str | None = typer.Option(
522
+ None, "--batch-evaluation-arn", help="Use a batch evaluation ARN directly as trace source"
523
+ ),
524
+ online_evaluation_arn: str | None = typer.Option(
525
+ None, "--online-evaluation-arn", help="Use an online evaluation config ARN as trace source"
526
+ ),
527
+ wait: bool = typer.Option(False, "--wait", help="Block until the recommendation reaches a terminal state"),
528
+ as_json: bool = typer.Option(False, "--json", help="Output as JSON"),
529
+ ) -> None:
530
+ require_project()
531
+ source_flags = [
532
+ ("--batch-evaluation-arn", bool(batch_evaluation_arn)),
533
+ ("--from-insights", bool(from_insights)),
534
+ ("--online-evaluation-arn", bool(online_evaluation_arn)),
535
+ ("--spans-file", bool(spans_file)),
536
+ ("--session-id", bool(session_id)),
537
+ ]
538
+ has_source = any(is_set for _, is_set in source_flags)
539
+ if not runtime and not has_source and not as_json:
540
+ from agentcore.cli import interactive
541
+ from agentcore.cli.commands._run_wizards import run_recommendation_wizard
542
+
543
+ interactive.require_tty()
544
+ run_recommendation_wizard()
545
+ raise typer.Exit(0)
546
+
547
+ set_flags = [n for n, is_set in source_flags if is_set]
548
+ if len(set_flags) > 1:
549
+ fail_early(
550
+ as_json,
551
+ f"Only one trace source may be specified. Got: {', '.join(set_flags)}. Use exactly one of "
552
+ "--batch-evaluation-arn, --from-insights, --online-evaluation-arn, --spans-file, or --session-id.",
553
+ )
554
+ type_key = type_ if type_ is not None else "system-prompt"
555
+ rec_type = RECOMMENDATION_TYPE_MAP.get(type_key)
556
+ if not rec_type:
557
+ fail_early(as_json, f'Invalid --type "{type_key}". Must be one of: {", ".join(RECOMMENDATION_TYPE_MAP)}')
558
+ is_batch = bool(from_insights or batch_evaluation_arn)
559
+ is_online = bool(online_evaluation_arn)
560
+ no_agent = is_batch or is_online
561
+ if not runtime and not no_agent:
562
+ fail_early(
563
+ as_json,
564
+ "--runtime is required (unless --from-insights, --batch-evaluation-arn, or --online-evaluation-arn is "
565
+ "provided)",
566
+ )
567
+ if rec_type == "SYSTEM_PROMPT_RECOMMENDATION" and not evaluator and not no_agent:
568
+ fail_early(
569
+ as_json,
570
+ "--evaluator is required for system-prompt recommendations (unless using --from-insights, "
571
+ "--batch-evaluation-arn, or --online-evaluation-arn)",
572
+ )
573
+ if prompt_file:
574
+ input_source = "file"
575
+ elif inline:
576
+ input_source = "inline"
577
+ elif bundle_name:
578
+ input_source = "config-bundle"
579
+ else:
580
+ input_source = "inline"
581
+ if is_batch:
582
+ trace_source = "batch-evaluation"
583
+ elif is_online:
584
+ trace_source = "online-evaluation"
585
+ elif spans_file:
586
+ trace_source = "spans-file"
587
+ elif session_id:
588
+ trace_source = "sessions"
589
+ else:
590
+ trace_source = "cloudwatch"
591
+ pairs = []
592
+ for pair in tool_desc_json_path or []:
593
+ idx = pair.find(":")
594
+ if idx > 0:
595
+ pairs.append({"toolName": pair[:idx], "toolDescriptionJsonPath": pair[idx + 1 :]})
596
+
597
+ def run() -> None:
598
+ engine = create_job_engine(ConfigIO())
599
+ start = engine.start(
600
+ "recommendation",
601
+ {
602
+ "type": rec_type,
603
+ "agent": runtime or "",
604
+ "evaluators": [evaluator] if evaluator else [],
605
+ "promptFile": prompt_file,
606
+ "inlineContent": inline,
607
+ "bundleName": bundle_name,
608
+ "bundleVersion": bundle_version,
609
+ "systemPromptJsonPath": system_prompt_json_path,
610
+ "toolDescJsonPaths": pairs or None,
611
+ "tools": list(tools) if tools else None,
612
+ "lookbackDays": parse_int(lookback),
613
+ "sessionIds": list(session_id) if session_id else None,
614
+ "spansFile": spans_file,
615
+ "fromInsights": from_insights,
616
+ "batchEvaluationArn": batch_evaluation_arn,
617
+ "onlineEvaluationArn": online_evaluation_arn,
618
+ "recommendationName": run_name,
619
+ "region": region,
620
+ "kmsKeyArn": kms_key,
621
+ "inputSource": input_source,
622
+ "traceSource": trace_source,
623
+ "onProgress": None if as_json else (lambda _s, m: typer.echo(m)),
624
+ },
625
+ )
626
+ if not start.success:
627
+ raise start.error
628
+ record = start.value
629
+ if wait:
630
+
631
+ def tick(status: str) -> None:
632
+ if not as_json:
633
+ typer.echo(f"Status: {status}")
634
+
635
+ final = wait_for_terminal(engine, "recommendation", record["id"], on_tick=tick)
636
+ if final:
637
+ record = final
638
+ if as_json:
639
+ _job_json(record)
640
+ else:
641
+ typer.echo(f"\n✓ Recommendation started: {record['id']} ({record['status']})")
642
+ print_recommendation_result(record)
643
+ if not wait:
644
+ suffix = (
645
+ " — the new config bundle will be applied to agentcore.json automatically."
646
+ if input_source == "config-bundle"
647
+ else ""
648
+ )
649
+ typer.echo(f"\nNext: agentcore view recommendation {record['id']}{suffix}")
650
+ typer.echo("")
651
+
652
+ run_cli_command(as_json, run)
653
+
654
+
655
+ # ──────────────────────────────────────────────────────────────────────────────
656
+ # run ab-test
657
+ # ──────────────────────────────────────────────────────────────────────────────
658
+
659
+ _AB_TEST_EPILOG = """\b
660
+ Config-bundle mode example:
661
+ agentcore run ab-test -n MyTest -g MyGateway \\
662
+ --control-bundle PromptV1 --control-version LATEST \\
663
+ --treatment-bundle PromptV2 --treatment-version LATEST \\
664
+ --online-eval QualityEval
665
+
666
+ \b
667
+ Target-based mode example:
668
+ agentcore run ab-test -n MyTest -g MyGateway --mode target-based \\
669
+ --control-target prod-target --treatment-target staging-target \\
670
+ --control-online-eval ProdEval --treatment-online-eval StagingEval
671
+ """
672
+
673
+
674
+ def weight_error(control_raw: str, treatment_raw: str) -> tuple[int | None, int | None, str | None]:
675
+ cw, tw = parse_int(control_raw), parse_int(treatment_raw)
676
+ if cw is None or cw < 0 or cw > 100:
677
+ return cw, tw, f'Invalid --control-weight "{control_raw}". Must be an integer between 0 and 100.'
678
+ if tw is None or tw < 0 or tw > 100:
679
+ return cw, tw, f'Invalid --treatment-weight "{treatment_raw}". Must be an integer between 0 and 100.'
680
+ if cw + tw != 100:
681
+ return cw, tw, f"Variant weights must sum to 100 (got {cw} + {tw} = {cw + tw})."
682
+ return cw, tw, None
683
+
684
+
685
+ def start_ab_test(opts: dict[str, Any], *, wait: bool, as_json: bool) -> None:
686
+ engine = create_job_engine(ConfigIO())
687
+ start = engine.start("ab-test", opts)
688
+ if not start.success:
689
+ raise start.error
690
+ record = start.value
691
+ if wait:
692
+
693
+ def tick(status: str) -> None:
694
+ if not as_json:
695
+ typer.echo(f"Status: {status}")
696
+
697
+ final = wait_for_terminal(engine, "ab-test", record["id"], on_tick=tick)
698
+ if final:
699
+ record = final
700
+ if as_json:
701
+ _job_json(record)
702
+ else:
703
+ typer.echo(f"\n✓ A/B test started: {record['id']} ({record['status']})")
704
+ print_ab_test_detail(record)
705
+ if not wait:
706
+ typer.echo(f"\nNext: agentcore view ab-test {record['id']}")
707
+ typer.echo("")
708
+
709
+
710
+ @run_app.command(
711
+ "ab-test", help="Start an A/B test comparing two config-bundle or gateway-target variants", epilog=_AB_TEST_EPILOG
712
+ )
713
+ def run_ab_test(
714
+ name: str | None = typer.Option(None, "-n", "--name", help="Name for the A/B test [non-interactive]"),
715
+ gateway: str | None = typer.Option(
716
+ None, "-g", "--gateway", help="Gateway name (must be deployed) [non-interactive]"
717
+ ),
718
+ mode: str = typer.Option(
719
+ "config-bundle", "-m", "--mode", help="config-bundle | target-based (default: config-bundle)"
720
+ ),
721
+ description: str | None = typer.Option(None, "--description", help="Description"),
722
+ runtime: str | None = typer.Option(None, "-r", "--runtime", help="Runtime name (recorded as the agent)"),
723
+ control_weight: str = typer.Option("50", "--control-weight", help="Control traffic weight 0-100 (default: 50)"),
724
+ treatment_weight: str = typer.Option(
725
+ "50", "--treatment-weight", help="Treatment traffic weight 0-100 (default: 50)"
726
+ ),
727
+ role_arn: str | None = typer.Option(None, "--role-arn", help="Execution role ARN (auto-created if omitted)"),
728
+ disable_on_create: bool = typer.Option(
729
+ False, "--disable-on-create", help="Create without starting (default: enabled)"
730
+ ),
731
+ region: str | None = typer.Option(None, "--region", help="AWS region (auto-detected if omitted)"),
732
+ wait: bool = typer.Option(False, "--wait", help="Block until terminal state"),
733
+ as_json: bool = typer.Option(False, "--json", help="Output as JSON"),
734
+ control_bundle: str | None = typer.Option(
735
+ None, "--control-bundle", help="[config-bundle] Control bundle name or ARN"
736
+ ),
737
+ control_version: str | None = typer.Option(
738
+ None, "--control-version", help="[config-bundle] Control bundle version (or LATEST)"
739
+ ),
740
+ treatment_bundle: str | None = typer.Option(
741
+ None, "--treatment-bundle", help="[config-bundle] Treatment bundle name or ARN"
742
+ ),
743
+ treatment_version: str | None = typer.Option(
744
+ None, "--treatment-version", help="[config-bundle] Treatment bundle version (or LATEST)"
745
+ ),
746
+ online_eval: str | None = typer.Option(
747
+ None, "--online-eval", help="[config-bundle] Shared online eval config name or ARN"
748
+ ),
749
+ control_target: str | None = typer.Option(
750
+ None, "--control-target", help="[target-based] Control gateway-target name"
751
+ ),
752
+ treatment_target: str | None = typer.Option(
753
+ None, "--treatment-target", help="[target-based] Treatment gateway-target name"
754
+ ),
755
+ control_online_eval: str | None = typer.Option(
756
+ None, "--control-online-eval", help="[target-based] Online eval for control endpoint (required)"
757
+ ),
758
+ treatment_online_eval: str | None = typer.Option(
759
+ None, "--treatment-online-eval", help="[target-based] Online eval for treatment endpoint (required)"
760
+ ),
761
+ gateway_filter: str | None = typer.Option(
762
+ None,
763
+ "--gateway-filter",
764
+ help='Single gateway target path pattern to scope the test (e.g. "/orders/*"). Applies to both modes. '
765
+ "Optional; omit for no gateway filter.",
766
+ ),
767
+ ) -> None:
768
+ require_project()
769
+ if not name and not as_json:
770
+ from agentcore.cli import interactive
771
+ from agentcore.cli.commands._run_wizards import run_ab_test_wizard
772
+
773
+ interactive.require_tty()
774
+ run_ab_test_wizard()
775
+ raise typer.Exit(0)
776
+ if not name or not gateway:
777
+ fail_early(as_json, "--name and --gateway are required in non-interactive mode")
778
+ if mode not in ("config-bundle", "target-based"):
779
+ fail_early(as_json, f'Invalid --mode "{mode}". Must be one of: config-bundle, target-based')
780
+ cw, tw, error = weight_error(control_weight, treatment_weight)
781
+ if error:
782
+ fail_early(as_json, error)
783
+
784
+ opts = {
785
+ "name": name,
786
+ "mode": mode,
787
+ "description": description,
788
+ "gateway": gateway,
789
+ "agent": runtime,
790
+ "controlBundle": control_bundle,
791
+ "controlVersion": control_version,
792
+ "treatmentBundle": treatment_bundle,
793
+ "treatmentVersion": treatment_version,
794
+ "onlineEval": online_eval,
795
+ "runtime": runtime,
796
+ "controlTarget": control_target,
797
+ "treatmentTarget": treatment_target,
798
+ "controlOnlineEval": control_online_eval,
799
+ "treatmentOnlineEval": treatment_online_eval,
800
+ "gatewayFilter": gateway_filter,
801
+ "controlWeight": cw,
802
+ "treatmentWeight": tw,
803
+ "enableOnCreate": not disable_on_create,
804
+ "region": region,
805
+ "roleArn": role_arn,
806
+ "onProgress": None if as_json else (lambda _s, m: typer.echo(m)),
807
+ }
808
+ run_cli_command(as_json, lambda: start_ab_test(opts, wait=wait, as_json=as_json))