langchain-trigger-server 0.2.7__py3-none-any.whl → 0.2.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of langchain-trigger-server might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langchain-trigger-server
3
- Version: 0.2.7
3
+ Version: 0.2.9
4
4
  Summary: Generic event-driven triggers framework
5
5
  Project-URL: Homepage, https://github.com/langchain-ai/open-agent-platform
6
6
  Project-URL: Repository, https://github.com/langchain-ai/open-agent-platform
@@ -1,7 +1,7 @@
1
1
  langchain_triggers/__init__.py,sha256=WoW9LC_FJRs42mLWq2iuM-jjPow2Rue50q2zm56Oul0,536
2
- langchain_triggers/app.py,sha256=zuVJZQujipZgovEcYMKMJZdzhaniCNi17I_x3K25MVU,34265
3
- langchain_triggers/core.py,sha256=UyIex-wMoIaI3sxrDN7TAMNg6-gK7N1vcwvlCsIVKBw,3511
4
- langchain_triggers/cron_manager.py,sha256=RYtaco1mMYRI0BnB-u9NKoI55mTinn485h8HwWNoxJU,10268
2
+ langchain_triggers/app.py,sha256=MARlj82Ena79n0MG23m-Vu9w6YDQWqp0Ao24TuEKTzs,35325
3
+ langchain_triggers/core.py,sha256=_CNZRyj78yCHG8FACwhCmZ0zvRoWls924OIFYMOC27Q,3772
4
+ langchain_triggers/cron_manager.py,sha256=ISo-P2gw7eQ6y7xWQOfojqcJr_K-zagZt9Ocy8nX0fw,10477
5
5
  langchain_triggers/decorators.py,sha256=zsfgf171qkEDdIiSn8LUr--3dz6bxBBKZO6dpRM2ILs,3711
6
6
  langchain_triggers/auth/__init__.py,sha256=RtDKuBoKYuyHzLNpKr74cmALO0PhHlWO9Ho7k3CUYFE,349
7
7
  langchain_triggers/auth/slack_hmac.py,sha256=kiwjhTXITgQvLAtEcOv8BnnWJRJcxaQ9dXkQm3JJDQ4,2948
@@ -10,6 +10,6 @@ langchain_triggers/database/interface.py,sha256=jpADOOwcBQo1ZichgiZVaOvfZqEqVVo8
10
10
  langchain_triggers/database/supabase.py,sha256=zi_75GbqRvzzlXd5EgfYof4h6vHWOLS4I1759wvY9kQ,17009
11
11
  langchain_triggers/triggers/__init__.py,sha256=Uw1544gxzN4XDRn2RzpZ5EAG6EAF38ZYQtVvlciEsMs,146
12
12
  langchain_triggers/triggers/cron_trigger.py,sha256=SeWz_ETBCBO1_r96tzTZgsvn4BdF4yMKabygjmHoGwY,3174
13
- langchain_trigger_server-0.2.7.dist-info/METADATA,sha256=F0bp-gz6a_wlW8MmcjSjsfX73gAXYpsxpCUh9StJ4OM,1486
14
- langchain_trigger_server-0.2.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
15
- langchain_trigger_server-0.2.7.dist-info/RECORD,,
13
+ langchain_trigger_server-0.2.9.dist-info/METADATA,sha256=8ER3hixfKxyvOIn308bFj64yjZkscTxotQRkah3pS60,1486
14
+ langchain_trigger_server-0.2.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
15
+ langchain_trigger_server-0.2.9.dist-info/RECORD,,
langchain_triggers/app.py CHANGED
@@ -5,8 +5,10 @@ from __future__ import annotations
5
5
  import logging
6
6
  import os
7
7
  from collections.abc import Callable
8
+ from datetime import UTC, datetime, timedelta
8
9
  from typing import Any
9
10
 
11
+ import jwt
10
12
  from fastapi import Depends, FastAPI, HTTPException, Request
11
13
  from langchain_auth.client import Client
12
14
  from langgraph_sdk import get_client
@@ -27,6 +29,28 @@ from .triggers.cron_trigger import CRON_TRIGGER_ID
27
29
  logger = logging.getLogger(__name__)
28
30
 
29
31
 
32
+ def get_x_service_jwt_token(
33
+ payload: dict[str, Any] | None = None, expiration_seconds: int = 60 * 60
34
+ ) -> str:
35
+ exp_datetime = datetime.now(tz=UTC) + timedelta(seconds=expiration_seconds)
36
+ exp = int(exp_datetime.timestamp())
37
+
38
+ payload = payload or {}
39
+ payload = {
40
+ "sub": "unspecified",
41
+ "exp": exp,
42
+ **payload,
43
+ }
44
+
45
+ secret = os.environ["X_SERVICE_AUTH_JWT_SECRET"]
46
+
47
+ return jwt.encode(
48
+ payload,
49
+ secret,
50
+ algorithm="HS256",
51
+ )
52
+
53
+
30
54
  class AuthenticationMiddleware(BaseHTTPMiddleware):
31
55
  """Middleware to handle authentication for API endpoints."""
32
56
 
@@ -106,7 +130,6 @@ class TriggerServer:
106
130
 
107
131
  # LangGraph configuration
108
132
  self.langgraph_api_url = os.getenv("LANGGRAPH_API_URL")
109
- self.langsmith_api_key = os.getenv("LANGCHAIN_API_KEY")
110
133
  self.trigger_server_auth_api_url = os.getenv("TRIGGER_SERVER_HOST_API_URL")
111
134
 
112
135
  if not self.langgraph_api_url:
@@ -115,16 +138,10 @@ class TriggerServer:
115
138
  self.langgraph_api_url = self.langgraph_api_url.rstrip("/")
116
139
 
117
140
  # Initialize LangGraph SDK client
118
- self.langgraph_client = get_client(
119
- url=self.langgraph_api_url, api_key=self.langsmith_api_key
120
- )
141
+ self.langgraph_client = get_client(url=self.langgraph_api_url, api_key=None)
121
142
  logger.info(
122
143
  f"✓ LangGraph client initialized with URL: {self.langgraph_api_url}"
123
144
  )
124
- if self.langsmith_api_key:
125
- logger.info("✓ LangGraph client initialized with API key.")
126
- else:
127
- logger.warning("⚠ LangGraph client initialized without API key")
128
145
 
129
146
  # Initialize LangChain auth client
130
147
  langchain_api_key = os.getenv("LANGCHAIN_API_KEY")
@@ -323,6 +340,7 @@ class TriggerServer:
323
340
  raise HTTPException(
324
341
  status_code=400, detail=f"Unknown trigger type: {trigger_id}"
325
342
  )
343
+ client_metadata = payload.pop("metadata", None)
326
344
 
327
345
  # Parse payload into registration model first
328
346
  try:
@@ -368,11 +386,16 @@ class TriggerServer:
368
386
 
369
387
  resource_dict = registration_instance.model_dump()
370
388
 
389
+ merged_metadata = {}
390
+ if client_metadata:
391
+ merged_metadata["client_metadata"] = client_metadata
392
+ merged_metadata.update(result.metadata)
393
+
371
394
  registration = await self.database.create_trigger_registration(
372
395
  user_id=user_id,
373
396
  template_id=trigger.id,
374
397
  resource=resource_dict,
375
- metadata=result.metadata,
398
+ metadata=merged_metadata,
376
399
  )
377
400
 
378
401
  if not registration:
@@ -579,6 +602,7 @@ class TriggerServer:
579
602
  body_bytes = await request.body()
580
603
  body_str = body_bytes.decode("utf-8")
581
604
 
605
+ # TODO(sam/palash): We should not have API specific things in this framework repo. We should clean this up.
582
606
  if self._is_slack_trigger(trigger):
583
607
  await self._verify_slack_webhook_auth_with_body(
584
608
  request, body_str
@@ -623,6 +647,11 @@ class TriggerServer:
623
647
  # Ensure agent_id and user_id are strings for JSON serialization
624
648
  agent_id_str = str(agent_id)
625
649
  user_id_str = str(result.registration["user_id"])
650
+ tenant_id_str = str(
651
+ result.registration.get("metadata", {})
652
+ .get("client_metadata", {})
653
+ .get("tenant_id")
654
+ )
626
655
 
627
656
  agent_input = {"messages": [{"role": "human", "content": message}]}
628
657
 
@@ -630,6 +659,7 @@ class TriggerServer:
630
659
  success = await self._invoke_agent(
631
660
  agent_id=agent_id_str,
632
661
  user_id=user_id_str,
662
+ tenant_id=tenant_id_str,
633
663
  input_data=agent_input,
634
664
  )
635
665
  if success:
@@ -656,6 +686,7 @@ class TriggerServer:
656
686
  self,
657
687
  agent_id: str,
658
688
  user_id: str,
689
+ tenant_id: str,
659
690
  input_data: dict[str, Any],
660
691
  ) -> bool:
661
692
  """Invoke LangGraph agent using the SDK."""
@@ -665,20 +696,23 @@ class TriggerServer:
665
696
 
666
697
  try:
667
698
  headers = {
668
- "x-auth-scheme": "agent-builder-trigger",
699
+ "x-api-key": "",
700
+ "x-auth-scheme": "langsmith-agent",
669
701
  "x-user-id": user_id_str,
702
+ "x-tenant-id": tenant_id,
703
+ "x-service-key": get_x_service_jwt_token(
704
+ payload={
705
+ "tenant_id": tenant_id,
706
+ "user_id": user_id_str,
707
+ }
708
+ ),
670
709
  }
671
710
 
672
- # Note: API key is already set in client initialization, no need to add to headers
673
- if not self.langsmith_api_key:
674
- logger.warning(
675
- "No LANGSMITH_API_KEY available - authentication may fail"
676
- )
677
-
678
711
  thread = await self.langgraph_client.threads.create(
679
712
  metadata={
680
713
  "triggered_by": "langchain-triggers",
681
714
  "user_id": user_id_str,
715
+ "tenant_id": tenant_id,
682
716
  },
683
717
  headers=headers,
684
718
  )
@@ -691,6 +725,7 @@ class TriggerServer:
691
725
  metadata={
692
726
  "triggered_by": "langchain-triggers",
693
727
  "user_id": user_id_str,
728
+ "tenant_id": tenant_id,
694
729
  },
695
730
  headers=headers,
696
731
  )
@@ -88,6 +88,13 @@ class TriggerRegistrationResult(BaseModel):
88
88
  """Validate that required fields are provided based on create_registration."""
89
89
  if self.create_registration and not self.metadata:
90
90
  self.metadata = {} # Allow empty metadata for create_registration=True
91
+
92
+ if "client_metadata" in self.metadata:
93
+ raise ValueError(
94
+ "The 'client_metadata' key is reserved for client-provided metadata. "
95
+ "Registration handlers must not use this key in their metadata."
96
+ )
97
+
91
98
  if not self.create_registration and (
92
99
  not self.response_body or not self.status_code
93
100
  ):
@@ -202,6 +202,9 @@ class CronTriggerManager:
202
202
  """Execute a cron job - invoke agents. Can be called manually or by scheduler."""
203
203
  registration_id = registration["id"]
204
204
  user_id = registration["user_id"]
205
+ tenant_id = (
206
+ registration.get("metadata", {}).get("client_metadata", {}).get("tenant_id")
207
+ )
205
208
 
206
209
  # Get agent links
207
210
  agent_links = await self.trigger_server.database.get_agents_for_trigger(
@@ -222,6 +225,7 @@ class CronTriggerManager:
222
225
  # Ensure agent_id and user_id are strings for JSON serialization
223
226
  agent_id_str = str(agent_id)
224
227
  user_id_str = str(user_id)
228
+ tenant_id_str = str(tenant_id)
225
229
 
226
230
  current_time = datetime.utcnow()
227
231
  current_time_str = current_time.strftime("%A, %B %d, %Y at %H:%M UTC")
@@ -239,6 +243,7 @@ class CronTriggerManager:
239
243
  success = await self.trigger_server._invoke_agent(
240
244
  agent_id=agent_id_str,
241
245
  user_id=user_id_str,
246
+ tenant_id=tenant_id_str,
242
247
  input_data=agent_input,
243
248
  )
244
249
  if success: