ibm-watsonx-orchestrate 1.8.0b1__py3-none-any.whl → 1.9.0b0__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.
@@ -5,7 +5,7 @@
5
5
 
6
6
  pkg_name = "ibm-watsonx-orchestrate"
7
7
 
8
- __version__ = "1.8.0b1"
8
+ __version__ = "1.9.0b0"
9
9
 
10
10
 
11
11
 
@@ -14,7 +14,7 @@ from ibm_watsonx_orchestrate.utils.utils import yaml_safe_load
14
14
  from .types import ToolSpec
15
15
  from .base_tool import BaseTool
16
16
  from .types import HTTP_METHOD, ToolPermission, ToolRequestBody, ToolResponseBody, \
17
- OpenApiToolBinding, \
17
+ OpenApiToolBinding, AcknowledgementBinding, \
18
18
  JsonSchemaObject, ToolBinding, OpenApiSecurityScheme, CallbackBinding
19
19
 
20
20
  import json
@@ -207,35 +207,82 @@ def create_openapi_json_tool(
207
207
 
208
208
  # If it's an async tool, add callback binding
209
209
  if spec.is_async:
210
-
211
-
212
210
  callbacks = route_spec.get('callbacks', {})
213
211
  callback_name = next(iter(callbacks.keys()))
214
212
  callback_spec = callbacks[callback_name]
215
213
  callback_path = next(iter(callback_spec.keys()))
216
214
  callback_method = next(iter(callback_spec[callback_path].keys()))
215
+ callback_operation = callback_spec[callback_path][callback_method]
217
216
 
218
- # Phase 1: Create a separate input schema for callback that excludes callbackUrl
219
- # Note: Currently assuming the callback URL parameter will be named 'callbackUrl' in the OpenAPI spec
220
- # Future phases will handle other naming conventions
217
+ # Extract callback input schema from the callback requestBody
221
218
  callback_input_schema = ToolRequestBody(
219
+ type='object',
220
+ properties={},
221
+ required=[]
222
+ )
223
+
224
+ # Handle callback parameters (query, path, header params)
225
+ callback_parameters = callback_operation.get('parameters') or []
226
+ for parameter in callback_parameters:
227
+ name = f"{parameter['in']}_{parameter['name']}"
228
+ if parameter.get('required'):
229
+ callback_input_schema.required.append(name)
230
+ parameter['schema']['title'] = parameter['name']
231
+ parameter['schema']['description'] = parameter.get('description', None)
232
+ callback_input_schema.properties[name] = JsonSchemaObject.model_validate(parameter['schema'])
233
+ callback_input_schema.properties[name].in_field = parameter['in']
234
+ callback_input_schema.properties[name].aliasName = parameter['name']
235
+
236
+ # Handle callback request body
237
+ callback_request_body_params = callback_operation.get('requestBody', {}).get('content', {}).get(http_response_content_type, {}).get('schema', None)
238
+ if callback_request_body_params is not None:
239
+ callback_input_schema.required.append('__requestBody__')
240
+ callback_request_body_params = copy.deepcopy(callback_request_body_params)
241
+ callback_request_body_params['in'] = 'body'
242
+ if callback_request_body_params.get('title') is None:
243
+ callback_request_body_params['title'] = 'CallbackRequestBody'
244
+ if callback_request_body_params.get('description') is None:
245
+ callback_request_body_params['description'] = 'The callback request body used for this async operation.'
246
+
247
+ callback_input_schema.properties['__requestBody__'] = JsonSchemaObject.model_validate(callback_request_body_params)
248
+
249
+ # Extract callback output schema
250
+ callback_responses = callback_operation.get('responses', {})
251
+ callback_response = callback_responses.get(str(http_success_response_code), {})
252
+ callback_response_description = callback_response.get('description')
253
+ callback_response_schema = callback_response.get('content', {}).get(http_response_content_type, {}).get('schema', {})
254
+
255
+ callback_response_schema['required'] = []
256
+ callback_output_schema = ToolResponseBody.model_validate(callback_response_schema)
257
+ callback_output_schema.description = callback_response_description
258
+
259
+ # Remove callbackUrl parameter from main tool input schema
260
+ original_input_schema = ToolRequestBody(
222
261
  type='object',
223
262
  properties={k: v for k, v in spec.input_schema.properties.items() if not k.endswith('_callbackUrl')},
224
263
  required=[r for r in spec.input_schema.required if not r.endswith('_callbackUrl')]
225
264
  )
265
+ spec.input_schema = original_input_schema
226
266
 
227
- if callback_input_schema:
228
- spec.input_schema = callback_input_schema
229
-
267
+ original_response_schema = spec.output_schema
268
+
230
269
  callback_binding = CallbackBinding(
231
270
  callback_url=callback_path,
232
271
  method=callback_method.upper(),
233
- input_schema=callback_input_schema,
234
- output_schema=spec.output_schema
272
+ output_schema=callback_output_schema
235
273
  )
236
274
 
275
+ # Create acknowledgement binding with the original response schema
276
+ acknowledgement_binding = AcknowledgementBinding(
277
+ output_schema=original_response_schema
278
+ )
279
+
280
+ # For async tools, set the main tool's output_schema to the callback's input_schema
281
+ spec.output_schema = callback_input_schema
282
+
237
283
  else:
238
284
  callback_binding = None
285
+ acknowledgement_binding = None
239
286
 
240
287
  openapi_binding = OpenApiToolBinding(
241
288
  http_path=http_path,
@@ -248,6 +295,9 @@ def create_openapi_json_tool(
248
295
  if callback_binding is not None:
249
296
  openapi_binding.callback = callback_binding
250
297
 
298
+ if acknowledgement_binding is not None:
299
+ openapi_binding.acknowledgement = acknowledgement_binding
300
+
251
301
  spec.binding = ToolBinding(openapi=openapi_binding)
252
302
 
253
303
  return OpenAPITool(spec=spec)
@@ -97,9 +97,13 @@ HTTP_METHOD = Literal['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
97
97
  class CallbackBinding(BaseModel):
98
98
  callback_url: str
99
99
  method: HTTP_METHOD
100
- input_schema: ToolRequestBody
100
+ input_schema: Optional[ToolRequestBody] = None
101
101
  output_schema: ToolResponseBody
102
102
 
103
+ class AcknowledgementBinding(BaseModel):
104
+ output_schema: ToolResponseBody
105
+
106
+
103
107
  class OpenApiToolBinding(BaseModel):
104
108
  http_method: HTTP_METHOD
105
109
  http_path: str
@@ -107,7 +111,8 @@ class OpenApiToolBinding(BaseModel):
107
111
  security: Optional[List[OpenApiSecurityScheme]] = None
108
112
  servers: Optional[List[str]] = None
109
113
  connection_id: str | None = None
110
- callback: CallbackBinding = None
114
+ callback: Optional[CallbackBinding] = None
115
+ acknowledgement: Optional[AcknowledgementBinding] = None
111
116
 
112
117
  @model_validator(mode='after')
113
118
  def validate_openapi_tool_binding(self):
@@ -769,7 +769,7 @@ class AgentsController:
769
769
  for agent in native_agents:
770
770
  agents_list.append(json.loads(agent.dumps_spec()))
771
771
 
772
- rich.print(rich.json.JSON(json.dumps(agents_list, indent=4)))
772
+ rich.print_json(json.dumps(agents_list, indent=4))
773
773
  else:
774
774
  native_table = rich.table.Table(
775
775
  show_header=True,
@@ -832,7 +832,7 @@ class AgentsController:
832
832
  if verbose:
833
833
  for agent in external_agents:
834
834
  external_agents_list.append(json.loads(agent.dumps_spec()))
835
- rich.print(rich.json.JSON(json.dumps(external_agents_list, indent=4)))
835
+ rich.print_json(json.dumps(external_agents_list, indent=4))
836
836
  else:
837
837
  external_table = rich.table.Table(
838
838
  show_header=True,
@@ -900,7 +900,7 @@ class AgentsController:
900
900
 
901
901
  if verbose:
902
902
  for agent in assistant_agents:
903
- rich.print(agent.dumps_spec())
903
+ rich.print_json(agent.dumps_spec())
904
904
  else:
905
905
  assistants_table = rich.table.Table(
906
906
  show_header=True,
@@ -13,8 +13,8 @@ class ChannelType(str, Enum):
13
13
 
14
14
  def __str__(self):
15
15
  return self.value
16
-
17
-
16
+
17
+
18
18
  class RuntimeEnvironmentType(str, Enum):
19
19
  LOCAL = 'local'
20
20
  CPD = 'cpd'
@@ -11,6 +11,7 @@ from ibm_watsonx_orchestrate.client.agents.agent_client import AgentClient
11
11
 
12
12
  from ibm_watsonx_orchestrate.client.utils import instantiate_client
13
13
 
14
+
14
15
  logger = logging.getLogger(__name__)
15
16
 
16
17
  class ChannelsWebchatController:
@@ -96,8 +97,6 @@ class ChannelsWebchatController:
96
97
  if target_env == 'draft' and is_saas == True:
97
98
  logger.error(f'For SAAS, please ensure this agent exists in a Live Environment')
98
99
  exit(1)
99
-
100
-
101
100
 
102
101
  return filtered_environments[0].get("id")
103
102
 
@@ -182,7 +181,7 @@ class ChannelsWebchatController:
182
181
  case _:
183
182
  logger.error("Environment not recognized")
184
183
  sys.exit(1)
185
-
184
+
186
185
  host_url = self.get_host_url()
187
186
  agent_id = self.get_agent_id(self.agent_name)
188
187
  agent_env_id = self.get_environment_id(self.agent_name, self.env)
@@ -2,11 +2,12 @@ import json
2
2
  import logging
3
3
  import typer
4
4
  import os
5
- import yaml
6
5
  import csv
7
6
  import rich
8
7
  import sys
9
8
  import shutil
9
+ import tempfile
10
+ import random
10
11
 
11
12
  from rich.panel import Panel
12
13
  from pathlib import Path
@@ -16,11 +17,37 @@ from typing_extensions import Annotated
16
17
 
17
18
  from ibm_watsonx_orchestrate import __version__
18
19
  from ibm_watsonx_orchestrate.cli.commands.evaluations.evaluations_controller import EvaluationsController
20
+ from ibm_watsonx_orchestrate.cli.commands.agents.agents_controller import AgentsController
19
21
 
20
22
  logger = logging.getLogger(__name__)
21
23
 
22
24
  evaluation_app = typer.Typer(no_args_is_help=True)
23
25
 
26
+ def _native_agent_template():
27
+ return {
28
+ "spec_version": "v1",
29
+ "style": "default",
30
+ "llm": "watsonx/meta-llama/llama-3-405b-instruct",
31
+ "name": "",
32
+ "description": "Native agent for validating external agent",
33
+ "instructions": "Use the tools and external agent(s) provided to answer the user's question. If you do not have enough information to answer the question, say so. If you need more information, ask follow up questions.",
34
+ "collaborators": []
35
+ }
36
+
37
+ def _random_native_agent_name(external_agent_name):
38
+ """ Generate a native agent name in the following format to ensure uniqueness:
39
+
40
+ "external_agent_validation_{external_agent_name}_{random number}
41
+
42
+ So if the external agent name is, "QA_Agent", and the random number generated is, '100', the native agent name is:
43
+ "external_agent_validation_QA_Agent_100"
44
+
45
+ """
46
+ seed = 42
47
+ random.seed(seed)
48
+
49
+ return f"external_agent_validation_{external_agent_name}_{random.randint(0, 100)}"
50
+
24
51
  def read_env_file(env_path: Path|str) -> dict:
25
52
  return dotenv_values(str(env_path))
26
53
 
@@ -218,7 +245,7 @@ def validate_external(
218
245
  str,
219
246
  typer.Option(
220
247
  "--external-agent-config", "-ext",
221
- help="Path to the external agent yaml",
248
+ help="Path to the external agent json file",
222
249
 
223
250
  )
224
251
  ],
@@ -244,33 +271,65 @@ def validate_external(
244
271
  help="Path to a .env file that overrides default.env. Then environment variables override both."
245
272
  ),
246
273
  ] = None,
247
- agent_name: Annotated[
248
- str,
274
+ perf_test: Annotated[
275
+ bool,
249
276
  typer.Option(
250
- "--agent_name", "-a",
251
- help="Name of the native agent which has the external agent to test registered as a collaborater. See: https://developer.watson-orchestrate.ibm.com/agents/build_agent#native-agents)." \
252
- " If this parameter is pased, validation of the external agent is not run.",
253
- rich_help_panel="Parameters for Input Evaluation"
277
+ "--perf", "-p",
278
+ help="Performance test your external agent against the provide user stories.",
279
+ rich_help_panel="Parameters for Input Evaluation",
254
280
  )
255
- ] = None
281
+ ] = False
256
282
  ):
257
283
 
258
284
  validate_watsonx_credentials(user_env_file)
259
- Path(output_dir).mkdir(exist_ok=True)
260
- shutil.copy(data_path, os.path.join(output_dir, "input_sample.tsv"))
261
285
 
262
- if agent_name is not None:
263
- eval_dir = os.path.join(output_dir, "evaluation")
286
+ with open(external_agent_config, 'r') as f:
287
+ try:
288
+ external_agent_config = json.load(f)
289
+ except Exception:
290
+ rich.print(
291
+ f"[red]: Please provide a valid external agent spec in JSON format. See 'examples/evaluations/external_agent_validation/sample_external_agent_config.json' for an example."
292
+ )
293
+ sys.exit(1)
294
+
295
+ eval_dir = os.path.join(output_dir, "evaluations")
296
+ if perf_test:
264
297
  if os.path.exists(eval_dir):
265
298
  rich.print(f"[yellow]: found existing {eval_dir} in target directory. All content is removed.")
266
- shutil.rmtree(os.path.join(output_dir, "evaluation"))
267
- Path(eval_dir).mkdir(exist_ok=True)
299
+ shutil.rmtree(eval_dir)
300
+ Path(eval_dir).mkdir(exist_ok=True, parents=True)
268
301
  # save external agent config even though its not used for evaluation
269
302
  # it can help in later debugging customer agents
270
- with open(os.path.join(eval_dir, "external_agent_cfg.yaml"), "w+") as f:
271
- with open(external_agent_config, "r") as cfg:
272
- external_agent_config = yaml.safe_load(cfg)
273
- yaml.safe_dump(external_agent_config, f, indent=4)
303
+ with open(os.path.join(eval_dir, f"external_agent_cfg.json"), "w+") as f:
304
+ json.dump(external_agent_config, f, indent=4)
305
+
306
+ logger.info("Registering External Agent")
307
+ agent_controller = AgentsController()
308
+
309
+ external_agent_config["title"] = external_agent_config["name"]
310
+ external_agent_config["auth_config"] = {"token": credential}
311
+ external_agent_config["spec_version"] = external_agent_config.get("spec_version", "v1")
312
+ external_agent_config["provider"] = "external_chat"
313
+
314
+ with tempfile.NamedTemporaryFile(mode="w+", encoding="utf-8", suffix=".json", delete=True) as fp:
315
+ json.dump(external_agent_config, fp, indent=4)
316
+ fp.flush()
317
+ agents = agent_controller.import_agent(file=os.path.abspath(fp.name), app_id=None)
318
+ agent_controller.publish_or_update_agents(agents)
319
+
320
+ logger.info("Registering Native Agent")
321
+
322
+ native_agent_template = _native_agent_template()
323
+ agent_name = _random_native_agent_name(external_agent_config["name"])
324
+ rich.print(f"[blue][b]Generated native agent name is: [i]{agent_name}[/i][/b]")
325
+ native_agent_template["name"] = agent_name
326
+ native_agent_template["collaborators"] = [external_agent_config["name"]]
327
+
328
+ with tempfile.NamedTemporaryFile(mode="w+", encoding="utf-8", suffix=".json", delete=True) as fp:
329
+ json.dump(native_agent_template, fp, indent=4)
330
+ fp.flush()
331
+ agents = agent_controller.import_agent(file=os.path.abspath(fp.name), app_id=None)
332
+ agent_controller.publish_or_update_agents(agents)
274
333
 
275
334
  rich.print(f"[gold3]Starting evaluation of inputs in '{data_path}' against '{agent_name}'[/gold3]")
276
335
  performance_test(
@@ -281,8 +340,6 @@ def validate_external(
281
340
  )
282
341
 
283
342
  else:
284
- with open(external_agent_config, "r") as f:
285
- external_agent_config = yaml.safe_load(f)
286
343
  controller = EvaluationsController()
287
344
  test_data = []
288
345
  with open(data_path, "r") as f:
@@ -290,31 +347,29 @@ def validate_external(
290
347
  for line in csv_reader:
291
348
  test_data.append(line[0])
292
349
 
293
- # save validation results in "validation_results" sub-dir
294
- validation_folder = Path(output_dir) / "validation_results"
350
+ # save validation results in "validate_external" sub-dir
351
+ validation_folder = Path(output_dir) / "validate_external"
295
352
  if os.path.exists(validation_folder):
296
353
  rich.print(f"[yellow]: found existing {validation_folder} in target directory. All content is removed.")
297
354
  shutil.rmtree(validation_folder)
298
355
  validation_folder.mkdir(exist_ok=True, parents=True)
356
+ shutil.copy(data_path, os.path.join(validation_folder, "input_sample.tsv"))
299
357
 
300
358
  # validate the inputs in the provided csv file
301
359
  summary = controller.external_validate(external_agent_config, test_data, credential)
302
- with open(validation_folder / "validation_results.json", "w") as f:
303
- json.dump(summary, f, indent=4)
304
-
305
360
  # validate sample block inputs
306
- rich.print("[gold3]Validating external agent to see if it can handle an array of messages.")
361
+ rich.print("[gold3]Validating external agent against an array of messages.")
307
362
  block_input_summary = controller.external_validate(external_agent_config, test_data, credential, add_context=True)
308
- with open(validation_folder / "sample_block_validation_results.json", "w") as f:
309
- json.dump(block_input_summary, f, indent=4)
310
-
363
+
364
+ with open(validation_folder / "validation_results.json", "w") as f:
365
+ json.dump([summary, block_input_summary], f, indent=4)
366
+
311
367
  user_validation_successful = all([item["success"] for item in summary])
312
368
  block_validation_successful = all([item["success"] for item in block_input_summary])
313
369
 
314
370
  if user_validation_successful and block_validation_successful:
315
371
  msg = (
316
372
  f"[green]Validation is successful. The result is saved to '{str(validation_folder)}'.[/green]\n"
317
- "You can add the external agent as a collaborator agent. See: https://developer.watson-orchestrate.ibm.com/agents/build_agent#native-agents."
318
373
  )
319
374
  else:
320
375
  msg = f"[dark_orange]Schema validation did not succeed. See '{str(validation_folder)}' for failures.[/dark_orange]"
@@ -167,15 +167,12 @@ class ModelsController:
167
167
  logger.error("Error: WATSONX_URL is required in the environment.")
168
168
  sys.exit(1)
169
169
 
170
- if is_cpd_env(models_client.base_url):
171
- virtual_models = []
172
- virtual_model_policies = []
173
- else:
174
- logger.info("Retrieving virtual-model models list...")
175
- virtual_models = models_client.list()
170
+
171
+ logger.info("Retrieving virtual-model models list...")
172
+ virtual_models = models_client.list()
176
173
 
177
- logger.info("Retrieving virtual-policies models list...")
178
- virtual_model_policies = model_policies_client.list()
174
+ logger.info("Retrieving virtual-policies models list...")
175
+ virtual_model_policies = model_policies_client.list()
179
176
 
180
177
  logger.info("Retrieving watsonx.ai models list...")
181
178
  found_models = _get_wxai_foundational_models()
@@ -877,7 +877,7 @@ def server_start(
877
877
  if experimental_with_langfuse:
878
878
  logger.info(f"You can access the observability platform Langfuse at http://localhost:3010, username: orchestrate@ibm.com, password: orchestrate")
879
879
  if with_doc_processing:
880
- logger.info(f"Document processing capabilities are now available for use in Flows (both ADK and runtime). Note: This option is currently available only in the Developer edition.")
880
+ logger.info(f"Document processing in Flows (Public Preview) has been enabled.")
881
881
 
882
882
  @server_app.command(name="stop")
883
883
  def server_stop(
@@ -63,12 +63,7 @@ class ConnectionsClient(BaseAPIClient):
63
63
  # GET /api/v1/connections/applications/{app_id}
64
64
  def get(self, app_id: str) -> GetConnectionResponse | None:
65
65
  try:
66
- path = (
67
- f"/connections/applications/{app_id}"
68
- if is_cpd_env(self.base_url)
69
- else f"/connections/applications?app_id={app_id}"
70
- )
71
- return GetConnectionResponse.model_validate(self._get(path))
66
+ return GetConnectionResponse.model_validate(self._get(f"/connections/applications?app_id={app_id}"))
72
67
  except ClientAPIException as e:
73
68
  if e.response.status_code == 404:
74
69
  return None
@@ -78,12 +73,7 @@ class ConnectionsClient(BaseAPIClient):
78
73
  # GET api/v1/connections/applications
79
74
  def list(self) -> List[ListConfigsResponse]:
80
75
  try:
81
- path = (
82
- f"/connections/applications"
83
- if is_cpd_env(self.base_url)
84
- else f"/connections/applications?include_details=true"
85
- )
86
- res = self._get(path)
76
+ res = self._get(f"/connections/applications?include_details=true")
87
77
  import json
88
78
  json.dumps(res)
89
79
  return [ListConfigsResponse.model_validate(conn) for conn in res.get("applications", [])]
@@ -135,19 +125,9 @@ class ConnectionsClient(BaseAPIClient):
135
125
  def get_credentials(self, app_id: str, env: ConnectionEnvironment, use_app_credentials: bool) -> dict:
136
126
  try:
137
127
  if use_app_credentials:
138
- path = (
139
- f"/connections/applications/{app_id}/credentials?env={env}"
140
- if is_cpd_env(self.base_url)
141
- else f"/connections/applications/{app_id}/credentials/{env}"
142
- )
143
- return self._get(path)
128
+ return self._get(f"/connections/applications/{app_id}/credentials/{env}")
144
129
  else:
145
- path = (
146
- f"/connections/applications/{app_id}/configs/runtime_credentials?env={env}"
147
- if is_cpd_env(self.base_url)
148
- else f"/connections/applications/runtime_credentials?app_id={app_id}&env={env}"
149
- )
150
- return self._get(path)
130
+ return self._get(f"/connections/applications/runtime_credentials?app_id={app_id}&env={env}")
151
131
  except ClientAPIException as e:
152
132
  if e.response.status_code == 404:
153
133
  return None
@@ -177,12 +157,7 @@ class ConnectionsClient(BaseAPIClient):
177
157
  if conn_id is None:
178
158
  return ""
179
159
  try:
180
- path = (
181
- f"/connections/applications/id/{conn_id}"
182
- if is_cpd_env(self.base_url)
183
- else f"/connections/applications?connection_id={conn_id}"
184
- )
185
- app_details = self._get(path)
160
+ app_details = self._get(f"/connections/applications?connection_id={conn_id}")
186
161
  return app_details.get("app_id")
187
162
  except ClientAPIException as e:
188
163
  if e.response.status_code == 404:
@@ -33,18 +33,6 @@ def get_current_env_url() -> str:
33
33
  active_env = cfg.read(CONTEXT_SECTION_HEADER, CONTEXT_ACTIVE_ENV_OPT)
34
34
  return cfg.get(ENVIRONMENTS_SECTION_HEADER, active_env, ENV_WXO_URL_OPT)
35
35
 
36
- def get_cpd_instance_id_from_url(url: str | None = None) -> str:
37
- if url is None:
38
- url = get_current_env_url()
39
-
40
- if not is_cpd_env(url):
41
- logger.error(f"The host {url} is not a CPD instance")
42
- sys.exit(1)
43
-
44
- url_fragments = url.split('/')
45
- return url_fragments[-1] if url_fragments[-1] else url_fragments[-2]
46
-
47
-
48
36
  def is_local_dev(url: str | None = None) -> bool:
49
37
  if url is None:
50
38
  url = get_current_env_url()
@@ -63,11 +51,11 @@ def is_local_dev(url: str | None = None) -> bool:
63
51
 
64
52
  return False
65
53
 
66
- def is_cpd_env(url: str | None = None) -> bool:
54
+ def is_ga_platform(url: str | None = None) -> bool:
67
55
  if url is None:
68
56
  url = get_current_env_url()
69
57
 
70
- if url.lower().startswith("https://cpd"):
58
+ if url.__contains__("orchestrate.ibm.com"):
71
59
  return True
72
60
  return False
73
61
 
@@ -82,14 +70,27 @@ def is_ibm_cloud_platform(url:str | None = None) -> bool:
82
70
  return True
83
71
  return False
84
72
 
85
- def is_ga_platform(url: str | None = None) -> bool:
73
+ def is_cpd_env(url: str | None = None) -> bool:
86
74
  if url is None:
87
75
  url = get_current_env_url()
88
76
 
89
- if url.__contains__("orchestrate.ibm.com"):
77
+ if url.lower().startswith("https://cpd"):
90
78
  return True
91
79
  return False
92
80
 
81
+ def get_cpd_instance_id_from_url(url: str | None = None) -> str:
82
+ if url is None:
83
+ url = get_current_env_url()
84
+
85
+ if not is_cpd_env(url):
86
+ logger.error(f"The host {url} is not a CPD instance")
87
+ sys.exit(1)
88
+
89
+ url_fragments = url.split('/')
90
+ return url_fragments[-1] if url_fragments[-1] else url_fragments[-2]
91
+
92
+
93
+
93
94
 
94
95
  def get_environment() -> str:
95
96
  if is_local_dev():
@@ -302,7 +302,7 @@ services:
302
302
  JWT_PRIVATE_CONFIGS_PATH: "/"
303
303
  VECTOR_STORE_PROVIDER: ${VECTOR_STORE_PROVIDER:-milvus}
304
304
  CELERY_RESULTS_TTL: "3600"
305
- EVENT_BROKER_TTL: "-1"
305
+ EVENT_BROKER_TTL: "3600"
306
306
  TAVILY_API_KEY: ${TAVILY_API_KEY:-dummy_tavily_api_key}
307
307
  WATSONX_APIKEY: ${WATSONX_APIKEY}
308
308
  WATSONX_URL: ${WATSONX_URL}
@@ -404,7 +404,7 @@ services:
404
404
  WXAI_API_KEY: ${WXAI_API_KEY}
405
405
  VECTOR_STORE_PROVIDER: ${VECTOR_STORE_PROVIDER:-milvus}
406
406
  CELERY_RESULTS_TTL: "3600"
407
- EVENT_BROKER_TTL: "-1"
407
+ EVENT_BROKER_TTL: "3600"
408
408
  TAVILY_API_KEY: ${TAVILY_API_KEY:-dummy_tavily_api_key}
409
409
  WATSONX_APIKEY: ${WATSONX_APIKEY}
410
410
  WATSONX_URL: ${WATSONX_URL}
@@ -789,7 +789,7 @@ services:
789
789
  WO_AUTH_TYPE: ${WO_AUTH_TYPE}
790
790
  healthcheck:
791
791
  test: curl -k http://localhost:9044/readiness --fail
792
- interval: 5s
792
+ interval: 30s
793
793
  timeout: 60s
794
794
  retries: 5
795
795
  ports:
@@ -42,7 +42,7 @@ LANGFUSE_PRIVATE_KEY=sk-lf-7bc4da63-7b2b-40c0-b5eb-1e0cf64f9af2
42
42
 
43
43
  CELERY_WORKER_CONCURRENCY=12
44
44
  CELERY_RESULTS_TTL="3600"
45
- EVENT_BROKER_TTL="-1"
45
+ EVENT_BROKER_TTL="3600"
46
46
 
47
47
  # START -- IMAGE REGISTRIES AND TAGS
48
48
  # The registry URL to pull the private images from, including the name of the repository in the registry.
@@ -53,13 +53,13 @@ EVENT_BROKER_TTL="-1"
53
53
  REGISTRY_URL=
54
54
 
55
55
 
56
- SERVER_TAG=10-07-2025-beb40a3a
56
+ SERVER_TAG=22-07-2025
57
57
  SERVER_REGISTRY=
58
58
 
59
- WORKER_TAG=10-07-2025-beb40a3a
59
+ WORKER_TAG=22-07-2025
60
60
  WORKER_REGISTRY=
61
61
 
62
- AI_GATEWAY_TAG=01-07-2025
62
+ AI_GATEWAY_TAG=21-07-2025
63
63
  AI_GATEWAY_REGISTRY=
64
64
 
65
65
  AGENT_GATEWAY_TAG=07-07-2025
@@ -68,23 +68,23 @@ AGENT_GATEWAY_REGISTRY=
68
68
  DB_REGISTRY=
69
69
  # If you build multiarch set all three of these to the same, we have a pr against main
70
70
  # to not have this separation, but we can merge it later
71
- DBTAG=24-06-2025-v1
71
+ DBTAG=22-07-2025
72
72
  AMDDBTAG=24-06-2025-v1
73
73
  ARM64DBTAG=24-06-2025-v1
74
74
 
75
75
  UI_REGISTRY=
76
- UITAG=27-06-2025
76
+ UITAG=23-07-2025
77
77
 
78
78
  CM_REGISTRY=
79
- CM_TAG=27-06-2025
79
+ CM_TAG=24-07-2025
80
80
 
81
- TRM_TAG=08-07-2025
81
+ TRM_TAG=23-07-2025-3c60549f0bac275de3e5736265a3fd49cdd3a203
82
82
  TRM_REGISTRY=
83
83
 
84
- TR_TAG=08-07-2025
84
+ TR_TAG=23-07-2025-3c60549f0bac275de3e5736265a3fd49cdd3a203
85
85
  TR_REGISTRY=
86
86
 
87
- BUILDER_TAG=15-07-2025
87
+ BUILDER_TAG=22-07-2025-v1
88
88
  BUILDER_REGISTRY=
89
89
 
90
90
  FLOW_RUNTIME_TAG=15-07-2025
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ibm-watsonx-orchestrate
3
- Version: 1.8.0b1
3
+ Version: 1.9.0b0
4
4
  Summary: IBM watsonx.orchestrate SDK
5
5
  Author-email: IBM <support@ibm.com>
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
- ibm_watsonx_orchestrate/__init__.py,sha256=9zMqS0YMNcmpeGzYGa0IjjaKiXHm21buJ4ZsqNKJ1mo,427
1
+ ibm_watsonx_orchestrate/__init__.py,sha256=2UaugDcM-5kU7VcYFZlaSUp30w1dBcZbs9OZJ-nA2vA,427
2
2
  ibm_watsonx_orchestrate/agent_builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  ibm_watsonx_orchestrate/agent_builder/agents/__init__.py,sha256=lmZwaiWXD4Ea19nrMwZXaqCxFMG29xNS8vUoZtK3yI4,392
4
4
  ibm_watsonx_orchestrate/agent_builder/agents/agent.py,sha256=W0uya81fQPrYZFaO_tlsxBL56Bfpw0xrqdxQJhAZ6XI,983
@@ -23,9 +23,9 @@ ibm_watsonx_orchestrate/agent_builder/toolkits/types.py,sha256=yY-V4Hqct91-Rs4rJ
23
23
  ibm_watsonx_orchestrate/agent_builder/tools/__init__.py,sha256=adkYX0wgB-RKFCUBw6LPJhNVelUjUdsxipGPk2ghLns,479
24
24
  ibm_watsonx_orchestrate/agent_builder/tools/base_tool.py,sha256=0vwMIAyKyB8v1QmNrubLy8Al58g3qT78EUgrmOjegoI,1220
25
25
  ibm_watsonx_orchestrate/agent_builder/tools/flow_tool.py,sha256=DJWYVmIjw1O_cbzPpwU0a_vIZGvo0mj8UsjW9zkKMlA,2589
26
- ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py,sha256=IuXJ6-A66Jiss-4jI7yMhg3QZRKFdc2GKBB8D52Wxvc,16473
26
+ ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py,sha256=h9ma18GUQHt88UIakd6QZHic822bAXzYokh6sfqAMZk,19410
27
27
  ibm_watsonx_orchestrate/agent_builder/tools/python_tool.py,sha256=FDY-y9jy4bNy88i7JG85Zj_YrxnPfJPD0DjwvL9ITxc,12012
28
- ibm_watsonx_orchestrate/agent_builder/tools/types.py,sha256=NIH0p-iqi6s0KmAjSnsGuMXnyW_gaob9Pi192vaCjYE,7998
28
+ ibm_watsonx_orchestrate/agent_builder/tools/types.py,sha256=SAyDEnWYuguTFk6WxgSDnMaONqDqcr6QhBAxD1u5FDU,8165
29
29
  ibm_watsonx_orchestrate/agent_builder/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
30
  ibm_watsonx_orchestrate/agent_builder/utils/pydantic_utils.py,sha256=QEanM6FpkmntvS02whdhWx1d4v6zT_1l9ipEbfTgHs8,7623
31
31
  ibm_watsonx_orchestrate/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -34,12 +34,12 @@ ibm_watsonx_orchestrate/cli/init_helper.py,sha256=qxnKdFcPtGsV_6RqP_IuLshRxgB004
34
34
  ibm_watsonx_orchestrate/cli/main.py,sha256=eE71dfx-EdDYHymYDqXcTjyMXpX0b3cueXOxCI2YLLs,3119
35
35
  ibm_watsonx_orchestrate/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  ibm_watsonx_orchestrate/cli/commands/agents/agents_command.py,sha256=Zif3bH3X7j5qf7MWGcr53mJ2oEKXNRHeg3ZHeoHTIqQ,8984
37
- ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py,sha256=skAElLfh8Ip4wVkxpn1wnLskHb1eLU1p9W7GF1abHus,47998
37
+ ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py,sha256=AvDZ3HSRFzaCQ00Kgu9IsOtq0Dv6HPv2E0o9IrisA7Y,47981
38
38
  ibm_watsonx_orchestrate/cli/commands/channels/channels_command.py,sha256=fVIFhPUTPdxsxIE10nWL-W5wvBR-BS8V8D6r__J8R98,822
39
39
  ibm_watsonx_orchestrate/cli/commands/channels/channels_controller.py,sha256=WjQxwJujvo28SsWgfJSXIpkcgniKcskJ2arL4MOz0Ys,455
40
- ibm_watsonx_orchestrate/cli/commands/channels/types.py,sha256=yX5hvnm_DBgcjdTzStXAtwT5dxIZDtPyq_Z38RhFTVc,483
40
+ ibm_watsonx_orchestrate/cli/commands/channels/types.py,sha256=hMFvWPr7tAmDrhBqtzfkCsrubX3lsU6lapTSOFsUbHM,475
41
41
  ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_command.py,sha256=vPCr6z1n1yzGDjTlM4f3_9MiuVRzNmXbvUifm6XyQi8,1103
42
- ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_controller.py,sha256=QkONhvadCyXrTSZECq5_RrE5Hze1yiBftOiEL-VLZUU,8583
42
+ ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_controller.py,sha256=CGfmKsCBX4E3HMZ8C0IXD-DHQNwe96V1Y_BxUZM2us0,8557
43
43
  ibm_watsonx_orchestrate/cli/commands/chat/chat_command.py,sha256=Q9vg2Z5Fsunu6GQFY_TIsNRhUCa0SSGSPnK4jxSGK34,1581
44
44
  ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py,sha256=bZBzaaVMFmGY4Guk-JCknZqd8HvXY5L-FirxpxddQfc,10497
45
45
  ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py,sha256=odsqxthEDyPO3C-GEtSn31sxLjRYgUBf1Vdkg6ZEwms,22290
@@ -49,15 +49,15 @@ ibm_watsonx_orchestrate/cli/commands/copilot/copilot_server_controller.py,sha256
49
49
  ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py,sha256=xwq7gdyjMtl2RYAnLAahGk2wDetr9BStt8yu7JkeBhk,3768
50
50
  ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py,sha256=oHZ7LONtPg3-SSnU_rRZryLi8N2mplz5h-LGg4XjzD4,10261
51
51
  ibm_watsonx_orchestrate/cli/commands/environment/types.py,sha256=X6jEnyBdxakromA7FhQ5btZMj9kwGcwRSFz8vpD65jA,224
52
- ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_command.py,sha256=1bgzMu1gF1dGKmi3bzIVR6twnUXSgTt-yc3M5_EVYDM,12065
52
+ ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_command.py,sha256=nOVxeZSTp1bfV_l_06B6x6wfNeusNAr5KImJYkwGWx8,14298
53
53
  ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_controller.py,sha256=dZEAD0rIS9DQjWD2-i6367RjNd2PWB3Fm_DDk25toBg,7855
54
54
  ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_command.py,sha256=hOzRcGVoqq7dTc4bSregKxH-kYbrVqaFdhBLawqnRNo,2668
55
55
  ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py,sha256=M19rRMFEEcAarPVw4fOr3S94Se1ZEo4hD7sCUr0xYTI,10115
56
56
  ibm_watsonx_orchestrate/cli/commands/login/login_command.py,sha256=xArMiojoozg7Exn6HTpbTcjDO2idZRA-y0WV-_Ic1Sk,651
57
57
  ibm_watsonx_orchestrate/cli/commands/models/model_provider_mapper.py,sha256=RVZfFCuPWiASkR9Mox61v5SZ1AoRxo4_g9stnbfjCkc,7994
58
58
  ibm_watsonx_orchestrate/cli/commands/models/models_command.py,sha256=PW-PIM5Nq0qdCopWjANGBWEuEoA3NLTFThYrN8ggGCI,6425
59
- ibm_watsonx_orchestrate/cli/commands/models/models_controller.py,sha256=BNfUoWST60x3k7yIvSbtBR3rmyTQmz9g0TDK2WOoOE4,18610
60
- ibm_watsonx_orchestrate/cli/commands/server/server_command.py,sha256=Tx5MbxH2MeMQ3GReI2FsESkZyefSwHlgkJjLniED2MU,39787
59
+ ibm_watsonx_orchestrate/cli/commands/models/models_controller.py,sha256=eZSYQUg9TL_-8lgcPVpKIx7MtOE7K_NCvZW9Y9YsFA0,18466
60
+ ibm_watsonx_orchestrate/cli/commands/server/server_command.py,sha256=ho1rSTN_fIJKeKzA5d4BdoQELl_4aF5Gzx90VySbaX8,39687
61
61
  ibm_watsonx_orchestrate/cli/commands/server/types.py,sha256=UCrgGErbSVBnOzesfjrIii4tTCuVfWemYz5AKGZX0oA,4213
62
62
  ibm_watsonx_orchestrate/cli/commands/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
63
  ibm_watsonx_orchestrate/cli/commands/settings/settings_command.py,sha256=CzXRkd-97jXyS6LtaaNtMah-aZu0919dYl-mDwzGThc,344
@@ -78,7 +78,7 @@ ibm_watsonx_orchestrate/client/client_errors.py,sha256=72MKCNZbKoo2QXyY0RicLhP3r
78
78
  ibm_watsonx_orchestrate/client/credentials.py,sha256=gDVeeQZDdbbjJiO1EI61yx2oRgTQctxA2ZesSDHI4DA,3786
79
79
  ibm_watsonx_orchestrate/client/local_service_instance.py,sha256=dt7vfLnjgt7mT8wSq8SJZndNTwsPzhb0XDhcnPUPFpU,3524
80
80
  ibm_watsonx_orchestrate/client/service_instance.py,sha256=fp3Lc4yQf4zTkxVS5WnIAkrHT0xG_a5i44qcLeQkaa4,6600
81
- ibm_watsonx_orchestrate/client/utils.py,sha256=_jP-qkOkjAIZ4yakQANKy0oaAOtUtfjrPP7cO-uPteU,5839
81
+ ibm_watsonx_orchestrate/client/utils.py,sha256=MUw11r0_wYv3RdF6-1BmSxcwYNF6q2_Urte7tMYTKVA,5836
82
82
  ibm_watsonx_orchestrate/client/agents/agent_client.py,sha256=v1ZqXKj3p5JeJyOLpV84UUI2LY8XPjW1ejo5yzkeiMQ,4708
83
83
  ibm_watsonx_orchestrate/client/agents/assistant_agent_client.py,sha256=1JQN0E4T_uz5V0LM-LD1ahNu2KCeFBjXAr8WCiP9mkE,1745
84
84
  ibm_watsonx_orchestrate/client/agents/external_agent_client.py,sha256=iQ44XBdC4rYfS-zFn4St1xC5y5gf5SNqKHzMNQcFDZc,1808
@@ -86,7 +86,7 @@ ibm_watsonx_orchestrate/client/analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
86
86
  ibm_watsonx_orchestrate/client/analytics/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
87
  ibm_watsonx_orchestrate/client/analytics/llm/analytics_llm_client.py,sha256=0YS_BCpmf5oGFawpZkJ38cuz5ArhKsZIbSydWRd194s,1340
88
88
  ibm_watsonx_orchestrate/client/connections/__init__.py,sha256=J7TOyVg38h71AlaJjlFs5fOuAXTceHvELtOJ9oz4Mvg,207
89
- ibm_watsonx_orchestrate/client/connections/connections_client.py,sha256=B6LQPwoFHg_CIXHEJBjVu6fXnRj_xVsLGsC-DhmdfSQ,8478
89
+ ibm_watsonx_orchestrate/client/connections/connections_client.py,sha256=8f_olWVgQVLi6xKO_DvV68zu_AMLe1DMhoQAhC-BG3g,7583
90
90
  ibm_watsonx_orchestrate/client/connections/utils.py,sha256=f6HsiDI6cycOqfYN6P4uZ3SQds83xlh83zTUioZPeYk,2618
91
91
  ibm_watsonx_orchestrate/client/copilot/cpe/copilot_cpe_client.py,sha256=eGE5VJb47XZxiMszBVQ7u0NKTVeHPuGVyfRJ6qPKlVs,1939
92
92
  ibm_watsonx_orchestrate/client/knowledge_bases/knowledge_base_client.py,sha256=YjC16dcL_l0jd-6yZ6uH8anlL4yaIv9f-7Y_urPuXWM,2201
@@ -97,8 +97,8 @@ ibm_watsonx_orchestrate/client/models/models_client.py,sha256=ZvP3iPgUFw_SXp41kJ
97
97
  ibm_watsonx_orchestrate/client/toolkit/toolkit_client.py,sha256=TLFNS39EeBD_t4Y-rX9sGp4sWBDr--mE5qVtHq8Q2hk,3121
98
98
  ibm_watsonx_orchestrate/client/tools/tempus_client.py,sha256=24fKDZUOVHBW-Vj4mubnpnUmab5LgGn8u5hOVyJaozI,1804
99
99
  ibm_watsonx_orchestrate/client/tools/tool_client.py,sha256=d3i3alVwa0TCN72w9sWOrM20GCbNmnpTnqEOJVbBIFM,1994
100
- ibm_watsonx_orchestrate/docker/compose-lite.yml,sha256=gn6BmT1xGlnmrufo4w6l-FmeyVaXcSjlDt40g4cx2fA,39432
101
- ibm_watsonx_orchestrate/docker/default.env,sha256=-yrzVhSP8lng5m6IqCDDGN32tul38gUCiNr-sismIM0,5828
100
+ ibm_watsonx_orchestrate/docker/compose-lite.yml,sha256=igtukwqVFamdaRbuAbrlLPU8EfZ7hpveWSA0Ka34YHo,39437
101
+ ibm_watsonx_orchestrate/docker/default.env,sha256=84p3BEFeA0mVe_C_WKMi4JLiOhQkFLq8hwI_Hoe1eWE,5894
102
102
  ibm_watsonx_orchestrate/docker/proxy-config-single.yaml,sha256=WEbK4ENFuTCYhzRu_QblWp1_GMARgZnx5vReQafkIG8,308
103
103
  ibm_watsonx_orchestrate/docker/start-up.sh,sha256=LTtwHp0AidVgjohis2LXGvZnkFQStOiUAxgGABOyeUI,1811
104
104
  ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0-py3-none-any.whl,sha256=Hi3-owh5OM0Jz2ihX9nLoojnr7Ky1TV-GelyqLcewLE,2047417
@@ -122,8 +122,8 @@ ibm_watsonx_orchestrate/utils/utils.py,sha256=U7z_2iASoFiZ2zM0a_2Mc2Y-P5oOT7hOwu
122
122
  ibm_watsonx_orchestrate/utils/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
123
123
  ibm_watsonx_orchestrate/utils/logging/logger.py,sha256=FzeGnidXAjC7yHrvIaj4KZPeaBBSCniZFlwgr5yV3oA,1037
124
124
  ibm_watsonx_orchestrate/utils/logging/logging.yaml,sha256=9_TKfuFr1barnOKP0fZT5D6MhddiwsXVTFjtRbcOO5w,314
125
- ibm_watsonx_orchestrate-1.8.0b1.dist-info/METADATA,sha256=3gAUVcjqPm5Ce9PAXrrhQ9A-0bjMCVYkCPpRP6V7xDs,1431
126
- ibm_watsonx_orchestrate-1.8.0b1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
127
- ibm_watsonx_orchestrate-1.8.0b1.dist-info/entry_points.txt,sha256=SfIT02-Jen5e99OcLhzbcM9Bdyf8SGVOCtnSplgZdQI,69
128
- ibm_watsonx_orchestrate-1.8.0b1.dist-info/licenses/LICENSE,sha256=Shgxx7hTdCOkiVRmfGgp_1ISISrwQD7m2f0y8Hsapl4,1083
129
- ibm_watsonx_orchestrate-1.8.0b1.dist-info/RECORD,,
125
+ ibm_watsonx_orchestrate-1.9.0b0.dist-info/METADATA,sha256=UJ2foCbjQAimZdumyE7BfggZo_iLLQGeNDZKWbtz5Po,1431
126
+ ibm_watsonx_orchestrate-1.9.0b0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
127
+ ibm_watsonx_orchestrate-1.9.0b0.dist-info/entry_points.txt,sha256=SfIT02-Jen5e99OcLhzbcM9Bdyf8SGVOCtnSplgZdQI,69
128
+ ibm_watsonx_orchestrate-1.9.0b0.dist-info/licenses/LICENSE,sha256=Shgxx7hTdCOkiVRmfGgp_1ISISrwQD7m2f0y8Hsapl4,1083
129
+ ibm_watsonx_orchestrate-1.9.0b0.dist-info/RECORD,,