From 4375dfb5f20f61a18283125ba717aaa028a43041 Mon Sep 17 00:00:00 2001 From: Ojus Chugh Date: Mon, 22 Jun 2026 00:52:22 +0530 Subject: [PATCH] fix: drop hardcoded api key, require env at first use The Smithery fallback in agent_bridge.py was a real committed secret, not a placeholder. The "your key" Anthropic fallbacks masked missing env. Drop both. Lazy-init the Anthropic client so import still works without the env, but the first call raises a clear error. Adds .env.example and tightens .gitignore. Closes #15 --- .env.example | 22 ++++++++++++++++++++++ .gitignore | 13 +++++++++---- README.md | 8 ++++++-- nanda_adapter/core/agent_bridge.py | 24 +++++++++++++++--------- nanda_adapter/core/mcp_utils.py | 6 ++++-- nanda_adapter/core/nanda.py | 1 - 6 files changed, 56 insertions(+), 18 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..00fcc28 --- /dev/null +++ b/.env.example @@ -0,0 +1,22 @@ +# Copy this file to .env and fill in your own values. +# .env is gitignored, never commit real credentials. + +# Required +ANTHROPIC_API_KEY= +DOMAIN_NAME= + +# Optional, used by the Smithery MCP registry integration +SMITHERY_API_KEY= + +# Optional agent configuration +AGENT_ID= +PORT=6000 +TERMINAL_PORT=6010 +PUBLIC_URL= +API_URL= + +# Optional behavior toggles +IMPROVE_MESSAGES=true +UI_MODE=true +UI_CLIENT_URL= +LOG_DIR=conversation_logs diff --git a/.gitignore b/.gitignore index e254ce5..4db7e38 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,18 @@ .env +.venv/ +venv/ jinoos/ .DS_Store +__pycache__/ +*.pyc +nanda_adapter/__pycache__/ +nanda_adapter/core/__pycache__/ agents/__pycache__/ -conversation_logs/ agents/test.py -nanda_agent/__pycache__ +conversation_logs/ +logs_*/ # Build artifacts dist/ +build/ *.egg-info/ - -nanda_adapter/core/__pycache__ \ No newline at end of file diff --git a/README.md b/README.md index 7ca262a..26f9343 100644 --- a/README.md +++ b/README.md @@ -48,9 +48,13 @@ pip install nanda-adapter ### 4. Set Your enviroment variables ANTHROPIC_API_KEY (For running your personal hosted agents, need API key and your own domain) -> export ANTHROPIC_API_KEY="your-api-key-here +Copy `.env.example` to `.env` and fill it in, or export the variables directly: -> export DOMAIN_NAME=" +> export ANTHROPIC_API_KEY="your-api-key-here" + +> export DOMAIN_NAME="" + +If you use the Smithery MCP registry, set `SMITHERY_API_KEY` too. ### 5. Run an example agent (langchain_pirate.py) > nohup python3 langchain_pirate.py > out.log 2>&1 & diff --git a/nanda_adapter/core/agent_bridge.py b/nanda_adapter/core/agent_bridge.py index 26361d6..d26b1d3 100644 --- a/nanda_adapter/core/agent_bridge.py +++ b/nanda_adapter/core/agent_bridge.py @@ -19,14 +19,21 @@ import sys sys.stdout.reconfigure(line_buffering=True) -# Set API key through environment variable or directly in the code -ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY") or "your key" +ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY") # Toggle for message improvement feature IMPROVE_MESSAGES = os.getenv("IMPROVE_MESSAGES", "true").lower() in ("true", "1", "yes", "y") -# Create Anthropic client with explicit API key -anthropic = Anthropic(api_key=ANTHROPIC_API_KEY) +_anthropic_client = None + +def _get_anthropic_client(): + global _anthropic_client + if _anthropic_client is None: + api_key = os.getenv("ANTHROPIC_API_KEY") + if not api_key: + raise RuntimeError("ANTHROPIC_API_KEY is not set (see .env.example)") + _anthropic_client = Anthropic(api_key=api_key) + return _anthropic_client # Get agent configuration from environment variables def get_agent_id(): @@ -58,7 +65,7 @@ def get_agent_id(): "default": "Improve the following message to make it more clear, compelling, and professional without changing the core content or adding fictional information. Keep the same overall meaning but enhance the phrasing and structure. Don't make it too verbose - keep it concise but impactful. Return only the improved message without explanations or introductions." } -SMITHERY_API_KEY = os.getenv("SMITHERY_API_KEY") or "bfcb8cec-9d56-4957-8156-bced0bfca532" +SMITHERY_API_KEY = os.getenv("SMITHERY_API_KEY") def get_registry_url(): """Get the registry URL from file or use default""" @@ -169,7 +176,7 @@ def call_claude(prompt: str, additional_context: str, conversation_id: str, curr agent_id = get_agent_id() print(f"Agent {agent_id}: Calling Claude with prompt: {full_prompt[:50]}...") - resp = anthropic.messages.create( + resp = _get_anthropic_client().messages.create( model="claude-3-5-sonnet-20241022", max_tokens=512, messages=[{"role":"user","content":full_prompt}], @@ -201,7 +208,7 @@ def call_claude_direct(message_text: str, system_prompt: str = None) -> Optional agent_id = get_agent_id() print(f"Agent {agent_id}: Calling Claude with prompt: {full_prompt[:50]}...") - resp = anthropic.messages.create( + resp = _get_anthropic_client().messages.create( model="claude-3-5-sonnet-20241022", max_tokens=512, messages=[{"role":"user","content":full_prompt}], @@ -409,10 +416,9 @@ def form_mcp_server_url(url: str, config: dict, registry_name: str) -> Optional[ """ try: if registry_name == "smithery": - print("🔑 Using SMITHERY_API_KEY: ", SMITHERY_API_KEY) smithery_api_key = SMITHERY_API_KEY if not smithery_api_key: - print("❌ SMITHERY_API_KEY not found in environment.") + print("SMITHERY_API_KEY not set") return None config_b64 = base64.b64encode(json.dumps(config).encode()) mcp_server_url = f"{url}?api_key={smithery_api_key}&config={config_b64}" diff --git a/nanda_adapter/core/mcp_utils.py b/nanda_adapter/core/mcp_utils.py index 6042c28..ccd952d 100644 --- a/nanda_adapter/core/mcp_utils.py +++ b/nanda_adapter/core/mcp_utils.py @@ -38,8 +38,10 @@ class MCPClient: def __init__(self): self.session = None self.exit_stack = AsyncExitStack() - ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY") or "your-key" - self.anthropic = Anthropic(api_key=ANTHROPIC_API_KEY) + api_key = os.getenv("ANTHROPIC_API_KEY") + if not api_key: + raise RuntimeError("ANTHROPIC_API_KEY is not set (see .env.example)") + self.anthropic = Anthropic(api_key=api_key) async def connect_to_mcp_and_get_tools(self, mcp_server_url, transport_type="http"): """Connect to MCP server and return available tools diff --git a/nanda_adapter/core/nanda.py b/nanda_adapter/core/nanda.py index 9bc8dc7..2773a10 100644 --- a/nanda_adapter/core/nanda.py +++ b/nanda_adapter/core/nanda.py @@ -68,7 +68,6 @@ def start_server(self): api_url = os.getenv("API_URL") agent_id = os.getenv("AGENT_ID") - ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY") or "your key" AGENT_ID = os.getenv("AGENT_ID", "default") # Default to 'default' if not specified PORT = int(os.getenv("PORT", "6000")) TERMINAL_PORT = int(os.getenv("TERMINAL_PORT", "6010"))