|
| 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) |
0 commit comments