Skip to content

Commit e530dea

Browse files
authored
Merge pull request #26 from red-hat-data-services/add-langflow-template
feat: add Langflow simple tool calling agent template
2 parents 72c0a29 + 1d2a0dc commit e530dea

8 files changed

Lines changed: 2775 additions & 0 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ config.toml
1313
milvus_data/
1414
*.egg-info/
1515
uv.lock
16+
agents/langflow/simple_tool_calling_agent/local/.ollama-enabled
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
<div style="text-align: center;">
2+
3+
# Langflow Simple Tool Calling Agent
4+
5+
</div>
6+
7+
---
8+
9+
## What this agent does
10+
11+
Outdoor activity planning agent built with Langflow. It recommends the best day and time for outdoor activities by reasoning across weather forecasts, air quality, and National Park Service data.
12+
13+
**Example query:** *"I want to go hiking near Denver this weekend. What day is best?"*
14+
15+
### Tools
16+
| Tool | API | Description |
17+
|------|-----|-------------|
18+
| Open-Meteo Forecast | Open-Meteo | Daily weather forecast (temp, wind, precipitation, UV) |
19+
| NPS Search Parks | NPS API | Search national parks by state |
20+
| NPS Park Alerts | NPS API | Active alerts and closures for a park |
21+
22+
---
23+
24+
## Run locally
25+
26+
### Prerequisites
27+
28+
- **Podman** + **podman-compose** installed
29+
30+
**macOS:**
31+
```bash
32+
brew install podman # install podman runtime
33+
brew install podman-compose # install compose plugin
34+
podman machine init # create a Linux VM (podman runs containers in a VM on macOS)
35+
podman machine start # start the VM
36+
```
37+
38+
**Linux:**
39+
```bash
40+
sudo dnf install -y podman # install podman runtime
41+
pip install podman-compose # install compose plugin
42+
sudo systemctl start podman # start the podman service
43+
```
44+
45+
### Start the local stack
46+
47+
```bash
48+
cd agents/langflow/simple_tool_calling_agent
49+
chmod +x deploy-local.sh cleanup-local.sh
50+
./deploy-local.sh
51+
```
52+
53+
This starts:
54+
- **Langflow** on http://localhost:7860 — the agent UI
55+
- **PostgreSQL** — shared database server. Hosts two databases: `langflow` (flows, users, settings) and `langfuse` (traces). The `langflow` database is created automatically by PostgreSQL; the `langfuse` database is created by `local/init-db.sh` on first startup
56+
- **Ollama** on http://localhost:11434 — local LLM (qwen2.5:7b), runs natively on host for GPU acceleration
57+
- **Langfuse v2** on http://localhost:3000 — tracing (admin@langflow.local / admin123)
58+
59+
### Import and configure the flow
60+
61+
1. Open http://localhost:7860
62+
2. On first launch, Langflow asks you to create a flow — create a **Blank Flow** (this is just to get past the initial screen)
63+
3. Click the **Langflow icon** (top left) to go to the projects page
64+
4. Click **Upload Flow** and select `flows/outdoor-activity-agent.json`
65+
5. Configure the flow components:
66+
67+
| Component | Field | Value |
68+
|-----------|-------|-------|
69+
| KServe vLLM | api_base | http://host.containers.internal:11434/v1 |
70+
| KServe vLLM | model_name | qwen2.5:7b |
71+
| KServe vLLM | api_key | dummy |
72+
| NPS Search Parks | api_key | Get one free at https://developer.nps.gov |
73+
| NPS Park Alerts | api_key | Same NPS key as above |
74+
6. Run the agent from the Langflow UI
75+
76+
> **Note:** Ollama runs natively on your machine (not in a container) to leverage GPU acceleration. On Apple Silicon Macs, this uses Metal for faster inference. Response times vary by hardware — expect 30 seconds to a few minutes per tool call. For faster responses, point the agent to a GPU-backed cluster endpoint (see [Remote model](#remote-model-instead-of-ollama)).
77+
78+
### Query the agent via API
79+
80+
Once the flow is running, you can query it via the Langflow API:
81+
82+
```bash
83+
curl -X POST http://localhost:7860/api/v1/run/<flow-id> \
84+
-H "Content-Type: application/json" \
85+
-d '{"input_value": "What is the best day to hike near Denver?", "output_type": "chat", "input_type": "chat"}'
86+
```
87+
88+
Replace `<flow-id>` with the flow ID from the Langflow UI. You can find it in the browser URL bar when you open the flow — e.g., `http://localhost:7860/flow/27e7203d-b2b1-4700-962a-144a66155f14` → the flow ID is `27e7203d-b2b1-4700-962a-144a66155f14`.
89+
90+
On the cluster, replace `localhost:7860` with your cluster's Langflow route URL.
91+
92+
### Stop the local stack
93+
94+
```bash
95+
./cleanup-local.sh # stop services, keep data
96+
./cleanup-local.sh --force # stop services, remove all data
97+
```
98+
99+
**What gets preserved vs wiped:**
100+
101+
| Data | `cleanup-local.sh` | `cleanup-local.sh --force` |
102+
|------|---------------------|----------------------------|
103+
| Downloaded Ollama models (e.g., qwen2.5:7b) | Kept | Kept (stored on host, not in containers) |
104+
| Imported Langflow flows | Kept | **Deleted** (re-import needed) |
105+
| Langfuse traces | Kept | **Deleted** |
106+
| PostgreSQL data | Kept | **Deleted** |
107+
| `.env` and `.ollama-enabled` config | Kept | **Deleted** |
108+
109+
---
110+
111+
## Deploy to cluster
112+
113+
There is nothing to build or deploy — no Dockerfiles, no Helm charts, no k8s manifests. This agent assumes Langflow, Langfuse, and an LLM (LlamaStack/KServe) are already running on the cluster. You just import the flow JSON into the existing Langflow instance and configure it.
114+
115+
### Finding cluster endpoints
116+
117+
Reach out to your cluster admin for the Langflow URL and LlamaStack endpoint/model names. However, if you have `oc` CLI access, you can find them yourself:
118+
119+
```bash
120+
# Langflow UI URL
121+
oc get routes --all-namespaces | grep langflow
122+
123+
# LlamaStack URL
124+
oc get routes --all-namespaces | grep llama
125+
126+
# KServe model (internal endpoint + model name)
127+
oc get inferenceservice --all-namespaces
128+
```
129+
130+
### Steps
131+
132+
1. Open the Langflow UI on your cluster
133+
2. Import `flows/outdoor-activity-agent.json`
134+
3. Configure the flow components:
135+
- **KServe vLLM**: set `api_base` and `model_name`. You can connect through LlamaStack or directly to KServe:
136+
137+
| Option | api_base | model_name |
138+
|--------|----------|------------|
139+
| Via LlamaStack (external route) | https://\<llamastack-route-host\>/v1 | vllm//mnt/models |
140+
| Via LlamaStack (internal) | http://llamastack-service.\<namespace\>.svc.cluster.local:8321/v1 | vllm//mnt/models |
141+
| Direct to KServe (internal) | http://\<model\>-predictor.\<namespace\>.svc.cluster.local:8080/v1 | /mnt/models |
142+
143+
Use the external route if Langflow can't reach LlamaStack internally (network policy). Use `oc get routes` and `oc get inferenceservice` to find the actual hostnames and namespaces.
144+
- **NPS Search Parks**: set `api_key` (get one free at https://developer.nps.gov)
145+
- **NPS Park Alerts**: set `api_key` (same NPS key)
146+
4. Run the agent
147+
148+
149+
---
150+
151+
## Pointing agent to different models
152+
153+
### Local model (Ollama)
154+
155+
By default, the local stack runs **qwen2.5:7b** on Ollama. After importing the flow, set these values in the **KServe vLLM** component:
156+
157+
| Field | Value |
158+
|-------|-------|
159+
| api_base | http://host.containers.internal:11434/v1 |
160+
| model_name | qwen2.5:7b |
161+
| api_key | dummy |
162+
163+
> Ollama runs natively on your host machine (not in a container) for GPU acceleration. Use `host.containers.internal` so containerized Langflow can reach it. Ollama doesn't require authentication, so api_key can be any non-empty string (e.g., dummy).
164+
165+
If you want to use a different model:
166+
167+
1. Pull the model on Ollama:
168+
```bash
169+
ollama pull <model-name>
170+
```
171+
Or edit `local/.env` to change the default model and restart:
172+
```
173+
OLLAMA_MODEL=llama3.1:8b
174+
```
175+
Then: `./cleanup-local.sh && ./deploy-local.sh`
176+
177+
2. Update the **KServe vLLM** component in the Langflow UI:
178+
179+
| Field | Value |
180+
|-------|-------|
181+
| api_base | http://host.containers.internal:11434/v1 |
182+
| model_name | your-model-name |
183+
184+
> **Note:** Make sure you have enough CPU/GPU resources locally to run the model. Also, not all models handle tool calling well — for example, smaller models like Llama 3.2 1B may fail at tool calling, causing connection errors when the agent tries to invoke tools. Models like `qwen2.5:7b` and `llama3.1:8b` are known to work well with tool calling.
185+
186+
### Remote model (instead of Ollama)
187+
188+
If you primarily work with a remote model endpoint, or don't have enough local CPU/GPU resources to host a model, you can skip installing Ollama entirely by answering **n** when prompted by `deploy-local.sh`.
189+
190+
Then update the **KServe vLLM** component in the Langflow UI to point to your remote endpoint:
191+
192+
| Field | Value |
193+
|-------|-------|
194+
| api_base | your-model-endpoint/v1 |
195+
| model_name | your-model-id |
196+
| api_key | your-api-key |
197+
198+
---
199+
200+
## Viewing traces in Langfuse
201+
202+
After running the agent, traces are automatically sent to Langfuse.
203+
204+
**Locally:**
205+
1. Open http://localhost:3000 (login: admin@langflow.local / admin123)
206+
2. Select the **Langflow Agent** project
207+
3. Click **Traces** in the left sidebar
208+
4. Click on any trace to see the full agent execution — LLM calls, tool invocations, inputs, and outputs
209+
210+
**On cluster:**
211+
1. Open the Langfuse route on your cluster
212+
2. Select the **Langflow Agent** project
213+
3. Click **Traces** in the left sidebar
214+
215+
---
216+
217+
## Exporting flows
218+
219+
When exporting a flow from Langflow, API keys and secrets can be embedded in the exported JSON file. To avoid leaking secrets:
220+
221+
1. In the export dialog, **uncheck "Save with API keys"** — this excludes all API keys from the exported file
222+
2. If you already exported with keys included, you can strip them manually by searching for `"api_key"` fields in the JSON and clearing their `"value"` entries
223+
224+
---
225+
226+
## APIs Used
227+
228+
- [Open-Meteo](https://open-meteo.com/) — Weather and air quality (free, no key required)
229+
- [National Park Service API](https://developer.nps.gov) — Park search and alerts (free key required)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env bash
2+
# Cleanup script — keeps going on errors to clean up as much as possible
3+
set -uo pipefail
4+
5+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6+
LOCAL_DIR="$SCRIPT_DIR/local"
7+
8+
cd "$LOCAL_DIR" || { echo "ERROR: Directory $LOCAL_DIR not found."; exit 1; }
9+
10+
stop_ollama() {
11+
if pgrep -f "ollama serve" >/dev/null 2>&1; then
12+
pkill -f "ollama serve" || true
13+
if pgrep -f "ollama serve" >/dev/null 2>&1; then
14+
echo "WARNING: Could not stop Ollama. Stop it manually: pkill -f 'ollama serve'"
15+
else
16+
echo "Ollama stopped."
17+
fi
18+
fi
19+
}
20+
21+
if [ "${1:-}" = "--force" ]; then
22+
echo "Stopping services and removing all data..."
23+
# Stop containerized services
24+
podman-compose down --remove-orphans -v -t 5 || true
25+
# Force kill and remove any lingering containers from this compose project
26+
for c in $(podman ps -a --filter "label=io.podman.compose.project=local" -q 2>/dev/null); do
27+
podman rm -f "$c" || true
28+
done
29+
# Remove project volumes
30+
for v in $(podman volume ls --filter "label=io.podman.compose.project=local" -q 2>/dev/null); do
31+
podman volume rm -f "$v" || true
32+
done
33+
# Remove project network
34+
podman network rm local_default || true
35+
# Stop native Ollama
36+
stop_ollama
37+
# Clean up config
38+
rm -f "$LOCAL_DIR/.ollama-enabled"
39+
rm -f "$LOCAL_DIR/.env"
40+
echo "Done. All services stopped and data removed."
41+
else
42+
echo "Stopping services (data preserved)..."
43+
podman-compose down --remove-orphans || true
44+
# Stop native Ollama
45+
stop_ollama
46+
echo "Done. Run './deploy-local.sh' to start again."
47+
fi

0 commit comments

Comments
 (0)