This document defines the supported architecture and responsibility boundaries for the repo.
panda / MCP client -> server -> proxy router -> proxy/proxies -> upstream datasources
| |
| -> embedded local proxy -> local datasources
-> sandbox -> server
pandaand MCP clients are the only user or agent entry points.serveris the only product API boundary.proxyis not a product API. It is an internal credentialed gateway, and the server may route across multiple configured proxies plus an embedded local proxy.- sandboxed Python never talks to
proxydirectly.
server owns all product behavior:
- MCP transports and HTTP API
execute_python,manage_session, andsearch- sandbox lifecycle and execution routing
- runtime session tokens for sandbox-to-server calls
- server-owned operation semantics and response shaping
- module lifecycle, docs, examples, resources, and availability
- semantic search runtime and indices
- auth bootstrap metadata for hosted proxy access
If a change affects product semantics, defaults, validation, output shape, or the user-facing contract, it belongs in server.
proxy is intentionally thin. Each proxy route owns:
- datasource identity and credentials for the datasources it advertises
- datasource discovery via
GET /datasources(authenticated, returns metadata without credentials) - hosted auth control plane for remote users
- proxy-scoped bearer token validation
- raw upstream relay to ClickHouse, Prometheus, Loki, Ethereum nodes, and the workflow engine
- rate limiting and audit logging
proxy must not own user-facing operation semantics.
panda is a thin client over the server API:
- config lookup
- local auth bootstrap UX (
panda auth ...) - output formatting
- no local module bootstrapping
- no sandbox ownership
- no direct datasource or proxy logic
The Python runtime inside the sandbox is server-facing only:
- uses
ETHPANDAOPS_API_URL - uses
ETHPANDAOPS_API_TOKEN - calls
serverruntime endpoints for operations and storage - never receives datasource credentials
- never receives proxy auth tokens
Only two deployment modes are supported.
panda -> local server -> local proxy -> upstreams
|
-> local sandbox -> local server
- intended for trusted local operation
- no hosted auth requirement
- the sandbox-to-
proxyisolation is a convention here, not a network boundary: in the defaultdocker composestack the sandbox shares a network with the proxy and proxy auth defaults tonone. Sandbox code is expected to reachserveronly; if the local proxy holds privileged or shared credentials, enforce the boundary with a sandbox-only network or proxy auth.
panda -> local server -> hosted proxy -> upstreams
|
-> local sandbox -> local server
- code still executes on the user's machine
- hosted proxy keeps credentials remote
panda auth loginbootstraps access to the hosted proxy- the sandbox cannot reach the hosted proxy (remote and authenticated), so the sandbox-to-
proxyboundary is enforced by topology in this mode
There is no supported hosted-server product topology in this repo.
Integrations are called modules and live under modules/ (plus the content-only datasets/ module at the repo root).
Base contract:
NameInitApplyDefaultsValidateStartStop
Optional capabilities are declared explicitly in pkg/module/module.go, for example:
- sandbox env
- datasource metadata
- examples
- Python API docs
- custom resources
- proxy-aware startup
- proxy-discoverable
- cartographoor-aware startup
Modules are server-side integrations. They do not define new MCP tools.
Datasource identity (name, description, metadata) is owned by whichever proxy advertised it.
The server builds a proxy router from every configured proxies: entry and, when enabled, an embedded loopback local_proxy route.
Queries are routed to the proxy that owns the requested datasource.
Modules that implement ProxyDiscoverable initialize from discovered datasources.
The proxy client refreshes datasource info every 60 seconds by default (the embedded local proxy polls every 5 seconds).
- do not add new MCP tools for modules
- do not make sandbox code talk to
proxy - do not move product semantics back into
proxy - do not make
pandareconstruct server state locally - datasource identity belongs to the proxy route that advertised it; modules must not define their own datasource config