Skip to content

Commit 3a8d535

Browse files
Restructure use cases (#1653)
* restructure 02-use-cases into three agent-type categories Reorganizes all 27 use case samples into category subfolders aligned with the AgentCore GTM workload definitions: - 01-conversational-agents/ (19 samples): user-facing agents with streaming, user OAuth, and session/long-term memory - 02-automation-agents/ (4 samples): event-driven agents with service identity and stateless execution - 03-coding-assistants/ (3 samples): developer tools with sandboxed execution and project-scoped memory Other changes: - Moves okta-auth-three-tier-end-to-end-demo to 01-features/05-authenticate-and-authorize (identity pattern, not a use case) - Adds 02-use-cases/README.md with category index and sample table - Adds category README for each subfolder, aligned with GTM definitions, no em-dashes - Adds use-case-assessment.md with per-sample scoring, recommendations, and a starter toolkit migration list (18 of 27 samples need migrating) - Fixes all cross-folder relative links broken by the restructure (LICENSE, LOCAL_DEVELOPMENT.md, AGENTCORE_DEPLOYMENT.md) * cull low-quality conversational agent samples and reorganise identity demos Reviewed all 19 conversational agent samples against actual AgentCore feature usage, blog post references, and code quality. Removed 9 samples that did not meet the bar and moved 2 identity-pattern demos to the correct location. Dropped from 01-conversational-agents/: - gateway-schema-support-agent: misclassified coding agent, 82-line README, only 1 real feature, no blog post - slide-deck-generator-memory-agent: narrow use case, no blog post, deprecated starter toolkit, 5 features - local-prototype-to-agentcore: claimed 9 features, only 3 in code, tutorial format belongs in 01-tutorials/ - role-based-hr-data-agent: no blog post, deprecated starter toolkit, Cedar pattern needs full rebuild to be useful - A2A-realestate-agentcore-multiagents: claimed 10 features, only 3 in code (Runtime, Cognito, A2A), no blog post - cost-optimization-agent: only Runtime in code, notebook-driven, no blog post - DB-performance-analyzer: only Gateway + Cognito in code, no blog post - farm-management-advisor: notebook-only, mixed deprecated/native SDK, 191-line README, no blog post Moved to 01-features/05-authenticate-and-authorize/: - auth0-multi-agent-obo: RFC 8693 OBO token exchange is an identity pattern, not a use case; sits alongside okta and entra OBO samples - okta-auth-three-tier-end-to-end-demo: (previous commit) Other changes: - Rename 02-automation-agents/ to 02-workflow-automation-agents/ - Update use-case-assessment.md with DROPPED/MOVED entries for all removed samples - Update all README counts and sample tables - Add auth0-multi-agent-obo to identity README folder table and auth pattern quick reference * update use-case-assessment with decisions, actual features, and authors contacted * untrack use-case-assessment.md (local only) * fix CONTRIBUTING.md relative paths broken by use-cases restructure Samples moved one level deeper (into category subfolders) so ../../CONTRIBUTING.md no longer resolves to the repo root. Updated to ../../../CONTRIBUTING.md in three files: - 01-conversational-agents/customer-support-assistant/README.md - 02-workflow-automation-agents/event-driven-claims-agent/README.md - 03-coding-assistants/claude-code-gateway-mcp-server/README.md * fix: address checkov security findings in CloudFormation templates AWS-operations-agent mcp-tool-template.yaml and mcp-tool-template-zip.yaml: - Scope IAM wildcard resources to account/region-specific ARNs (lambda:InvokeFunction, iam:PassRole, s3:*, logs:*) - Split S3 permissions into bucket-level and object-level statements - Scope bedrock:InvokeModel to foundation-model ARN pattern - Add KMS keys for Lambda env var encryption (CKV_AWS_173) and CloudWatch log group encryption (CKV_AWS_158) - Add SQS dead letter queue and DeadLetterQueue config (CKV_AWS_116) - Add ReservedConcurrentExecutions (CKV_AWS_115) - Add checkov:skip for VPC (CKV_AWS_117) - demo function, VPC not required customer-support-assistant cognito.yaml: - Scope logs resource to account/region ARN prefix - Scope cognito-idp:AdminAddUserToGroup to UserPool ARN - Add SQS DLQ and DeadLetterConfig to PostSignupFunction (CKV_AWS_116) - Add ReservedConcurrentExecutions (CKV_AWS_115) - Add checkov:skip for VPC (CKV_AWS_117) - Cognito trigger, VPC not needed customer-support-assistant infrastructure.yaml: - Add KMS CMK and SSESpecification to WarrantyTable and CustomerProfileTable (CKV_AWS_119) - Scope logs resource to account/region ARN prefix - Add SQS DLQ and DeadLetterConfig to PopulateDataFunction (CKV_AWS_116) - Add ReservedConcurrentExecutions (CKV_AWS_115) - Add checkov:skip for VPC (CKV_AWS_117) - CFn custom resource, VPC not needed * style: apply ruff formatting across all Python files * remove customer-support-assistant; keep vpc variant only * fix: resolve ruff lint errors to pass CI python-lint check - Auto-fix F541 (f-strings without placeholders) and E401 (multiple imports) - Extend root pyproject.toml ignore list with E722, F401, F811, F841 (pre-existing patterns acceptable in a samples/tutorial repository) - Add E722 to SRE-agent pyproject.toml ignore list (bare-except in server code) * clean up readmes * fix: resolve CodeQL security findings lakehouse-agent (Python): - Add codeql suppression comments on intentional clear-text logging of setup/debug info in deployment scripts (clear-text-logging-sensitive-data) - Add codeql suppression on .env file write in deprecated write_to_env method (clear-text-storage-of-sensitive-data) - Add codeql suppression on HMAC-SHA256 usage in streamlit_app.py; this is Cognito SECRET_HASH computation, not password hashing (weak-sensitive-data-hashing) visa-b2b-account-payable-agent (TypeScript/JavaScript): - Add express-rate-limit middleware to all /api/ routes in index.ts and lambda.ts (missing-rate-limiting) - Fix CORS origin in lambda.ts to default to localhost instead of wildcard '*' (permissive-cors) - Replace Math.random() with crypto.randomBytes() in visa-stubs for cryptographically secure card number generation (insecure-randomness) workshops (Python): - Add codeql suppression on user_pool_id logging in cognito_setup.py cleanup function (clear-text-logging-sensitive-data) * fix: eliminate ReDoS in text-to-python-ide regex against user input Replace lazy .+? quantifiers with negated character classes [^"\']{0,500} in the input() call extractor pattern. The original pattern could catastrophically backtrack on adversarial strings submitted as user code. Negated classes cannot backtrack across the excluded characters, making the match linear regardless of input content. * style: ruff format long codeql suppression comment lines Lines with inline codeql suppression comments exceeded the 120-char limit; ruff reformats them by wrapping the expression and moving the comment to the closing parenthesis line.
1 parent 2745264 commit 3a8d535

2,521 files changed

Lines changed: 9932 additions & 91810 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,4 +302,5 @@ plan/
302302

303303
# Browser test report cards
304304
01-features/03-connect-your-agent-to-anything/02-browser/TEST_REPORT_CARD.md
305+
02-use-cases/use-case-assessment.md
305306
**/lambda_config.json

01-features/01-harness/01-advanced-examples/01-custom-containers/custom_container.py

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,19 +86,11 @@
8686
default="node",
8787
help="Language preset (default: node)",
8888
)
89-
parser.add_argument(
90-
"--container", default=None, metavar="URI", help="Override container image URI"
91-
)
89+
parser.add_argument("--container", default=None, metavar="URI", help="Override container image URI")
9290
parser.add_argument("--message", "-m", default=None, help="Override prompt to agent")
93-
parser.add_argument(
94-
"--model", default="global.anthropic.claude-haiku-4-5-20251001-v1:0"
95-
)
96-
parser.add_argument(
97-
"--role-arn", default=None, metavar="ARN", help="Use existing IAM role ARN"
98-
)
99-
parser.add_argument(
100-
"--skip-cleanup", action="store_true", help="Keep resources after the demo"
101-
)
91+
parser.add_argument("--model", default="global.anthropic.claude-haiku-4-5-20251001-v1:0")
92+
parser.add_argument("--role-arn", default=None, metavar="ARN", help="Use existing IAM role ARN")
93+
parser.add_argument("--skip-cleanup", action="store_true", help="Keep resources after the demo")
10294
args = parser.parse_args()
10395

10496
# ── Resolve preset ─────────────────────────────────────────────────────────────
@@ -196,9 +188,7 @@ def run_command(harness_arn, session_id, command):
196188
print(f"\n=== Step 2: Attach Custom Container ({container_uri}) ===")
197189
control.update_harness(
198190
harnessId=harness_id,
199-
environmentArtifact={
200-
"optionalValue": {"containerConfiguration": {"containerUri": container_uri}}
201-
},
191+
environmentArtifact={"optionalValue": {"containerConfiguration": {"containerUri": container_uri}}},
202192
systemPrompt=[{"text": system_prompt}],
203193
)
204194
print("Waiting for container update...")

01-features/01-harness/01-advanced-examples/02-gateway-integration/gateway_integration.py

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,7 @@
8080
# ── Helpers ───────────────────────────────────────────────────────────────────
8181

8282

83-
def poll_gateway_status(
84-
control, gateway_id, target_status="READY", timeout=GATEWAY_POLL_TIMEOUT
85-
):
83+
def poll_gateway_status(control, gateway_id, target_status="READY", timeout=GATEWAY_POLL_TIMEOUT):
8684
deadline = time.monotonic() + timeout
8785
while True:
8886
resp = control.get_gateway(gatewayIdentifier=gateway_id)
@@ -97,14 +95,10 @@ def poll_gateway_status(
9795
time.sleep(GATEWAY_POLL_INTERVAL)
9896

9997

100-
def poll_target_status(
101-
control, gateway_id, target_id, target_status="READY", timeout=GATEWAY_POLL_TIMEOUT
102-
):
98+
def poll_target_status(control, gateway_id, target_id, target_status="READY", timeout=GATEWAY_POLL_TIMEOUT):
10399
deadline = time.monotonic() + timeout
104100
while True:
105-
resp = control.get_gateway_target(
106-
gatewayIdentifier=gateway_id, targetId=target_id
107-
)
101+
resp = control.get_gateway_target(gatewayIdentifier=gateway_id, targetId=target_id)
108102
status = resp["status"]
109103
print(f" Target status: {status}")
110104
if status == target_status:
@@ -116,9 +110,7 @@ def poll_target_status(
116110
time.sleep(GATEWAY_POLL_INTERVAL)
117111

118112

119-
def poll_harness_status(
120-
control, harness_id, target_status="READY", timeout=HARNESS_POLL_TIMEOUT
121-
):
113+
def poll_harness_status(control, harness_id, target_status="READY", timeout=HARNESS_POLL_TIMEOUT):
122114
deadline = time.monotonic() + timeout
123115
while True:
124116
resp = control.get_harness(harnessId=harness_id)
@@ -133,9 +125,7 @@ def poll_harness_status(
133125
time.sleep(GATEWAY_POLL_INTERVAL)
134126

135127

136-
def stream_response(
137-
client, harness_arn, session_id, message, model_id, gateway_arn, raw=False
138-
):
128+
def stream_response(client, harness_arn, session_id, message, model_id, gateway_arn, raw=False):
139129
response = client.invoke_harness(
140130
harnessArn=harness_arn,
141131
runtimeSessionId=session_id,
@@ -158,9 +148,7 @@ def stream_response(
158148
if "contentBlockStart" in event:
159149
start = event["contentBlockStart"].get("start", {})
160150
if "toolUse" in start:
161-
print(
162-
f"\n [Tool: {start['toolUse'].get('name', '?')}]", flush=True
163-
)
151+
print(f"\n [Tool: {start['toolUse'].get('name', '?')}]", flush=True)
164152
elif "contentBlockDelta" in event:
165153
delta = event["contentBlockDelta"].get("delta", {})
166154
if "text" in delta:
@@ -185,9 +173,7 @@ def _cleanup(gw_control, harness_control, gateway_id, target_id, harness_id):
185173
print(f" Warning: {e}")
186174
if gateway_id and target_id:
187175
try:
188-
gw_control.delete_gateway_target(
189-
gatewayIdentifier=gateway_id, targetId=target_id
190-
)
176+
gw_control.delete_gateway_target(gatewayIdentifier=gateway_id, targetId=target_id)
191177
print(f" Deleted target: {target_id}")
192178
time.sleep(10)
193179
except Exception as e:
@@ -260,9 +246,7 @@ def main(args=None):
260246
print("Step 3: Create Harness")
261247
print("=" * 60)
262248
harness_name = f"GatewayHarness_{uuid.uuid4().hex[:8]}"
263-
resp = harness_control.create_harness(
264-
harnessName=harness_name, executionRoleArn=role_arn
265-
)
249+
resp = harness_control.create_harness(harnessName=harness_name, executionRoleArn=role_arn)
266250
harness_id = resp["harness"]["harnessId"]
267251
harness_arn = resp["harness"]["arn"]
268252
print(f" Harness ID: {harness_id}")
@@ -276,9 +260,7 @@ def main(args=None):
276260
session_id = str(uuid.uuid4()).upper()
277261
print(f" Session ID: {session_id}")
278262
print(f" Model: {args.model}")
279-
print(
280-
f" Message: {args.message[:80]}{'...' if len(args.message) > 80 else ''}\n"
281-
)
263+
print(f" Message: {args.message[:80]}{'...' if len(args.message) > 80 else ''}\n")
282264

283265
stream_response(
284266
client,

01-features/01-harness/01-advanced-examples/03-execution-limits/execution_limits.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,7 @@ def invoke(prompt: str, **limits) -> str:
101101
meta = event["metadata"]
102102
usage = meta.get("usage", {})
103103
if usage:
104-
print(
105-
f"→ usage: input={usage.get('inputTokens', 0)}, output={usage.get('outputTokens', 0)}"
106-
)
104+
print(f"→ usage: input={usage.get('inputTokens', 0)}, output={usage.get('outputTokens', 0)}")
107105
elif "internalServerException" in event:
108106
print(f"\nError: {event['internalServerException']}")
109107
print()

01-features/01-harness/01-advanced-examples/04-mcp-integration/mcp_integration.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,7 @@ def stream_invoke(session_id, prompt, tools, timeout=300):
190190
{
191191
"type": "remote_mcp",
192192
"name": "invalid",
193-
"config": {
194-
"remoteMcp": {"url": "https://invalid-mcp-url.example.com/mcp"}
195-
},
193+
"config": {"remoteMcp": {"url": "https://invalid-mcp-url.example.com/mcp"}},
196194
}
197195
],
198196
timeout=60,

01-features/01-harness/01-advanced-examples/05-agent-skills/agent_skills.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,7 @@
7676
print(f"\n=== Part 1: Attach Node.js Container ({NODE_CONTAINER}) ===")
7777
control.update_harness(
7878
harnessId=harness_id,
79-
environmentArtifact={
80-
"optionalValue": {"containerConfiguration": {"containerUri": NODE_CONTAINER}}
81-
},
79+
environmentArtifact={"optionalValue": {"containerConfiguration": {"containerUri": NODE_CONTAINER}}},
8280
)
8381
print("Waiting for container update...")
8482
for i in range(12):
@@ -121,9 +119,7 @@
121119
resp = client.invoke_agent_runtime_command(
122120
agentRuntimeArn=harness_arn,
123121
runtimeSessionId=session_id,
124-
body={
125-
"command": "ls -la .agents/skills/xlsx/ 2>/dev/null && echo 'skill directory OK' || echo 'skill not found'"
126-
},
122+
body={"command": "ls -la .agents/skills/xlsx/ 2>/dev/null && echo 'skill directory OK' || echo 'skill not found'"},
127123
)
128124
for event in resp["stream"]:
129125
if "chunk" in event and "contentDelta" in event["chunk"]:

01-features/01-harness/01-advanced-examples/07-oauth/oauth_gateway.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,8 @@
6363
)
6464

6565
# ── CLI ────────────────────────────────────────────────────────────────────────
66-
parser = argparse.ArgumentParser(
67-
description="Harness JWT inbound + OAuth outbound demo"
68-
)
69-
parser.add_argument(
70-
"--skip-cleanup", action="store_true", help="Keep all resources after the demo"
71-
)
66+
parser = argparse.ArgumentParser(description="Harness JWT inbound + OAuth outbound demo")
67+
parser.add_argument("--skip-cleanup", action="store_true", help="Keep all resources after the demo")
7268
args = parser.parse_args()
7369

7470
# ── Configuration ─────────────────────────────────────────────────────────────
@@ -145,11 +141,7 @@
145141
"allowedClients": [pool1["client_id"]],
146142
}
147143
},
148-
model={
149-
"bedrockModelConfig": {
150-
"modelId": "us.anthropic.claude-haiku-4-5-20251001-v1:0"
151-
}
152-
},
144+
model={"bedrockModelConfig": {"modelId": "us.anthropic.claude-haiku-4-5-20251001-v1:0"}},
153145
systemPrompt=[
154146
{
155147
"text": (

0 commit comments

Comments
 (0)