Commit c0a3122ba364

Vincent Demeester <vincent@sbr.pm>
2026-01-14 13:16:46
feat(xmpp): migrate bot to use Vertex AI instead of direct API
- Update bot.py to use AnthropicVertex client - Use Application Default Credentials (no API key needed) - Configure for itpc-gcp-pnd-pe-eng-claude project - Remove anthropic-api-key secret (not needed with Vertex) - Only requires bot password secret now This sets us up for future Gemini integration as well. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent e04d7ea
Changed files (4)
modules
xmpp-research-bot
systems
modules/xmpp-research-bot/bot.py
@@ -14,7 +14,7 @@ from datetime import datetime
 from pathlib import Path
 
 import slixmpp
-from anthropic import Anthropic
+from anthropic import AnthropicVertex
 
 # Configure logging
 logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
@@ -22,13 +22,15 @@ log = logging.getLogger(__name__)
 
 
 class ResearchBot(slixmpp.ClientXMPP):
-    """XMPP bot that performs research using Claude API"""
+    """XMPP bot that performs research using Claude API via Vertex AI"""
 
-    def __init__(self, jid, password, owner_jid, api_key, inbox_path):
+    def __init__(self, jid, password, owner_jid, project_id, region, inbox_path):
         super().__init__(jid, password)
         self.owner_jid = owner_jid
         self.inbox_path = Path(inbox_path)
-        self.client = Anthropic(api_key=api_key)
+
+        # Initialize Vertex AI client (uses Application Default Credentials)
+        self.client = AnthropicVertex(project_id=project_id, region=region)
 
         # Register event handlers
         self.add_event_handler("session_start", self.on_session_start)
@@ -36,6 +38,7 @@ class ResearchBot(slixmpp.ClientXMPP):
 
         log.info(f"Bot initialized: {jid}")
         log.info(f"Owner: {owner_jid}")
+        log.info(f"Vertex AI: {project_id} / {region}")
         log.info(f"Inbox: {inbox_path}")
 
     async def on_session_start(self, event):
@@ -172,16 +175,17 @@ async def main():
     jid = os.getenv("XMPP_JID")
     password = os.getenv("XMPP_PASSWORD")
     owner_jid = os.getenv("XMPP_OWNER_JID")
-    api_key = os.getenv("ANTHROPIC_API_KEY")
+    project_id = os.getenv("VERTEX_PROJECT_ID")
+    region = os.getenv("VERTEX_REGION", "us-east5")
     inbox_path = os.getenv("INBOX_PATH", "/home/vincent/desktop/org/inbox.org")
 
-    if not all([jid, password, owner_jid, api_key]):
+    if not all([jid, password, owner_jid, project_id]):
         log.error("Missing required environment variables:")
-        log.error("  XMPP_JID, XMPP_PASSWORD, XMPP_OWNER_JID, ANTHROPIC_API_KEY")
+        log.error("  XMPP_JID, XMPP_PASSWORD, XMPP_OWNER_JID, VERTEX_PROJECT_ID")
         sys.exit(1)
 
     # Create and start bot
-    bot = ResearchBot(jid, password, owner_jid, api_key, inbox_path)
+    bot = ResearchBot(jid, password, owner_jid, project_id, region, inbox_path)
 
     log.info("Connecting to XMPP server...")
     bot.connect()
modules/xmpp-research-bot/default.nix
@@ -18,7 +18,8 @@ let
     export XMPP_JID="${cfg.jid}"
     export XMPP_PASSWORD="$(cat ${cfg.passwordFile})"
     export XMPP_OWNER_JID="${cfg.ownerJid}"
-    export ANTHROPIC_API_KEY="$(cat ${cfg.apiKeyFile})"
+    export VERTEX_PROJECT_ID="${cfg.vertexProjectId}"
+    export VERTEX_REGION="${cfg.vertexRegion}"
     export INBOX_PATH="${cfg.inboxPath}"
 
     exec ${pythonEnv}/bin/python3 ${./bot.py}
@@ -45,9 +46,15 @@ in
       description = "XMPP JID of the bot owner (only responds to this user)";
     };
 
-    apiKeyFile = lib.mkOption {
-      type = lib.types.path;
-      description = "Path to file containing Anthropic API key";
+    vertexProjectId = lib.mkOption {
+      type = lib.types.str;
+      description = "Google Cloud project ID for Vertex AI";
+    };
+
+    vertexRegion = lib.mkOption {
+      type = lib.types.str;
+      default = "us-east5";
+      description = "Google Cloud region for Vertex AI";
     };
 
     inboxPath = lib.mkOption {
systems/aomi/extra.nix
@@ -71,12 +71,6 @@
     owner = "vincent";
     group = "users";
   };
-  age.secrets."anthropic-api-key" = {
-    file = ../../secrets/aomi/anthropic-api-key.age;
-    mode = "400";
-    owner = "vincent";
-    group = "users";
-  };
 
   # TODO make it an option ? (otherwise I'll add it for all)
   users.users.vincent.linger = true;
@@ -122,13 +116,14 @@
     configFile = "/home/vincent/.config/nixpkgs-automation/branches.conf";
   };
 
-  # XMPP Research Bot
+  # XMPP Research Bot (uses Vertex AI with Application Default Credentials)
   services.xmpp-research-bot = {
     enable = true;
     jid = "researchbot@xmpp.sbr.pm";
     ownerJid = "vincent@xmpp.sbr.pm";
     passwordFile = config.age.secrets."xmpp-research-bot-password".path;
-    apiKeyFile = config.age.secrets."anthropic-api-key".path;
+    vertexProjectId = "itpc-gcp-pnd-pe-eng-claude";
+    vertexRegion = "us-east5";
     inboxPath = "/home/vincent/desktop/org/inbox.org";
     user = "vincent";
     group = "users";
secrets.nix
@@ -144,7 +144,6 @@ in
   "secrets/demeter/mosquitto-homeassistant-password.age".publicKeys = users ++ [ demeter ];
   "secrets/aion/restic-aix-password.age".publicKeys = users ++ [ aion ];
   "secrets/aomi/xmpp-research-bot-password.age".publicKeys = users ++ [ aomi ];
-  "secrets/aomi/anthropic-api-key.age".publicKeys = users ++ [ aomi ];
   "secrets/rhea/restic-aix-password.age".publicKeys = users ++ [ rhea ];
 
   # Harmonia binary cache signing keys