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,971 @@
1
+ """AgentCore data-plane runtime operations (port of ``agentcore.ts``).
2
+
3
+ Covers HTTP/SSE invocation, MCP and A2A JSON-RPC over ``InvokeAgentRuntime``, AG-UI event
4
+ streaming, evaluation, session control, and ``InvokeAgentRuntimeCommand`` (exec). SigV4 calls go
5
+ through boto3's ``bedrock-agentcore`` client; ``CUSTOM_JWT`` runtimes are called with a bearer
6
+ token over plain HTTPS, as upstream does with ``fetch``.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import codecs
12
+ import itertools
13
+ import json
14
+ import time
15
+ from collections.abc import Iterable, Iterator, Mapping
16
+ from dataclasses import dataclass, field, replace
17
+ from typing import Any, Literal, NamedTuple, NotRequired, Protocol, TypedDict
18
+
19
+ from botocore.client import BaseClient
20
+ from botocore.config import Config
21
+
22
+ from agentcore.aws._http import encode_uri_component, http_request, iter_stream_chunks
23
+ from agentcore.aws._util import drop_none, js_string, js_template
24
+ from agentcore.aws.account import create_aws_client
25
+ from agentcore.aws.agui_parser import parse_agui_sse_stream
26
+ from agentcore.aws.agui_types import AguiEvent, AguiRunInput
27
+ from agentcore.aws.partition import service_endpoint
28
+ from agentcore.aws.stage_endpoint import data_plane_endpoint
29
+ from agentcore.lib.utils.json_format import to_json_string
30
+ from agentcore.lib.utils.json_rpc import parse_json_rpc_response
31
+
32
+ DEFAULT_RUNTIME_USER_ID = "default-user"
33
+ """Default user ID sent with invocations. Container agents need it to obtain workload access tokens."""
34
+
35
+ MCP_PROTOCOL_VERSION = "2025-03-26"
36
+ SESSION_ID_HEADER = "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id"
37
+ USER_ID_HEADER = "X-Amzn-Bedrock-AgentCore-Runtime-User-Id"
38
+ _ACCEPT_JSON_OR_SSE = "application/json, text/event-stream"
39
+
40
+ # Runtime invocations can stream for many minutes; botocore's 60s default read timeout is too short.
41
+ _INVOKE_READ_TIMEOUT_S = 900
42
+
43
+ # Indirection point for tests.
44
+ _sleep = time.sleep
45
+
46
+
47
+ class SSELogger(Protocol):
48
+ def log_sse_event(self, raw_line: str) -> None: ...
49
+
50
+
51
+ class EvaluationReferenceInput(TypedDict):
52
+ context: dict[str, Any]
53
+ """``{"spanContext": {"sessionId": str, "traceId"?: str}}``"""
54
+ expectedTrajectory: NotRequired[dict[str, list[str]]]
55
+ assertions: NotRequired[list[dict[str, str]]]
56
+ expectedResponse: NotRequired[dict[str, str]]
57
+
58
+
59
+ def _create_agentcore_client(region: str, headers: Mapping[str, str] | None = None) -> BaseClient:
60
+ """``bedrock-agentcore`` client on the stage-aware data-plane endpoint, injecting ``headers`` pre-signing."""
61
+ client = create_aws_client(
62
+ "bedrock-agentcore",
63
+ region,
64
+ endpoint_url=data_plane_endpoint(region),
65
+ config=Config(read_timeout=_INVOKE_READ_TIMEOUT_S),
66
+ )
67
+ if headers:
68
+ extra = dict(headers)
69
+
70
+ def add_custom_headers(request: Any, **_: Any) -> None:
71
+ for name, value in extra.items():
72
+ request.headers[name] = value
73
+
74
+ client.meta.events.register("before-sign.bedrock-agentcore", add_custom_headers)
75
+ return client
76
+
77
+
78
+ # ---------------------------------------------------------------------------
79
+ # Options / results
80
+ # ---------------------------------------------------------------------------
81
+
82
+
83
+ @dataclass(slots=True)
84
+ class InvokeAgentRuntimeOptions:
85
+ region: str
86
+ runtime_arn: str
87
+ payload: str
88
+ session_id: str | None = None
89
+ user_id: str | None = None
90
+ """Runtime user ID header (defaults to ``default-user``); scopes OAuth tokens for Container agents."""
91
+ logger: SSELogger | None = None
92
+ headers: dict[str, str] | None = None
93
+ """Custom headers forwarded to the agent runtime."""
94
+ bearer_token: str | None = None
95
+ """CUSTOM_JWT token; when set, raw HTTPS with ``Authorization: Bearer`` replaces SigV4."""
96
+ baggage: str | None = None
97
+ """W3C baggage header value (e.g. a config bundle ref)."""
98
+ endpoint: str | None = None
99
+ """Runtime endpoint qualifier (defaults to ``DEFAULT``)."""
100
+ payment_instrument_id: str | None = None
101
+ payment_session_id: str | None = None
102
+ payment_user_id: str | None = None
103
+ """Payments end-user identity, sent in the body as ``user_id`` (distinct from ``user_id``)."""
104
+
105
+
106
+ @dataclass(slots=True)
107
+ class InvokeAgentRuntimeResult:
108
+ content: str
109
+ session_id: str | None = None
110
+
111
+
112
+ @dataclass(slots=True)
113
+ class StreamingInvokeResult:
114
+ stream: Iterator[str]
115
+ session_id: str | None
116
+
117
+
118
+ class StopRuntimeSessionResult(TypedDict):
119
+ sessionId: str | None
120
+ statusCode: int | None
121
+
122
+
123
+ class SSELineResult(NamedTuple):
124
+ content: str | None
125
+ error: str | None
126
+
127
+
128
+ # ---------------------------------------------------------------------------
129
+ # SSE / response parsing
130
+ # ---------------------------------------------------------------------------
131
+
132
+
133
+ def parse_sse_line(line: str) -> SSELineResult:
134
+ """Content or error carried by one SSE ``data:`` line (both ``None`` for other lines)."""
135
+ if not line.startswith("data: "):
136
+ return SSELineResult(None, None)
137
+ raw = line[6:]
138
+ try:
139
+ parsed = json.loads(raw)
140
+ except ValueError:
141
+ return SSELineResult(raw, None)
142
+ if isinstance(parsed, str):
143
+ return SSELineResult(parsed, None)
144
+ if isinstance(parsed, dict) and "error" in parsed:
145
+ return SSELineResult(None, js_string(parsed["error"]))
146
+ # ConverseStream-shaped event: extract the text delta.
147
+ if isinstance(parsed, dict):
148
+ event = parsed.get("event")
149
+ delta = event.get("contentBlockDelta") if isinstance(event, dict) else None
150
+ delta = delta.get("delta") if isinstance(delta, dict) else None
151
+ text = delta.get("text") if isinstance(delta, dict) else None
152
+ if isinstance(text, str):
153
+ return SSELineResult(text, None)
154
+ return SSELineResult(None, None)
155
+
156
+
157
+ def parse_sse(text: str) -> str:
158
+ """Concatenate the content of an SSE body; stops at the first error (``"Error: ..."``)."""
159
+ parts: list[str] = []
160
+ for line in text.split("\n"):
161
+ content, error = parse_sse_line(line)
162
+ if error:
163
+ return f"Error: {error}"
164
+ if content:
165
+ parts.append(content)
166
+ return "".join(parts)
167
+
168
+
169
+ def extract_result(text: str) -> str:
170
+ """``{"result": ...}`` payload text, a JSON string's value, pretty JSON, or the raw text."""
171
+ try:
172
+ parsed = json.loads(text)
173
+ except ValueError:
174
+ return text
175
+ if isinstance(parsed, dict) and "result" in parsed:
176
+ result = parsed["result"]
177
+ return result if isinstance(result, str) else to_json_string(result)
178
+ return parsed if isinstance(parsed, str) else to_json_string(parsed)
179
+
180
+
181
+ def build_invoke_payload(options: InvokeAgentRuntimeOptions) -> str:
182
+ """JSON invoke body; payment fields are included only when set."""
183
+ body: dict[str, str] = {"prompt": options.payload}
184
+ # The agent reads payload.user_id to scope the payment wallet/budget and applies its own
185
+ # "default-user" fallback, so it is never baked into the wire when unset.
186
+ if options.payment_user_id:
187
+ body["user_id"] = options.payment_user_id
188
+ if options.payment_instrument_id:
189
+ body["payment_instrument_id"] = options.payment_instrument_id
190
+ if options.payment_session_id:
191
+ body["payment_session_id"] = options.payment_session_id
192
+ return to_json_string(body, indent=None)
193
+
194
+
195
+ def _stream_sse_text(chunks: Iterable[bytes], logger: SSELogger | None) -> Iterator[str]:
196
+ """Incrementally parse an SSE byte stream into text content, falling back to plain JSON."""
197
+ decoder = codecs.getincrementaldecoder("utf-8")(errors="replace")
198
+ buffer = ""
199
+ full_response = ""
200
+ yielded_content = False
201
+ source = iter(chunks)
202
+ try:
203
+ for chunk in source:
204
+ decoded = decoder.decode(chunk)
205
+ buffer += decoded
206
+ full_response += decoded
207
+ lines = buffer.split("\n")
208
+ buffer = lines.pop()
209
+ for line in lines:
210
+ if logger is not None and line.strip():
211
+ logger.log_sse_event(line)
212
+ content, error = parse_sse_line(line)
213
+ if error:
214
+ yield f"Error: {error}"
215
+ return
216
+ if content:
217
+ yield content
218
+ yielded_content = True
219
+
220
+ if buffer:
221
+ if logger is not None and buffer.strip():
222
+ logger.log_sse_event(buffer)
223
+ content, error = parse_sse_line(buffer)
224
+ if error:
225
+ yield f"Error: {error}"
226
+ elif content:
227
+ yield content
228
+ yielded_content = True
229
+
230
+ # Plain JSON (non-SSE) response.
231
+ if not yielded_content and full_response.strip():
232
+ yield extract_result(full_response.strip())
233
+ finally:
234
+ close = getattr(source, "close", None)
235
+ if close is not None:
236
+ close()
237
+
238
+
239
+ # ---------------------------------------------------------------------------
240
+ # Bearer token (CUSTOM_JWT) thin HTTP client
241
+ # ---------------------------------------------------------------------------
242
+
243
+
244
+ def _build_invoke_url(region: str, runtime_arn: str, endpoint: str | None = None) -> str:
245
+ qualifier = endpoint if endpoint is not None else "DEFAULT"
246
+ host = service_endpoint("bedrock-agentcore", region)
247
+ return f"https://{host}/runtimes/{encode_uri_component(runtime_arn)}/invocations?qualifier={qualifier}"
248
+
249
+
250
+ def build_bearer_invoke_headers(options: Any, accept: str) -> dict[str, str]:
251
+ """Headers for bearer-token invocations (``options``: ``bearer_token``/``session_id``/``user_id``/``headers``/``baggage``)."""
252
+ headers = {
253
+ "Authorization": f"Bearer {options.bearer_token}",
254
+ "Content-Type": "application/json",
255
+ "Accept": accept,
256
+ }
257
+ if options.session_id:
258
+ headers[SESSION_ID_HEADER] = options.session_id
259
+ headers[USER_ID_HEADER] = options.user_id if options.user_id is not None else DEFAULT_RUNTIME_USER_ID
260
+ baggage = getattr(options, "baggage", None)
261
+ if baggage:
262
+ headers["baggage"] = baggage
263
+ if options.headers:
264
+ headers.update(options.headers)
265
+ return headers
266
+
267
+
268
+ def _raise_invoke_failed(response: Any, prefix: str = "Invoke failed") -> None:
269
+ try:
270
+ body = response.text()
271
+ except Exception: # noqa: BLE001
272
+ body = ""
273
+ raise RuntimeError(f"{prefix} ({response.status}): {body or response.reason}")
274
+
275
+
276
+ def _invoke_with_bearer_token_streaming(options: InvokeAgentRuntimeOptions) -> StreamingInvokeResult:
277
+ url = _build_invoke_url(options.region, options.runtime_arn, options.endpoint)
278
+ headers = build_bearer_invoke_headers(options, _ACCEPT_JSON_OR_SSE)
279
+ response = http_request("POST", url, headers=headers, body=build_invoke_payload(options), stream=True)
280
+ if not response.ok:
281
+ _raise_invoke_failed(response)
282
+ session_id = response.header(SESSION_ID_HEADER)
283
+ return StreamingInvokeResult(stream=_stream_sse_text(response.iter_bytes(), options.logger), session_id=session_id)
284
+
285
+
286
+ def _invoke_with_bearer_token(options: InvokeAgentRuntimeOptions) -> InvokeAgentRuntimeResult:
287
+ url = _build_invoke_url(options.region, options.runtime_arn, options.endpoint)
288
+ headers = build_bearer_invoke_headers(options, "application/json")
289
+ response = http_request("POST", url, headers=headers, body=build_invoke_payload(options))
290
+ if not response.ok:
291
+ _raise_invoke_failed(response)
292
+ session_id = response.header(SESSION_ID_HEADER)
293
+ text = response.text()
294
+ content = parse_sse(text) if "data: " in text else extract_result(text)
295
+ return InvokeAgentRuntimeResult(content=content, session_id=session_id)
296
+
297
+
298
+ # ---------------------------------------------------------------------------
299
+ # SDK-based invoke (SigV4)
300
+ # ---------------------------------------------------------------------------
301
+
302
+
303
+ def _invoke_params(options: InvokeAgentRuntimeOptions) -> dict[str, Any]:
304
+ params: dict[str, Any] = {
305
+ "agentRuntimeArn": options.runtime_arn,
306
+ "payload": build_invoke_payload(options).encode("utf-8"),
307
+ "contentType": "application/json",
308
+ "accept": _ACCEPT_JSON_OR_SSE,
309
+ "runtimeUserId": options.user_id if options.user_id is not None else DEFAULT_RUNTIME_USER_ID,
310
+ }
311
+ if options.session_id is not None:
312
+ params["runtimeSessionId"] = options.session_id
313
+ if options.baggage:
314
+ params["baggage"] = options.baggage
315
+ return params
316
+
317
+
318
+ def invoke_agent_runtime_streaming(options: InvokeAgentRuntimeOptions) -> StreamingInvokeResult:
319
+ """Invoke a runtime and stream text chunks as they arrive."""
320
+ if options.bearer_token:
321
+ return _invoke_with_bearer_token_streaming(options)
322
+
323
+ client = _create_agentcore_client(options.region, options.headers)
324
+ response = client.invoke_agent_runtime(**_invoke_params(options))
325
+ body = response.get("response")
326
+ if body is None:
327
+ raise RuntimeError("No response from AgentCore Runtime")
328
+ return StreamingInvokeResult(
329
+ stream=_stream_sse_text(iter_stream_chunks(body), options.logger),
330
+ session_id=response.get("runtimeSessionId"),
331
+ )
332
+
333
+
334
+ def invoke_agent_runtime(options: InvokeAgentRuntimeOptions) -> InvokeAgentRuntimeResult:
335
+ """Invoke a runtime and return the full response text."""
336
+ if options.bearer_token:
337
+ return _invoke_with_bearer_token(options)
338
+
339
+ client = _create_agentcore_client(options.region, options.headers)
340
+ response = client.invoke_agent_runtime(**_invoke_params(options))
341
+ body = response.get("response")
342
+ if body is None:
343
+ raise RuntimeError("No response from AgentCore Runtime")
344
+ text = body.read().decode("utf-8", errors="replace")
345
+ content = parse_sse(text) if "data: " in text else extract_result(text)
346
+ return InvokeAgentRuntimeResult(content=content, session_id=response.get("runtimeSessionId"))
347
+
348
+
349
+ # ============================================================================
350
+ # Evaluate
351
+ # ============================================================================
352
+
353
+
354
+ class EvaluationResultContext(TypedDict):
355
+ sessionId: str | None
356
+ traceId: str | None
357
+ spanId: str | None
358
+
359
+
360
+ class EvaluationResultTokenUsage(TypedDict):
361
+ inputTokens: int
362
+ outputTokens: int
363
+ totalTokens: int
364
+
365
+
366
+ class EvaluationResult(TypedDict):
367
+ evaluatorArn: str | None
368
+ evaluatorId: str | None
369
+ evaluatorName: str | None
370
+ explanation: str | None
371
+ value: float | None
372
+ label: str | None
373
+ errorMessage: str | None
374
+ errorCode: str | None
375
+ context: EvaluationResultContext | None
376
+ tokenUsage: EvaluationResultTokenUsage | None
377
+
378
+
379
+ class EvaluateResult(TypedDict):
380
+ evaluationResults: list[EvaluationResult]
381
+
382
+
383
+ def evaluate(
384
+ *,
385
+ region: str,
386
+ evaluator_id: str,
387
+ session_spans: list[Any],
388
+ target_span_ids: list[str] | None = None,
389
+ target_trace_ids: list[str] | None = None,
390
+ evaluation_reference_inputs: list[EvaluationReferenceInput] | None = None,
391
+ ) -> EvaluateResult:
392
+ """Run an on-demand evaluation of agent spans with one evaluator."""
393
+ client = create_aws_client("bedrock-agentcore", region)
394
+
395
+ params: dict[str, Any] = {"evaluatorId": evaluator_id, "evaluationInput": {"sessionSpans": session_spans}}
396
+ if target_span_ids is not None:
397
+ params["evaluationTarget"] = {"spanIds": target_span_ids}
398
+ elif target_trace_ids is not None:
399
+ params["evaluationTarget"] = {"traceIds": target_trace_ids}
400
+ if evaluation_reference_inputs is not None:
401
+ params["evaluationReferenceInputs"] = evaluation_reference_inputs
402
+
403
+ response = client.evaluate(**params)
404
+ results = response.get("evaluationResults")
405
+ if results is None:
406
+ raise RuntimeError("No evaluation results returned")
407
+
408
+ def map_result(r: dict[str, Any]) -> EvaluationResult:
409
+ ctx = r.get("context")
410
+ span_context = ctx.get("spanContext") if isinstance(ctx, dict) else None
411
+ usage = r.get("tokenUsage")
412
+ return {
413
+ "evaluatorArn": r.get("evaluatorArn"),
414
+ "evaluatorId": r.get("evaluatorId"),
415
+ "evaluatorName": r.get("evaluatorName"),
416
+ "explanation": r.get("explanation"),
417
+ "value": r.get("value"),
418
+ "label": r.get("label"),
419
+ "errorMessage": r.get("errorMessage"),
420
+ "errorCode": r.get("errorCode"),
421
+ "context": {
422
+ "sessionId": span_context.get("sessionId"),
423
+ "traceId": span_context.get("traceId"),
424
+ "spanId": span_context.get("spanId"),
425
+ }
426
+ if span_context
427
+ else None,
428
+ "tokenUsage": {
429
+ "inputTokens": usage.get("inputTokens") or 0,
430
+ "outputTokens": usage.get("outputTokens") or 0,
431
+ "totalTokens": usage.get("totalTokens") or 0,
432
+ }
433
+ if usage
434
+ else None,
435
+ }
436
+
437
+ return {"evaluationResults": [map_result(r) for r in results]}
438
+
439
+
440
+ # ---------------------------------------------------------------------------
441
+ # MCP: JSON-RPC over InvokeAgentRuntime
442
+ # ---------------------------------------------------------------------------
443
+
444
+
445
+ @dataclass(slots=True)
446
+ class McpInvokeOptions:
447
+ region: str
448
+ runtime_arn: str
449
+ user_id: str | None = None
450
+ mcp_session_id: str | None = None
451
+ logger: SSELogger | None = None
452
+ headers: dict[str, str] | None = None
453
+ bearer_token: str | None = None
454
+
455
+
456
+ class McpToolDef(TypedDict):
457
+ name: str
458
+ description: NotRequired[str]
459
+ inputSchema: NotRequired[dict[str, Any]]
460
+
461
+
462
+ @dataclass(slots=True)
463
+ class McpListToolsResult:
464
+ tools: list[McpToolDef]
465
+ mcp_session_id: str | None = None
466
+
467
+
468
+ @dataclass(slots=True)
469
+ class _McpRpcResult:
470
+ result: dict[str, Any]
471
+ mcp_session_id: str | None = None
472
+ error: dict[str, Any] | None = None
473
+
474
+
475
+ _mcp_request_ids = itertools.count(1)
476
+ _a2a_request_ids = itertools.count(1)
477
+
478
+ _TRANSIENT_STATUS_CODES = frozenset({429, 500, 502, 503, 504})
479
+ _MAX_FETCH_RETRIES = 3
480
+ _FETCH_RETRY_DELAY_S = 1.0
481
+ _COLD_START_RETRIES = 3
482
+ _COLD_START_DELAY_S = 2.0
483
+
484
+
485
+ def _log(logger: SSELogger | None, line: str) -> None:
486
+ if logger is not None:
487
+ logger.log_sse_event(line)
488
+
489
+
490
+ def _fetch_with_retry(url: str, headers: Mapping[str, str], body: str, logger: SSELogger | None) -> Any:
491
+ """POST with retries on transient failures (5xx, 429, network errors)."""
492
+ for attempt in range(_MAX_FETCH_RETRIES):
493
+ try:
494
+ response = http_request("POST", url, headers=headers, body=body)
495
+ if response.ok or response.status not in _TRANSIENT_STATUS_CODES or attempt == _MAX_FETCH_RETRIES - 1:
496
+ return response
497
+ _log(logger, f"Transient failure ({response.status}), retrying ({attempt + 1}/{_MAX_FETCH_RETRIES})...")
498
+ except Exception:
499
+ if attempt == _MAX_FETCH_RETRIES - 1:
500
+ raise
501
+ _log(logger, f"Network error, retrying ({attempt + 1}/{_MAX_FETCH_RETRIES})...")
502
+ _sleep(_FETCH_RETRY_DELAY_S)
503
+ raise RuntimeError("fetchWithRetry: exhausted retries")
504
+
505
+
506
+ def _build_mcp_bearer_headers(options: McpInvokeOptions) -> dict[str, str]:
507
+ headers = {
508
+ "Authorization": f"Bearer {options.bearer_token}",
509
+ "Content-Type": "application/json",
510
+ "Accept": _ACCEPT_JSON_OR_SSE,
511
+ "Mcp-Protocol-Version": MCP_PROTOCOL_VERSION,
512
+ USER_ID_HEADER: options.user_id if options.user_id is not None else DEFAULT_RUNTIME_USER_ID,
513
+ }
514
+ if options.mcp_session_id:
515
+ headers["Mcp-Session-Id"] = options.mcp_session_id
516
+ if options.headers:
517
+ headers.update(options.headers)
518
+ return headers
519
+
520
+
521
+ def _rpc_result(parsed: dict[str, Any], session_id: str | None) -> _McpRpcResult:
522
+ result = parsed.get("result")
523
+ return _McpRpcResult(
524
+ result=result if result is not None else {},
525
+ mcp_session_id=session_id,
526
+ error=parsed.get("error"),
527
+ )
528
+
529
+
530
+ def _mcp_rpc_call_with_bearer(options: McpInvokeOptions, body: dict[str, Any]) -> _McpRpcResult:
531
+ url = _build_invoke_url(options.region, options.runtime_arn)
532
+ headers = _build_mcp_bearer_headers(options)
533
+ serialized = to_json_string(body, indent=None)
534
+ _log(options.logger, f"MCP request: {serialized}")
535
+
536
+ response = _fetch_with_retry(url, headers, serialized, options.logger)
537
+ if not response.ok:
538
+ _raise_invoke_failed(response, "MCP call failed")
539
+
540
+ text = response.text()
541
+ _log(options.logger, f"MCP response: {text}")
542
+ return _rpc_result(parse_json_rpc_response(text), response.header("Mcp-Session-Id"))
543
+
544
+
545
+ def _mcp_rpc_notify_with_bearer(options: McpInvokeOptions, body: dict[str, Any]) -> None:
546
+ url = _build_invoke_url(options.region, options.runtime_arn)
547
+ headers = _build_mcp_bearer_headers(options)
548
+ response = _fetch_with_retry(url, headers, to_json_string(body, indent=None), options.logger)
549
+ if not response.ok:
550
+ _raise_invoke_failed(response, "MCP notification failed")
551
+
552
+
553
+ def _mcp_invoke_params(options: McpInvokeOptions, body: dict[str, Any]) -> dict[str, Any]:
554
+ params: dict[str, Any] = {
555
+ "agentRuntimeArn": options.runtime_arn,
556
+ "payload": to_json_string(body, indent=None).encode("utf-8"),
557
+ "contentType": "application/json",
558
+ "accept": _ACCEPT_JSON_OR_SSE,
559
+ "mcpProtocolVersion": MCP_PROTOCOL_VERSION,
560
+ "runtimeUserId": options.user_id if options.user_id is not None else DEFAULT_RUNTIME_USER_ID,
561
+ }
562
+ if options.mcp_session_id is not None:
563
+ params["mcpSessionId"] = options.mcp_session_id
564
+ return params
565
+
566
+
567
+ def _mcp_rpc_call(options: McpInvokeOptions, body: dict[str, Any]) -> _McpRpcResult:
568
+ """Send a JSON-RPC request through InvokeAgentRuntime and parse the response."""
569
+ if options.bearer_token:
570
+ return _mcp_rpc_call_with_bearer(options, body)
571
+
572
+ client = _create_agentcore_client(options.region, options.headers)
573
+ _log(options.logger, f"MCP request: {to_json_string(body, indent=None)}")
574
+ response = client.invoke_agent_runtime(**_mcp_invoke_params(options, body))
575
+ stream = response.get("response")
576
+ if stream is None:
577
+ raise RuntimeError("No response from AgentCore Runtime")
578
+ text = stream.read().decode("utf-8", errors="replace")
579
+ _log(options.logger, f"MCP response: {text}")
580
+ return _rpc_result(parse_json_rpc_response(text), response.get("mcpSessionId"))
581
+
582
+
583
+ def _mcp_rpc_call_strict(options: McpInvokeOptions, body: dict[str, Any]) -> _McpRpcResult:
584
+ """:func:`_mcp_rpc_call`, raising on JSON-RPC errors."""
585
+ result = _mcp_rpc_call(options, body)
586
+ if result.error:
587
+ message = result.error.get("message")
588
+ raise RuntimeError(message if message is not None else f"MCP error (code {result.error.get('code')})")
589
+ return result
590
+
591
+
592
+ def _mcp_rpc_notify(options: McpInvokeOptions, body: dict[str, Any]) -> None:
593
+ """Send a JSON-RPC notification (no id, response ignored)."""
594
+ if options.bearer_token:
595
+ _mcp_rpc_notify_with_bearer(options, body)
596
+ return
597
+ client = _create_agentcore_client(options.region, options.headers)
598
+ response = client.invoke_agent_runtime(**_mcp_invoke_params(options, body))
599
+ stream = response.get("response")
600
+ if stream is not None:
601
+ stream.close()
602
+
603
+
604
+ def _initialize_request() -> dict[str, Any]:
605
+ return {
606
+ "jsonrpc": "2.0",
607
+ "id": next(_mcp_request_ids),
608
+ "method": "initialize",
609
+ "params": {
610
+ "protocolVersion": MCP_PROTOCOL_VERSION,
611
+ "capabilities": {},
612
+ "clientInfo": {"name": "agentcore-cli", "version": "1.0.0"},
613
+ },
614
+ }
615
+
616
+
617
+ def _is_cold_start(err: BaseException) -> bool:
618
+ msg = str(err)
619
+ return "initialization time exceeded" in msg or "initialization" in msg
620
+
621
+
622
+ def mcp_list_tools(options: McpInvokeOptions) -> McpListToolsResult:
623
+ """Initialize an MCP session and list tools; retries cold-start initialization timeouts."""
624
+ for attempt in range(_COLD_START_RETRIES):
625
+ try:
626
+ return _mcp_list_tools_once(options)
627
+ except Exception as exc:
628
+ if _is_cold_start(exc) and attempt < _COLD_START_RETRIES - 1:
629
+ _log(options.logger, f"MCP cold start (attempt {attempt + 1}/{_COLD_START_RETRIES}), retrying...")
630
+ _sleep(_COLD_START_DELAY_S)
631
+ continue
632
+ raise
633
+ raise RuntimeError("Failed to list MCP tools after retries")
634
+
635
+
636
+ def _mcp_list_tools_once(options: McpInvokeOptions) -> McpListToolsResult:
637
+ # Stateless servers may reject initialize but still return a session ID, so errors are tolerated.
638
+ init_result = _mcp_rpc_call(options, _initialize_request())
639
+ if init_result.error:
640
+ _log(
641
+ options.logger,
642
+ "MCP initialize returned error (expected for stateless servers): "
643
+ f"{js_template(init_result.error.get('message'))}",
644
+ )
645
+
646
+ session_id = init_result.mcp_session_id
647
+ with_session = replace(options, mcp_session_id=session_id)
648
+ _mcp_rpc_notify(with_session, {"jsonrpc": "2.0", "method": "notifications/initialized"})
649
+
650
+ list_result = _mcp_rpc_call_strict(
651
+ with_session, {"jsonrpc": "2.0", "id": next(_mcp_request_ids), "method": "tools/list", "params": {}}
652
+ )
653
+ tools = list_result.result.get("tools") or []
654
+ mapped: list[McpToolDef] = [
655
+ drop_none({"name": t.get("name"), "description": t.get("description"), "inputSchema": t.get("inputSchema")}) # type: ignore[misc]
656
+ for t in tools
657
+ ]
658
+ return McpListToolsResult(tools=mapped, mcp_session_id=session_id)
659
+
660
+
661
+ def mcp_init_session(options: McpInvokeOptions) -> str | None:
662
+ """Initialize an MCP session (without listing tools); returns its session ID."""
663
+ init_result = _mcp_rpc_call(options, _initialize_request())
664
+ session_id = init_result.mcp_session_id
665
+ _mcp_rpc_notify(
666
+ replace(options, mcp_session_id=session_id), {"jsonrpc": "2.0", "method": "notifications/initialized"}
667
+ )
668
+ return session_id
669
+
670
+
671
+ def mcp_call_tool(options: McpInvokeOptions, tool_name: str, args: dict[str, Any]) -> str:
672
+ """Call an MCP tool; returns its concatenated text content (or pretty JSON of the result)."""
673
+ for attempt in range(_COLD_START_RETRIES):
674
+ try:
675
+ rpc = _mcp_rpc_call_strict(
676
+ options,
677
+ {
678
+ "jsonrpc": "2.0",
679
+ "id": next(_mcp_request_ids),
680
+ "method": "tools/call",
681
+ "params": {"name": tool_name, "arguments": args},
682
+ },
683
+ )
684
+ content = rpc.result.get("content")
685
+ if content:
686
+ texts = [item["text"] for item in content if isinstance(item, dict) and item.get("text") is not None]
687
+ if texts:
688
+ return "".join(texts)
689
+ return to_json_string(rpc.result)
690
+ except Exception as exc:
691
+ if _is_cold_start(exc) and attempt < _COLD_START_RETRIES - 1:
692
+ _log(options.logger, f"MCP cold start (attempt {attempt + 1}/{_COLD_START_RETRIES}), retrying...")
693
+ _sleep(_COLD_START_DELAY_S)
694
+ continue
695
+ raise
696
+ raise RuntimeError("Failed to call MCP tool after retries")
697
+
698
+
699
+ # ---------------------------------------------------------------------------
700
+ # A2A: JSON-RPC message/send over InvokeAgentRuntime
701
+ # ---------------------------------------------------------------------------
702
+
703
+
704
+ @dataclass(slots=True)
705
+ class A2AInvokeOptions:
706
+ region: str
707
+ runtime_arn: str
708
+ user_id: str | None = None
709
+ session_id: str | None = None
710
+ logger: SSELogger | None = None
711
+ headers: dict[str, str] | None = None
712
+ bearer_token: str | None = None
713
+
714
+
715
+ def _single_value_stream(value: str) -> Iterator[str]:
716
+ yield value
717
+
718
+
719
+ def invoke_a2a_runtime(options: A2AInvokeOptions, message: str) -> StreamingInvokeResult:
720
+ """Send an A2A ``message/send`` request and return the agent's text as a one-item stream."""
721
+ body = {
722
+ "jsonrpc": "2.0",
723
+ "id": next(_a2a_request_ids),
724
+ "method": "message/send",
725
+ "params": {
726
+ "message": {
727
+ "role": "user",
728
+ "parts": [{"kind": "text", "text": message}],
729
+ "messageId": f"msg-{int(time.time() * 1000)}",
730
+ }
731
+ },
732
+ }
733
+ serialized = to_json_string(body, indent=None)
734
+ _log(options.logger, f"A2A request: {serialized}")
735
+
736
+ if options.bearer_token:
737
+ url = _build_invoke_url(options.region, options.runtime_arn)
738
+ headers = build_bearer_invoke_headers(options, _ACCEPT_JSON_OR_SSE)
739
+ response = http_request("POST", url, headers=headers, body=serialized)
740
+ if not response.ok:
741
+ _raise_invoke_failed(response)
742
+ text = response.text()
743
+ _log(options.logger, f"A2A response: {text}")
744
+ return StreamingInvokeResult(
745
+ stream=_single_value_stream(parse_a2a_response(text)), session_id=response.header(SESSION_ID_HEADER)
746
+ )
747
+
748
+ client = _create_agentcore_client(options.region, options.headers)
749
+ params: dict[str, Any] = {
750
+ "agentRuntimeArn": options.runtime_arn,
751
+ "payload": serialized.encode("utf-8"),
752
+ "contentType": "application/json",
753
+ "accept": _ACCEPT_JSON_OR_SSE,
754
+ "runtimeUserId": options.user_id if options.user_id is not None else DEFAULT_RUNTIME_USER_ID,
755
+ }
756
+ if options.session_id:
757
+ params["runtimeSessionId"] = options.session_id
758
+ response = client.invoke_agent_runtime(**params)
759
+ stream = response.get("response")
760
+ if stream is None:
761
+ raise RuntimeError("No response from AgentCore Runtime")
762
+ text = stream.read().decode("utf-8", errors="replace")
763
+ _log(options.logger, f"A2A response: {text}")
764
+ # Upstream does not surface the session ID on the SigV4 A2A path.
765
+ return StreamingInvokeResult(stream=_single_value_stream(parse_a2a_response(text)), session_id=None)
766
+
767
+
768
+ def _text_parts(parts: Any) -> list[str]:
769
+ if not isinstance(parts, list):
770
+ return []
771
+ return [
772
+ js_string(p["text"])
773
+ for p in parts
774
+ if isinstance(p, dict) and (p.get("kind") == "text" or p.get("type") == "text") and p.get("text") is not None
775
+ ]
776
+
777
+
778
+ def parse_a2a_response(text: str) -> str:
779
+ """Text of an A2A JSON-RPC response (``kind: 'text'`` and ``type: 'text'`` parts)."""
780
+ try:
781
+ parsed = json.loads(text)
782
+ if not isinstance(parsed, dict):
783
+ return text
784
+
785
+ error = parsed.get("error")
786
+ if isinstance(error, (dict, list)):
787
+ message = error.get("message") if isinstance(error, dict) else None
788
+ return f"Error: {js_string(message) if message is not None else to_json_string(error, indent=None)}"
789
+
790
+ result = parsed.get("result")
791
+ if not result:
792
+ return text
793
+
794
+ artifacts = result.get("artifacts") if isinstance(result, dict) else None
795
+ if artifacts:
796
+ texts = [
797
+ t for artifact in artifacts if isinstance(artifact, dict) for t in _text_parts(artifact.get("parts"))
798
+ ]
799
+ if texts:
800
+ return "".join(texts)
801
+
802
+ # Fallback: last agent message in the history.
803
+ history = result.get("history") if isinstance(result, dict) else None
804
+ if history:
805
+ for msg in reversed(history):
806
+ if isinstance(msg, dict) and msg.get("role") == "agent" and msg.get("parts"):
807
+ agent_texts = _text_parts(msg.get("parts"))
808
+ if agent_texts:
809
+ return "".join(agent_texts)
810
+
811
+ return to_json_string(result)
812
+ except Exception: # noqa: BLE001 - any malformed shape falls back to the raw text
813
+ return text
814
+
815
+
816
+ # ---------------------------------------------------------------------------
817
+ # AGUI: structured event streaming over InvokeAgentRuntime
818
+ # ---------------------------------------------------------------------------
819
+
820
+
821
+ @dataclass(slots=True)
822
+ class AguiInvokeOptions:
823
+ region: str
824
+ runtime_arn: str
825
+ session_id: str | None = None
826
+ user_id: str | None = None
827
+ logger: SSELogger | None = None
828
+ headers: dict[str, str] | None = None
829
+ bearer_token: str | None = None
830
+ """Not yet supported for AG-UI; raises if provided."""
831
+
832
+
833
+ @dataclass(slots=True)
834
+ class AguiStreamingInvokeResult:
835
+ stream: Iterator[AguiEvent]
836
+ """All AG-UI events, for rich rendering."""
837
+ text_stream: Iterator[str]
838
+ """Only TEXT_MESSAGE_CONTENT deltas (and RUN_ERROR messages)."""
839
+ session_id: str | None
840
+
841
+
842
+ def invoke_agui_runtime(options: AguiInvokeOptions, input: AguiRunInput) -> AguiStreamingInvokeResult:
843
+ """Invoke an AG-UI runtime and stream its structured events."""
844
+ if options.bearer_token:
845
+ raise RuntimeError("Bearer token auth is not yet supported for AGUI. Use SigV4 credentials.")
846
+
847
+ client = _create_agentcore_client(options.region, options.headers)
848
+ params: dict[str, Any] = {
849
+ "agentRuntimeArn": options.runtime_arn,
850
+ "payload": to_json_string(input, indent=None).encode("utf-8"),
851
+ "contentType": "application/json",
852
+ "accept": "text/event-stream",
853
+ "runtimeUserId": options.user_id if options.user_id is not None else DEFAULT_RUNTIME_USER_ID,
854
+ }
855
+ if options.session_id is not None:
856
+ params["runtimeSessionId"] = options.session_id
857
+ response = client.invoke_agent_runtime(**params)
858
+ body = response.get("response")
859
+ if body is None:
860
+ raise RuntimeError("No response from AgentCore Runtime")
861
+
862
+ streams = parse_agui_sse_stream(iter_stream_chunks(body), logger=options.logger)
863
+ if streams.text_stream is None:
864
+ raise RuntimeError("AGUI parser created in single-consumer mode — textStream unavailable")
865
+ return AguiStreamingInvokeResult(
866
+ stream=streams.event_stream, text_stream=streams.text_stream, session_id=response.get("runtimeSessionId")
867
+ )
868
+
869
+
870
+ def stop_runtime_session(*, region: str, runtime_arn: str, session_id: str) -> StopRuntimeSessionResult:
871
+ """Stop a runtime session."""
872
+ client = create_aws_client("bedrock-agentcore", region)
873
+ response = client.stop_runtime_session(agentRuntimeArn=runtime_arn, runtimeSessionId=session_id)
874
+ return {"sessionId": response.get("runtimeSessionId"), "statusCode": response.get("statusCode")}
875
+
876
+
877
+ # ---------------------------------------------------------------------------
878
+ # Delete capacity provider session (data plane)
879
+ # ---------------------------------------------------------------------------
880
+
881
+
882
+ class DeleteCapacityProviderSessionResult(TypedDict, total=False):
883
+ capacityProviderArn: str
884
+ sessionId: str
885
+ status: str
886
+ """Session status after the asynchronous delete, typically ``Deprovisioning``."""
887
+
888
+
889
+ def delete_capacity_provider_session(
890
+ *, region: str, capacity_provider_id: str, session_id: str
891
+ ) -> DeleteCapacityProviderSessionResult:
892
+ """Deprovision one capacity provider session (idempotent, asynchronous; deletes attached EBS volumes).
893
+
894
+ ``capacity_provider_id`` is the ``{cpName}-{suffix}`` id, not the ARN.
895
+ """
896
+ client = _create_agentcore_client(region)
897
+ response = client.delete_capacity_provider_session(capacityProviderId=capacity_provider_id, sessionId=session_id)
898
+ return drop_none( # type: ignore[return-value]
899
+ {
900
+ "capacityProviderArn": response.get("capacityProviderArn"),
901
+ "sessionId": response.get("sessionId"),
902
+ "status": response.get("status"),
903
+ }
904
+ )
905
+
906
+
907
+ # ---------------------------------------------------------------------------
908
+ # Execute bash: run shell commands in runtime containers
909
+ # ---------------------------------------------------------------------------
910
+
911
+
912
+ @dataclass(slots=True)
913
+ class ExecuteBashOptions:
914
+ region: str
915
+ runtime_arn: str
916
+ command: str
917
+ session_id: str | None = None
918
+ timeout: int | None = None
919
+ headers: dict[str, str] | None = None
920
+ bearer_token: str | None = None
921
+ """Not yet supported for exec; raises if provided."""
922
+
923
+
924
+ class ExecuteBashStreamEvent(TypedDict):
925
+ type: Literal["start", "stdout", "stderr", "stop"]
926
+ data: NotRequired[str]
927
+ exitCode: NotRequired[int | None]
928
+ status: NotRequired[str | None]
929
+
930
+
931
+ @dataclass(slots=True)
932
+ class ExecuteBashResult:
933
+ stream: Iterator[ExecuteBashStreamEvent]
934
+ session_id: str | None = field(default=None)
935
+
936
+
937
+ def execute_bash_command(options: ExecuteBashOptions) -> ExecuteBashResult:
938
+ """Run a shell command in a running runtime container, streaming stdout/stderr and the exit code."""
939
+ if options.bearer_token:
940
+ raise RuntimeError("Bearer token auth for exec is not yet supported. Use SigV4 credentials.")
941
+
942
+ client = _create_agentcore_client(options.region, options.headers)
943
+ body: dict[str, Any] = {"command": options.command}
944
+ if options.timeout is not None:
945
+ body["timeout"] = options.timeout
946
+ params: dict[str, Any] = {"agentRuntimeArn": options.runtime_arn, "body": body}
947
+ if options.session_id is not None:
948
+ params["runtimeSessionId"] = options.session_id
949
+ response = client.invoke_agent_runtime_command(**params)
950
+
951
+ def stream_events() -> Iterator[ExecuteBashStreamEvent]:
952
+ event_stream = response.get("stream")
953
+ if event_stream is None:
954
+ raise RuntimeError("No stream in response from AgentCore Runtime")
955
+ for event in event_stream:
956
+ chunk = event.get("chunk") if isinstance(event, dict) else None
957
+ if not isinstance(chunk, dict):
958
+ continue
959
+ if chunk.get("contentStart") is not None:
960
+ yield {"type": "start"}
961
+ delta = chunk.get("contentDelta")
962
+ if delta:
963
+ if delta.get("stdout"):
964
+ yield {"type": "stdout", "data": delta["stdout"]}
965
+ if delta.get("stderr"):
966
+ yield {"type": "stderr", "data": delta["stderr"]}
967
+ stop = chunk.get("contentStop")
968
+ if stop is not None:
969
+ yield {"type": "stop", "exitCode": stop.get("exitCode"), "status": stop.get("status")}
970
+
971
+ return ExecuteBashResult(stream=stream_events(), session_id=response.get("runtimeSessionId"))