This is an automated email from the ASF dual-hosted git repository.

bobbai00 pushed a commit to branch release/v1.1.0-incubating
in repository https://gitbox.apache.org/repos/asf/texera.git


The following commit(s) were added to refs/heads/release/v1.1.0-incubating by 
this push:
     new 14051c4d4e feat(deployment, v1.1.0-incubating): add agent-service and 
litellm to single-node deployment (#4592)
14051c4d4e is described below

commit 14051c4d4eab41f777886fea08f1f565714c18f6
Author: Jiadong Bai <[email protected]>
AuthorDate: Thu Apr 30 23:09:34 2026 -0700

    feat(deployment, v1.1.0-incubating): add agent-service and litellm to 
single-node deployment (#4592)
    
    ### What changes were proposed in this PR?
    
    Backport of #4544.
    
    ### Any related issues, documentation, discussions?
    
    
    ### How was this PR tested?
    
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
    Co-authored-by: Xinyuan Lin <[email protected]>
    Co-authored-by: Chen Li <[email protected]>
---
 .github/workflows/build-and-push-images.yml |  3 ++
 bin/agent-service.dockerfile                | 36 +++++++++++++++
 bin/single-node/.env                        | 14 ++++++
 bin/single-node/README.md                   | 71 +++++++++++++++++++++++++++--
 bin/single-node/docker-compose.yml          | 46 ++++++++++++++++++-
 bin/single-node/litellm-config.yaml         | 29 ++++++++++++
 bin/single-node/nginx.conf                  | 27 +++++++++++
 7 files changed, 219 insertions(+), 7 deletions(-)

diff --git a/.github/workflows/build-and-push-images.yml 
b/.github/workflows/build-and-push-images.yml
index b63743ec2c..d6688336b8 100644
--- a/.github/workflows/build-and-push-images.yml
+++ b/.github/workflows/build-and-push-images.yml
@@ -276,6 +276,9 @@ jobs:
                 "workflow-computing-unit-managing-service")
                   image_name="texera-workflow-computing-unit-managing-service"
                   ;;
+                "agent-service")
+                  image_name="texera-agent-service"
+                  ;;
                 *)
                   # Default: use service name as-is
                   image_name="$service"
diff --git a/bin/agent-service.dockerfile b/bin/agent-service.dockerfile
new file mode 100644
index 0000000000..e0f6c0c232
--- /dev/null
+++ b/bin/agent-service.dockerfile
@@ -0,0 +1,36 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+FROM oven/bun:1-alpine
+
+WORKDIR /app
+
+COPY agent-service/package.json agent-service/bun.lock ./
+
+RUN bun install --frozen-lockfile --production
+
+COPY agent-service/src ./src
+COPY agent-service/tsconfig.json ./
+
+COPY LICENSE-binary ./LICENSE
+COPY NOTICE-binary ./NOTICE
+COPY DISCLAIMER-WIP ./DISCLAIMER-WIP
+COPY licenses ./licenses
+
+EXPOSE 3001
+
+CMD ["bun", "run", "src/server.ts"]
diff --git a/bin/single-node/.env b/bin/single-node/.env
index dafec10ccc..54aa2f5b32 100644
--- a/bin/single-node/.env
+++ b/bin/single-node/.env
@@ -83,3 +83,17 @@ STORAGE_ICEBERG_CATALOG_POSTGRES_PASSWORD=password
 # File service endpoints
 
FILE_SERVICE_GET_PRESIGNED_URL_ENDPOINT=http://file-service:9092/api/dataset/presign-download
 
FILE_SERVICE_UPLOAD_ONE_FILE_TO_DATASET_ENDPOINT=http://file-service:9092/api/dataset/did/upload
+
+# Toggles the texera agent panel; set false to hide it in the GUI.
+GUI_WORKFLOW_WORKSPACE_COPILOT_ENABLED=true
+
+# Litellm key and URL for internal LLM traffic
+LITELLM_MASTER_KEY=sk-texera-internal-do-not-share
+LITELLM_BASE_URL=http://litellm:4000
+
+# Configurations for agent-service to connect to Texera's services
+LLM_ENDPOINT=http://nginx:8080
+LLM_API_KEY=dummy
+TEXERA_DASHBOARD_SERVICE_ENDPOINT=http://dashboard-service:8080
+WORKFLOW_COMPILING_SERVICE_ENDPOINT=http://workflow-compiling-service:9090
+WORKFLOW_EXECUTION_SERVICE_ENDPOINT=http://workflow-runtime-coordinator-service:8085
diff --git a/bin/single-node/README.md b/bin/single-node/README.md
index 605801f216..fd45b068c4 100644
--- a/bin/single-node/README.md
+++ b/bin/single-node/README.md
@@ -88,7 +88,7 @@ Press `Ctrl+C` in the terminal to stop Texera.
 
 If you already closed the terminal, you can go to the installation folder and 
run:
 ```bash
-docker compose stop
+docker compose --profile examples stop
 ```
 to stop Texera.
 
@@ -98,11 +98,33 @@ Same as the way you [launch Texera](#launch-texera).
 ### Uninstall
 To remove Texera and all its data, go to the installation folder and run:
 ```bash
-docker compose down -v
+docker compose --profile examples down -v
 ```
 > ⚠️ Warning: This will permanently delete all the data used by Texera.
 
 
+## Enable the Texera Agent
+
+The Texera agent is powered by a large language model (LLM). By default, 
Texera uses [Claude Haiku 4.5](https://www.anthropic.com/claude/haiku) as the 
LLM and queries it through [LiteLLM](https://docs.litellm.ai/). Without an API 
key, the Texera agent panel still appears but model calls will fail with a 
provider auth error.
+
+To enable it:
+
+1. [Stop Texera](#stop) if it is already running.
+2. Get an API key for the LLM. Since Claude Haiku 4.5 is enabled by default, 
you need an [Anthropic API key](https://console.anthropic.com/settings/keys).
+3. Export the key and restart Texera:
+   ```bash
+   export ANTHROPIC_API_KEY=sk-ant-...
+   docker compose --profile examples up
+   ```
+
+Once Texera is up, create a new workflow and open the Texera agent panel at 
the bottom right. Type a task like:
+
+> For /texera/popular-movies-of-imdb/v1/TMDb_updated.csv, visualize the top 10 
most-voted movies.
+
+To switch providers or add more LLMs, see [Add more LLMs or 
providers](#add-more-llms-or-providers).
+
+
+
 ## Advanced Settings
 
 Before making any of the changes below, please [stop Texera](#stop) first. 
Once you finish the changes, [restart Texera](#restart) to apply them.
@@ -146,6 +168,45 @@ $ docker compose up
 y // answer y to this prompt
 ```
 
+### Add more LLMs or providers
+Only Claude Haiku 4.5 is enabled by default. To add more LLMs, open 
`litellm-config.yaml` in the installation folder and append entries under 
`model_list`. Each entry follows this shape:
+```diff
+  model_list:
+    ...
++   - model_name: <name shown in Texera>
++     litellm_params:
++       model: <provider model id>
++       api_key: "os.environ/<API_KEY_ENV_VAR>"
+```
+For example, to add OpenAI's GPT-5.2 and Google's Gemini 2.5 Pro:
+```diff
+  model_list:
+    ...
++   - model_name: gpt-5.2
++     litellm_params:
++       model: gpt-5.2
++       api_key: "os.environ/OPENAI_API_KEY"
++
++   - model_name: gemini-2.5-pro
++     litellm_params:
++       model: gemini/gemini-2.5-pro
++       api_key: "os.environ/GEMINI_API_KEY"
+```
+Make sure to set the corresponding API key environment variable when you 
launch Texera (see [Enable the Texera Agent](#enable-the-texera-agent)). Get 
keys from each provider's console — for example, 
[OpenAI](https://platform.openai.com/api-keys) or 
[Google](https://aistudio.google.com/apikey).
+
+If your provider is not Anthropic, OpenAI, or Google, also pass its key into 
the LiteLLM container by editing `docker-compose.yml`:
+```diff
+  litellm:
+    ...
+    environment:
+      ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
+      OPENAI_API_KEY: ${OPENAI_API_KEY:-}
+      GEMINI_API_KEY: ${GEMINI_API_KEY:-}
++     <NEW_API_KEY>: ${<NEW_API_KEY>:-}
+```
+
+For the full list of supported providers and model IDs, see the [LiteLLM proxy 
config docs](https://docs.litellm.ai/docs/providers).
+
 ## Troubleshooting
 
 ### Port conflicts
@@ -166,8 +227,8 @@ PostgreSQL only runs the database initialization scripts on 
first startup (when
 To resolve this, remove all existing volumes and start fresh:
 
 ```
-docker compose down -v
-docker compose up
+docker compose --profile examples down -v
+docker compose --profile examples up
 ```
 
-> ⚠️ Warning: `docker compose down -v` permanently deletes all Texera data.
+> ⚠️ Warning: `docker compose --profile examples down -v` permanently deletes 
all Texera data.
diff --git a/bin/single-node/docker-compose.yml 
b/bin/single-node/docker-compose.yml
index 4329bb3e71..e26fe8aa95 100644
--- a/bin/single-node/docker-compose.yml
+++ b/bin/single-node/docker-compose.yml
@@ -299,7 +299,7 @@ services:
       timeout: 3s
       retries: 10
 
-  # AccessControlService handles user permissions and access control
+  # AccessControlService handles user permissions and proxies LLM API traffic
   access-control-service:
     image: 
${IMAGE_REGISTRY:-ghcr.io/apache}/texera-access-control-service:${IMAGE_TAG:-latest}
     container_name: access-control-service
@@ -364,7 +364,7 @@ services:
     volumes:
       - workflow_result_data:/amber/user-resources
 
-  # DashboardService provides endpoints for hub resource management.
+  # DashboardService provides endpoints for community resource (e.g. 
workflows, users) management
   dashboard-service:
     image: 
${IMAGE_REGISTRY:-ghcr.io/apache}/texera-dashboard-service:${IMAGE_TAG:-latest}
     container_name: dashboard-service
@@ -386,6 +386,47 @@ services:
       timeout: 3s
       retries: 10
 
+  # LLM API proxy for different providers
+  litellm:
+    image: ghcr.io/berriai/litellm:v1.83.10-stable
+    container_name: litellm
+    restart: always
+    # Keys read from shell first, falling back to .env.
+    environment:
+      ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
+      OPENAI_API_KEY: ${OPENAI_API_KEY:-}
+      GEMINI_API_KEY: ${GEMINI_API_KEY:-}
+      LITELLM_MASTER_KEY: ${LITELLM_MASTER_KEY:-}
+    volumes:
+      - ./litellm-config.yaml:/app/config.yaml:ro
+    command: ["--config", "/app/config.yaml", "--port", "4000", "--host", 
"0.0.0.0"]
+    healthcheck:
+      test: ["CMD", "python", "-c", "import urllib.request; 
urllib.request.urlopen('http://localhost:4000/health/liveliness').read()"]
+      interval: 10s
+      timeout: 5s
+      retries: 10
+      start_period: 15s
+
+  # AgentService manages the texera agents' interal states, and provide 
endpoints for CRUD agents
+  agent-service:
+    image: 
${IMAGE_REGISTRY:-ghcr.io/apache}/texera-agent-service:${IMAGE_TAG:-latest}
+    container_name: agent-service
+    restart: always
+    depends_on:
+      dashboard-service:
+        condition: service_healthy
+      workflow-compiling-service:
+        condition: service_healthy
+      workflow-runtime-coordinator-service:
+        condition: service_started
+    env_file:
+      - .env
+    healthcheck:
+      test: ["CMD", "wget", "--spider", "-q", 
"http://localhost:3001/api/healthcheck";]
+      interval: 5s
+      timeout: 3s
+      retries: 10
+
   # Part 3: reverse proxy service for Texera's micro services
   nginx:
     image: nginx:alpine
@@ -398,6 +439,7 @@ services:
       - config-service
       - access-control-service
       - workflow-computing-unit-managing-service
+      - agent-service
     volumes:
       - ./nginx.conf:/etc/nginx/nginx.conf:ro
     ports:
diff --git a/bin/single-node/litellm-config.yaml 
b/bin/single-node/litellm-config.yaml
new file mode 100644
index 0000000000..1a4ff14a4c
--- /dev/null
+++ b/bin/single-node/litellm-config.yaml
@@ -0,0 +1,29 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# LiteLLM model list for the single-node deployment. API keys are read
+# from environment variables passed to the container. To add more
+# models, follow the same shape — see 
https://docs.litellm.ai/docs/proxy/configs.
+
+litellm_settings:
+  drop_params: true
+
+model_list:
+  - model_name: claude-haiku-4.5
+    litellm_params:
+      model: claude-haiku-4-5-20251001
+      api_key: "os.environ/ANTHROPIC_API_KEY"
diff --git a/bin/single-node/nginx.conf b/bin/single-node/nginx.conf
index 7ab4295a2b..515a7016da 100644
--- a/bin/single-node/nginx.conf
+++ b/bin/single-node/nginx.conf
@@ -21,6 +21,9 @@ http {
     include       mime.types;
     default_type  application/octet-stream;
 
+    # Suppress per-request access logs; errors still go to error_log.
+    access_log off;
+
     server {
         listen 8080;
 
@@ -54,6 +57,30 @@ http {
             proxy_set_header X-Real-IP $remote_addr;
         }
 
+        # LLM API traffic goes through access-control-service, which then 
forwards to LiteLLM.
+        location = /api/models {
+            proxy_pass http://access-control-service:9096;
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+        }
+
+        location /api/chat/ {
+            proxy_pass http://access-control-service:9096;
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+        }
+
+        location /api/agents {
+            proxy_pass http://agent-service:3001;
+            proxy_http_version 1.1;
+            proxy_set_header Upgrade $http_upgrade;
+            proxy_set_header Connection "upgrade";
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+            proxy_read_timeout 1d;
+            proxy_send_timeout 1d;
+        }
+
         location /api/ {
             proxy_pass http://dashboard-service:8080;
             proxy_set_header Host $host;

Reply via email to