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,909 @@
1
+ """Custom evaluator add/remove (port of src/cli/primitives/EvaluatorPrimitive.ts).
2
+
3
+ Also hosts the evaluator wizard constants from tui/screens/evaluator/types.ts (rating scale
4
+ presets, level placeholders, model options) since the flags and the prompts share them.
5
+ """
6
+
7
+ import json
8
+ import math
9
+ import os
10
+ import re
11
+ import shutil
12
+ from dataclasses import dataclass
13
+ from typing import Any
14
+
15
+ import typer
16
+ from pydantic import TypeAdapter
17
+ from pydantic import ValidationError as PydanticValidationError
18
+
19
+ from agentcore.cli import interactive
20
+ from agentcore.cli.errors import get_error_message
21
+ from agentcore.cli.naming import generate_unique_name
22
+ from agentcore.cli.run_command import run_cli_command
23
+ from agentcore.lib import ConflictError, ResourceNotFoundError, find_config_root, serialize_result
24
+ from agentcore.lib.errors.types import to_error
25
+ from agentcore.lib.result import Err, Ok
26
+ from agentcore.lib.schemas.io.config_io import to_jsonable
27
+ from agentcore.operations.jobs.shared.format import parse_int
28
+ from agentcore.primitives.base import BasePrimitive, RemovableResource, RemovalPreview, SchemaChange, emit_json
29
+ from agentcore.schema import EVALUATION_LEVELS, EvaluatorModelId, EvaluatorName, is_valid_kms_key_arn
30
+ from agentcore.schema.schemas.primitives.evaluator import is_valid_bedrock_model_id
31
+ from agentcore.templates import render_code_based_evaluator_template, render_third_party_evaluator_template
32
+
33
+ # ============================================================================
34
+ # Third-party library registry
35
+ # ============================================================================
36
+
37
+ THIRD_PARTY_EVALUATOR_LIBRARIES: dict[str, dict[str, Any]] = {
38
+ "deepeval": {
39
+ "templateDir": "deepeval-lambda",
40
+ "defaultTimeoutSeconds": 300,
41
+ "warnings": [
42
+ {
43
+ "metrics": {
44
+ "FaithfulnessMetric",
45
+ "HallucinationMetric",
46
+ "ContextualRelevancyMetric",
47
+ "ContextualPrecisionMetric",
48
+ "ContextualRecallMetric",
49
+ },
50
+ "message": "requires retrieval_context from tool-role messages. "
51
+ "If your agent has no tool calls, the evaluator will return MISSING_REQUIRED_FIELD at runtime.",
52
+ },
53
+ {
54
+ "metrics": {"ContextualPrecisionMetric", "ContextualRecallMetric"},
55
+ "message": "requires expected_output via evaluationReferenceInputs. "
56
+ "Caller must provide referenceInputs when invoking the Evaluate API.",
57
+ },
58
+ ],
59
+ },
60
+ "autoevals": {
61
+ "templateDir": "autoevals-lambda",
62
+ "defaultTimeoutSeconds": 60,
63
+ "warnings": [
64
+ {
65
+ "metrics": {"Factuality", "ClosedQA"},
66
+ "message": "requires expected_output via evaluationReferenceInputs. "
67
+ "Caller must provide referenceInputs when invoking the Evaluate API.",
68
+ },
69
+ {
70
+ "metrics": {"SQL"},
71
+ "message": "requires expected_output (reference SQL) via evaluationReferenceInputs. "
72
+ "Caller must provide referenceInputs when invoking the Evaluate API.",
73
+ },
74
+ ],
75
+ },
76
+ }
77
+ SUPPORTED_LIBRARIES = list(THIRD_PARTY_EVALUATOR_LIBRARIES)
78
+ MODEL_PROVIDERS = ("openai", "bedrock")
79
+
80
+ DEFAULT_CODE_ENTRYPOINT = "lambda_function.handler"
81
+ DEFAULT_CODE_TIMEOUT = 60
82
+ _KWARG_NAME = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
83
+ _LAMBDA_ARN = re.compile(r"^arn:aws[a-z-]*:lambda:[a-z0-9-]+:\d{12}:function:.+$")
84
+ KMS_ARN_ERROR = (
85
+ "--kms-key-arn must be a valid KMS key ARN "
86
+ "(e.g. arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012)"
87
+ )
88
+
89
+ # ============================================================================
90
+ # Wizard constants (tui/screens/evaluator/types.ts)
91
+ # ============================================================================
92
+
93
+ EVALUATOR_TYPE_OPTIONS = (
94
+ ("code-based", "Code-based (custom Lambda function)", "Write custom Python code for evaluation logic"),
95
+ ("llm-as-a-judge", "LLM-as-a-Judge (model-based)", "Use a foundation model to evaluate quality"),
96
+ )
97
+ CODE_BASED_TYPE_OPTIONS = (
98
+ ("managed", "Create new (CLI scaffolds and deploys the Lambda for you)", "CLI scaffolds code and deploys Lambda"),
99
+ ("external", "Existing Lambda ARN (bring your own)", "Use an existing Lambda function"),
100
+ )
101
+ EVALUATION_LEVEL_OPTIONS = (
102
+ ("SESSION", "Session", "Overall quality across an entire conversation"),
103
+ ("TRACE", "Trace", "Per-turn accuracy of individual agent responses"),
104
+ ("TOOL_CALL", "Tool Call", "Correctness of individual tool selections and usage"),
105
+ )
106
+ DEFAULT_MODEL = "us.anthropic.claude-sonnet-4-5-20250929-v1:0"
107
+ DEFAULT_OPENAI_MODEL = "openai.gpt-5.4"
108
+ CUSTOM_MODEL_ID = "__custom__"
109
+ EVALUATOR_MODEL_PROVIDER_OPTIONS = (
110
+ ("Bedrock", "Amazon Bedrock", "Use the Bedrock Converse API"),
111
+ ("OpenResponses", "OpenAI on Bedrock", "Use the OpenResponses API through Bedrock Mantle"),
112
+ )
113
+ BEDROCK_EVALUATOR_MODEL_OPTIONS = (
114
+ ("us.anthropic.claude-sonnet-4-5-20250929-v1:0", "Claude Sonnet 4.5", "Recommended — balanced speed and accuracy"),
115
+ (
116
+ "global.anthropic.claude-opus-4-5-20251101-v1:0",
117
+ "Claude Opus 4.5",
118
+ "Most capable — best for complex evaluations",
119
+ ),
120
+ ("us.anthropic.claude-haiku-4-5-20251001-v1:0", "Claude Haiku 4.5", "Fastest — good for high-volume evaluations"),
121
+ ("us.amazon.nova-pro-v1:0", "Amazon Nova Pro", "Amazon foundation model — strong reasoning"),
122
+ ("us.amazon.nova-lite-v1:0", "Amazon Nova Lite", "Amazon foundation model — fast and cost-effective"),
123
+ (CUSTOM_MODEL_ID, "Other", "Enter a custom Bedrock model ID or ARN"),
124
+ )
125
+ OPENAI_EVALUATOR_MODEL_OPTIONS = (
126
+ ("openai.gpt-5.4", "GPT-5.4", "Recommended — high-quality reasoning and evaluation"),
127
+ ("openai.gpt-5.5", "GPT-5.5", "Most capable OpenAI model"),
128
+ ("openai.gpt-oss-120b", "GPT OSS 120B", "Open-weight model for complex evaluations"),
129
+ ("openai.gpt-oss-20b", "GPT OSS 20B", "Open-weight model for faster evaluations"),
130
+ (CUSTOM_MODEL_ID, "Other", "Enter a custom OpenAI model ID"),
131
+ )
132
+
133
+ LEVEL_PLACEHOLDERS: dict[str, list[str]] = {
134
+ "SESSION": ["context", "available_tools"],
135
+ "TRACE": ["context", "assistant_turn"],
136
+ "TOOL_CALL": [
137
+ "available_tools",
138
+ "context",
139
+ "tool_turn",
140
+ "available_skills",
141
+ "invoked_skill",
142
+ "skill_content",
143
+ "user_message",
144
+ ],
145
+ }
146
+ REFERENCE_INPUT_PLACEHOLDERS: dict[str, list[str]] = {
147
+ "SESSION": ["assertions", "expected_tool_trajectory", "actual_tool_trajectory"],
148
+ "TRACE": ["expected_response"],
149
+ "TOOL_CALL": [],
150
+ }
151
+ PLACEHOLDER_DESCRIPTIONS: dict[str, str] = {
152
+ "context": "full conversation history (user + assistant messages)",
153
+ "assistant_turn": "the specific assistant response being evaluated",
154
+ "available_tools": "list of tools the agent can call",
155
+ "tool_turn": "the specific tool call and its result",
156
+ "assertions": "caller-provided assertions the agent should satisfy",
157
+ "expected_tool_trajectory": "caller-provided expected sequence of tool calls",
158
+ "actual_tool_trajectory": "actual sequence of tool calls from the session",
159
+ "expected_response": "caller-provided expected agent response",
160
+ "available_skills": "skills offered to the agent (name + description)",
161
+ "invoked_skill": "the skill the agent selected for this span",
162
+ "skill_content": "the selected skill's SKILL.md instructions",
163
+ "user_message": "the user request in the turn that triggered the skill invocation",
164
+ }
165
+ DEFAULT_INSTRUCTIONS: dict[str, str] = {
166
+ "SESSION": "Evaluate the agent session. Context: {context}. Available tools: {available_tools}. The agent must "
167
+ "satisfy: {assertions}. Expected trajectory: {expected_tool_trajectory}. Actual trajectory: "
168
+ "{actual_tool_trajectory}. Rate the overall quality.",
169
+ "TRACE": "Evaluate the agent trace. Context: {context}. Assistant turn: {assistant_turn}. Expected response: "
170
+ "{expected_response}. Rate the quality of this response.",
171
+ "TOOL_CALL": "Evaluate the tool call. Context: {context}. Tool turn: {tool_turn}. Rate the quality of this tool "
172
+ "usage.",
173
+ }
174
+ CUSTOM_RATING_SCALE_ID = "__custom__"
175
+ RATING_SCALE_TYPE_OPTIONS = (
176
+ ("numerical", "Numerical", "Scored values (e.g. 1–5)"),
177
+ ("categorical", "Categorical", "Named labels (e.g. Pass/Fail)"),
178
+ )
179
+ RATING_SCALE_PRESETS: list[dict[str, Any]] = [
180
+ {
181
+ "id": "1-5-quality",
182
+ "title": "1–5 Quality",
183
+ "description": "Numerical · Poor(1), Fair(2), Good(3), Very Good(4), Excellent(5)",
184
+ "ratingScale": {
185
+ "numerical": [
186
+ {"value": 1, "label": "Poor", "definition": "Fails to meet expectations"},
187
+ {"value": 2, "label": "Fair", "definition": "Partially meets expectations"},
188
+ {"value": 3, "label": "Good", "definition": "Meets expectations"},
189
+ {"value": 4, "label": "Very Good", "definition": "Exceeds expectations"},
190
+ {"value": 5, "label": "Excellent", "definition": "Far exceeds expectations"},
191
+ ]
192
+ },
193
+ },
194
+ {
195
+ "id": "1-3-simple",
196
+ "title": "1–3 Simple",
197
+ "description": "Numerical · Low(1), Medium(2), High(3)",
198
+ "ratingScale": {
199
+ "numerical": [
200
+ {"value": 1, "label": "Low", "definition": "Below acceptable quality"},
201
+ {"value": 2, "label": "Medium", "definition": "Acceptable quality"},
202
+ {"value": 3, "label": "High", "definition": "Above acceptable quality"},
203
+ ]
204
+ },
205
+ },
206
+ {
207
+ "id": "pass-fail",
208
+ "title": "Pass / Fail",
209
+ "description": "Categorical · binary pass or fail assessment",
210
+ "ratingScale": {
211
+ "categorical": [
212
+ {"label": "Pass", "definition": "Meets the evaluation criteria"},
213
+ {"label": "Fail", "definition": "Does not meet the evaluation criteria"},
214
+ ]
215
+ },
216
+ },
217
+ {
218
+ "id": "good-neutral-bad",
219
+ "title": "Good / Neutral / Bad",
220
+ "description": "Categorical · three-tier quality assessment",
221
+ "ratingScale": {
222
+ "categorical": [
223
+ {"label": "Good", "definition": "Positive outcome, meets or exceeds criteria"},
224
+ {"label": "Neutral", "definition": "Acceptable but unremarkable outcome"},
225
+ {"label": "Bad", "definition": "Negative outcome, fails to meet criteria"},
226
+ ]
227
+ },
228
+ },
229
+ ]
230
+ PRESET_IDS = [p["id"] for p in RATING_SCALE_PRESETS]
231
+
232
+
233
+ def validate_instruction_placeholders(instructions: str, level: str) -> str | None:
234
+ """Error message unless the instructions contain a level placeholder."""
235
+ placeholders = LEVEL_PLACEHOLDERS[level]
236
+ if any(f"{{{p}}}" in instructions for p in placeholders):
237
+ return None
238
+ return f"Instructions must contain at least one placeholder: {', '.join(f'{{{p}}}' for p in placeholders)}"
239
+
240
+
241
+ def _js_number(raw: str) -> float | int | None:
242
+ """``Number(raw)``; None for NaN."""
243
+ text = raw.strip()
244
+ if text == "":
245
+ return 0
246
+ try:
247
+ value = float(int(text, 0)) if re.fullmatch(r"0[xXoObB][0-9a-fA-F]+", text) else float(text)
248
+ except ValueError:
249
+ return None
250
+ if math.isnan(value):
251
+ return None
252
+ return int(value) if value.is_integer() else value
253
+
254
+
255
+ def parse_custom_rating_scale(text: str, scale_type: str) -> tuple[bool, Any]:
256
+ """(True, ratingScale) or (False, error) from "1:Poor:Def, 5:Great:Def" / "Pass:Def, Fail:Def"."""
257
+ entries = [e.strip() for e in text.split(",") if e.strip()]
258
+ if len(entries) < 2:
259
+ return False, "At least 2 entries required (comma-separated)"
260
+ if scale_type == "numerical":
261
+ numerical = []
262
+ for entry in entries:
263
+ first = entry.find(":")
264
+ second = entry.find(":", first + 1) if first >= 0 else -1
265
+ if first < 0 or second < 0:
266
+ return False, f'Invalid entry "{entry}". Format: value:label:definition'
267
+ raw = entry[:first].strip()
268
+ value = _js_number(raw)
269
+ if value is None:
270
+ return False, f'"{raw}" is not a valid number in "{entry}"'
271
+ numerical.append(
272
+ {"value": value, "label": entry[first + 1 : second].strip(), "definition": entry[second + 1 :].strip()}
273
+ )
274
+ return True, {"numerical": numerical}
275
+ categorical = []
276
+ for entry in entries:
277
+ first = entry.find(":")
278
+ if first < 0:
279
+ return False, f'Invalid entry "{entry}". Format: label:definition'
280
+ categorical.append({"label": entry[:first].strip(), "definition": entry[first + 1 :].strip()})
281
+ return True, {"categorical": categorical}
282
+
283
+
284
+ def json_to_python_value(value: Any) -> str:
285
+ if value is None:
286
+ return "None"
287
+ if value is True:
288
+ return "True"
289
+ if value is False:
290
+ return "False"
291
+ if isinstance(value, (int, float)):
292
+ return str(int(value)) if isinstance(value, float) and value.is_integer() else str(value)
293
+ if isinstance(value, str):
294
+ return json.dumps(value, ensure_ascii=False)
295
+ if isinstance(value, list):
296
+ return f"[{', '.join(json_to_python_value(v) for v in value)}]"
297
+ if isinstance(value, dict):
298
+ return (
299
+ "{"
300
+ + ", ".join(f"{json.dumps(k, ensure_ascii=False)}: {json_to_python_value(v)}" for k, v in value.items())
301
+ + "}"
302
+ )
303
+ return str(value)
304
+
305
+
306
+ def json_to_kwargs(text: str) -> str:
307
+ obj = json.loads(text)
308
+ if not isinstance(obj, dict):
309
+ raise TypeError("Expected a JSON object of keyword arguments")
310
+ parts = []
311
+ for key, value in obj.items():
312
+ if not _KWARG_NAME.match(key):
313
+ raise Exception(f'Invalid Python kwarg name "{key}"')
314
+ parts.append(f"{key}={json_to_python_value(value)}")
315
+ return ", ".join(parts)
316
+
317
+
318
+ def get_warnings_for_metric(library_config: dict[str, Any], metric_class: str) -> list[str]:
319
+ return [f"⚠️ {metric_class} {w['message']}" for w in library_config["warnings"] if metric_class in w["metrics"]]
320
+
321
+
322
+ def _parse_schema(schema: Any, value: Any) -> tuple[bool, Any]:
323
+ try:
324
+ return True, TypeAdapter(schema).validate_python(value)
325
+ except PydanticValidationError as exc:
326
+ errors = exc.errors()
327
+ return False, errors[0]["msg"] if errors else str(exc)
328
+
329
+
330
+ @dataclass
331
+ class ThirdPartyLibraryOptions:
332
+ library: str
333
+ metric_class: str
334
+ metric_params: str | None = None
335
+ model_provider: str | None = None
336
+ model: str | None = None
337
+
338
+
339
+ @dataclass
340
+ class AddEvaluatorOptions:
341
+ name: str
342
+ level: str
343
+ config: dict[str, Any]
344
+ description: str | None = None
345
+ kms_key_arn: str | None = None
346
+ third_party: ThirdPartyLibraryOptions | None = None
347
+
348
+
349
+ def build_code_based_config(name: str, lambda_arn: str | None = None, timeout: str | None = None) -> dict:
350
+ if lambda_arn:
351
+ return {"codeBased": {"external": {"lambdaArn": lambda_arn}}}
352
+ return {
353
+ "codeBased": {
354
+ "managed": {
355
+ "codeLocation": f"app/{name}/",
356
+ "entrypoint": DEFAULT_CODE_ENTRYPOINT,
357
+ "timeoutSeconds": parse_int(timeout) if timeout else DEFAULT_CODE_TIMEOUT,
358
+ "additionalPolicies": ["execution-role-policy.json"],
359
+ }
360
+ }
361
+ }
362
+
363
+
364
+ def build_third_party_config(name: str, library_config: dict[str, Any], timeout: str | None = None) -> dict:
365
+ return {
366
+ "codeBased": {
367
+ "managed": {
368
+ "codeLocation": f"app/{name}/",
369
+ "entrypoint": DEFAULT_CODE_ENTRYPOINT,
370
+ "timeoutSeconds": parse_int(timeout) if timeout else library_config["defaultTimeoutSeconds"],
371
+ "additionalPolicies": ["execution-role-policy.json"],
372
+ }
373
+ }
374
+ }
375
+
376
+
377
+ class _Fail(Exception):
378
+ pass
379
+
380
+
381
+ class EvaluatorPrimitive(BasePrimitive):
382
+ kind = "evaluator"
383
+ label = "Evaluator"
384
+ article = "an"
385
+
386
+ def _project(self) -> dict[str, Any]:
387
+ return to_jsonable(self.read_project_spec())
388
+
389
+ def _project_root(self) -> str:
390
+ return os.path.dirname(find_config_root() or "")
391
+
392
+ def add(self, options: AddEvaluatorOptions) -> Ok | Err:
393
+ try:
394
+ evaluator: dict[str, Any] = {"name": options.name, "level": options.level}
395
+ if options.description:
396
+ evaluator["description"] = options.description
397
+ evaluator["config"] = options.config
398
+ if options.kms_key_arn:
399
+ evaluator["kmsKeyArn"] = options.kms_key_arn
400
+
401
+ def mutate(project: Any) -> Any:
402
+ data = to_jsonable(project)
403
+ self.check_duplicate([RemovableResource(e["name"]) for e in data["evaluators"]], options.name)
404
+ data["evaluators"].append(evaluator)
405
+ return data
406
+
407
+ self.update_project_spec(mutate)
408
+
409
+ managed = (options.config.get("codeBased") or {}).get("managed")
410
+ if managed:
411
+ target_dir = os.path.join(self._project_root(), managed["codeLocation"])
412
+ if options.third_party:
413
+ tp = options.third_party
414
+ data: dict[str, Any] = {
415
+ "Name": options.name,
416
+ "EvaluatorClass": tp.metric_class,
417
+ "EvaluatorParams": tp.metric_params or "",
418
+ }
419
+ if tp.model_provider == "bedrock":
420
+ data["ModelProviderBedrock"] = True
421
+ if tp.model:
422
+ data["Model"] = tp.model
423
+ render_third_party_evaluator_template(
424
+ THIRD_PARTY_EVALUATOR_LIBRARIES[tp.library]["templateDir"], data, target_dir
425
+ )
426
+ else:
427
+ render_code_based_evaluator_template(options.name, target_dir)
428
+ return Ok({"evaluatorName": options.name, "codePath": managed["codeLocation"]})
429
+ return Ok({"evaluatorName": options.name})
430
+ except Exception as exc: # noqa: BLE001
431
+ return Err(to_error(exc))
432
+
433
+ def remove(self, name: str) -> Ok | Err:
434
+ try:
435
+ project = self._project()
436
+ index = next((i for i, e in enumerate(project["evaluators"]) if e["name"] == name), -1)
437
+ if index == -1:
438
+ return Err(ResourceNotFoundError(f'Evaluator "{name}" not found.'))
439
+ refs = [c["name"] for c in project["onlineEvalConfigs"] if name in (c.get("evaluators") or [])]
440
+ if refs:
441
+ return Err(
442
+ ConflictError(
443
+ f'Evaluator "{name}" is referenced by online eval config(s): {", ".join(refs)}. '
444
+ "Remove those references first."
445
+ )
446
+ )
447
+ managed = ((project["evaluators"][index].get("config") or {}).get("codeBased") or {}).get("managed")
448
+ if managed:
449
+ code_dir = os.path.join(self._project_root(), managed["codeLocation"])
450
+ if os.path.exists(code_dir):
451
+ shutil.rmtree(code_dir, ignore_errors=True)
452
+ project["evaluators"].pop(index)
453
+ self.write_project_spec(project)
454
+ return Ok(None)
455
+ except Exception as exc: # noqa: BLE001
456
+ return Err(to_error(exc))
457
+
458
+ def preview_remove(self, name: str) -> RemovalPreview:
459
+ project = self._project()
460
+ evaluator = next((e for e in project["evaluators"] if e["name"] == name), None)
461
+ if evaluator is None:
462
+ raise Exception(f'Evaluator "{name}" not found.')
463
+ summary = [f"Removing evaluator: {name}"]
464
+ directories: list[str] = []
465
+ refs = [c["name"] for c in project["onlineEvalConfigs"] if name in (c.get("evaluators") or [])]
466
+ if refs:
467
+ summary.append(
468
+ f"Blocked: Referenced by online eval config(s): {', '.join(refs)}. Remove those references first."
469
+ )
470
+ managed = ((evaluator.get("config") or {}).get("codeBased") or {}).get("managed")
471
+ if managed:
472
+ location = managed["codeLocation"]
473
+ if os.path.exists(os.path.join(self._project_root(), location)):
474
+ directories.append(location)
475
+ summary.append(f"Will delete directory: {location}")
476
+ after = {**project, "evaluators": [e for e in project["evaluators"] if e["name"] != name]}
477
+ return RemovalPreview(summary, directories, [SchemaChange("agentcore/agentcore.json", project, after)])
478
+
479
+ def get_removable(self) -> list[RemovableResource]:
480
+ try:
481
+ return [RemovableResource(e["name"]) for e in self._project()["evaluators"]]
482
+ except Exception: # noqa: BLE001
483
+ return []
484
+
485
+ def get_all_names(self) -> list[str]:
486
+ return [r.name for r in self.get_removable()]
487
+
488
+ # --- CLI ----------------------------------------------------------------------------
489
+
490
+ def register_commands(self, add_app: typer.Typer, remove_app: typer.Typer) -> None:
491
+ @add_app.command("evaluator", help="Add a custom evaluator to the project")
492
+ def add_evaluator(
493
+ name: str | None = typer.Option(None, "--name", help="Evaluator name"),
494
+ level: str | None = typer.Option(None, "--level", help="Evaluation level: SESSION, TRACE, TOOL_CALL"),
495
+ type_: str | None = typer.Option(
496
+ None, "--type", help="Evaluator type: llm-as-a-judge (default) or code-based"
497
+ ),
498
+ model: str | None = typer.Option(
499
+ None, "--model", help="[LLM] Bedrock inference profile ID or OpenResponses model ID for LLM-as-a-Judge"
500
+ ),
501
+ model_provider: str | None = typer.Option(
502
+ None, "--model-provider", help="[LLM] Model provider: Bedrock (default) or OpenResponses"
503
+ ),
504
+ instructions: str | None = typer.Option(
505
+ None,
506
+ "--instructions",
507
+ help="[LLM] Evaluation prompt instructions (must include level-appropriate placeholders, e.g. {context})",
508
+ ),
509
+ rating_scale: str | None = typer.Option(
510
+ None,
511
+ "--rating-scale",
512
+ help=f"[LLM] Rating scale preset: {', '.join(PRESET_IDS)} (default: 1-5-quality)",
513
+ ),
514
+ lambda_arn: str | None = typer.Option(
515
+ None, "--lambda-arn", help="[Code-based] Existing Lambda function ARN (external)"
516
+ ),
517
+ timeout: str | None = typer.Option(
518
+ None, "--timeout", help="[Code-based] Lambda timeout in seconds, 1-300 (default: 60)"
519
+ ),
520
+ template_json: str | None = typer.Option(
521
+ None,
522
+ "--3p-template-json",
523
+ help='[Code-based] Inline JSON with 3P library config: {"library", "metric", "modelProvider", '
524
+ '"model", "params"}',
525
+ ),
526
+ template_json_file: str | None = typer.Option(
527
+ None,
528
+ "--3p-template-json-file",
529
+ help="[Code-based] Path to JSON file with 3P library config (same format as --3p-template-json)",
530
+ ),
531
+ config: str | None = typer.Option(
532
+ None,
533
+ "--config",
534
+ help="Path to evaluator config JSON file (overrides --model, --instructions, --rating-scale) "
535
+ "[non-interactive]",
536
+ ),
537
+ kms_key_arn: str | None = typer.Option(
538
+ None, "--kms-key-arn", help="KMS key ARN for evaluator encryption (optional)"
539
+ ),
540
+ as_json: bool = typer.Option(False, "--json", help="Output as JSON [non-interactive]"),
541
+ ) -> None:
542
+ if not find_config_root():
543
+ typer.echo("No agentcore project found. Run `agentcore create` first.", err=True)
544
+ raise typer.Exit(1)
545
+ if not (name or as_json):
546
+ try:
547
+ interactive.require_tty()
548
+ self.add_interactive()
549
+ except typer.Exit:
550
+ raise
551
+ except Exception as exc: # noqa: BLE001
552
+ typer.echo(get_error_message(exc), err=True)
553
+ raise typer.Exit(1) from None
554
+ raise typer.Exit(0)
555
+
556
+ run_cli_command(
557
+ as_json,
558
+ lambda: self._add_from_flags(
559
+ name=name,
560
+ level=level,
561
+ eval_type=type_,
562
+ model=model,
563
+ model_provider=model_provider,
564
+ instructions=instructions,
565
+ rating_scale=rating_scale,
566
+ lambda_arn=lambda_arn,
567
+ timeout=timeout,
568
+ template_json=template_json,
569
+ template_json_file=template_json_file,
570
+ config=config,
571
+ kms_key_arn=kms_key_arn,
572
+ as_json=as_json,
573
+ ),
574
+ )
575
+
576
+ self.register_remove_subcommand(remove_app)
577
+
578
+ def _add_from_flags(self, **o: Any) -> None:
579
+ def fail(message: str) -> None:
580
+ raise Exception(message)
581
+
582
+ name, level = o["name"], o["level"]
583
+ if not name or not level:
584
+ fail("--name and --level are required in non-interactive mode")
585
+ if level not in EVALUATION_LEVELS:
586
+ fail(f'Invalid --level "{level}". Must be one of: SESSION, TRACE, TOOL_CALL')
587
+ if o["template_json"] and o["template_json_file"]:
588
+ fail("--3p-template-json and --3p-template-json-file cannot be used together")
589
+ template_text = None
590
+ if o["template_json"]:
591
+ template_text = o["template_json"]
592
+ elif o["template_json_file"]:
593
+ if not os.path.exists(o["template_json_file"]):
594
+ fail(f"--3p-template-json-file not found: {o['template_json_file']}")
595
+ with open(o["template_json_file"], encoding="utf-8") as fh:
596
+ template_text = fh.read()
597
+
598
+ library = metric = tp_provider = tp_model = tp_params = None
599
+ if template_text:
600
+ try:
601
+ template = json.loads(template_text)
602
+ except ValueError:
603
+ raise Exception("--3p-template-json must be valid JSON") from None
604
+ if not isinstance(template, dict):
605
+ template = {}
606
+ if not template.get("library") or not isinstance(template.get("library"), str):
607
+ fail('--3p-template-json must include "library" (e.g. "deepeval" or "autoevals")')
608
+ if not template.get("metric") or not isinstance(template.get("metric"), str):
609
+ fail('--3p-template-json must include "metric" (e.g. "AnswerRelevancyMetric")')
610
+ library = str(template["library"])
611
+ if library not in THIRD_PARTY_EVALUATOR_LIBRARIES:
612
+ fail(f'Invalid library "{library}". Supported: {", ".join(SUPPORTED_LIBRARIES)}')
613
+ metric = template["metric"]
614
+ if template.get("modelProvider"):
615
+ raw_provider = str(template["modelProvider"])
616
+ if raw_provider.lower() not in MODEL_PROVIDERS:
617
+ fail(f'Invalid modelProvider "{raw_provider}". Supported: {", ".join(MODEL_PROVIDERS)}')
618
+ tp_provider = raw_provider.lower()
619
+ if template.get("model"):
620
+ tp_model = template["model"]
621
+ if template.get("params") and isinstance(template["params"], (dict, list)):
622
+ try:
623
+ params = template["params"]
624
+ items = params.items() if isinstance(params, dict) else enumerate(params)
625
+ parts = []
626
+ for k, v in items:
627
+ if not _KWARG_NAME.match(str(k)):
628
+ raise Exception(f'Invalid Python kwarg name "{k}"')
629
+ parts.append(f"{k}={json_to_python_value(v)}")
630
+ tp_params = ", ".join(parts)
631
+ except Exception as exc: # noqa: BLE001
632
+ fail(f"Invalid params in --3p-template-json: {get_error_message(exc)}")
633
+ if not tp_provider and tp_model:
634
+ tp_provider = "bedrock"
635
+ if tp_provider == "bedrock" and not tp_model:
636
+ fail(
637
+ '--3p-template-json requires "model" when modelProvider is bedrock. '
638
+ "Pass a Bedrock inference profile ID (e.g. us.anthropic.claude-sonnet-4-20250514-v1:0)"
639
+ )
640
+ if tp_provider == "openai":
641
+ typer.echo(
642
+ "\n ⚠️ OpenAI model provider selected. You must set OPENAI_API_KEY as a Lambda "
643
+ "environment variable after deployment.\n",
644
+ err=True,
645
+ )
646
+
647
+ timeout = o["timeout"]
648
+ if timeout:
649
+ value = parse_int(timeout)
650
+ if value is None or value < 1 or value > 300:
651
+ fail("--timeout must be an integer between 1 and 300")
652
+
653
+ eval_type = o["eval_type"] or ("code-based" if library else "llm-as-a-judge")
654
+ if eval_type not in ("llm-as-a-judge", "code-based"):
655
+ fail(f'Invalid --type "{eval_type}". Must be one of: llm-as-a-judge, code-based')
656
+ if eval_type != "code-based":
657
+ if o["lambda_arn"]:
658
+ fail("--lambda-arn requires --type code-based")
659
+ if timeout:
660
+ fail("--timeout requires --type code-based")
661
+ if library:
662
+ fail("--3p-template-json requires --type code-based")
663
+ if eval_type == "code-based":
664
+ if o["model"]:
665
+ fail("--model cannot be used with --type code-based")
666
+ if o["model_provider"]:
667
+ fail("--model-provider cannot be used with --type code-based")
668
+ if o["instructions"]:
669
+ fail("--instructions cannot be used with --type code-based")
670
+ if o["rating_scale"]:
671
+ fail("--rating-scale cannot be used with --type code-based")
672
+ if o["config"] and o["model_provider"]:
673
+ fail(
674
+ "--model-provider cannot be used with --config; set config.llmAsAJudge.modelProvider in the config file"
675
+ )
676
+
677
+ third_party = None
678
+ if library:
679
+ config = build_third_party_config(name, THIRD_PARTY_EVALUATOR_LIBRARIES[library], timeout)
680
+ third_party = ThirdPartyLibraryOptions(library, metric, tp_params, tp_provider, tp_model) # type: ignore[arg-type]
681
+ elif o["config"]:
682
+ with open(o["config"], encoding="utf-8") as fh:
683
+ config = json.load(fh)
684
+ elif eval_type == "code-based":
685
+ config = build_code_based_config(name, o["lambda_arn"], timeout)
686
+ else:
687
+ if not o["model"]:
688
+ fail("Either --config or --model is required for LLM-as-a-Judge evaluators")
689
+ ok, model_id = _parse_schema(EvaluatorModelId, o["model"])
690
+ if not ok:
691
+ fail(model_id or "Invalid --model")
692
+ provider = o["model_provider"] if o["model_provider"] is not None else "Bedrock"
693
+ if provider not in ("Bedrock", "OpenResponses"):
694
+ fail(f'Invalid --model-provider "{o["model_provider"]}". Must be one of: Bedrock, OpenResponses')
695
+ instructions = o["instructions"]
696
+ if not instructions:
697
+ placeholders = ", ".join(f"{{{p}}}" for p in LEVEL_PLACEHOLDERS[level])
698
+ fail(
699
+ "--instructions is required in non-interactive mode (or use --config). "
700
+ f"Must include at least one placeholder for {level}: {placeholders}"
701
+ )
702
+ problem = validate_instruction_placeholders(instructions, level)
703
+ if problem:
704
+ fail(problem)
705
+ scale_input = o["rating_scale"] if o["rating_scale"] is not None else "1-5-quality"
706
+ preset = next((p for p in RATING_SCALE_PRESETS if p["id"] == scale_input), None)
707
+ if preset:
708
+ scale = preset["ratingScale"]
709
+ else:
710
+ numerical = bool(re.match(r"^\d", scale_input.strip()))
711
+ ok, scale = parse_custom_rating_scale(scale_input, "numerical" if numerical else "categorical")
712
+ if not ok:
713
+ fail(
714
+ f'Invalid --rating-scale "{scale_input}". Use a preset ({", ".join(PRESET_IDS)}) '
715
+ 'or custom format: "1:Label:Definition, 2:Label:Definition" (numerical) '
716
+ 'or "Label:Definition, Label:Definition" (categorical)'
717
+ )
718
+ llm: dict[str, Any] = {}
719
+ if provider == "OpenResponses":
720
+ llm["modelProvider"] = provider
721
+ llm.update({"model": model_id, "instructions": instructions, "ratingScale": scale})
722
+ config = {"llmAsAJudge": llm}
723
+
724
+ if o["kms_key_arn"] and not is_valid_kms_key_arn(o["kms_key_arn"]):
725
+ fail(KMS_ARN_ERROR)
726
+
727
+ result = self.add(
728
+ AddEvaluatorOptions(
729
+ name=name, level=level, config=config, kms_key_arn=o["kms_key_arn"], third_party=third_party
730
+ )
731
+ )
732
+ if not result.success:
733
+ raise result.error
734
+ if o["as_json"]:
735
+ emit_json(serialize_result(result))
736
+ return
737
+ value = result.value
738
+ if value.get("codePath"):
739
+ typer.echo(f"Created evaluator '{value['evaluatorName']}'")
740
+ typer.echo(f" Code: {value['codePath']}lambda_function.py")
741
+ typer.echo(f" IAM: {value['codePath']}execution-role-policy.json")
742
+ typer.echo("\n Next: Edit lambda_function.py with your evaluation logic, then run `agentcore deploy`")
743
+ else:
744
+ typer.echo(f"Added evaluator '{value['evaluatorName']}'")
745
+ if third_party:
746
+ for warning in get_warnings_for_metric(
747
+ THIRD_PARTY_EVALUATOR_LIBRARIES[third_party.library], third_party.metric_class
748
+ ):
749
+ typer.echo(f"\n {warning}", err=True)
750
+ if third_party.model_provider == "openai":
751
+ typer.echo(
752
+ "\n ⚠️ OpenAI model provider selected. You must set OPENAI_API_KEY as a Lambda "
753
+ "environment variable for the evaluator to call the LLM judge.",
754
+ err=True,
755
+ )
756
+
757
+ # --- interactive (tui/screens/evaluator/AddEvaluatorScreen) ---------------------------
758
+
759
+ def add_interactive(self) -> None:
760
+ existing = self.get_all_names()
761
+ choice = interactive.Choice
762
+ eval_type = interactive.select(
763
+ "What type of evaluator would you like to create?",
764
+ [choice(t, i, d) for i, t, d in EVALUATOR_TYPE_OPTIONS],
765
+ )
766
+ code_type = "managed"
767
+ if eval_type == "code-based":
768
+ code_type = interactive.select(
769
+ "How would you like to provide the Lambda?", [choice(t, i, d) for i, t, d in CODE_BASED_TYPE_OPTIONS]
770
+ )
771
+
772
+ def validate_name(value: str) -> str | None:
773
+ ok, msg = _parse_schema(EvaluatorName, value)
774
+ if not ok:
775
+ return msg
776
+ return "Evaluator name already exists" if value in existing else None
777
+
778
+ name = interactive.text(
779
+ "Evaluator name", default=generate_unique_name("MyEvaluator", existing), validate=validate_name
780
+ )
781
+ level = interactive.select(
782
+ "What level should this evaluator operate at?", [choice(t, i, d) for i, t, d in EVALUATION_LEVEL_OPTIONS]
783
+ )
784
+ rows: list[tuple[str, str]] = [("Type", eval_type), ("Name", name), ("Level", level)]
785
+
786
+ if eval_type == "llm-as-a-judge":
787
+ provider = interactive.select(
788
+ "Select model provider", [choice(t, i, d) for i, t, d in EVALUATOR_MODEL_PROVIDER_OPTIONS]
789
+ )
790
+ options = OPENAI_EVALUATOR_MODEL_OPTIONS if provider == "OpenResponses" else BEDROCK_EVALUATOR_MODEL_OPTIONS
791
+ model = interactive.select("Select model", [choice(t, i, d) for i, t, d in options])
792
+ if model == CUSTOM_MODEL_ID:
793
+ if provider == "OpenResponses":
794
+ model = interactive.text(
795
+ "OpenResponses model ID",
796
+ validate=lambda v: (
797
+ None
798
+ if _parse_schema(EvaluatorModelId, v)[0]
799
+ else "A valid OpenResponses model ID is required"
800
+ ),
801
+ )
802
+ else:
803
+ model = interactive.text(
804
+ "Bedrock model ID",
805
+ validate=lambda v: (
806
+ None
807
+ if is_valid_bedrock_model_id(v)
808
+ else "Must be a valid Bedrock model ID (e.g. us.anthropic.claude-sonnet-4-5-20250929-v1:0) "
809
+ "or model ARN"
810
+ ),
811
+ )
812
+ typer.echo("Evaluation instructions")
813
+ typer.echo("Available placeholders:")
814
+ for p in LEVEL_PLACEHOLDERS[level]:
815
+ typer.echo(f" {{{p}}} — {PLACEHOLDER_DESCRIPTIONS.get(p, p)}")
816
+ if REFERENCE_INPUT_PLACEHOLDERS[level]:
817
+ typer.echo("Reference inputs — provided by caller at eval time, may be empty:")
818
+ for p in REFERENCE_INPUT_PLACEHOLDERS[level]:
819
+ typer.echo(f" {{{p}}} — {PLACEHOLDER_DESCRIPTIONS.get(p, p)}")
820
+ instructions = interactive.text(
821
+ "Instructions",
822
+ default=DEFAULT_INSTRUCTIONS[level],
823
+ validate=lambda v: validate_instruction_placeholders(v, level),
824
+ )
825
+ scale_id = interactive.select(
826
+ "Rating scale",
827
+ [choice(p["title"], p["id"], p["description"]) for p in RATING_SCALE_PRESETS]
828
+ + [choice("Custom", CUSTOM_RATING_SCALE_ID, "Define your own rating scale")],
829
+ )
830
+ if scale_id == CUSTOM_RATING_SCALE_ID:
831
+ scale_type = interactive.select(
832
+ "Scale type", [choice(t, i, d) for i, t, d in RATING_SCALE_TYPE_OPTIONS]
833
+ )
834
+ typer.echo("Define rating scale entries")
835
+ typer.echo(
836
+ "Format: value:label:definition, ... (e.g. 1:Poor:Fails, 3:Good:Meets, 5:Excellent:Exceeds)"
837
+ if scale_type == "numerical"
838
+ else "Format: label:definition, ... (e.g. Pass:Meets criteria, Fail:Does not meet)"
839
+ )
840
+ scale_text = interactive.text(
841
+ "Entries",
842
+ validate=lambda v: (
843
+ None
844
+ if parse_custom_rating_scale(v, scale_type)[0]
845
+ else parse_custom_rating_scale(v, scale_type)[1]
846
+ ),
847
+ )
848
+ scale = parse_custom_rating_scale(scale_text, scale_type)[1]
849
+ else:
850
+ scale = next(p["ratingScale"] for p in RATING_SCALE_PRESETS if p["id"] == scale_id)
851
+ llm: dict[str, Any] = {}
852
+ if provider == "OpenResponses":
853
+ llm["modelProvider"] = provider
854
+ llm.update({"model": model, "instructions": instructions, "ratingScale": scale})
855
+ config: dict[str, Any] = {"llmAsAJudge": llm}
856
+ rows += [("Provider", provider), ("Model", model), ("Prompt", instructions)]
857
+ elif code_type == "external":
858
+ arn = interactive.text(
859
+ "Lambda function ARN",
860
+ validate=lambda v: None if _LAMBDA_ARN.match(v) else "Must be a valid Lambda function ARN",
861
+ )
862
+ config = build_code_based_config(name, arn)
863
+ rows.append(("Lambda", arn))
864
+ else:
865
+
866
+ def validate_timeout(v: str) -> str | None:
867
+ num = parse_int(v)
868
+ if num is None:
869
+ return "Must be a number"
870
+ return None if 1 <= num <= 300 else "Must be between 1 and 300"
871
+
872
+ timeout = interactive.text(
873
+ "Lambda timeout in seconds (1-300)", default=str(DEFAULT_CODE_TIMEOUT), validate=validate_timeout
874
+ )
875
+ config = build_code_based_config(name, None, timeout)
876
+ rows.append(("Timeout", f"{parse_int(timeout)}s"))
877
+
878
+ kms = interactive.text(
879
+ "KMS key ARN for encryption (optional, press Enter to skip)",
880
+ validate=lambda v: (
881
+ None
882
+ if v == "" or is_valid_kms_key_arn(v)
883
+ else "Must be a valid KMS key ARN (e.g. arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012)"
884
+ ),
885
+ )
886
+ if kms:
887
+ rows.append(("KMS Key", kms))
888
+ for label, value in rows:
889
+ typer.echo(f" {label}: {value}")
890
+ if not interactive.confirm("Add this evaluator?", default=True):
891
+ typer.echo("Cancelled.")
892
+ return
893
+ result = self.add(AddEvaluatorOptions(name=name, level=level, config=config, kms_key_arn=kms or None))
894
+ if not result.success:
895
+ typer.echo("Failed to add evaluator", err=True)
896
+ typer.echo(get_error_message(result.error), err=True)
897
+ raise typer.Exit(1)
898
+ typer.echo(f"Added evaluator: {name}")
899
+ code_path = result.value.get("codePath")
900
+ if code_path:
901
+ typer.echo(f'Created evaluator "{name}"')
902
+ typer.echo(f" Code: {code_path}lambda_function.py")
903
+ typer.echo(f" IAM: {code_path}execution-role-policy.json")
904
+ typer.echo("\n Next: Edit lambda_function.py with your evaluation logic, then run `agentcore deploy`")
905
+ else:
906
+ typer.echo("Evaluator added to project in `agentcore/agentcore.json`. Deploy with `agentcore deploy`.")
907
+
908
+
909
+ PRIMITIVE = EvaluatorPrimitive()