From d3da0b490bd23bb5aebd0f41423d6f7e7345572c Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Thu, 29 Jan 2026 17:15:39 -0800 Subject: [PATCH] fix: bedrock invoke - does not support prompt-caching-scope --- cookbook/anthropic_agent_sdk/main.py | 112 +++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 cookbook/anthropic_agent_sdk/main.py diff --git a/cookbook/anthropic_agent_sdk/main.py b/cookbook/anthropic_agent_sdk/main.py new file mode 100644 index 00000000000..2dcda89506f --- /dev/null +++ b/cookbook/anthropic_agent_sdk/main.py @@ -0,0 +1,112 @@ +""" +Simple Interactive Claude Agent SDK CLI using LiteLLM Gateway + +This example demonstrates an interactive CLI chat with the Anthropic Agent SDK using LiteLLM as a proxy. +LiteLLM acts as a unified interface, allowing you to use any LLM provider (OpenAI, Azure, Bedrock, etc.) +through the Claude Agent SDK by pointing it to the LiteLLM gateway. +""" + +import os +import asyncio +from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions + + +class Config: + """Configuration for LiteLLM Gateway connection""" + + # LiteLLM proxy URL (default to local instance) + LITELLM_PROXY_URL = os.getenv("LITELLM_PROXY_URL", "http://localhost:4000") + + # LiteLLM API key (master key or virtual key) + LITELLM_API_KEY = os.getenv("LITELLM_API_KEY", "sk-1234") + + # Model name as configured in LiteLLM (e.g., "bedrock-claude-sonnet-4", "gpt-4", etc.) + LITELLM_MODEL = os.getenv("LITELLM_MODEL", "bedrock-claude-sonnet-4.5") + + +async def interactive_chat(): + """ + Interactive CLI chat with the agent + """ + config = Config() + + # Configure Anthropic SDK to point to LiteLLM gateway + # Note: We don't add /anthropic to the base URL - LiteLLM handles routing + litellm_base_url = config.LITELLM_PROXY_URL.rstrip('/') + os.environ["ANTHROPIC_BASE_URL"] = litellm_base_url + os.environ["ANTHROPIC_API_KEY"] = config.LITELLM_API_KEY + + print("=" * 70) + print("šŸ¤– Claude Agent SDK with LiteLLM Gateway - Interactive Chat") + print("=" * 70) + print(f"šŸš€ Connected to: {litellm_base_url}") + print(f"šŸ“¦ Using model: {config.LITELLM_MODEL}") + print("\nType your messages below. Commands:") + print(" - 'quit' or 'exit' to end the conversation") + print(" - 'clear' to start a new conversation") + print("=" * 70) + print() + + while True: + # Configure agent options for each conversation + options = ClaudeAgentOptions( + system_prompt="You are a helpful AI assistant. Be concise, accurate, and friendly.", + model=config.LITELLM_MODEL, + max_turns=50, + ) + + # Create agent client + async with ClaudeSDKClient(options=options) as client: + conversation_active = True + + while conversation_active: + # Get user input + try: + user_input = input("\nšŸ‘¤ You: ").strip() + except (EOFError, KeyboardInterrupt): + print("\n\nšŸ‘‹ Goodbye!") + return + + # Handle commands + if user_input.lower() in ['quit', 'exit']: + print("\nšŸ‘‹ Goodbye!") + return + + if user_input.lower() == 'clear': + print("\nšŸ”„ Starting new conversation...\n") + conversation_active = False + continue + + if not user_input: + continue + + # Send query to agent + print("\nšŸ¤– Assistant: ", end='', flush=True) + + try: + await client.query(user_input) + + # Stream the response + async for msg in client.receive_response(): + if hasattr(msg, 'content'): + for content_block in msg.content: + if hasattr(content_block, 'text'): + print(content_block.text, end='', flush=True) + + print() # New line after response + + except Exception as e: + print(f"\n\nāŒ Error: {e}") + print("Please check your LiteLLM gateway is running and configured correctly.") + + +def main(): + """Run interactive chat""" + try: + asyncio.run(interactive_chat()) + except KeyboardInterrupt: + print("\n\nšŸ‘‹ Goodbye!") + + +if __name__ == "__main__": + main()