xpander-sdk 2.0.226__py3-none-any.whl → 2.0.227__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.
@@ -175,6 +175,8 @@ class Agent(XPanderSharedModel):
175
175
  use_oidc_pre_auth: Optional[bool] = False
176
176
  pre_auth_audiences: Optional[List[str]] = []
177
177
  use_oidc_pre_auth_token_for_llm: Optional[bool] = False
178
+ oidc_pre_auth_token_mcp_audience: Optional[bool] = False
179
+ oidc_pre_auth_token_llm_audience: Optional[str] = None
178
180
 
179
181
  Example:
180
182
  >>> agent = Agent(id="agent123", name="Example Agent")
@@ -226,6 +228,8 @@ class Agent(XPanderSharedModel):
226
228
  use_oidc_pre_auth: Optional[bool] = False
227
229
  pre_auth_audiences: Optional[List[str]] = []
228
230
  use_oidc_pre_auth_token_for_llm: Optional[bool] = False
231
+ oidc_pre_auth_token_llm_audience: Optional[str] = None
232
+ oidc_pre_auth_token_mcp_audience: Optional[str] = None
229
233
 
230
234
  _connection_string: Optional[DatabaseConnectionString] = None
231
235
 
@@ -43,7 +43,7 @@ async def build_agent_args(
43
43
  is_async: Optional[bool] = True,
44
44
  auth_events_callback: Optional[Callable] = None,
45
45
  ) -> Dict[str, Any]:
46
- model = _load_llm_model(agent=xpander_agent, override=override)
46
+ model = _load_llm_model(agent=xpander_agent, override=override, task=task)
47
47
  args: Dict[str, Any] = {
48
48
  "id": xpander_agent.id,
49
49
  "store_events": True
@@ -576,7 +576,7 @@ def _configure_deep_planning_guidance(args: Dict[str, Any], agent: Agent, task:
576
576
  plan_str = task.deep_planning.model_dump_json() if task.deep_planning and task.deep_planning.enabled and len(task.deep_planning.tasks) != 0 else "No execution plan, please generate"
577
577
  args["additional_context"] += f" \n Current execution plan: {plan_str}"
578
578
 
579
- def _load_llm_model(agent: Agent, override: Optional[Dict[str, Any]] = {}) -> Any:
579
+ def _load_llm_model(agent: Agent, override: Optional[Dict[str, Any]] = {}, task: Optional[Task] = None) -> Any:
580
580
  """
581
581
  Load and configure the appropriate LLM model based on the agent's provider configuration.
582
582
 
@@ -613,6 +613,12 @@ def _load_llm_model(agent: Agent, override: Optional[Dict[str, Any]] = {}) -> An
613
613
  has_custom_llm_key = (
614
614
  True if agent.llm_credentials and agent.llm_credentials.value else False
615
615
  )
616
+
617
+ oidc_llm_token = None
618
+
619
+ # OIDC pre-auth token claim by audience
620
+ if agent and agent.pre_auth_audiences and agent.use_oidc_pre_auth_token_for_llm and agent.oidc_pre_auth_token_llm_audience and task and task.user_tokens and isinstance(task.user_tokens, dict) and "oidc_tokens" in task.user_tokens and isinstance(task.user_tokens["oidc_tokens"], dict):
621
+ oidc_llm_token = task.user_tokens["oidc_tokens"].get(agent.oidc_pre_auth_token_llm_audience, None)
616
622
 
617
623
  def get_llm_key(env_var_name: str) -> Optional[str]:
618
624
  """
@@ -624,6 +630,11 @@ def _load_llm_model(agent: Agent, override: Optional[Dict[str, Any]] = {}) -> An
624
630
  Returns:
625
631
  Optional[str]: The resolved API key or None if not available.
626
632
  """
633
+
634
+ # return oidc claimed api key
635
+ if oidc_llm_token:
636
+ return oidc_llm_token
637
+
627
638
  env_llm_key = getenv(env_var_name)
628
639
 
629
640
  # If no custom key available, use environment variable
@@ -641,6 +652,9 @@ def _load_llm_model(agent: Agent, override: Optional[Dict[str, Any]] = {}) -> An
641
652
 
642
653
  llm_extra_headers = {}
643
654
 
655
+ if oidc_llm_token:
656
+ llm_extra_headers["x-oidc-token"] = oidc_llm_token
657
+
644
658
  # Get organization default LLM extra headers
645
659
  api_client = APIClient(configuration=agent.configuration)
646
660
  org_default_llm_headers = run_sync(
@@ -975,27 +989,35 @@ async def _resolve_agent_tools(agent: Agent, task: Optional[Task] = None, auth_e
975
989
  else StreamableHTTPClientParams
976
990
  )
977
991
 
978
- # handle mcp auth
979
- if mcp.auth_type == MCPServerAuthType.OAuth2:
980
- if not task:
981
- raise ValueError("MCP server with OAuth authentication detected but task not sent")
982
-
983
- # check if we have user tokens for this mcp
984
- graph_item = next((gi for gi in agent.graph.items if gi.type == AgentGraphItemType.MCP and gi.settings and gi.settings.mcp_settings and gi.settings.mcp_settings.url and gi.settings.mcp_settings.url == mcp.url), None)
985
- if graph_item and task.user_tokens and isinstance(task.user_tokens, dict) and graph_item.id in task.user_tokens:
986
- mcp.api_key = task.user_tokens[graph_item.id]
987
- else:
988
- if not task.input.user or not task.input.user.id:
989
- raise ValueError("MCP server with OAuth authentication detected but user id not set on the task (task.input.user.id)")
992
+ oidc_mcp_token = None
993
+ # OIDC pre-auth token claim by audience
994
+ if agent and agent.pre_auth_audiences and agent.oidc_pre_auth_token_mcp_audience and task and task.user_tokens and isinstance(task.user_tokens, dict) and "oidc_tokens" in task.user_tokens and isinstance(task.user_tokens["oidc_tokens"], dict):
995
+ oidc_mcp_token = task.user_tokens["oidc_tokens"].get(agent.oidc_pre_auth_token_mcp_audience, None)
996
+ if oidc_mcp_token and oidc_mcp_token != "__none__":
997
+ mcp.api_key = oidc_mcp_token
998
+
999
+ if not oidc_mcp_token:
1000
+ # handle mcp auth
1001
+ if mcp.auth_type == MCPServerAuthType.OAuth2:
1002
+ if not task:
1003
+ raise ValueError("MCP server with OAuth authentication detected but task not sent")
990
1004
 
991
- auth_result: MCPOAuthGetTokenResponse = await authenticate_mcp_server(mcp_server=mcp,task=task,user_id=task.input.user.id, auth_events_callback=auth_events_callback)
992
- if auth_result and auth_result.data and isinstance(auth_result.data, MCPOAuthGetTokenGenericResponse) and auth_result.data.message:
993
- raise ValueError(f"MCP authentication failed: {auth_result.data.message}")
994
- if not auth_result:
995
- raise ValueError("MCP Server authentication failed")
996
- if auth_result.type != MCPOAuthResponseType.TOKEN_READY:
997
- raise ValueError("MCP Server authentication timeout")
998
- mcp.api_key = auth_result.data.access_token
1005
+ # check if we have user tokens for this mcp
1006
+ graph_item = next((gi for gi in agent.graph.items if gi.type == AgentGraphItemType.MCP and gi.settings and gi.settings.mcp_settings and gi.settings.mcp_settings.url and gi.settings.mcp_settings.url == mcp.url), None)
1007
+ if graph_item and task.user_tokens and isinstance(task.user_tokens, dict) and graph_item.id in task.user_tokens:
1008
+ mcp.api_key = task.user_tokens[graph_item.id]
1009
+ else:
1010
+ if not task.input.user or not task.input.user.id:
1011
+ raise ValueError("MCP server with OAuth authentication detected but user id not set on the task (task.input.user.id)")
1012
+
1013
+ auth_result: MCPOAuthGetTokenResponse = await authenticate_mcp_server(mcp_server=mcp,task=task,user_id=task.input.user.id, auth_events_callback=auth_events_callback)
1014
+ if auth_result and auth_result.data and isinstance(auth_result.data, MCPOAuthGetTokenGenericResponse) and auth_result.data.message:
1015
+ raise ValueError(f"MCP authentication failed: {auth_result.data.message}")
1016
+ if not auth_result:
1017
+ raise ValueError("MCP Server authentication failed")
1018
+ if auth_result.type != MCPOAuthResponseType.TOKEN_READY:
1019
+ raise ValueError("MCP Server authentication timeout")
1020
+ mcp.api_key = auth_result.data.access_token
999
1021
 
1000
1022
  if mcp.api_key:
1001
1023
 
@@ -1007,6 +1029,7 @@ async def _resolve_agent_tools(agent: Agent, task: Optional[Task] = None, auth_e
1007
1029
  if not mcp.headers:
1008
1030
  mcp.headers = {}
1009
1031
  mcp.headers["Authorization"] = f"Bearer {mcp.api_key}"
1032
+
1010
1033
  mcp_tools.append(
1011
1034
  MCPTools(
1012
1035
  transport=transport,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xpander-sdk
3
- Version: 2.0.226
3
+ Version: 2.0.227
4
4
  Summary: xpander.ai Backend-as-a-service for AI Agents - SDK
5
5
  Home-page: https://www.xpander.ai
6
6
  Author: xpanderAI
@@ -27,7 +27,7 @@ xpander_sdk/modules/agents/models/agent.py,sha256=9foTMH4UOfgT9mPfObpeRxHEJButyQ
27
27
  xpander_sdk/modules/agents/models/agent_list.py,sha256=byEayS2uLwDKaVT3lAHltrFocQFKpr8XEwQ6NTEEEMo,4081
28
28
  xpander_sdk/modules/agents/models/knowledge_bases.py,sha256=YimpjVJxWe8YTbGMD6oGQOA_YV8ztHQHTTBOaBB44ZM,1037
29
29
  xpander_sdk/modules/agents/sub_modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
- xpander_sdk/modules/agents/sub_modules/agent.py,sha256=hNy-FvOQy0Eh6jpqWy-MRVLc9UnAqQcbCZ11UEzk0oQ,38093
30
+ xpander_sdk/modules/agents/sub_modules/agent.py,sha256=EMiGgToBsENdN1lUU0OVx7bKIaMACQ9Klqot8oM9hmY,38347
31
31
  xpander_sdk/modules/agents/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
32
  xpander_sdk/modules/agents/utils/generic.py,sha256=XbG4OeHMQo4gVYCsasMlW_b8OoqS1xL3MlUZSjXivu0,81
33
33
  xpander_sdk/modules/backend/__init__.py,sha256=-NjikuZgHBhOM9xHML2vKsG0ICX9S2RKHktrWaODCBE,171
@@ -36,7 +36,7 @@ xpander_sdk/modules/backend/events_registry.py,sha256=d0V-lsz3I3G1QB643EM1i-a5oJ
36
36
  xpander_sdk/modules/backend/decorators/__init__.py,sha256=ub9c8G0Ll6AuCvfcFB6rqR8iamMJxtcW7QjWw3WSkPU,106
37
37
  xpander_sdk/modules/backend/decorators/on_auth_event.py,sha256=Xt_x9nncujMcF_SgM5hG6M-iZ6B-rDS97EPmgZkGdMk,4715
38
38
  xpander_sdk/modules/backend/frameworks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- xpander_sdk/modules/backend/frameworks/agno.py,sha256=eAnfhIxk3cXmh0p18QXV6-A6Uzr-qznm_rM1w08DAB0,43898
39
+ xpander_sdk/modules/backend/frameworks/agno.py,sha256=q0ImRrPYpYpGhZE2J0XqCYmXgZECRpgVqAGCkCVleDY,45336
40
40
  xpander_sdk/modules/backend/frameworks/dispatch.py,sha256=ht9hT5-cHATofQbWsbWeTARx51Hne3TNNNjw6KECRtA,1814
41
41
  xpander_sdk/modules/backend/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
42
  xpander_sdk/modules/backend/utils/mcp_oauth.py,sha256=5sYJcw557V3pSgutxUFzkBp5YxUJFUoB1V1rEe814pc,5430
@@ -90,8 +90,8 @@ xpander_sdk/utils/generic.py,sha256=XrRj2-L8c0YWpfPdDyXE-pVL-6lKF9VpyZzKHQ4wuCc,
90
90
  xpander_sdk/utils/tools.py,sha256=lyFkq2yP7DxBkyXYVlnFRwDhQCvf0fZZMDm5fBycze4,1244
91
91
  xpander_sdk/utils/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
92
  xpander_sdk/utils/agents/compactization_agent.py,sha256=S_U1dSmDC7I0JUsp_THUYjfutEI5QMBaMPJEXGp0_Sw,14389
93
- xpander_sdk-2.0.226.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
94
- xpander_sdk-2.0.226.dist-info/METADATA,sha256=r6ATsBbKKNEDbMLLT4W2XbVgj7MLCkhpk-SjvWu_QUc,17952
95
- xpander_sdk-2.0.226.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
96
- xpander_sdk-2.0.226.dist-info/top_level.txt,sha256=UCjnxQpsMy5Zoe7lmRuVDO6DI2V_6PgRFfm4oizRbVs,12
97
- xpander_sdk-2.0.226.dist-info/RECORD,,
93
+ xpander_sdk-2.0.227.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
94
+ xpander_sdk-2.0.227.dist-info/METADATA,sha256=GsWF2uvdIA45EhMTa_hv_zGPnpLRDyTkLNjwI7T_kHg,17952
95
+ xpander_sdk-2.0.227.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
96
+ xpander_sdk-2.0.227.dist-info/top_level.txt,sha256=UCjnxQpsMy5Zoe7lmRuVDO6DI2V_6PgRFfm4oizRbVs,12
97
+ xpander_sdk-2.0.227.dist-info/RECORD,,