GitHunt
PS

psenger/python-nodejs-bridge-poc

Faced with the fact that NodeJS just is a better Web Application and Python a Better AI app, how can we tie them together

Node.js + Python Bridge

A hybrid architecture that refuses to compromise.

License: MIT
Node.js
Python
TypeScript
FastAPI
Docker


Stop choosing between Node.js and Python. Use both.

Building agentic chat backends means choosing: Node.js for streaming and type safety, or Python for AI orchestration. This project proves you don't have to pick sides.

Getting Started · Architecture · Contributing


The Problem

Building a production-grade conversational AI backend demands two things that live in different ecosystems:

Requirement Best Tool Why
Multi-format delivery Node.js Content negotiation across MIME types (SSE, JSON, Markdown, plain text) with Accept header routing
SSE streaming to clients Node.js Async-native event loop, res.write() direct socket control, zero silent blocking
Hexagonal architecture TypeScript Structural typing makes ports discoverable, safe, and refactorable at compile time
LLM agent orchestration Python LangGraph, LangChain, CrewAI — the AI ecosystem lives here
LLM observability Python LangFuse tracing, token cost tracking, prompt versioning

Pick one language? You lose half the table. This POC validates that you can have the entire table.

The Solution

A bridge architecture where each language owns what it does best, connected by an internal HTTP sidecar with sub-millisecond overhead:

                  ┌──────────────────────────────────────────┐
                  │        Node.js (Express + TypeScript)    │
                  │                                          │
  Client ────────▶│  Content Negotiation (Accept header)     │
   ▲              │  ┌─────────┬──────┬──────────┬────────┐  │
   │              │  │text/SSE │ JSON │ Markdown │  Text  │  │
   │              │  └─────────┴──────┴──────────┴────────┘  │
   │              │  HTTP Routing · Session Mgmt             │
   │              │  Hexagonal Architecture (7 ports)        │
   │              └───────────────────┬──────────────────────┘
   │                                  │
   │                        HTTP Bridge (internal)
   │                      ~5─12ms overhead · <1% of total
   │                    Atomic success/failure · Retry logic
   │                                  │
   │              ┌───────────────────▼──────────────────────┐
   │              │        Python (FastAPI + LangGraph)      │
   │              │        Agent Orchestration · Tools       │
   │              │        LLM Calls · AI/ML Ecosystem       │
   │              └───────────────────┬──────────────────────┘
   │                                  │
   │              ┌───────────────────▼──────────────────────┐
   │              │                  LLM                     │
   └──────────────└──────────────────────────────────────────┘
   SSE · JSON
   Markdown · Text

Node.js owns the edges. HTTP routing, content negotiation across MIME types (text/event-stream, application/json, text/markdown, text/plain), session management, and a hexagonal architecture with 7 port interfaces and 14+ adapters — all with compile-time safety. Clients request their preferred format via the Accept header; Node.js handles the rest.

Python owns the intelligence. LLM orchestration via LangGraph/LangChain, agent tool-calling loops, and the full AI/ML ecosystem — sitting cleanly behind an ILLMProvider port.

Key Hypotheses

This POC validates three claims before the team commits to production:

  1. Bridge pattern works — HTTP bridge adds ~5-12ms overhead (<1% of total request time) with clean failure semantics
  2. Best of both worlds — Neither language compromises; each handles what it was designed for
  3. Architecture is de-risked — TypeScript's hexagonal ports + Python's agent orchestration coexist without async safety issues

Architecture

Hexagonal Ports & Adapters

The TypeScript layer defines 7 port interfaces, each with swappable adapter implementations:

┌────────────────────────────────────────────────────────┐
│                      Express HTTP                      │
│          Content Negotiation · SSE · JSON · MD         │
├────────────────────────────────────────────────────────┤
│                                                        │
│  ┌────────────────┐ ┌────────────────┐ ┌────────────┐  │
│  │  ILLMProvider  │ │   IDatabase    │ │   ICache   │  │
│  │   (→ Python)   │ │ (PostgreSQL)   │ │  (Redis)   │  │
│  └────────────────┘ └────────────────┘ └────────────┘  │
│                                                        │
│  ┌────────────────┐ ┌────────────────┐ ┌────────────┐  │
│  │ IMessageQueue  │ │    ISecrets    │ │ IBlobStore │  │
│  │ (Redis Stream) │ │                │ │            │  │
│  └────────────────┘ └────────────────┘ └────────────┘  │
│                                                        │
│  ┌──────────────────────────────────────────────────┐  │
│  │                 IObservability                   │  │
│  │           (Pino + Sentry + New Relic)            │  │
│  └──────────────────────────────────────────────────┘  │
│                                                        │
└────────────────────────────────────────────────────────┘

End-to-End Token Streaming

                                                          ┌─ text/event-stream (SSE)
┌─────────┐  tokens  ┌──────────────┐  HTTP   ┌─────────┐ │
│   LLM   │ ───────▶ │ Python Agent │ ──────▶ │ Node.js │─┼─ application/json
│         │          │ (LangGraph)  │ bridge  │(Express)│ │
└─────────┘          └──────────────┘         └─────────┘ ├─ text/markdown
                                                          │
                                                          └─ text/plain

Tokens flow from the LLM through the Python agent service, across the HTTP bridge, and into the Node.js layer — which negotiates the response format based on the client's Accept header. Correlation IDs are tracked at every hop.

Tech Stack

LayerTechnology
Node.js RuntimeNode.js 20+ · TypeScript (strict) · Express · Zod
Python RuntimePython 3.12+ · FastAPI · Uvicorn · Pydantic
AI / LLMAnthropic SDK · LangChain · LangGraph
MCP@modelcontextprotocol/sdk (TS) · FastMCP (Python)
DatabasePostgreSQL · Redis (cache + streams + search)
ObservabilityPino · structlog · Sentry · New Relic · LangFuse*
InfrastructureDocker Compose · ECS Fargate*
TestingTDD · Blue-Green testing · No UI required

* Planned for Phase 2

Getting Started

Prerequisites

Quick Start

# Clone the repository
git clone https://github.com/psenger/python-nodejs-bridge-poc.git
cd python-nodejs-bridge-poc

# Copy environment config
cp .env.example .env

# Start all services (Node.js + Python + Redis + PostgreSQL)
docker-compose up

# Or run services individually:

# Terminal 1 — Infrastructure
docker-compose up -d redis postgres

# Terminal 2 — Node.js
cd services/node
npm install
npm run dev

# Terminal 3 — Python
cd services/python
pip install -r requirements.txt  # or: poetry install
uvicorn src.main:app --reload --port 8001

# Run tests
cd services/node && npm test       # Node.js layer
cd services/python && pytest       # Python layer

Roadmap

Phase 1: MVP

  • Product architecture and technical design
  • Node.js HTTP server with SSE streaming (res.write() direct socket control)
  • Python agent service (FastAPI + Anthropic SDK + LangGraph)
  • HTTP bridge with atomic failure semantics
  • End-to-end token streaming (LLM → Python → Bridge → Node.js → SSE)
  • Hexagonal architecture (7 ports, 14+ adapters)
  • MCP tool handlers (Redis-backed data lookup, business logic)
  • Structured logging with correlation ID propagation across bridge
  • Docker Compose local dev environment
  • TDD with Blue-Green testing

Phase 2: Production Hardening

  • ECS Fargate deployment with health checks and auto-scaling
  • Circuit breakers and load testing
  • LangGraph multi-agent orchestration
  • LangFuse tracing (token costs, prompt versioning, agent step traces)
  • Multi-channel support (voice, third-party connectors)

Why Not Just Use [X]?

Alternative What You Lose
Node.js only No LangGraph/LangChain, limited AI ecosystem, no LangFuse observability
Python only Retrofitted asyncio risks silent event loop blocking under concurrent SSE + tool-calling; no compile-time port safety
Microservices (gRPC) Operational overhead of service mesh, proto compilation pipeline, and deployment complexity for a POC
Monorepo monolith Forced to pick one language; the core tradeoff remains

Project Structure

python-nodejs-bridge-poc/
├── services/
│   ├── node/                    # TypeScript/Express (HTTP, SSE, hex architecture)
│   │   ├── src/
│   │   │   ├── ports/           # 7 port interfaces
│   │   │   ├── adapters/        # Adapter implementations (14+)
│   │   │   ├── routes/          # Express route handlers
│   │   │   ├── services/        # Business logic
│   │   │   ├── middleware/      # Express middleware
│   │   │   ├── config/          # Configuration loading
│   │   │   ├── models/          # Domain models / DTOs
│   │   │   ├── repositories/    # Data access
│   │   │   ├── utils/           # Utilities
│   │   │   └── types/           # TypeScript type definitions
│   │   └── tests/               # Unit, integration, e2e
│   └── python/                  # FastAPI/LangGraph (AI orchestration)
│       ├── src/
│       │   ├── agents/          # LangGraph agent definitions
│       │   ├── tools/           # MCP tool implementations
│       │   ├── prompts/         # Prompt templates (versioned)
│       │   ├── api/v1/          # FastAPI route handlers
│       │   ├── services/        # Business logic
│       │   ├── schemas/         # Pydantic request/response schemas
│       │   ├── utils/           # Utilities
│       │   └── core/            # Core abstractions
│       └── tests/               # Unit, integration, fixtures
├── shared/
│   ├── api/openapi/             # Bridge contract (OpenAPI specs)
│   ├── configs/                 # Shared configuration
│   └── scripts/                 # Cross-service scripts
├── deploy/
│   ├── docker/                  # Dockerfiles, compose config
│   ├── ci/                      # CI/CD pipelines
│   └── scripts/                 # Deployment scripts
├── docs/
│   ├── architecture/            # Architecture Decision Records
│   ├── api/                     # API documentation
│   └── runbooks/                # Operational runbooks
├── agent-os/
│   ├── product/                 # Mission, roadmap, tech stack
│   ├── specs/                   # Feature specifications
│   └── standards/               # Coding standards (global, TS, Python, testing)
├── CLAUDE.md                    # Claude Code project instructions
├── .env.example                 # Environment variable template
├── LICENSE                      # MIT
├── CONTRIBUTING.md              # Contribution guidelines
└── README.md

License

This project is licensed under the MIT License — see the LICENSE file for details.


Built with the belief that the best architecture uses the best tool for each job.

Report a Bug · Request a Feature

psenger/python-nodejs-bridge-poc | GitHunt