-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathkubiya_bundle.json
More file actions
201 lines (201 loc) · 23.3 KB
/
kubiya_bundle.json
File metadata and controls
201 lines (201 loc) · 23.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
{
"tools": [
{
"name": "empty_req",
"source": null,
"alias": null,
"description": "Test empty req",
"type": "docker",
"content": "\n. .venv/bin/activate > /dev/null 2>&1\n\npython /tmp/main.py \n",
"content_url": null,
"args": [],
"env": [],
"secrets": [],
"dependencies": null,
"dependencies_url": null,
"openapi": null,
"with_files": [
{
"source": null,
"destination": "/tmp/main.py",
"content": "\nfrom typing import Annotated\n\nimport typer\n\napp = typer.Typer(rich_markup_mode=None, add_completion=False)\n\ndef empty_req():\n print(\"Works!!!\")\n\n\napp.command()(empty_req)\n\nif __name__ == \"__main__\":\n app()\n"
}
],
"with_services": [],
"with_git_repo": null,
"with_volumes": [],
"entrypoint": [],
"icon_url": null,
"image": "python:3.12-slim",
"image_provider": null,
"long_running": false,
"on_start": null,
"on_build": "\napt-get update && apt-get install -y curl > /dev/null 2>&1\n\ncurl -LsSf https://astral.sh/uv/0.4.27/install.sh | sh > /dev/null 2>&1\n\nexport PATH=\"/root/.cargo/bin/:$PATH\"\n\nuv venv > /dev/null 2>&1\n\n. .venv/bin/activate > /dev/null 2>&1\n\nuv pip install typer==0.12.5 > /dev/null 2>&1\n",
"on_complete": null,
"mermaid": "graph TD\n %% Styles\n classDef triggerClass fill:#3498db,color:#fff,stroke:#2980b9,stroke-width:2px,font-weight:bold\n classDef paramClass fill:#2ecc71,color:#fff,stroke:#27ae60,stroke-width:2px\n classDef execClass fill:#e74c3c,color:#fff,stroke:#c0392b,stroke-width:2px,font-weight:bold\n classDef envClass fill:#f39c12,color:#fff,stroke:#f1c40f,stroke-width:2px\n\n %% Main Components\n Trigger(\"Trigger\"):::triggerClass\n Params(\"Parameters\"):::paramClass\n Exec(\"empty_req\"):::execClass\n Env(\"Environment\"):::envClass\n\n %% Flow\n Trigger --> Params --> Exec\n Env --> Exec\n\n %% Trigger Options\n User(\"User\")\n API(\"API\")\n Webhook(\"Webhook\")\n Cron(\"Scheduled\")\n User --> Trigger\n API --> Trigger\n Webhook --> Trigger\n Cron --> Trigger\n\n %% Parameters\n subgraph Parameters[\"Parameters\"]\n direction TB\n end\n Parameters --- Params\n\n %% Execution\n subgraph Execution[\"Execution\"]\n direction TB\n Code(\"Script: <br/>. .venv/bin/activate > /dev/null 2>&1<br/><br/>python /tm...\")\n Type(\"Type: Docker\")\n Image(\"Docker Image: python:3.12-slim\")\n end\n Execution --- Exec\n\n %% Environment\n subgraph Environment[\"Environment\"]\n direction TB\n end\n Environment --- Env\n\n %% Context Note\n ContextNote(\"Parameter values can be<br/>fetched from context<br/>based on the trigger\")\n ContextNote -.-> Params",
"workflow": false,
"metadata": {}
},
{
"name": "litellm_hello_world",
"source": null,
"alias": null,
"description": "Greats a person via llm {name}!",
"type": "docker",
"content": "\n. .venv/bin/activate > /dev/null 2>&1\n\npython /tmp/main.py \"{{ .name }}\"\n",
"content_url": null,
"args": [
{
"name": "name",
"type": null,
"description": "Input param for arg: name, type: string",
"required": true,
"default": null,
"options": null,
"options_from": null
}
],
"env": [
"LLM_BASE_URL"
],
"secrets": [
"LLM_API_KEY"
],
"dependencies": null,
"dependencies_url": null,
"openapi": null,
"with_files": [
{
"source": null,
"destination": "/tmp/main.py",
"content": "\nfrom typing import Annotated\n\nimport typer\n\napp = typer.Typer(rich_markup_mode=None, add_completion=False)\n\ndef litellm_hello_world(\n name: str,\n):\n print(\"starting tool\")\n import os\n import litellm\n\n llm_key = os.environ[\"LLM_API_KEY\"]\n llm_base_url = os.environ[\"LLM_BASE_URL\"]\n\n try:\n response = litellm.completion(\n model=\"openai/gpt-4o\",\n api_key=llm_key,\n base_url=llm_base_url,\n messages=[\n {\n \"content\": f\"Your task it to great people in a random movie star way, you must say which movie star you choose\",\n \"role\": \"system\",\n },\n {\"content\": f\"My name is {name}, greet me!\", \"role\": \"user\"},\n ],\n )\n except Exception as e:\n print(e)\n print(\"tool ended with error\")\n return\n\n print(response.choices[0].message.content)\n print(\"tool ended successfully\")\n\n\napp.command()(litellm_hello_world)\n\nif __name__ == \"__main__\":\n app()\n"
}
],
"with_services": [],
"with_git_repo": null,
"with_volumes": [],
"entrypoint": [],
"icon_url": null,
"image": "python:3.12-slim",
"image_provider": null,
"long_running": false,
"on_start": null,
"on_build": "\napt-get update && apt-get install -y curl > /dev/null 2>&1\n\ncurl -LsSf https://astral.sh/uv/0.4.27/install.sh | sh > /dev/null 2>&1\n\nexport PATH=\"/root/.cargo/bin/:$PATH\"\n\nuv venv > /dev/null 2>&1\n\n. .venv/bin/activate > /dev/null 2>&1\n\nuv pip install litellm==1.49.4 typer==0.12.5 > /dev/null 2>&1\n",
"on_complete": null,
"mermaid": "graph TD\n %% Styles\n classDef triggerClass fill:#3498db,color:#fff,stroke:#2980b9,stroke-width:2px,font-weight:bold\n classDef paramClass fill:#2ecc71,color:#fff,stroke:#27ae60,stroke-width:2px\n classDef execClass fill:#e74c3c,color:#fff,stroke:#c0392b,stroke-width:2px,font-weight:bold\n classDef envClass fill:#f39c12,color:#fff,stroke:#f1c40f,stroke-width:2px\n\n %% Main Components\n Trigger(\"Trigger\"):::triggerClass\n Params(\"Parameters\"):::paramClass\n Exec(\"litellm_hello_world\"):::execClass\n Env(\"Environment\"):::envClass\n\n %% Flow\n Trigger --> Params --> Exec\n Env --> Exec\n\n %% Trigger Options\n User(\"User\")\n API(\"API\")\n Webhook(\"Webhook\")\n Cron(\"Scheduled\")\n User --> Trigger\n API --> Trigger\n Webhook --> Trigger\n Cron --> Trigger\n\n %% Parameters\n subgraph Parameters[\"Parameters\"]\n direction TB\n Param0(\"name (Required)<br/>Input param for arg: name, type: string\"):::paramClass\n end\n Parameters --- Params\n\n %% Execution\n subgraph Execution[\"Execution\"]\n direction TB\n Code(\"Script: <br/>. .venv/bin/activate > /dev/null 2>&1<br/><br/>python /tm...\")\n Type(\"Type: Docker\")\n Image(\"Docker Image: python:3.12-slim\")\n end\n Execution --- Exec\n\n %% Environment\n subgraph Environment[\"Environment\"]\n direction TB\n EnvVars(\"Environment Variables:<br/>LLM_BASE_URL\"):::envClass\n Secrets(\"Secrets:<br/>LLM_API_KEY\"):::envClass\n end\n Environment --- Env\n\n %% Context Note\n ContextNote(\"Parameter values can be<br/>fetched from context<br/>based on the trigger\")\n ContextNote -.-> Params",
"workflow": false,
"metadata": {}
},
{
"name": "slack_api_test",
"source": null,
"alias": null,
"description": "sends a message to a slack channel",
"type": "docker",
"content": "\n. .venv/bin/activate > /dev/null 2>&1\n\npython /tmp/main.py \"{{ .channel_id }}\" \"{{ .message }}\"\n",
"content_url": null,
"args": [
{
"name": "channel_id",
"type": null,
"description": "Input param for arg: channel_id, type: string",
"required": true,
"default": null,
"options": null,
"options_from": null
},
{
"name": "message",
"type": null,
"description": "Input param for arg: message, type: string",
"required": true,
"default": null,
"options": null,
"options_from": null
}
],
"env": [],
"secrets": [
"SLACK_API_TOKEN"
],
"dependencies": null,
"dependencies_url": null,
"openapi": null,
"with_files": [
{
"source": null,
"destination": "/tmp/main.py",
"content": "\nfrom typing import Annotated\n\nimport typer\n\napp = typer.Typer(rich_markup_mode=None, add_completion=False)\n\ndef slack_api_test(\n channel_id: str,\n message: str,\n):\n import os\n from slack_sdk import WebClient\n from slack_sdk.errors import SlackApiError\n\n # Initialize the client with your bot token\n token = os.environ[\"SLACK_API_TOKEN\"]\n client = WebClient(token=token)\n\n # Send a message\n try:\n client.chat_postMessage(\n channel=channel_id,\n text=message,\n )\n print(\"Message sent successfully\")\n except SlackApiError as e:\n print(f\"Error sending message: {e.response['error']}\")\n\n\napp.command()(slack_api_test)\n\nif __name__ == \"__main__\":\n app()\n"
}
],
"with_services": [],
"with_git_repo": null,
"with_volumes": [],
"entrypoint": [],
"icon_url": null,
"image": "python:3.12-slim",
"image_provider": null,
"long_running": false,
"on_start": null,
"on_build": "\napt-get update && apt-get install -y curl > /dev/null 2>&1\n\ncurl -LsSf https://astral.sh/uv/0.4.27/install.sh | sh > /dev/null 2>&1\n\nexport PATH=\"/root/.cargo/bin/:$PATH\"\n\nuv venv > /dev/null 2>&1\n\n. .venv/bin/activate > /dev/null 2>&1\n\nuv pip install slack-sdk==3.33.3 typer==0.12.5 > /dev/null 2>&1\n",
"on_complete": null,
"mermaid": "graph TD\n %% Styles\n classDef triggerClass fill:#3498db,color:#fff,stroke:#2980b9,stroke-width:2px,font-weight:bold\n classDef paramClass fill:#2ecc71,color:#fff,stroke:#27ae60,stroke-width:2px\n classDef execClass fill:#e74c3c,color:#fff,stroke:#c0392b,stroke-width:2px,font-weight:bold\n classDef envClass fill:#f39c12,color:#fff,stroke:#f1c40f,stroke-width:2px\n\n %% Main Components\n Trigger(\"Trigger\"):::triggerClass\n Params(\"Parameters\"):::paramClass\n Exec(\"slack_api_test\"):::execClass\n Env(\"Environment\"):::envClass\n\n %% Flow\n Trigger --> Params --> Exec\n Env --> Exec\n\n %% Trigger Options\n User(\"User\")\n API(\"API\")\n Webhook(\"Webhook\")\n Cron(\"Scheduled\")\n User --> Trigger\n API --> Trigger\n Webhook --> Trigger\n Cron --> Trigger\n\n %% Parameters\n subgraph Parameters[\"Parameters\"]\n direction TB\n Param0(\"channel_id (Required)<br/>Input param for arg: channel_id, type: string\"):::paramClass\n Param1(\"message (Required)<br/>Input param for arg: message, type: string\"):::paramClass\n end\n Parameters --- Params\n\n %% Execution\n subgraph Execution[\"Execution\"]\n direction TB\n Code(\"Script: <br/>. .venv/bin/activate > /dev/null 2>&1<br/><br/>python /tm...\")\n Type(\"Type: Docker\")\n Image(\"Docker Image: python:3.12-slim\")\n end\n Execution --- Exec\n\n %% Environment\n subgraph Environment[\"Environment\"]\n direction TB\n Secrets(\"Secrets:<br/>SLACK_API_TOKEN\"):::envClass\n end\n Environment --- Env\n\n %% Context Note\n ContextNote(\"Parameter values can be<br/>fetched from context<br/>based on the trigger\")\n ContextNote -.-> Params",
"workflow": false,
"metadata": {}
},
{
"name": "slack_knowledge",
"source": null,
"alias": null,
"description": "answers questions based on the slack channel history",
"type": "docker",
"content": "\n. .venv/bin/activate > /dev/null 2>&1\n\npython /tmp/main.py \n",
"content_url": null,
"args": [],
"env": [
"LLM_BASE_URL",
"SLACK_DOMAIN",
"KUBIYA_API_URL",
"KUBIYA_USER_ORG",
"SLACK_THREAD_TS",
"SLACK_CHANNEL_ID",
"KUBIYA_USER_EMAIL",
"KUBIYA_USER_MESSAGE",
"TEST_SLACK_CHANNEL_ID",
"TEST_SLACK_THREAD_TS"
],
"secrets": [
"LLM_API_KEY",
"KUBIYA_API_KEY",
"SLACK_API_TOKEN",
"TEST_SLACK_API_TOKEN"
],
"dependencies": null,
"dependencies_url": null,
"openapi": null,
"with_files": [
{
"source": null,
"destination": "/tmp/main.py",
"content": "\nfrom typing import Annotated\n\nimport typer\n\napp = typer.Typer(rich_markup_mode=None, add_completion=False)\n\ndef slack_knowledge():\n import os\n import json\n import litellm\n import requests\n\n from pydantic import BaseModel\n from slack_sdk import WebClient\n\n # TODO: remove this\n os.environ[\"SLACK_CHANNEL_ID\"] = os.environ[\"TEST_SLACK_CHANNEL_ID\"]\n os.environ[\"SLACK_THREAD_TS\"] = os.environ[\"TEST_SLACK_THREAD_TS\"]\n os.environ[\"SLACK_API_TOKEN\"] = os.environ[\"TEST_SLACK_API_TOKEN\"]\n\n class SlackMessage(BaseModel):\n ts: str\n user: str\n text: str\n thread_ts: str | None = None\n channel_id: str\n\n class SlackMessageKnowledgeMD(BaseModel):\n ts: str\n user: str\n channel_id: str\n thread_ts: str | None = None\n\n class SlackThreadedMessageKnowledge(BaseModel):\n content: str\n metadata: SlackMessageKnowledgeMD\n\n class SlackMessageKnowledge(BaseModel):\n content: str\n metadata: SlackMessageKnowledgeMD\n relevance: float\n thread: list[SlackThreadedMessageKnowledge]\n\n class ThreadResponse(BaseModel):\n answer: str | None = None\n question: str | None = None\n\n class AnswerReference(BaseModel):\n ts: str\n channel_id: str\n\n class Answer(BaseModel):\n content: str\n references: list[AnswerReference]\n\n def get_thread_messages(channel_id: str, ts: str) -> list[SlackMessage]:\n client = WebClient(token=os.environ[\"SLACK_API_TOKEN\"])\n response = client.conversations_replies(ts=ts, channel=channel_id, limit=100)\n\n return [SlackMessage(**m, channel_id=channel_id) for m in response[\"messages\"]]\n\n def remove_kubi_messages(\n messages: list[SlackMessageKnowledge],\n ) -> list[SlackMessageKnowledge]:\n filtered_messages = []\n for msg in messages:\n # Filter out kubi messages from the thread\n filtered_thread = []\n for thread_msg in msg.thread:\n if thread_msg.metadata.user != \"U07RN2DSPL7\":\n filtered_thread.append(thread_msg)\n \n # Create a new SlackMessageKnowledge with filtered thread\n filtered_msg = SlackMessageKnowledge(\n content=msg.content,\n metadata=msg.metadata,\n relevance=msg.relevance,\n thread=filtered_thread\n )\n filtered_messages.append(filtered_msg)\n \n return filtered_messages\n\n def format_slack_thread(messages: list[SlackMessage]):\n formatted = \"Message Thread:\\n\"\n for msg in messages:\n formatted_msg = f\"User: {msg.user} Text: {msg.text}\\n\"\n\n formatted += formatted_msg\n\n return formatted\n\n def format_slack_threads(messages: list[SlackMessageKnowledge]):\n formatted = []\n for msg in messages:\n main_content = msg.content.strip()\n metadata = msg.metadata\n channel_id = metadata.channel_id\n ts = metadata.ts\n\n formatted_msg = (\n f\"Main Message (relevance score: {msg.relevance}):\\n\"\n f\"{main_content}\\n\"\n f\"(channel_id: {channel_id}, ts: {ts})\"\n )\n\n thread_replies = msg.thread\n if thread_replies:\n formatted_msg += \"\\n\\nThread Replies:\"\n for reply in thread_replies:\n reply_content = reply.content.strip()\n reply_channel_id = reply.metadata.channel_id\n reply_ts = reply.metadata.ts\n formatted_msg += (\n f\"\\n - {reply_content} \"\n f\"(Channel ID: {reply_channel_id}, Timestamp: {reply_ts})\"\n )\n\n formatted.append(formatted_msg)\n\n return \"\\n\\n---\\n\\n\".join(formatted)\n\n def query_rag(query: str, channel_id: str) -> list[SlackMessageKnowledge]:\n kubiya_api_url = os.environ[\"KUBIYA_API_URL\"]\n payload = {\n \"threshold\": 0.55,\n \"query\": query,\n \"channel_id\": channel_id,\n }\n headers = {\n \"Authorization\": f\"UserKey {os.environ['KUBIYA_API_KEY']}\",\n }\n result = requests.post(\n f\"{kubiya_api_url}/api/v1/rag/query/slack\", json=payload, headers=headers\n )\n result.raise_for_status()\n\n return [SlackMessageKnowledge(**msg) for msg in result.json()]\n\n def pretty_print_answer(answer: Answer):\n slack_domain = os.environ[\"SLACK_DOMAIN\"]\n print(f\"Answer: {answer.content}\")\n print(\"\\n References:\")\n for ref in answer.references:\n print(\n f\" - https://{slack_domain}.slack.com/archives/{ref.channel_id}/p{ref.ts}\"\n )\n\n llm_key = os.environ[\"LLM_API_KEY\"]\n llm_base_url = os.environ[\"LLM_BASE_URL\"]\n\n try:\n thread_messages = get_thread_messages(\n os.environ[\"SLACK_CHANNEL_ID\"], os.environ[\"SLACK_THREAD_TS\"]\n )\n thread_context = format_slack_thread(thread_messages)\n response = litellm.completion(\n model=\"openai/gpt-4o\",\n api_key=llm_key,\n base_url=llm_base_url,\n response_format=ThreadResponse,\n messages=[\n {\n \"content\": \"\"\"\nExtract the most relevant user question from the thread to search a knowledge base.\n\t•\tIf the users latest message is a question, return it.\n\t•\tIf not, return the most recent user question from the thread.\n\t•\tIf the thread already contains an answer to that question, return the answer instead.\n\"\"\",\n \"role\": \"system\",\n },\n {\n \"content\": f\"Thread context: {thread_context}\\n\\nUser message: {os.environ['KUBIYA_USER_MESSAGE']}\",\n \"role\": \"user\",\n },\n ],\n )\n\n thread_res = ThreadResponse(**json.loads(response.choices[0].message.content))\n\n if thread_res.answer:\n print(f\"Answer (based on the thread): {thread_res.answer}\")\n return\n\n if not thread_res.question:\n print(\"Question could not be extracted from the thread\")\n return\n\n result = query_rag(thread_res.question, os.environ[\"SLACK_CHANNEL_ID\"])\n\n if not result:\n print(\"No relevant information found in the knowledge base\")\n return\n\n result = remove_kubi_messages(result)\n has_thread = False\n for msg in result:\n if len(msg.thread) > 0:\n has_thread = True\n\n if has_thread is False:\n print(\"No thread messages found for relevant answers\")\n return\n\n formated_result = format_slack_threads(result)\n\n response = litellm.completion(\n model=\"openai/gpt-4o\",\n api_key=llm_key,\n base_url=llm_base_url,\n response_format=Answer,\n messages=[\n {\n \"content\": \"\"\"\nYou are a helpful assistant that can answer questions based on the provided knowledge base ONLY. You are given a query and a result from a knowledge base. You need to answer the query based on the result.\nKeep your response concise and to the point. Answer and cite answers from the knowledge base BUT make sure they are in an answer format.\n \"\"\",\n \"role\": \"system\",\n },\n {\n \"content\": f\"question: {thread_res.question}\\n\\v knowledge base:\\n{formated_result}\",\n \"role\": \"user\",\n },\n ],\n )\n answer = Answer(**json.loads(response.choices[0].message.content))\n\n pretty_print_answer(answer)\n\n except Exception as e:\n print(e)\n print(\"tool ended with error\")\n exit(1)\n\n\napp.command()(slack_knowledge)\n\nif __name__ == \"__main__\":\n app()\n"
}
],
"with_services": [],
"with_git_repo": null,
"with_volumes": [],
"entrypoint": [],
"icon_url": null,
"image": "python:3.12-slim",
"image_provider": null,
"long_running": false,
"on_start": null,
"on_build": "\napt-get update && apt-get install -y curl > /dev/null 2>&1\n\ncurl -LsSf https://astral.sh/uv/0.4.27/install.sh | sh > /dev/null 2>&1\n\nexport PATH=\"/root/.cargo/bin/:$PATH\"\n\nuv venv > /dev/null 2>&1\n\n. .venv/bin/activate > /dev/null 2>&1\n\nuv pip install litellm==1.71.1 requests==2.32.3 pydantic==2.11.5 slack-sdk==3.35.0 typer==0.12.5 > /dev/null 2>&1\n",
"on_complete": null,
"mermaid": "graph TD\n %% Styles\n classDef triggerClass fill:#3498db,color:#fff,stroke:#2980b9,stroke-width:2px,font-weight:bold\n classDef paramClass fill:#2ecc71,color:#fff,stroke:#27ae60,stroke-width:2px\n classDef execClass fill:#e74c3c,color:#fff,stroke:#c0392b,stroke-width:2px,font-weight:bold\n classDef envClass fill:#f39c12,color:#fff,stroke:#f1c40f,stroke-width:2px\n\n %% Main Components\n Trigger(\"Trigger\"):::triggerClass\n Params(\"Parameters\"):::paramClass\n Exec(\"slack_knowledge\"):::execClass\n Env(\"Environment\"):::envClass\n\n %% Flow\n Trigger --> Params --> Exec\n Env --> Exec\n\n %% Trigger Options\n User(\"User\")\n API(\"API\")\n Webhook(\"Webhook\")\n Cron(\"Scheduled\")\n User --> Trigger\n API --> Trigger\n Webhook --> Trigger\n Cron --> Trigger\n\n %% Parameters\n subgraph Parameters[\"Parameters\"]\n direction TB\n end\n Parameters --- Params\n\n %% Execution\n subgraph Execution[\"Execution\"]\n direction TB\n Code(\"Script: <br/>. .venv/bin/activate > /dev/null 2>&1<br/><br/>python /tm...\")\n Type(\"Type: Docker\")\n Image(\"Docker Image: python:3.12-slim\")\n end\n Execution --- Exec\n\n %% Environment\n subgraph Environment[\"Environment\"]\n direction TB\n EnvVars(\"Environment Variables:<br/>LLM_BASE_URL<br/>SLACK_DOMAIN<br/>KUBIYA_API_URL<br/>KUBIYA_USER_ORG<br/>SLACK_THREAD_TS<br/>SLACK_CHANNEL_ID<br/>KUBIYA_USER_EMAIL<br/>KUBIYA_USER_MESSAGE<br/>TEST_SLACK_CHANNEL_ID<br/>TEST_SLACK_THREAD_TS\"):::envClass\n Secrets(\"Secrets:<br/>LLM_API_KEY<br/>KUBIYA_API_KEY<br/>SLACK_API_TOKEN<br/>TEST_SLACK_API_TOKEN\"):::envClass\n end\n Environment --- Env\n\n %% Context Note\n ContextNote(\"Parameter values can be<br/>fetched from context<br/>based on the trigger\")\n ContextNote -.-> Params",
"workflow": false,
"metadata": {}
}
],
"errors": [],
"python_bundle_version": "3.11.9"
}