name: create-module
description: "Add a new datasource module to ethpandaops/panda. Triggers on: add module, new module, create module, add plugin, new plugin, create plugin, add datasource."
argument-hint:
disable-model-invocation: true
metadata:
internal: true
Create New Module
Use this when adding a new integration like ClickHouse, Prometheus, Loki, Dora, or Ethnode. The architecture is module + server operations, not plugins + bespoke proxy endpoints.
Files To Create
Create the module folder:
modules/{name}/
├── config.go
├── module.go
├── examples.go
├── examples.yaml
└── python/{name}.py
Add these when needed:
resources.gofor custom MCP resources- helper files for schemas, discovery, or API clients
pkg/proxy/handlers/{name}_operations.gopkg/proxy/handlers/{name}_operations_test.go
Copy From
modules/prometheus/ormodules/loki/for simple JSON passthrough APIsmodules/clickhouse/for streamed table results and datasource discoverymodules/dora/ormodules/ethnode/for external HTTP APIs with curated helpers
Required Wiring
pkg/app/app.goAddreg.Add({name}module.New())inbuildModuleRegistry().pkg/server/operations_<domain>.goAdd new server-owned operation handling for the module.pkg/server/operations_dispatch.goWire the module's handler into dispatch.pkg/proxy/server_config.goAdd proxy server config translation only if the module needs proxy-held credentials or typed proxy config.sandbox/ethpandaops/ethpandaops/__init__.pyAdd the lazy import if the module exposes a Python module.sandbox/DockerfileCopymodules/{name}/python/{name}.pyinto the installedethpandaopspackage.
Architecture Rules
- Do not add a new MCP tool. MCP stays limited to platform primitives.
- Module semantics live in Go.
- Python wrappers stay thin and go through
sandbox/ethpandaops/ethpandaops/_runtime.py. - Default remote execution path is
POST /api/v1/operations/{module.operation}. - Server operation handlers own validation, defaults, routing, and error mapping.
- Upstream-backed bulk data must stay passthrough when possible. Do not materialize large tables into row-object JSON in the server.
- Small synthetic/object operations can still return the JSON envelope.
- Credentials never go into the sandbox. Only metadata and server runtime tokens do.
Module Contract
Implement module.Module from pkg/module/module.go and only the optional capability interfaces you need:
- base lifecycle:
Name,Init,ApplyDefaults,Validate,Start,Stop - optional capabilities:
SandboxEnvProvider,DatasourceInfoProvider,ExamplesProvider,PythonAPIDocsProvider,ResourceProvider
Python Rules
- Keep Python ergonomic, not semantic.
clickhouse.query(...)style wrappers should call_runtimehelpers and parse only at the edge.- If the operation returns bulk tables, prefer streaming formats like TSV instead of normalized JSON rows.
- If the operation already returns useful upstream JSON, return that JSON rather than reshaping it in Python.
CLI Rules
- Module-specific CLI commands should be thin adapters over server operations.
- Do not duplicate validation/default logic already implemented in the server operation handler.
- Pretty-printing belongs in CLI; semantic behavior does not.
Checklist
- New module implements
module.Module - Examples and Python API docs are added
- Server operation handler is wired into
pkg/server/operations_dispatch.go - No new MCP tool was added
- Python module is thin and copied via
sandbox/Dockerfile - CLI, if added, calls operations instead of bespoke transport logic
-
go test ./...passes -
python3 -m py_compile ...passes for touched Python files -
make docker-sandboxbuilds if sandbox files changed