bedrock-agentcore-starter-toolkit 0.0.1__py3-none-any.whl → 0.1.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.

Potentially problematic release.


This version of bedrock-agentcore-starter-toolkit might be problematic. Click here for more details.

Files changed (50) hide show
  1. bedrock_agentcore_starter_toolkit/__init__.py +5 -0
  2. bedrock_agentcore_starter_toolkit/cli/cli.py +32 -0
  3. bedrock_agentcore_starter_toolkit/cli/common.py +44 -0
  4. bedrock_agentcore_starter_toolkit/cli/gateway/__init__.py +1 -0
  5. bedrock_agentcore_starter_toolkit/cli/gateway/commands.py +88 -0
  6. bedrock_agentcore_starter_toolkit/cli/runtime/__init__.py +1 -0
  7. bedrock_agentcore_starter_toolkit/cli/runtime/commands.py +651 -0
  8. bedrock_agentcore_starter_toolkit/cli/runtime/configuration_manager.py +133 -0
  9. bedrock_agentcore_starter_toolkit/notebook/__init__.py +5 -0
  10. bedrock_agentcore_starter_toolkit/notebook/runtime/__init__.py +1 -0
  11. bedrock_agentcore_starter_toolkit/notebook/runtime/bedrock_agentcore.py +239 -0
  12. bedrock_agentcore_starter_toolkit/operations/__init__.py +1 -0
  13. bedrock_agentcore_starter_toolkit/operations/gateway/README.md +277 -0
  14. bedrock_agentcore_starter_toolkit/operations/gateway/__init__.py +6 -0
  15. bedrock_agentcore_starter_toolkit/operations/gateway/client.py +456 -0
  16. bedrock_agentcore_starter_toolkit/operations/gateway/constants.py +152 -0
  17. bedrock_agentcore_starter_toolkit/operations/gateway/create_lambda.py +85 -0
  18. bedrock_agentcore_starter_toolkit/operations/gateway/create_role.py +90 -0
  19. bedrock_agentcore_starter_toolkit/operations/gateway/exceptions.py +13 -0
  20. bedrock_agentcore_starter_toolkit/operations/runtime/__init__.py +26 -0
  21. bedrock_agentcore_starter_toolkit/operations/runtime/configure.py +241 -0
  22. bedrock_agentcore_starter_toolkit/operations/runtime/create_role.py +404 -0
  23. bedrock_agentcore_starter_toolkit/operations/runtime/invoke.py +129 -0
  24. bedrock_agentcore_starter_toolkit/operations/runtime/launch.py +439 -0
  25. bedrock_agentcore_starter_toolkit/operations/runtime/models.py +79 -0
  26. bedrock_agentcore_starter_toolkit/operations/runtime/status.py +66 -0
  27. bedrock_agentcore_starter_toolkit/services/codebuild.py +332 -0
  28. bedrock_agentcore_starter_toolkit/services/ecr.py +84 -0
  29. bedrock_agentcore_starter_toolkit/services/runtime.py +473 -0
  30. bedrock_agentcore_starter_toolkit/utils/endpoints.py +32 -0
  31. bedrock_agentcore_starter_toolkit/utils/logging_config.py +72 -0
  32. bedrock_agentcore_starter_toolkit/utils/runtime/config.py +129 -0
  33. bedrock_agentcore_starter_toolkit/utils/runtime/container.py +310 -0
  34. bedrock_agentcore_starter_toolkit/utils/runtime/entrypoint.py +197 -0
  35. bedrock_agentcore_starter_toolkit/utils/runtime/logs.py +33 -0
  36. bedrock_agentcore_starter_toolkit/utils/runtime/policy_template.py +74 -0
  37. bedrock_agentcore_starter_toolkit/utils/runtime/schema.py +151 -0
  38. bedrock_agentcore_starter_toolkit/utils/runtime/templates/Dockerfile.j2 +44 -0
  39. bedrock_agentcore_starter_toolkit/utils/runtime/templates/dockerignore.template +68 -0
  40. bedrock_agentcore_starter_toolkit/utils/runtime/templates/execution_role_policy.json.j2 +98 -0
  41. bedrock_agentcore_starter_toolkit/utils/runtime/templates/execution_role_trust_policy.json.j2 +21 -0
  42. bedrock_agentcore_starter_toolkit-0.1.1.dist-info/METADATA +137 -0
  43. bedrock_agentcore_starter_toolkit-0.1.1.dist-info/RECORD +47 -0
  44. bedrock_agentcore_starter_toolkit-0.1.1.dist-info/entry_points.txt +2 -0
  45. bedrock_agentcore_starter_toolkit-0.1.1.dist-info/licenses/NOTICE.txt +190 -0
  46. bedrock_agentcore_starter_toolkit/init.py +0 -3
  47. bedrock_agentcore_starter_toolkit-0.0.1.dist-info/METADATA +0 -26
  48. bedrock_agentcore_starter_toolkit-0.0.1.dist-info/RECORD +0 -5
  49. {bedrock_agentcore_starter_toolkit-0.0.1.dist-info → bedrock_agentcore_starter_toolkit-0.1.1.dist-info}/WHEEL +0 -0
  50. /bedrock_agentcore_starter_toolkit-0.0.1.dist-info/licenses/LICENSE → /bedrock_agentcore_starter_toolkit-0.1.1.dist-info/licenses/LICENSE.txt +0 -0
@@ -0,0 +1,651 @@
1
+ """Bedrock AgentCore CLI - Command line interface for Bedrock AgentCore."""
2
+
3
+ import json
4
+ import logging
5
+ import os
6
+ from pathlib import Path
7
+ from typing import List, Optional
8
+
9
+ import typer
10
+ from prompt_toolkit import prompt
11
+ from prompt_toolkit.completion import PathCompleter
12
+ from rich.panel import Panel
13
+ from rich.syntax import Syntax
14
+
15
+ from ...operations.runtime import (
16
+ configure_bedrock_agentcore,
17
+ get_status,
18
+ invoke_bedrock_agentcore,
19
+ launch_bedrock_agentcore,
20
+ validate_agent_name,
21
+ )
22
+ from ...utils.runtime.entrypoint import parse_entrypoint
23
+ from ..common import _handle_error, _print_success, console
24
+ from .configuration_manager import ConfigurationManager
25
+
26
+ # Create a module-specific logger
27
+ logger = logging.getLogger(__name__)
28
+
29
+
30
+ def _validate_requirements_file(file_path: str) -> str:
31
+ """Validate requirements file and return the path."""
32
+ from ...utils.runtime.entrypoint import validate_requirements_file
33
+
34
+ try:
35
+ deps = validate_requirements_file(Path.cwd(), file_path)
36
+ _print_success(f"Using requirements file: [dim]{deps.resolved_path}[/dim]")
37
+ return file_path
38
+ except (FileNotFoundError, ValueError) as e:
39
+ _handle_error(str(e), e)
40
+
41
+
42
+ def _prompt_for_requirements_file(prompt_text: str, default: str = "") -> Optional[str]:
43
+ """Prompt user for requirements file path with validation."""
44
+ response = prompt(prompt_text, completer=PathCompleter(), default=default)
45
+
46
+ if response.strip():
47
+ return _validate_requirements_file(response.strip())
48
+
49
+ return None
50
+
51
+
52
+ def _handle_requirements_file_display(requirements_file: Optional[str]) -> Optional[str]:
53
+ """Handle requirements file with display logic for CLI."""
54
+ from ...utils.runtime.entrypoint import detect_dependencies
55
+
56
+ if requirements_file:
57
+ # User provided file - validate and show confirmation
58
+ return _validate_requirements_file(requirements_file)
59
+
60
+ # Auto-detection with interactive prompt
61
+ deps = detect_dependencies(Path.cwd())
62
+
63
+ if deps.found:
64
+ console.print(f"\n🔍 [cyan]Detected dependency file:[/cyan] [bold]{deps.file}[/bold]")
65
+ console.print("[dim]Press Enter to use this file, or type a different path (use Tab for autocomplete):[/dim]")
66
+
67
+ result = _prompt_for_requirements_file("Path or Press Enter to use detected dependency file: ", default="")
68
+
69
+ if result is None:
70
+ # Use detected file
71
+ _print_success(f"Using detected file: [dim]{deps.file}[/dim]")
72
+
73
+ return result
74
+ else:
75
+ console.print("\n[yellow]⚠️ No dependency file found (requirements.txt or pyproject.toml)[/yellow]")
76
+ console.print("[dim]Enter path to requirements file (use Tab for autocomplete), or press Enter to skip:[/dim]")
77
+
78
+ result = _prompt_for_requirements_file("Path: ")
79
+
80
+ if result is None:
81
+ _handle_error("No requirements file specified and none found automatically")
82
+
83
+ return result
84
+
85
+
86
+ # Define options at module level to avoid B008
87
+ ENV_OPTION = typer.Option(None, "--env", "-env", help="Environment variables for local mode (format: KEY=VALUE)")
88
+
89
+ # Configure command group
90
+ configure_app = typer.Typer(name="configure", help="Configuration management")
91
+
92
+
93
+ @configure_app.command("list")
94
+ def list_agents():
95
+ """List configured agents."""
96
+ config_path = Path.cwd() / ".bedrock_agentcore.yaml"
97
+ try:
98
+ from ...utils.runtime.config import load_config
99
+
100
+ project_config = load_config(config_path)
101
+ if not project_config.agents:
102
+ console.print("[yellow]No agents configured.[/yellow]")
103
+ return
104
+
105
+ console.print("[bold]Configured Agents:[/bold]")
106
+ for name, agent in project_config.agents.items():
107
+ default_marker = " (default)" if name == project_config.default_agent else ""
108
+ status_icon = "✅" if agent.bedrock_agentcore.agent_arn else "⚠️"
109
+ status_text = "Ready" if agent.bedrock_agentcore.agent_arn else "Config only"
110
+
111
+ console.print(f" {status_icon} [cyan]{name}[/cyan]{default_marker} - {status_text}")
112
+ console.print(f" Entrypoint: {agent.entrypoint}")
113
+ console.print(f" Region: {agent.aws.region}")
114
+ console.print()
115
+ except FileNotFoundError:
116
+ console.print("[red].bedrock_agentcore.yaml not found.[/red]")
117
+
118
+
119
+ @configure_app.command("set-default")
120
+ def set_default(name: str = typer.Argument(...)):
121
+ """Set default agent."""
122
+ config_path = Path.cwd() / ".bedrock_agentcore.yaml"
123
+ try:
124
+ from ...utils.runtime.config import load_config, save_config
125
+
126
+ project_config = load_config(config_path)
127
+ if name not in project_config.agents:
128
+ available = list(project_config.agents.keys())
129
+ _handle_error(f"Agent '{name}' not found. Available: {available}")
130
+
131
+ project_config.default_agent = name
132
+ save_config(project_config, config_path)
133
+ _print_success(f"Set '{name}' as default")
134
+ except Exception as e:
135
+ _handle_error(f"Failed: {e}")
136
+
137
+
138
+ @configure_app.callback(invoke_without_command=True)
139
+ def configure(
140
+ ctx: typer.Context,
141
+ entrypoint: Optional[str] = typer.Option(None, "--entrypoint", "-e", help="Python file with BedrockAgentCoreApp"),
142
+ agent_name: Optional[str] = typer.Option(None, "--name", "-n"),
143
+ execution_role: Optional[str] = typer.Option(None, "--execution-role", "-er"),
144
+ ecr_repository: Optional[str] = typer.Option(None, "--ecr", "-ecr"),
145
+ container_runtime: Optional[str] = typer.Option(None, "--container-runtime", "-ctr"),
146
+ requirements_file: Optional[str] = typer.Option(
147
+ None, "--requirements-file", "-rf", help="Path to requirements file"
148
+ ),
149
+ disable_otel: bool = typer.Option(False, "--disable-otel", "-do", help="Disable OpenTelemetry"),
150
+ authorizer_config: Optional[str] = typer.Option(
151
+ None, "--authorizer-config", "-ac", help="OAuth authorizer configuration as JSON string"
152
+ ),
153
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose output"),
154
+ region: Optional[str] = typer.Option(None, "--region", "-r"),
155
+ protocol: Optional[str] = typer.Option(None, "--protocol", "-p", help="Server protocol (HTTP or MCP)"),
156
+ ):
157
+ """Configure a Bedrock AgentCore agent. The agent name defaults to your Python file name."""
158
+ if ctx.invoked_subcommand is not None:
159
+ return
160
+
161
+ if not entrypoint:
162
+ _handle_error("--entrypoint is required")
163
+
164
+ if protocol and protocol.upper() not in ["HTTP", "MCP"]:
165
+ _handle_error("Error: --protocol must be either HTTP or MCP")
166
+
167
+ console.print("[cyan]Configuring Bedrock AgentCore...[/cyan]")
168
+ try:
169
+ _, file_name = parse_entrypoint(entrypoint)
170
+ agent_name = agent_name or file_name
171
+
172
+ valid, error = validate_agent_name(agent_name)
173
+ if not valid:
174
+ _handle_error(error)
175
+
176
+ console.print(f"[dim]Agent name: {agent_name}[/dim]")
177
+ except ValueError as e:
178
+ _handle_error(f"Error: {e}", e)
179
+
180
+ # Create configuration manager for clean, elegant prompting
181
+ config_path = Path.cwd() / ".bedrock_agentcore.yaml"
182
+ config_manager = ConfigurationManager(config_path)
183
+
184
+ # Interactive prompts for missing values - clean and elegant
185
+ if not execution_role:
186
+ execution_role = config_manager.prompt_execution_role()
187
+
188
+ # Handle ECR repository
189
+ auto_create_ecr = True
190
+ if ecr_repository and ecr_repository.lower() == "auto":
191
+ # User explicitly requested auto-creation
192
+ ecr_repository = None
193
+ auto_create_ecr = True
194
+ _print_success("Will auto-create ECR repository")
195
+ elif not ecr_repository:
196
+ ecr_repository, auto_create_ecr = config_manager.prompt_ecr_repository()
197
+ else:
198
+ # User provided a specific ECR repository
199
+ auto_create_ecr = False
200
+ _print_success(f"Using existing ECR repository: [dim]{ecr_repository}[/dim]")
201
+
202
+ # Handle dependency file selection with simplified logic
203
+ final_requirements_file = _handle_requirements_file_display(requirements_file)
204
+
205
+ # Handle OAuth authorization configuration
206
+ oauth_config = None
207
+ if authorizer_config:
208
+ # Parse provided JSON configuration
209
+ try:
210
+ oauth_config = json.loads(authorizer_config)
211
+ _print_success("Using provided OAuth authorizer configuration")
212
+ except json.JSONDecodeError as e:
213
+ _handle_error(f"Invalid JSON in --authorizer-config: {e}", e)
214
+ else:
215
+ oauth_config = config_manager.prompt_oauth_config()
216
+
217
+ try:
218
+ result = configure_bedrock_agentcore(
219
+ agent_name=agent_name,
220
+ entrypoint_path=Path(entrypoint),
221
+ execution_role=execution_role,
222
+ ecr_repository=ecr_repository,
223
+ container_runtime=container_runtime,
224
+ auto_create_ecr=auto_create_ecr,
225
+ enable_observability=not disable_otel,
226
+ requirements_file=final_requirements_file,
227
+ authorizer_configuration=oauth_config,
228
+ verbose=verbose,
229
+ region=region,
230
+ protocol=protocol.upper() if protocol else None,
231
+ )
232
+
233
+ # Prepare authorization info for summary
234
+ auth_info = "IAM (default)"
235
+ if oauth_config:
236
+ auth_info = "OAuth (customJWTAuthorizer)"
237
+
238
+ console.print(
239
+ Panel(
240
+ f"[green]Configuration Summary[/green]\n\n"
241
+ f"Name: {agent_name}\n"
242
+ f"Runtime: {result.runtime}\n"
243
+ f"Region: {result.region}\n"
244
+ f"Account: {result.account_id}\n"
245
+ f"Execution Role: {result.execution_role}\n"
246
+ f"ECR: {'Auto-create' if result.auto_create_ecr else result.ecr_repository or 'N/A'}\n"
247
+ f"Authorization: {auth_info}\n\n"
248
+ f"Configuration saved to: {result.config_path}",
249
+ title="Bedrock AgentCore Configured",
250
+ border_style="green",
251
+ )
252
+ )
253
+
254
+ except ValueError as e:
255
+ # Handle validation errors from core layer
256
+ _handle_error(str(e), e)
257
+ except Exception as e:
258
+ _handle_error(f"Configuration failed: {e}", e)
259
+
260
+
261
+ def launch(
262
+ agent: Optional[str] = typer.Option(
263
+ None, "--agent", "-a", help="Agent name (use 'agentcore configure list' to see available agents)"
264
+ ),
265
+ local: bool = typer.Option(False, "--local", "-l", help="Run locally"),
266
+ push_ecr: bool = typer.Option(False, "--push-ecr", "-p", help="Build and push to ECR only (no deployment)"),
267
+ codebuild: bool = typer.Option(False, "--codebuild", "-cb", help="Use CodeBuild for ARM64 builds"),
268
+ auto_update_on_conflict: bool = typer.Option(
269
+ False, "--auto-update-on-conflict", help="Enable automatic update when agent already exists"
270
+ ),
271
+ envs: List[str] = typer.Option( # noqa: B008
272
+ None, "--env", "-env", help="Environment variables for agent (format: KEY=VALUE)"
273
+ ),
274
+ ):
275
+ """Launch Bedrock AgentCore locally or to cloud."""
276
+ # Validate mutually exclusive options
277
+ if sum([local, push_ecr, codebuild]) > 1:
278
+ _handle_error("Error: --local, --push-ecr, and --codebuild cannot be used together")
279
+
280
+ config_path = Path.cwd() / ".bedrock_agentcore.yaml"
281
+
282
+ try:
283
+ # Show launch mode
284
+ if local:
285
+ mode = "local"
286
+ elif push_ecr:
287
+ mode = "push-ecr"
288
+ elif codebuild:
289
+ mode = "codebuild"
290
+ else:
291
+ mode = "cloud"
292
+
293
+ console.print(f"[cyan]Launching Bedrock AgentCore ({mode} mode)...[/cyan]\n")
294
+
295
+ # Use the operations module
296
+ with console.status("[bold]Launching Bedrock AgentCore...[/bold]"):
297
+ # Parse environment variables for local mode
298
+ env_vars = None
299
+ if envs:
300
+ env_vars = {}
301
+ for env_var in envs:
302
+ if "=" not in env_var:
303
+ _handle_error(f"Invalid environment variable format: {env_var}. Use KEY=VALUE format.")
304
+ key, value = env_var.split("=", 1)
305
+ env_vars[key] = value
306
+
307
+ # Call the operation
308
+ result = launch_bedrock_agentcore(
309
+ config_path=config_path,
310
+ agent_name=agent,
311
+ local=local,
312
+ push_ecr_only=push_ecr,
313
+ use_codebuild=codebuild,
314
+ env_vars=env_vars,
315
+ auto_update_on_conflict=auto_update_on_conflict,
316
+ )
317
+
318
+ # Handle result based on mode
319
+ if result.mode == "local":
320
+ _print_success(f"Docker image built: {result.tag}")
321
+ _print_success("Ready to run locally")
322
+ console.print("Starting server at http://localhost:8080")
323
+ console.print("[yellow]Press Ctrl+C to stop[/yellow]\n")
324
+
325
+ if result.runtime is None or result.port is None:
326
+ _handle_error("Unable to launch locally")
327
+
328
+ try:
329
+ result.runtime.run_local(result.tag, result.port, result.env_vars)
330
+ except KeyboardInterrupt:
331
+ console.print("\n[yellow]Stopped[/yellow]")
332
+
333
+ elif result.mode == "push-ecr":
334
+ _print_success(f"Image pushed to ECR: [cyan]{result.ecr_uri}:latest[/cyan]")
335
+ console.print(
336
+ Panel(
337
+ f"[green]ECR Push Successful![/green]\n\n"
338
+ f"Image: [cyan]{result.tag}[/cyan]\n"
339
+ f"ECR URI: [cyan]{result.ecr_uri}:latest[/cyan]\n\n"
340
+ f"Your image is now available in ECR.\n"
341
+ f"Run [cyan]agentcore launch[/cyan] to deploy to Bedrock AgentCore.",
342
+ title="Push to ECR Complete",
343
+ border_style="green",
344
+ )
345
+ )
346
+
347
+ elif result.mode == "codebuild":
348
+ _print_success(f"CodeBuild completed: [cyan]{result.codebuild_id}[/cyan]")
349
+ _print_success(f"ARM64 image pushed to ECR: [cyan]{result.ecr_uri}:latest[/cyan]")
350
+
351
+ # Show deployment success panel
352
+ agent_name = result.tag.split(":")[0].replace("bedrock_agentcore-", "")
353
+ deploy_panel = (
354
+ f"[green]CodeBuild ARM64 Deployment Successful![/green]\n\n"
355
+ f"Agent Name: {agent_name}\n"
356
+ f"CodeBuild ID: [cyan]{result.codebuild_id}[/cyan]\n"
357
+ f"Agent ARN: [cyan]{result.agent_arn}[/cyan]\n"
358
+ f"ECR URI: [cyan]{result.ecr_uri}:latest[/cyan]\n\n"
359
+ f"ARM64 container deployed to Bedrock AgentCore.\n\n"
360
+ f"You can now check the status of your Bedrock AgentCore endpoint with:\n"
361
+ f"[cyan]agentcore status[/cyan]\n\n"
362
+ f"You can now invoke your Bedrock AgentCore endpoint with:\n"
363
+ f'[cyan]agentcore invoke \'{{"prompt": "Hello"}}\'[/cyan]'
364
+ )
365
+
366
+ # Add log information if we have agent_id
367
+ if result.agent_id:
368
+ from ...utils.runtime.logs import get_agent_log_paths, get_aws_tail_commands
369
+
370
+ runtime_logs, otel_logs = get_agent_log_paths(result.agent_id)
371
+ follow_cmd, since_cmd = get_aws_tail_commands(runtime_logs)
372
+ deploy_panel += (
373
+ f"\n\n📋 [cyan]Agent logs available at:[/cyan]\n"
374
+ f" {runtime_logs}\n"
375
+ f" {otel_logs}\n\n"
376
+ f"💡 [dim]Tail logs with:[/dim]\n"
377
+ f" {follow_cmd}\n"
378
+ f" {since_cmd}"
379
+ )
380
+
381
+ console.print(
382
+ Panel(
383
+ deploy_panel,
384
+ title="CodeBuild Deployment Complete",
385
+ border_style="green",
386
+ )
387
+ )
388
+
389
+ else: # cloud mode
390
+ _print_success(f"Image pushed to ECR: [cyan]{result.ecr_uri}:latest[/cyan]")
391
+
392
+ # Show deployment success panel
393
+ agent_name = result.tag.split(":")[0].replace("bedrock_agentcore-", "")
394
+ deploy_panel = (
395
+ f"[green]Deployment Successful![/green]\n\n"
396
+ f"Agent Name: {agent_name}\n"
397
+ f"Agent ARN: [cyan]{result.agent_arn}[/cyan]\n"
398
+ f"ECR URI: [cyan]{result.ecr_uri}[/cyan]\n\n"
399
+ f"You can now check the status of your Bedrock AgentCore endpoint with:\n"
400
+ f"[cyan]agentcore status[/cyan]\n\n"
401
+ f"You can now invoke your Bedrock AgentCore endpoint with:\n"
402
+ f'[cyan]agentcore invoke \'{{"prompt": "Hello"}}\'[/cyan]'
403
+ )
404
+
405
+ # Add log information if we have agent_id
406
+ if result.agent_id:
407
+ from ...utils.runtime.logs import get_agent_log_paths, get_aws_tail_commands
408
+
409
+ runtime_logs, otel_logs = get_agent_log_paths(result.agent_id)
410
+ follow_cmd, since_cmd = get_aws_tail_commands(runtime_logs)
411
+ deploy_panel += (
412
+ f"\n\n📋 [cyan]Agent logs available at:[/cyan]\n"
413
+ f" {runtime_logs}\n"
414
+ f" {otel_logs}\n\n"
415
+ f"💡 [dim]Tail logs with:[/dim]\n"
416
+ f" {follow_cmd}\n"
417
+ f" {since_cmd}"
418
+ )
419
+
420
+ console.print(
421
+ Panel(
422
+ deploy_panel,
423
+ title="Bedrock AgentCore Deployed",
424
+ border_style="green",
425
+ )
426
+ )
427
+
428
+ except FileNotFoundError:
429
+ _handle_error(".bedrock_agentcore.yaml not found. Run 'agentcore configure --entrypoint <file>' first")
430
+ except ValueError as e:
431
+ _handle_error(str(e), e)
432
+ except RuntimeError as e:
433
+ _handle_error(str(e), e)
434
+ except Exception as e:
435
+ if not isinstance(e, typer.Exit):
436
+ _handle_error(f"Launch failed: {e}", e)
437
+ raise
438
+
439
+
440
+ def invoke(
441
+ payload: str = typer.Argument(..., help="JSON payload to send"),
442
+ agent: Optional[str] = typer.Option(
443
+ None, "--agent", "-a", help="Agent name (use 'bedrock_agentcore configure list' to see available)"
444
+ ),
445
+ session_id: Optional[str] = typer.Option(None, "--session-id", "-s"),
446
+ bearer_token: Optional[str] = typer.Option(
447
+ None, "--bearer-token", "-bt", help="Bearer token for OAuth authentication"
448
+ ),
449
+ local_mode: Optional[bool] = typer.Option(False, "--local", "-l", help="Send request to a running local container"),
450
+ user_id: Optional[str] = typer.Option(None, "--user-id", "-u", help="User id for authorization flows"),
451
+ ):
452
+ """Invoke Bedrock AgentCore endpoint."""
453
+ config_path = Path.cwd() / ".bedrock_agentcore.yaml"
454
+
455
+ try:
456
+ from ...utils.runtime.config import load_config
457
+
458
+ # Load project configuration to check if auth is configured
459
+ project_config = load_config(config_path)
460
+ config = project_config.get_agent_config(agent)
461
+
462
+ # Parse payload
463
+ try:
464
+ payload_data = json.loads(payload)
465
+ except json.JSONDecodeError:
466
+ payload_data = {"message": payload}
467
+
468
+ # Handle bearer token - only use if auth config is defined in .bedrock_agentcore.yaml
469
+ final_bearer_token = None
470
+ if config.authorizer_configuration is not None:
471
+ # Auth is configured, check for bearer token
472
+ final_bearer_token = bearer_token
473
+ if not final_bearer_token:
474
+ final_bearer_token = os.getenv("BEDROCK_AGENTCORE_BEARER_TOKEN")
475
+
476
+ if final_bearer_token:
477
+ console.print("[dim]Using bearer token for OAuth authentication[/dim]")
478
+ else:
479
+ console.print("[yellow]Warning: OAuth is configured but no bearer token provided[/yellow]")
480
+ elif bearer_token or os.getenv("BEDROCK_AGENTCORE_BEARER_TOKEN"):
481
+ console.print(
482
+ "[yellow]Warning: Bearer token provided but OAuth is not configured in .bedrock_agentcore.yaml[/yellow]"
483
+ )
484
+
485
+ # Display payload
486
+ console.print("[bold]Payload:[/bold]")
487
+ console.print(Syntax(json.dumps(payload_data, indent=2), "json", background_color="default", word_wrap=True))
488
+
489
+ # Invoke
490
+ result = invoke_bedrock_agentcore(
491
+ config_path=config_path,
492
+ payload=payload_data,
493
+ agent_name=agent,
494
+ session_id=session_id,
495
+ bearer_token=final_bearer_token,
496
+ user_id=user_id,
497
+ local_mode=local_mode,
498
+ )
499
+ console.print(f"Session ID: [cyan]{result.session_id}[/cyan]")
500
+ console.print("\n[bold]Response:[/bold]")
501
+ console.print(
502
+ Syntax(
503
+ json.dumps(result.response, indent=2, default=str), "json", background_color="default", word_wrap=True
504
+ )
505
+ )
506
+
507
+ except FileNotFoundError:
508
+ _handle_error(".bedrock_agentcore.yaml not found. Run 'bedrock_agentcore configure --entrypoint <file>' first")
509
+ except ValueError as e:
510
+ if "not deployed" in str(e):
511
+ _handle_error("Bedrock AgentCore not deployed. Run 'bedrock_agentcore launch' first", e)
512
+ else:
513
+ _handle_error(f"Invocation failed: {e}", e)
514
+ except Exception as e:
515
+ _handle_error(f"Invocation failed: {e}", e)
516
+
517
+
518
+ def status(
519
+ agent: Optional[str] = typer.Option(
520
+ None, "--agent", "-a", help="Agent name (use 'bedrock_agentcore configure list' to see available)"
521
+ ),
522
+ verbose: Optional[bool] = typer.Option(
523
+ None, "--verbose", "-v", help="Verbose json output of config, agent and endpoint status"
524
+ ),
525
+ ):
526
+ """Get Bedrock AgentCore status including config and runtime details."""
527
+ config_path = Path.cwd() / ".bedrock_agentcore.yaml"
528
+
529
+ # Get status
530
+ result = get_status(config_path, agent)
531
+
532
+ # Output JSON
533
+ status_json = result.model_dump()
534
+
535
+ try:
536
+ if not verbose:
537
+ if "config" in status_json:
538
+ if status_json["agent"] is None:
539
+ console.print(
540
+ Panel(
541
+ f"[green]Status of the current Agent:[/green]\n\n"
542
+ f"[green]Agent Name: {status_json['config']['name']}[/green]\n"
543
+ f"[cyan]Configuration details:[/cyan]\n"
544
+ f"[cyan]- region: {status_json['config']['region']}[/cyan]\n"
545
+ f"[cyan]- account: {status_json['config']['account']}[/cyan]\n"
546
+ f"[cyan]- execution role: {status_json['config']['execution_role']}[/cyan]\n"
547
+ f"[cyan]- ecr repository: {status_json['config']['ecr_repository']}[/cyan]\n",
548
+ title="Bedrock AgentCore Agent Status",
549
+ border_style="green",
550
+ )
551
+ )
552
+
553
+ console.print(
554
+ Panel(
555
+ "[yellow]Agent is configured, but not launched yet. "
556
+ "Please use `agentcore launch` to launch the agent. [/yellow]\n\n",
557
+ title="Bedrock AgentCore Agent Status",
558
+ border_style="yellow",
559
+ )
560
+ )
561
+
562
+ elif "agent" in status_json and status_json["agent"] is not None:
563
+ agent_data = status_json["agent"]
564
+ console.print(
565
+ Panel(
566
+ f"[green]Status of the current Agent:[/green]\n\n"
567
+ f"[green]Agent Name: {status_json['config']['name']}[/green]\n"
568
+ f"[green]Agent ID: {status_json['config']['agent_id']}[/green]\n"
569
+ f"[green]Agent Arn: {status_json['config']['agent_arn']}[/green]\n"
570
+ f"[green]Created at: {agent_data.get('createdAt', 'Not available')}[/green]\n"
571
+ f"[green]Last Updated at: {agent_data.get('lastUpdatedAt', 'Not available')}[/green]\n"
572
+ f"[cyan]Configuration details:[/cyan]\n"
573
+ f"[cyan]- region: {status_json['config']['region']}[/cyan]\n"
574
+ f"[cyan]- account: {status_json['config'].get('account', 'Not available')}[/cyan]\n"
575
+ f"[cyan]- execution role: "
576
+ f"{status_json['config'].get('execution_role', 'Not available')}[/cyan]\n"
577
+ f"[cyan]- ecr repository: "
578
+ f"{status_json['config'].get('ecr_repository', 'Not available')}[/cyan]\n",
579
+ title="Bedrock AgentCore Agent Status",
580
+ border_style="green",
581
+ )
582
+ )
583
+ else:
584
+ console.print(
585
+ Panel(
586
+ "[green]Please launch agent first![/green]\n\n",
587
+ title="Bedrock AgentCore Agent Status",
588
+ border_style="yellow",
589
+ )
590
+ )
591
+
592
+ if "endpoint" in status_json and status_json["endpoint"] is not None:
593
+ endpoint_data = status_json["endpoint"]
594
+ console.print(
595
+ Panel(
596
+ f"[green]Status of the current Endpoint:[/green]\n\n"
597
+ f"[green]Endpoint Id: {endpoint_data.get('id', 'Not available')}[/green]\n"
598
+ f"[green]Endpoint Name: {endpoint_data.get('name', 'Not available')}[/green]\n"
599
+ f"[green]Endpoint Arn: "
600
+ f"{endpoint_data.get('agentRuntimeEndpointArn', 'Not available')}[/green]\n"
601
+ f"[green]Agent Arn: {endpoint_data.get('agentRuntimeArn', 'Not available')}[/green]\n"
602
+ f"[green]STATUS: [cyan]{endpoint_data.get('status', 'Unknown')}[/cyan][/green]\n"
603
+ f"[green]Last Updated at: "
604
+ f"{endpoint_data.get('lastUpdatedAt', 'Not available')}[/green]\n",
605
+ title="Bedrock AgentCore Endpoint Status",
606
+ border_style="green",
607
+ )
608
+ )
609
+ else:
610
+ console.print(
611
+ Panel(
612
+ "[yellow]Please launch agent first and make sure endpoint status is READY "
613
+ "before invoking![/yellow]\n\n",
614
+ title="Bedrock AgentCore Endpoint Status",
615
+ border_style="yellow",
616
+ )
617
+ )
618
+
619
+ # Show log information
620
+ agent_id = status_json.get("config", {}).get("agent_id")
621
+ if agent_id:
622
+ try:
623
+ from ...utils.runtime.logs import get_agent_log_paths, get_aws_tail_commands
624
+
625
+ endpoint_name = status_json.get("endpoint", {}).get("name")
626
+
627
+ runtime_logs, otel_logs = get_agent_log_paths(agent_id, endpoint_name)
628
+ follow_cmd, since_cmd = get_aws_tail_commands(runtime_logs)
629
+
630
+ console.print("\n📋 [cyan]Agent logs available at:[/cyan]")
631
+ console.print(f" {runtime_logs}")
632
+ console.print(f" {otel_logs}")
633
+ console.print("\n💡 [dim]Tail logs with:[/dim]")
634
+ console.print(f" {follow_cmd}")
635
+ console.print(f" {since_cmd}")
636
+ except (ValueError, TypeError) as e:
637
+ # If logging info fails, log the error and continue
638
+ logger.debug("Failed to display log paths: %s", str(e))
639
+ else: # full json verbose output
640
+ console.print(
641
+ Syntax(
642
+ json.dumps(status_json, indent=2, default=str), "json", background_color="default", word_wrap=True
643
+ )
644
+ )
645
+
646
+ except FileNotFoundError:
647
+ _handle_error(".bedrock_agentcore.yaml not found. Run 'bedrock_agentcore configure --entrypoint <file>' first")
648
+ except ValueError as e:
649
+ _handle_error(f"Status failed: {e}", e)
650
+ except Exception as e:
651
+ _handle_error(f"Status failed: {e}", e)