LabHub is a local operational hub for agentic labs: a Vite/TypeScript UI connected to a Python bridge that exposes per-lab dashboards, real/mock state, and independent chat sessions.
It pairs naturally with agentic-lab-eac — the framework for Co-Scientist hypothesis generation and Experiment-as-Code specs.
| Financial Lab dashboard | Cyber Security lab |
|---|---|
![]() |
![]() |
Per-lab chat — connected directly to the gateway, streaming SSE responses in real time
- Python bridge (
server/bridge.py) using FastAPI and async SSE — multiple labs stream concurrently without blocking each other. - Config-driven registry: add any number of labs via
labhub.yaml— no code changes needed. - Common data contract per lab:
summary,metrics,currentParams,status,timestamp,artifacts,lastAction,source_mode. - Per-lab chat with isolated sessions, in-memory history, and typed SSE events.
GenericLabAdapter— works out of the box for any git repo; no domain-specific code required.GatewayClientinterface with a configurable script backend and an echo fallback for development.- Frontend
PluginAPIandLabShellfor building custom per-lab dashboards. REAL/MOCKbadge driven bysource_mode(whether the lab repo exists on disk).- Five example plugins (financial, protein, cybersec, sair, agentlab) showing the full plugin contract.
- Python 3.11+
- Node.js 22.x
- npm
- PyYAML (
pip install pyyaml)
git clone https://github.com/Grizaceo/labhub.git
cd labhub
npm install
pip install pyyaml fastapi uvicorn loguruConfigure your labs (copy the example and edit paths):
cp examples/labhub.yaml labhub.yaml
# Edit labhub.yaml — adjust repo_path for each lab to match your filesystemTerminal 1 — bridge:
python3 -m server.bridge
# Bridge listens on 127.0.0.1:5281 by defaultTerminal 2 — UI:
npm run dev
# Vite serves the UI and proxies /api to the bridgeShortcut (both processes):
npm start
npm stop # to stopLabs are defined in labhub.yaml (see examples/labhub.yaml for the full format):
labs:
mylab:
plugin_module: server.plugins.mylab # optional — omit for generic fallback
repo_path: ~/projects/my-lab # path to the lab git repo
chat_enabled: true
context_sources: [plugin_snapshot, chat_history]
allowed_actions: [read_file, search_files, terminal]
default_params:
num_epochs:
type: slider
label: Epochs
default: 10
min: 1
max: 100
step: 1Override the config file path with the LABHUB_CONFIG env var:
LABHUB_CONFIG=/path/to/my-labs.yaml python3 -m server.bridgeLabHub forwards chat messages to an external gateway script that calls an LLM and streams responses.
# Use your own gateway script:
export LABHUB_GATEWAY_SCRIPT=/path/to/your/gateway
# Or use the built-in echo fallback for development:
export FALLBACK_GATEWAY=trueThe gateway contract — the script receives a JSON payload file and emits NDJSON to stdout:
your-gateway /tmp/labhub_<request_id>_xxx.json{"type": "delta", "delta": "Hello "}
{"type": "delta", "delta": "world"}
{"type": "completed", "message_id": "asst_1", "text": "Hello world"}GET /api/labs — list registered labs
GET /api/labs/<id>/data — lab snapshot / dashboard
GET /api/labs/<id>/config — editable parameters
POST /api/labs/<id>/config — apply parameter changes
POST /api/labs/<id>/run — execute a lab action
GET /api/labs/<id>/stream — SSE dashboard stream
GET /api/labs/<id>/adapter — adapter metadata and source_mode
POST /api/labs/<id>/chat/session
GET /api/labs/<id>/chat/history?session_id=...
POST /api/labs/<id>/chat/message
GET /api/labs/<id>/chat/stream?session_id=...
SSE chat events: chat.accepted, chat.started, chat.delta, chat.completed, chat.error, heartbeat.
- Add an entry to
labhub.yaml. - (Optional) Create
server/plugins/<lab_id>.pywith aregister()function returning a plugin withget_data(),apply_config(changes), andrun_action(action, params). If omitted, the bridge returns{"status": "no-data"}for dashboard requests. - (Optional) Create
src/plugins/<lab_id>/index.tsimplementingLabPlugin. If omitted, thecustomplugin renders a generic JSON view. - Run
npm run checkandpytest tests/ -q.
See CONTRIBUTING.md for the full walkthrough.
npm run dev # Vite dev server
npm run build # tsc + vite build
npm run test # vitest run
npm run check # tsc --noEmit + vitest + vite build
pytest tests/ -q # Python tests- The bridge binds to
127.0.0.1by default — not designed for network exposure. repo_pathandworkdircome from the server-sidelabhub.yaml; the frontend cannot influence them.- Chat history is in-memory only; restarting the bridge clears all sessions.
See SECURITY.md for the full threat model and how to report vulnerabilities.
Apache-2.0 — see LICENSE.

