"""Sales / shopping specialist (sample) — AgentCore Runtime + local catalog fixtures. Versions: Python 3.12+, strands-agents, bedrock-agentcore, Claude Sonnet 4.5 pin. In production, replace fixtures with Gateway tools (searchProducts, getCart, …). """ from __future__ import annotations import json import os from typing import Any from bedrock_agentcore.runtime import BedrockAgentCoreApp from strands import Agent, tool from strands.models.bedrock import BedrockModel MODEL_ID = os.environ.get( "BEDROCK_MODEL_ID", "global.anthropic.claude-sonnet-4-5-20250929-v1:0", ) # Fake catalog — demo only CATALOG = { "SKU-TEE-BLU-M": { "title": "Blue Cotton Tee", "price_usd": 29.99, "sizes": ["S", "M", "L"], "in_stock": True, }, "SKU-SHOE-RUN-10": { "title": "Trail Runner", "price_usd": 119.00, "sizes": ["9", "10", "11"], "in_stock": True, }, } app = BedrockAgentCoreApp() @tool def search_products(query: str) -> str: """Search the demo catalog by keyword.""" q = query.lower() hits = [ {"sku": sku, **meta} for sku, meta in CATALOG.items() if q in meta["title"].lower() or q in sku.lower() ] return json.dumps({"query": query, "hits": hits}) @tool def get_product(sku: str) -> str: """Get a single SKU from the demo catalog.""" item = CATALOG.get(sku) if not item: return json.dumps({"error": f"SKU {sku} not found"}) return json.dumps({"sku": sku, **item}) @tool def get_cart(cart_id: str) -> str: """Return a demo cart (fixed fixture).""" return json.dumps( { "cart_id": cart_id or "CART-DEMO-1", "lines": [{"sku": "SKU-TEE-BLU-M", "qty": 1, "price_usd": 29.99}], "subtotal_usd": 29.99, } ) agent = Agent( model=BedrockModel(model_id=MODEL_ID), tools=[search_products, get_product, get_cart], system_prompt=( "You are the sales specialist. Help with product discovery and cart. " "Do not process payments, refunds, or inventory writes." ), ) @app.entrypoint def invoke(payload: dict[str, Any]) -> dict[str, Any]: prompt = payload.get("prompt") or payload.get("inputText") or "" return {"output": str(agent(prompt))}