After making code changes, always run:
make agent-checkThis runs: fix-unused-imports, ruff format, ruff lint, plxt format/lint (.mthds/.toml), pyright, mypy.
make agent-testSilent on success, full output on failure. Excludes inference/LLM markers by default.
Run specific tests (local only): make tp TEST=test_function_name
make install- Create venv + install all deps (uses uv)make li- Lock + installmake cleanderived- Remove caches/compiled files (useful when linters get confused)make validate/make v- Lint/validate the.mthdsbundle with plxt (offline)make tb- Quick boot test (constructs the API client, no network)make fui- Fix unused imports onlymake plxt-format- Format.mthds/.tomlfiles with plxtmake plxt-lint- Lint.mthds/.tomlfiles with plxt
This starter calls the hosted Pipelex API via the pipelex-sdk package (PipelexAPIClient) — it does not run Pipelex as a local library. The .mthds bundle is read from disk and sent to the API as content (mthds_contents); the API runs the method and returns the output.
- Credentials/endpoint come from
PIPELEX_BASE_URL/PIPELEX_API_KEY(see.env.example).python-dotenvloads.envwhen running the CLI or tests. - The
piperCLI (piper/cli.py) is a Typer app;piper/runner.pydispatches each run by execution mode —blocking(client.execute), durable attended (client.start+client.wait_for_result), and durable detached (client.startonly, resumed viapiper runs status|result|wait <id>). It branches on mode explicitly rather than using the SDK'sstart_and_waitself-healing one-liner, because teaching the mode difference is the point. - The SDK resolves the main output on both modes:
client.executereturns aPipelexExecuteResultand the durable path aRunResults, both exposing a resolved.main_stuff(a completed run with no main stuff raisesMissingMainStuffError). Per-example narrowing lives inpiper/examples/, one "copy me" module per demo (bundle path, output model,parse()) —extract_entities.parse()validatesresults.main_stuffinto a typedExtractedEntitiesmodel. SDK errors are mapped to CLI-facing messages + hints inpiper/errors.py. - Three demo commands share that dispatch:
extract-entities(text in),summarize-pdf(a file in —piper/file_input.build_document_input()encodes a local file as a base64data:URL wrapped in a{"concept": "Document", "content": …}envelope), andgenerate-image(prompt in).generate-imageis the deliberate slow case that overruns the ~30s blocking cap, so it's how the starter demonstrates the durable-vs-blocking difference concretely.samples/sample-invoice.pdfis shipped forsummarize-pdf.
- Package:
piper/(Python 3.11+, target 3.11) - Tests:
tests/(unit = offline CLI/example/error-mapping tests; integration = offline boot/bundle checks + APIvalidate; e2e = full run via the API) - Dependency manager: uv (>=0.7.2)
- Pipelex dependency:
pipelex-sdkpackage from PyPI (the API client — see pyproject.toml). Thepipelexruntime is not a dependency. .mthdsfiles: Pipelex method definition files inpiper/methods/<name>/main.mthds
pipelex_api— reaches the hosted API (needs a key); excluded frommake agent-test/make gha-tests.inference— runs real LLM inference via the API; also excluded by default.- Offline tests (no marker) run everywhere, including CI.