Skip to content

Repository files navigation

FlowPulse

CI License: MIT

Local AI Workflow Debugger & Cost Optimizer.

A lightweight, zero-code-change proxy that sits between your AI workflow tools (n8n, LangChain, custom agents) and your LLM providers (OpenAI, Anthropic, Ollama) — capturing every request's latency, tokens, and cost in real time, with a live dashboard and built-in spend guardrails.

Point baseURL at FlowPulse. That's it. No SDK, no wrapper, no vendor lock-in.

FlowPulse dashboard live demo


Why FlowPulse?

Debugging and cost-tracking AI workflows usually means digging through provider dashboards after the fact, or instrumenting every agent by hand. FlowPulse takes a different approach:

  • Zero code changes — swap one URL (baseURL), keep your existing OpenAI/Anthropic SDK calls exactly as they are.
  • Runs entirely on your machine — traffic passes through your own proxy; nothing is sent anywhere except the LLM provider you already use.
  • See cost before it happens — Cost Guard blocks a request before it reaches the provider if it would blow your daily budget or a per-request token ceiling.
  • One dashboard, every request — live KPIs, a filterable request stream, and a full request/response inspector, updated over WebSocket as requests happen.

Features

🔌 Zero-code proxy OpenAI-compatible (/v1/chat/completions) and Anthropic-native (/v1/messages) endpoints, streaming and non-streaming
💰 Real-time cost tracking Per-request input/output cost breakdown, computed from a configurable pricing table
⏱️ Latency & TTFT Measures total duration and time-to-first-token, even for streamed responses
🛡️ Cost Guard Optional daily spend cap (MAX_DAILY_COST_USD) and per-request token ceiling (MAX_TOKENS_PER_REQUEST) — both enforced before the upstream call
📊 Live dashboard Next.js + Tailwind app with KPI cards, a live request table, and status/model filters
🔍 Request detail drawer Click any request to inspect the full prompt, raw response/error JSON, sanitized headers, and cost breakdown
🧩 Provider-agnostic Works with OpenAI, Anthropic, and any OpenAI-compatible endpoint (Ollama, local model servers, etc.)

Architecture

flowchart LR
    subgraph client["Your AI Workflow"]
        A["n8n / LangChain / Custom Agent"]
    end

    subgraph flowpulse["FlowPulse (local)"]
        B["Proxy — Fastify\nlocalhost:4000"]
        G{{"Cost Guard"}}
        D["/ws/metrics\nWebSocket"]
        E["Dashboard — Next.js\nlocalhost:3000"]
    end

    subgraph upstream["LLM Provider"]
        C[("OpenAI / Anthropic / Ollama")]
    end

    A -- "baseURL: localhost:4000/v1" --> B
    B --> G
    G -- "within budget" --> C
    G -. "over budget → HTTP 429" .-> A
    C -- "response" --> B
    B -- "response, unchanged" --> A
    B -- "metrics + cost + request/response detail" --> D
    D --> E
Loading

Only two things run: the proxy (Node/Fastify) and the dashboard (Next.js). No database, no external services — metrics live in memory and stream over WebSocket as they happen.

Screenshots

Live dashboard — KPI cards plus a request stream mixing successful calls, a 401 from a bad key, and 429s from the Cost Guard:

FlowPulse dashboard overview

Request Detail Drawer — click any row to see the exact prompt, sanitized headers, and full cost breakdown:

Request detail drawer

Cost Guard in action — a request blocked before it ever reached the provider, visible live in the stream:

Cost Guard blocking a request

Filtering — narrow the live stream to just the errors (or a specific model):

Error filter applied

Quick Start

Option A: Docker Compose (no local Node.js required)

cp .env.example .env
# set UPSTREAM_BASE_URL in .env to your real provider (OpenAI, Anthropic, or a local Ollama instance)
docker compose up --build

That's it — the proxy comes up on http://localhost:4000 and the dashboard on http://localhost:3000, wired together automatically. Stop everything with docker compose down.

Option B: Run locally with npm

1. Run the proxy

npm install
cp .env.example .env
# set UPSTREAM_BASE_URL in .env to your real provider (OpenAI, Anthropic, or a local Ollama instance)
npm start

The proxy listens on http://localhost:4000 and opens a metrics channel at ws://localhost:4000/ws/metrics.

2. Run the dashboard

cd dashboard
npm install
cp .env.local.example .env.local
npm run dev

Open http://localhost:3000 (or 3001 if 3000 is taken) to watch requests, costs, and latency come in live.

Point your workflow at it

In n8n, LangChain, or your own agent code, change the LLM client's baseURL — nothing else:

baseURL: http://localhost:4000/v1

For a step-by-step n8n walkthrough (HTTP Request node setup, a caveat about the native OpenAI node's custom Base URL support, a ready-to-import example workflow, and troubleshooting), see the n8n Integration Guide.

Cost Guard

Both limits are opt-in — set them in .env to enable, leave unset to disable:

  • MAX_DAILY_COST_USD — total spend allowed per UTC day across all requests. Once reached, new requests are rejected with HTTP 429 — FlowPulse: Daily Cost Limit Exceeded before they reach the provider. Resets automatically at midnight UTC.
  • MAX_TOKENS_PER_REQUEST — maximum tokens (estimated from prompt size + requested max_tokens) a single request may use. Requests over the limit are rejected upfront with HTTP 429 — FlowPulse: Request Token Limit Exceeded.

Blocked requests still appear in the console log and the live dashboard, so you can see the guard working in real time.

Metrics History

Every request is appended as a JSON line to data/metrics.jsonl (path configurable via METRICS_LOG_PATH), so history survives a proxy restart — restart the proxy and the dashboard still shows everything from before. This also means MAX_DAILY_COST_USD can't be reset by restarting the proxy: on startup, FlowPulse re-sums today's spend from this file before serving any requests.

The dashboard loads this history on page load via GET /metrics/history (newest first, capped at 200 entries by default — pass ?limit=), then switches to the live WebSocket stream for anything after that. Note that only the summary metrics are persisted, not the full prompt/response bodies — those stay in-memory and are only available for requests captured during the current WebSocket session, via the Request Detail Drawer.

data/ is gitignored and grows unbounded (no rotation) — it's meant for local debugging, not as a production audit log. Delete the file any time to reset history.

Supported Endpoints

  • POST /v1/chat/completions — OpenAI-compatible (OpenAI, Ollama's OpenAI-compatible mode)
  • POST /v1/messages — Anthropic native Messages API format
  • GET /metrics/history — persisted request history (JSON, newest first)
  • GET /health — health check

Supported Models (Cost Calculator)

Model Input ($/1M tokens) Output ($/1M tokens)
gpt-4o $2.50 $10.00
gpt-4o-mini $0.15 $0.60
claude-3-5-sonnet $3.00 $15.00
llama3 (Ollama) $0 $0

Prices can be updated in src/config/pricing.js. Unrecognized models are still proxied and measured — cost is just reported as $0 with an unknown model flag until you add pricing for them.

Project Structure

FlowPulse/
├── src/
│   ├── index.js               # Entry point (loads dotenv + starts the server)
│   ├── server.js               # Fastify instance and route registration
│   ├── config/
│   │   └── pricing.js          # Per-model pricing table
│   ├── services/
│   │   ├── costCalculator.js   # Cost calculation engine
│   │   ├── costGuard.js        # Daily budget & per-request token guardrails
│   │   ├── logger.js           # Console metric logging
│   │   ├── metricsStore.js     # Persists metrics to data/metrics.jsonl (survives restarts)
│   │   └── wsBroadcaster.js    # /ws/metrics channel - broadcasts metrics to the dashboard
│   ├── proxy/
│   │   └── chatProxy.js        # Streaming/non-streaming proxy middleware
│   └── routes/
│       └── chatCompletions.js
├── dashboard/                  # Next.js + Tailwind live metrics dashboard
│   └── Dockerfile              # Multi-stage build (Next.js standalone output)
├── docs/
│   ├── n8n-integration.md      # n8n integration guide
│   └── screenshots/            # README images
├── examples/
│   └── n8n/
│       └── flowpulse-demo.workflow.json  # Importable example n8n workflow
├── test/                       # node:test suite for the proxy (see Testing below)
├── .github/workflows/ci.yml    # Runs the test suite + dashboard build on every push/PR
├── Dockerfile                  # Proxy image
├── docker-compose.yml          # Runs proxy + dashboard together
├── .env.example
└── package.json

Testing

The proxy has a node:test suite (zero extra dependencies) covering pricing/cost math, Cost Guard, persisted history, and full request/response proxying (success, upstream errors, streaming, and Cost Guard blocks) against a real mock upstream server:

npm test

.github/workflows/ci.yml runs this suite plus a dashboard production build (next build, which includes type-checking and linting) on every push and pull request to main.

Roadmap

  • docker-compose.yml — run the proxy and dashboard with a single docker compose up, no local Node.js install required
  • n8n integration guide — a walkthrough for pointing n8n's OpenAI/HTTP nodes at FlowPulse and monitoring live workflow runs
  • Persisted metrics history — survives a proxy restart, see Metrics History below
  • Automated tests + CI — node:test suite for the proxy, dashboard build check, both run in GitHub Actions

Contributing

Issues and pull requests are welcome. This is an early-stage project — if you hit a rough edge or have an idea, open an issue.

License

MIT

About

Lightweight Local AI Proxy & Real-Time Cost/Debugging Dashboard for OpenAI, Anthropic & Ollama

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages