Changelog
[v0.40.0] - 2026-07-19
Added
- Durable runs now persist token usage: the delivery executor writes a
tokens_usages.jsonresult artifact ({"tokens_usages": [...], "usage_assembly_error": null}) alongsideworking_memory.json, themain_stuff.*renders, and the graph outputs. The records use the client-facingTokensUsageRecordwire shape — the same shape the/executeresponse carries onpipe_output.tokens_usages— so a client polling a durable run's result files reads costs the same way a sync/executecaller does. The artifact is written unconditionally: a run with usage assembly off yields explicit nulls, distinguishable from a pre-artifact run (file absent). TokensUsageRecord— a deliberate client wire shape for token usage (pipelex/reporting/usage_records.py). One flat record per inference call:model_type,inference_model_name,inference_model_id,pipe_code,job_category,unit_job_id,nb_tokens_by_category(raw provider counts), computed USDcost(nullwhen the model has no rate table), and ISOstarted_at/completed_at. Enum-ish fields are open string sets on the wire, so runtime enum churn is non-breaking for clients.compute_tokens_usage_costreuses the existing cost engine (model_cost_per_token+ the cached/non-cached split), so the wirecostequals the CLI cost table's total for the same call. Documented in TokensUsage Wire Records.
Changed
- Breaking:
tokens_usagesrecords on client surfaces are nowTokensUsageRecordwire records, not dumps of the internal usage models. Both the/executeresponse (pipe_output.tokens_usages, via the newapply_tokens_usage_wire_shapehelper API servers apply to the response dump) and the durabletokens_usages.jsonartifact stop leaking runtime internals:job_metadata(with itsuser_id,session_id,request_id,pipe_run_id,otel_context,trace_context,content_generation_job_id,pipeline_run_id) and theunit_costsrate table no longer cross the wire — the keptJobMetadatafields (pipe_code, job-kind enums, timing) are flattened onto the record andcostis computed server-side. Null semantics unchanged (null= assembly off,[]= no inference). Internal crossings (runtime-bridge payloads, Temporal transport, the usage-event telemetry stream) keep full-fidelity records, untouched.
Fixed
- Validation errors stay domain-qualified: every raise site that names a
pipe_codenow also carriesdomain_code. The presentation chain (VS Code extension + mthds-ui) identifies pipes by full pipe ref (domain_code.pipe_code); a handful ofPipeValidationErrorraise sites (PipeLLM static input checks, PipeStructure input-mismatch, the pipe sorter's circular-dependency error) omitteddomain_code, degrading node decorations and click-to-navigate for those errors in multi-domain bundles. The sorter gains adomain_codeparameter threaded from the bundle spec's domain. - Hosted PipeFunc dry runs now honor output multiplicity. In sandbox-hosted mode a PipeFunc with a multiplicity output (e.g.
Foo[]) mocked a single scalar item because the function annotation is unavailable in-process; downstream pipes expecting a list (e.g.batch_over) then failed the dry-run//validateof a perfectly valid method. The mock now takes its shape from the declared output multiplicity. get_optional_config()honors its non-raising contract before any hub exists. It used to raiseRuntimeError: PipelexHub is not initializedwhen no hub had been created at all, which broke the documented safe pre-boot path — e.g. constructing aPipeFuncin an isolated unit test crashed instead of defaulting to thedirectexecution mode.- PipeFunc transport hardening: the wire contract now rejects a non-finite
timeout_seconds(float("inf")used to disable the runaway-code guard entirely), and the transported executor removes its materialized source workdir on every path (success, timeout, failure) instead of leaking a temp directory per invocation, pruning thesys.pathentries it inserted for that workdir in the same cleanup so dead entries can't accumulate (or be hijacked by a recreated path) in a reused process. - Error reference pages generated for the PipeFunc transport errors (
PipeFuncTransportError,PipeFuncExecutionError,DuplicatePipeFuncExecutorError,UnknownPipeFuncExecutionModeError) — theirtype_uris previously dereferenced to 404s.
[v0.39.2] - 2026-07-17
Added
LibraryManagerAbstract.is_crate_loaded(*, library_id, fingerprint)— public query over the per-library crate-fingerprint bookkeeping that already backsload_from_crate's idempotency. ATrueanswer means the library's ClassRegistry holds the crate's dynamic classes, so callers can hydrate within an existing scope instead of opening a fresh one — preserving dynamic-class identity with instances that scope already produced. This is the core half of the fix for the PipeParallel same-concept combine failing over Temporal withexpected X, got Xpydantic model-type errors.
Fixed
- PipeCompose construct: whole-stuff copies into native fields now convert in every promised case.
{ from = "..." }referencing a whole native stuff used to hand the content wrapper (TextContent,ListContent, ...) to the composed field in several cases, failing the dry-run runnable gate on correct methods. Three gaps fixed: optional (non-required) fields never converted (theOptional[X]annotation defeated the type detection), list-of-text targets dumped each item as a{"text": ...}dict instead of extracting the string, and scalar wrappers other thanTextwere not handled at all. The conversion matrix now coversText → text,Number → number,YesNo → boolean, andDate → date, for both required and optional target fields, scalar and list-item positions — including nullable list items (list[str | None]), which normalize like their non-nullable counterparts. Unconvertible list items now raise a clearStructuredContentComposerTypeErrorinstead of surfacing as a cryptic pydantic error downstream. One fidelity guard: copying aDatethat carries a time of day into a baredatefield raises instead of silently dropping the time and its UTC offset (breaking: this case previously truncated silently).
[v0.39.1] - 2026-07-15
Changed
- Bumped the
pipelex-tools-pyruntime dependency to>=0.1.3and thepipelex-toolsdev dependency to>=0.7.2, picking up the latest MTHDS schema updates forplxtformatting and linting.
[v0.39.0] - 2026-07-14
Highlights
- From resolved library to typed clients:
pipelex resolveandpipelex codegen—pipelex resolvedistills a bundle's whole closure into the normalized library crate — a flat, fully-qualified, fingerprinted snapshot — andpipelex codegen typesprojects it into TypeScript (ts-zod) or Python (python-pydantic,python-structures) artifacts. A trust chain of stamped headers and acodegen.lockmakes drift detectable offline:pipelex codegen checkverifies artifacts by pure hashing — no engine, no network, no API key. - Validation now fixes what it finds — When an error has a deterministic safe fix, every surface says so: a 💡 suggested-fix line in the CLI output, a structured
suggested_fixobject in agent and API payloads. The newpipelex fix bundle/pipelex-agent fix bundlecommands apply those fixes in place through a shared fix loop, with--diffto preview the changes without writing anything. - Smart Inputs: the signature decides the shape — Inputs are now interpreted top-down against the pipe's declared input signature instead of bottom-up from their shape alone: a bare string becomes the declared concept (never silently degrading to generic
Text), lists shape element-wise, bare URLs/paths resolve forImage/Documentinputs, and generated input templates default to the light bare-value form. - New native concepts:
Date,Time, andYesNo— Built-in concepts for calendar dates (preserving source precision — no fabricated times of day), times of day, and boolean judgments, plus atimestructure-field type completing the temporal triple. Every native now materializes from its pinned normative definition, so crate fingerprints byte-agree across implementations.
Added
-
pipelex resolveand thepipelex codegenfamily:pipelex resolveassembles a bundle closure and emits the normalized library crate — a flat, fully-qualified, natives-expanded, self-contained, fingerprinted snapshot of a resolved library — as JSON or TOML. On top of the crate:pipelex codegen types --target ts-zod|python-pydantic|python-structuresprojects the crate's concept set into typed artifacts. Thets-zodtarget emits a puretypes.ts(imports onlyzod, with wire-native snake_case keys so a schema validates a wire payload directly) plus abinder.tsexposing a typedparse/serializepair per concept;python-pydanticemits self-containedBaseModels;python-structuresemits runtimeStructuredContentclasses.pipelex codegen inputs --pipe <ref>renders a runnable inputs template for a pipe (defaulting to the closure'smain_pipe).- Generated files are never edited — each carries an
AUTOGENERATEDheader pointing at the sibling extension-file mechanism. - Codegen trust chain (stamps ·
codegen.lock· offlinecodegen check): Every filepipelex codegen typeswrites now carries a self-describing stamp header (source crate fingerprint, engine version, projection, options, and a content hash of the body below it), and the artifact set is recorded in a siblingcodegen.lock.pipelex codegen check [DIR]verifies generated artifacts are current offline — pure hashing, no engine, network, or API key — reporting drift by category (missing, modified, hand-edited, orphan) with the verdict on the exit code (0current ·1drift ·2no lock). Emission is idempotent (write-if-changed — unchanged output leaves files untouched) and prunes previously-generated files that drop out of the set, so a deleted concept never lingers as a stale generated file. Input templates (codegen inputs) are deliberately not stamped or locked — they are user-editable scaffolds, not tracked generated code. - Agent-CLI codegen mirror (
pipelex-agent codegen types|check): The codegen family is now available to machine consumers through the agent CLI's two-stream envelopes (--format markdown|jsonsuccess stream,--error-formaterror stream).codegen typesruns the same engine and write-if-changed emission as the bare CLI;codegen checkpresents the offline drift verdict structurally — drift is aCodegenDriftErrorenvelope enumeratingdrifts[]by category (exit1), a missing or unreadablecodegen.lockis a no-verdict error (exit2). With the pipelex runner,mthds-agent codegen …forwards to these commands. - Host-facing resolve/codegen engine cores (what the HTTP routes ride):
pipelex.pipeline.resolve_bundle.resolve_crate_from_contentsresolves in-memory MTHDS contents into the normalized crate — same engine, sameValidateBundleErrorverdict vocabulary, and the same loaded-on-success library contract asvalidate_bundle— so a host (thepipelex-api/v1/resolve+/v1/codegenroutes) serves resolution without touching the filesystem.pipelex.codegen.emission.build_stamped_projectionis the new pure stamping core (stamped files +codegen.lockcontent, no disk writes) thatwrite_stamped_projectionnow rides, so artifacts served over HTTP are byte-identical to locally written ones and pass the offlinecodegen checkverbatim. The shared bundle-loading error cascadetranslate_to_validate_bundle_erroris now public (renamed from its underscore-private form) since it gained a third entry point. - Agent bundle fixer: Added
pipelex-agent fix bundle, a deterministic in-place fixer over the shared validation fix loop. The command supports--format/--error-format, repeatable--select/--ignorefix-rule filters,--allow-signatures,--max-iterations, and the same bundle-file or directory resolution aspipelex-agent validate bundle. Successful fix results reportpending_signaturesandis_runnable; by default the command exits non-zero when a fixed bundle remains valid-but-not-runnable. - Human bundle fixer: Added
pipelex fix bundle, the human counterpart of the agent fixer over the same fix loop, with Rich-rendered output naming every change made (fix descriptions, files written, iteration count), the same--select/--ignore/--allow-signatures/--max-iterationsoptions, and the same bundle-file or directory resolution aspipelex validate bundle. A new--diffflag previews the changes as a unified diff without writing anything — the real fix loop runs against a temp-copy sandbox, and exit codes keep the verdict semantics so--diffanswers "would it converge?". - Suggested fixes surfaced in
pipelex validate: When a validation error has a deterministic safe fix, the human error output now shows a per-error💡 Suggested fix:line and ends with an actionable footer naming the exactpipelex fix bundlecommand (echoing the invocation's-Ldirs) in place of the generic tip. suggested_fixfield in/validatepayloads: Each validation error that has a deterministic safe fix now carries an additive structuredsuggested_fixobject —fix_code(the kebab-case rule id),description(the author-facing 💡 text),safety(safe/unsafe), optionalsourcefile, andops(the semantic patch operations) — on everyvalidation_errors[]item, both in thepipelex-agent validate/fixJSON envelopes and in the API/validateresponse body. This is the machine-actionable counterpart of the 💡 line, letting a software consumer apply the fix directly from the structured payload.-
Smart Inputs (signature-driven input shaping): Inputs are now interpreted top-down against the pipe's declared input signature rather than bottom-up from their shape alone.
-
Bare values (strings, numbers, booleans, dicts, lists) are automatically shaped into the declared concept (e.g., a bare string becomes a
legal.Question, not a genericnative.Text). - Lists shape element-wise into the declared item concept; single values auto-wrap into lists where required, and empty lists are now legal.
- Bare URLs/paths for
ImageorDocumentinputs are resolved relative to the inputs file's directory. - Declared structured lists (e.g.,
Person[]) accept a direct path to a.csvfile by signature, without requiring an envelope. - Comprehensive input error handling: A suite of typed errors for input shaping failures (
WrongScalarKindError,ListWhereSingularError,MultiplicityCountMismatchError,StructureValidationError,UnknownInputNameError) that provide clear hints and render the expected JSON shape. - CLI
--explicitflag: Added--explicittopipelex build inputsandpipelex-agent inputsto generate the legacy{"concept", "content"}envelope templates. - Native
YesNoconcept: Built-in concept (backed byYesNoContent) for boolean judgments. Requires a strict boolean, renders asyes/noin downstream prompts, and can be read viapipe_output.main_stuff_as_yes_no.yes_no. - Native
Dateconcept: Built-in concept (backed byDateContent) for calendar dates. Requires adatetime.dateand accepts an optionaldatetime.time. Preserves source precision (never forcing the LLM to fabricate a time of day) and retains UTC offsets verbatim. - Native
Timeconcept: Built-in concept (backed byTimeContent) for a time of day, optionally with a UTC offset — never attached to an invented date. A top-level TOML time-of-day literal in an inputs file now maps toTime(Breaking:Timejoins the reserved native concept codes, and the former bare-time rejection —InputsTimeOnlyNotSupportedError— is gone). - Structure-field
type = "time": The concept structure language gains atimefield type (a time of day, optionally with a UTC offset), completing the temporal triple besidedateanddatetime. Generates adatetime.timefield; emitted by every codegen target. - Pinned normative native definitions: Native concepts now materialize into the normalized crate by lookup into the standard's pinned per-version definitions (
pipelex/core/concepts/native/pinned_blueprints.py, mirroring the mthds spec's newnative-concepts.md), never by reflection over the runtime content classes — so crate fingerprints over materialized natives byte-agree across implementations. The old reflection is retained solely as a consistency test proving each runtime content class still matches its pinned blueprint. - Subject-grants registry — the keyword-only convention hardened: A positional first parameter ("subject") in
pipelex/source is now legal only under an explicit grant recorded insubject_grants.tomlat the repo root, carrying the subject's param name and an honest, def-specific review rationale — every grant in the registry has been individually reviewed against the grant rubric.pipelex-dev subject-grantis the sole registry writer; thecheck-keyword-onlyAST guard enforces the registry symmetrically (an ungranted subject fails, and so does a stale grant whose def was renamed, moved, demoted, or newly carved out) inmake check, CI, and the edit-time hook. Subjects typedbool/int/floatare banned outright — no grant can cover them. The registry schema is strict: exactlyparam+rationale, unknown keys fail the check. Seedocs/contribute/keyword-only-arguments.md. -
Drift contracts (
pipelex-dev drift plan|check|ack): Deterministic review obligations between code and docs. A rootdrift.tomldeclares contracts ("when these trigger files change, these review targets must be re-examined and the examination recorded"); committed ack files under.drift/acks/record each fulfilled review with a digest, reviewer, and rationale. A contract is fulfilled iff its stored ack digest equals the digest recomputed from the current tree (staged blob OIDs from the git index — no base ref, no timestamps), so trigger edits, matched-file adds/deletes, and contract-definition edits all reopen it. -
make drift-checkgates themake checkaggregate and runs as an advisory CI job;make drift-planprints per-contract Markdown packets with exact per-file changes since the last ack. make drift-ack CONTRACT=… RATIONALE="…"runs the contract's verify commands, then records the review and stages the ack file it writes, so the local gate checks the same index the commit is built from. If staging that ack fails, the ack file is removed rather than left unstaged, so a later check reports a missing ack instead of a false green.- For a contract with verify commands, a trigger file left unstaged-modified or untracked is a hard ack error (the verify run would certify content the digest does not cover) — checked both before and after the verify commands, so a trigger the commands themselves format or generate is caught too. For other contracts it stays a warning.
- Seeded with contracts for the config docs, the CLI docs, and the keyword-only convention spec; workflow documented in
docs/contribute/drift-contracts.md.
Changed
- Keyword-only demotions across the public API (Breaking): The subject-grant review demoted every positional first parameter that failed the grant rubric to keyword-only, and external code calling these surfaces positionally (or subclassing them with positional signatures) breaks. Notable demoted families: the
PipeAbstractrun family (run_pipe,dry_run_pipe,validate_before_run, … —job_metadata/visited_pipesnow keyword-only),StuffContent.rendered_for_prompt/rendered_for_template_async(text_format) and theTextFormatRenderable/ImageRenderableprotocols with all their implementations, theLibraryManagerAbstractload family (library_id),ensure_pipelex_booted(config_overrides),pipeline_run_setup(execution_config),ConceptLibrary.is_compatible(tested_concept),GraphTracerProtocol.setup(graph_id), thePromptImageFactory/PromptDocumentFactorycontent factories (uri), the model-manager/backend-library setup+load (secrets_provider), the reporting protocol'sset_event_log/clear_event_log(context_key), and assorted tools helpers (pluralize/count_with_noun,LogLevel.from_int,set_dry_run_forced, …). pipelex build structuresis now an alias ofcodegen types --target python-structures(Breaking): The legacy always-qualified per-file generator is deleted. The alias resolves the target's whole directory closure and emits one stampedstructures.pymodule plus acodegen.lock(bare-when-unique class names, declared imprecision instead of the old silentTextContentguess for structureless concepts). The--forceflag is gone (emission is write-if-changed), a.mthdsfile target now resolves its parent directory's closure, and concepts-only loading of invalid-pipe bundles is no longer supported (the crate requires a valid library). The concepts-only loading API (load_concepts_only,load_concepts_only_from_directory, and the library-manager methods behind them) is removed with it.pipelex build runneremits its structures through the codegen engine (Breaking): The scaffoldedstructures/directory now contains the stamped single-module projection (structures.py+codegen.lock) instead of per-concept files, and the generated runner script imports and instantiates the emitted class spellings (from structures.structures import Invoice) — fixing dropped imports for nested custom concepts along the way. A user class backing astructure = "<ClassName>"concept is imported from its real module.- Human validation error rendering routed through the shared structured items:
pipelex validate's error details now render from the sameValidationErrorItems the agent CLI and API emit, which surfaces information the old renderer silently dropped: pipe-factory errors (e.g. an unknown concept) get their own section, a parse-level failure (e.g. a TOML syntax error) now shows its message instead of no detail at all, and pipe validation errors name their source file. The dry-run message remains visible alongside categorized errors. - Validation error messages now speak MTHDS author syntax: Pipe validation errors state the problem and the fix the way an author writes them — a sequence output-multiplicity mismatch now reads "declares its output as 'StoryIdea', but its last step yields 'StoryIdea[]'. Update the sequence's output to 'StoryIdea[]'", and an input-type mismatch reads "input 'dish' is declared as 'Number' but its step needs 'Text'. Update the input to 'Text'" — instead of leaking Python internals (
multiplicity=None,Concept(...)/PresenceMarkerreprs). The misleading(required: […], provided: …)suffix is suppressed for multiplicity errors (where both sides are identical by definition) and rendered as joined author-syntax refs — never Python list-repr brackets — elsewhere. - Agent
validate/fixoutput renders prose, not a JSON dump:pipelex-agent validate bundleandpipelex-agent fix bundlemarkdown output now renders validation errors as category-grouped prose (a humanized title, identity fields, the message, and a💡 Suggested fix:line) followed by a fix-aware footer naming the exactpipelex-agent fix bundlecommand when a safe fix exists — mirroring the human panel. The machine-facing JSON stream (--format json) is unchanged, so software consumers keep branching on the same structured fields. - Clean validation summary message on every surface: The top-level error
message(agent JSON, the API/validatebody) is now a clean, author-facing summary derived from the structured errors, instead of the raw pydantic dump (Validation error(s): … Value errors: '<field>': Value error, …). The API's opt-in invalid-verdictrendered_markdownnow carries the same per-error💡 Suggested fixprose as the CLI. A still-invalid fix that stops with no progress now names the re-proposed fix in author terms rather than dumping an internal fingerprint string. - Input templates default to "light" shape (Breaking):
pipelex build inputsandpipelex-agent inputsnow generate light templates by default, outputting the bare values expected by the signature rather than the verbose{"concept", "content"}envelopes. TOML templates include the declared concept as a# concept: ...comment. - Structure-field
type = "date"behavior (Breaking): Adatefield now generates adatetime.date(JSON schemaformat: date), preventing LLMs from hallucinating times for calendar dates. A newtype = "datetime"field handles full timestamps (format: date-time), and default-value validation now rejects adatetimedefault on adatefield. - Strict input validation (Breaking): Undeclared input names are now a hard error (previously silently ignored), and top-level
nullvalues are rejected — absence must be expressed by omitting the key. Known limitation: this also rejects the extra stuffs carried by apipelex-agent run --with-memoryenvelope, so piping one run's full working memory into a downstream pipe that declares only a subset of it now fails withUnknownInputNameError. Until envelope-derived inputs get their own leniency, narrow the envelope to the declared inputs before piping, or pass the inputs explicitly with--inputs. - Explicit envelope validation (Breaking): The
{"concept", "content"}escape hatch is now compatibility-checked against the pipe's declared signature; incompatible concepts raise a typed error. - TOML date/time handling (Breaking): TOML date and datetime literals are natively supported and map directly to the
Dateconcept; a bare time-of-day literal maps to the newTimeconcept (it never silently becomes aDate— shaping aTimeinto aDateslot fails the compatibility check). ImageContentflattens its pixel dimensions (Breaking):size: ImageSize | Noneis replaced by paired optionalwidth/heightinteger fields (both-or-neither, enforced by a validator) — a named nested shape in the crate is a concept, and the size grouping did not earn that citizenship.ImageSizeremains as the internal img-gen parameter type. Image wire payloads change shape accordingly.native.Datedeclares real structure (Breaking): MaterializedDateis no longer structureless — its pinned definition carries a requireddatefield plus an optionaltimefield (the newtimefield type), so generated clients get real Date types.DateContent's wire form is unchanged.
Fixed
- Library loaders now bind the target library for the whole load:
load_from_blueprints/load_from_crate/load_librariestook an explicitlibrary_idbut resolved concepts and the class registry through the ambient current-library ContextVar one hop below — so loading into a library that wasn't current read (and registered generated structure classes into) whatever library the ambient pointer happened to name. Production hosts always set the target current before loading, so this only bit multi-library callers — exactly the isolation the loaders exist to provide. The loaders (and blueprint removal) now wrap their body inscoped_current_library(library_id), restoring the caller's binding on exit, so everything beneath a load resolves against the load's target by construction. A regression test loads into a deliberately non-current library. PipeExtractbroke crate normalization (500s on every static-core route):PipeExtractBlueprint.validate_outputonly accepted the authoring spellingPage[], but normalization qualifies concept refs (Page[]→native.Page[]) and then rebuilds the blueprints — so the validator rejected its own normalized output, and any bundle containing aPipeExtractraised a raw pydanticValidationErrorout ofresolve_crate_from_contents, 500-ing/v1/build/inputs,/v1/build/output,/v1/resolve, and/v1/codegen. The validator now compares the parsed concept ref and multiplicity instead of the raw string, so it holds for both spellings. The output contract is unchanged and still exact — a variable-length list of nativePage— since a refined output would be an unverifiable promise:PipeExtractmechanically produces native pages and cannot make them more specific.resolve/codegenrejected bundles that pin a model: The resolve and codegen commands booted without model specs, so library validation could not check pipe model pins (model = "gpt-4o-mini") against the deck and rejected any bundle carrying one. They now boot likevalidate— offline, but with model specs loaded.- Native
Imageno longer materializes structureless: Every native now materializes from its pinned normative definition, so generated clients for image-producing pipes exposeurl,public_url,caption,width,height, etc. (The brief interim dict-with-imprecision mapping for the nested size model is superseded by theImageContentflatten above.) - Deterministic input-template placeholders: Mock URL placeholders in generated inputs templates (
codegen inputs/build inputs) are now deterministic (https://mock.invalid/<field>), so committed templates no longer churn on every regeneration. codegen inputsis write-if-changed: Likecodegen types, an already-current inputs template is left untouched (no mtime churn) and the console reportsUnchangedinstead of claimingGenerated.- Opaque generated classes no longer strip content: A structureless or Python-class-backed concept's generated Python class now carries
model_config = ConfigDict(extra="allow"), somodel_validatekeeps the payload verbatim instead of pydantic's defaultextra="ignore"silently dropping every field. Opaque is pass-through, never lossy — matching the ts-zodz.unknown()behavior. - Human CLI
~expansion:pipelex validate bundle(and the newpipelex fix bundle) now expand~in the bundle path and-L/--library-dirvalues, matching the agent CLI. - Validate telemetry label: The
CLI_COMMANDtelemetry tag forpipelex validatesubcommands no longer double-suffixes (previously "validate bundle bundle"). - Silent mistyping of inputs: Providing a bare string for a refined text concept (e.g.,
legal.Question) no longer silently degrades the type to a genericnative.Text; the declared concept type is now retained. - TOML inline table formatting: Light templates now use inline tables for structured values, preventing trailing scalars from being swallowed into
[sections].
Documentation
- Smart Inputs guides: Updated
provide-inputs.md,executing-pipelines.md, andnative-concepts.mdfor the Smart Inputs paradigm, leading with the bare-value approach and demoting the envelope format to an escape hatch.
[v0.38.0] - 2026-07-06
Highlights
- Optionality is a first-class language feature — Concept references in pipe
inputs/outputscan be marked?(optional) or!(force), so absent values become tracked, first-class data with provenance instead of crashes or silent nulls. Absence flows through a runtime trichotomy — a plain input skips its pipe, a?input absorbs it and runs, a!input fails loudly — and a static taint pass proves at author time that every maybe-absent value reaches an explicit sink. - Storage and secrets are now plugin seams — Both backends are selected at boot from a config-keyed registry, so third parties can ship
pipelex-storage-<backend>/pipelex-secrets-<backend>packages via thepipelex.pluginsentry point — the same discovery machinery the inference and orchestrator seams already use.
Added
-
Optionals & presence markers (
?,!): Concept references in pipeinputs/outputscan now be marked?(optional) or!(force), e.g.clause = "PenaltyClause?". Absent values are first-class data, tracked in working memory via anAbsenceRecordledger (variable, producing pipe, kind = declared-absent / skipped / not-provided, reason, upstream chain) with provenance captured at the moment absence is produced:- A plain input fed an absence causes the pipe to be skipped (implicitly lifted); its own output is recorded absent, chaining back to the origin so the miss short-circuits like Swift's
a?.b.c. - A
?input absorbs the absence and the pipe runs, handling both arms. - A
!input fed an absence fails loudly with a typedOptionalValueAbsentErrornaming the variable, the consuming pipe, the producing pipe, and the original reason. - Callers may omit
?-marked method inputs; the slot starts as a recordednot_providedabsence rather than raising a missing-inputs error, and the missing-required-inputs message now names the optional inputs a caller may omit. - Post-run reads get a tri-state resolved accessor (
WorkingMemory.resolve_stuff/resolve_main_stuff: a value or a recorded absence). A slot with neither a value nor a record is still a hard error — never-produced is a bug, not an absence. Markers round-trip through blueprints, builder specs, IO contracts, and bundle representations; grammar misuse (X[]?,!on an output, markers on concept definitions) is rejected at parse withoptional_marker_invalid. - Static optionality validation (the absence-taint pass): Validation proves the absence-safety theorem at author time — a taint pass over each controller's dataflow computes per-slot presence (
guaranteed/maybe-absent) and rejects any maybe-absent slot that escapes without an explicit sink, with typed errors (optional_not_handled,optional_output_required,optional_branch_required_field) that each name the absence origin, the propagation path, and the fixes. The validation report also lists every liftable (skippable) pipe (liftable_pipes) — build-time visibility for "may be skipped when X is absent" — and gains a generalwarningsarray for advisory lints that never flipis_valid(first occupant:optional_force_redundant, a!whose slot is guaranteed present in every flow). - Template guard-lint (
optional_input_unguarded): Every template reference to a declared-optional (?) input must be guarded —@?var, a{% if var %}…{% endif %}block, or an inline presence conditional — or validation fails with the precise fix. Applies toPipeLLMprompts and system prompts,PipeComposetemplates, andPipeConditionexpressions. In the same motion,@?finally means what it says: an optional variable is no longer presence-required by the controller miss-gates, so the pipe runs and its guarded templates take the absent arm. - Execution graph updates:
GraphSpecnodes gain theskippedstatus with askip_reason— "why did my workflow produce nothing?" is now answerable from the graph — and data edges fed by a declared-optional (?) output carryoptional: true. Both flow through the in-process tracer and the distributed event-replay assembler (newpipe_end_skippedtrace event). - Storage provider plugin seam: The storage backend (
local/in_memory/s3/gcp) is selected at boot from aStorageProviderRegistrykeyed by the openstorage_config.methodtoken, populated by the always-on built-inStoragePlugin. Third parties can ship apipelex-storage-<backend>package that advertises itself under thepipelex.pluginsentry-point group — the same discovery/denylist machinery the inference and orchestrator seams use.storage_config.methodis now an openstr: an unknown method fails loudly at boot withUnknownStorageMethodError(listing the registered methods), not at config parse. See the newdocs/under-the-hood/storage-provider-plugins.md. - Secrets provider plugin seam: The secrets backend is now a plugin seam selected via the new open
secrets_config.methodtoken (default"env") from aSecretsProviderRegistry, populated by the always-on built-inSecretsPlugin. Third parties can ship apipelex-secrets-<backend>package (Vault, AWS Secrets Manager, …) under thepipelex.pluginsentry-point group — the same mechanism the storage seam uses. Out-of-the-box behavior is unchanged:envstays the default. An unknown method fails loudly at boot withUnknownSecretsMethodError. See the newdocs/under-the-hood/secrets-provider-plugins.md. - TOML pipeline inputs & templates: The
--inputsfile passed topipelex runandpipelex-agent run(pipe/bundle/method) can now be TOML in addition to JSON, discriminated by file extension — TOML's multi-line strings make text-heavy inputs much easier to author.run bundle <dir>auto-detectsinputs.tomlalongsideinputs.jsonwhen--inputsis omitted, erroring if both exist. Complementarily,pipelex build inputsandpipelex-agent inputsaccept--format json|toml(defaultjson) to emit the generated inputs template as TOML. Inline JSON ({…}) and agent-CLI stdin inputs stay JSON-only; a bare TOML datetime/date/time literal is rejected with an explicit "quote it as a string" error (native datetime concept support is a separate track). - Gateway models: Added support for
nano-banana-2-litethrough Pipelex Gateway.
- A plain input fed an absence causes the pipe to be skipped (implicitly lifted); its own output is recorded absent, chaining back to the origin so the miss short-circuits like Swift's
Changed
- Dropped Python 3.10 support (Breaking):
requires-pythonis now>=3.11,<3.15. The 3.10 compatibility bridges are gone —StrEnum,Self, andTraversableare imported directly from the stdlib at every call site, thepipelex.typesre-export module that existed only to paper over 3.10 is deleted, and thebackports.strenumconditional dependency (and its type stub) is dropped. CI test/lint matrices, thepackage-checkrequires-pythonfloor gate, and the contributor docs now start at 3.11. - Plugin API version bumped to 3 (Breaking):
PLUGIN_API_VERSIONis now3(was2) to add theadd_storage_providerandadd_secrets_providerregistrar menu methods. Plugin discovery version-checks with strict equality, so every external plugin must re-declaretargets_api = 3.pipelex-mistralai-workflowsregisters no storage or secrets provider, so thetargets_apibump is its only change.pipelex-temporalneeds the bump and a code migration: its payload-codec factory imports the now-removedmake_storage_provider_from_config(see Removed) and must switch to resolving the provider via the registry (get_storage_provider_registry().get_required(method=...)). PipeSignatureis not a pipe type (Breaking): A signature is now declared by omittingtype— a[pipe.x]section with notypeand nothing but the contract (description,output, optionalinputs, optionalsignature_for) is aPipeSignature. Writingtype = "PipeSignature"explicitly is rejected with a migration error ("PipeSignatureis no longer a pipe type — delete thetypeline"), and a typeless section declaring any non-contract field is a hard error naming the field. Thepipelex-agent pipeauthoring command mirrors this. MTHDS JSON Schema shape change: the signature arm no longer carries atypeproperty (an explicit tag now fails schema validation), so the downstream schema copies (mthds,vscode-pipelex,mthds-ui) must be re-synced on the next release via themthds-schema-syncskill.PipeConditioncontinuenow resolves the output as absent (Breaking): Thecontinuespecial outcome no longer passes the current main stuff through (and no longer errors when there is none). It records a declared-absentAbsenceRecordfor the condition's declared output — with the evaluated expression as the reason — and returns success, memory otherwise unchanged. Acontinue-reachablePipeConditionmust therefore declare its output optional (e.g.output = "Constraint?"), or validation rejects it (optional_output_required). Dry-run parity holds. Migration: the previous value stays in working memory under its own name, so downstream pipes consume it explicitly by that name (declared?when it may be absent); a coalescing operator is the planned ergonomic replacement for pass-through.- Controllers combine under absence:
PipeParallelno longer crashes when a branch result resolves absent (lifted branch orcontinue): with aCompositeoutput the absent component is omitted (ledger note kept), and with a structured output a non-required field absorbs the absence as its default (Noneunless the author declared another), while a required field fed an absent branch raises a typed error naming the branch, the field, and the fixes.PipeBatchcompacts: absent branch results are dropped from the aggregated list, so batching a "keep or skip" condition over items yields only the kept results. - Absent output delivery is now a first-class success: A run whose declared
?output resolves absent succeeds everywhere.main_stuff_nameonPipelexPipeRunOutputand the/executeresponse names the declared output slot even when it resolved absent — consumers branch on the absence record in the serialized working memory (absences), never on transport, and the ledger round-trips cross-process (hydrate_working_memoryreconstructs it). Themain_stuff.json/md/htmlartifact files become an explicit absence document ({"absent": true}plus the provenance chain) on both the typed and raw delivery paths,pipelex run/--save-main-stuffand the agent CLI'srunsurface it instead of crashing, and OTel/Langfuse capture serializes it. A working memory with neither a value nor a recorded absence still fails delivery loudly.
Fixed
- Template truth-tests on singular values no longer crash:
{% if var %}(and@?var, which expands to it) on a present singular value used to raiseTypeError: '…' content does not support len().— Jinja2's truth test fell through to the artefact's list-only__len__.StuffArtefactnow defines__bool__: a present non-list artefact is truthy, a list artefact follows list emptiness. This makes the optionals guard idiom safe on both arms. PipeComposeescaped-sigil literals ($$,@@) no longer double-rewrite:PipeComposealone stored its template already-preprocessed and then re-ran the sigil rewriter at guard-lint and render time. Because the escape collapse ($$name→$name) is not idempotent, the second pass resurrected escaped literals into interpolations — raising a spuriousoptional_input_unguardedon a$$namethat only looks like an optional reference, and silently rendering the value ofnameinstead of the literal$name.PipeComposenow stores authored source and rewrites exactly once, like every other pipe.--inputs ~/…now expands onrun pipe/run bundle: a quoted or=-form tilde path (--inputs "~/inputs.json", which the shell leaves unexpanded) is nowexpanduser()-ed before loading, resolving to the home directory instead of failing on a literal~— matching the existingrun methodbehavior, on both the human and agent CLIs.- Invalid storage/secrets
methoderrors stay actionable under STRICT:UnknownStorageMethodError/UnknownSecretsMethodErrorare marked caller-facing, so their "registered methods: … — checkstorage_config.method" guidance survives STRICT error disclosure instead of being redacted to a generic internal-error message. - Non-string JSON pipe
typegives an actionable error: atypethat is a list/dict/number in apipelex-agent pipeJSON spec now surfaces as anArgumentErrornaming the valid pipe types, instead of a cryptic internalTypeError: unhashable type. - GitHub Actions: Removed an invalid
environmentblock from themanual-trigger-tests-check.ymlworkflow.
Documentation
- Optionality guide: New "Understanding Optionality" page (
docs/building-methods/pipes/understanding-optionality.md) beside the multiplicity guide — presence markers, the runtime trichotomy (skip / run / fail), absence records and provenance, template guards, controllers under absence, and the static safety net. PipeBatch documents compaction under absence, PipeLLM documents the@?optional block sigil, and the run CLI page documents the absence artifact an absent main output produces.
Removed
make_storage_provider_from_config(Breaking): The module-level storage-provider factory (pipelex/tools/storage/storage_provider_factory.py) is removed — storage is now resolved through the config-selectedStorageProviderRegistryat boot. Downstream code that imported this helper (notablypipelex-temporal's payload-codec factory) must select through the registry instead.
[v0.37.0] - 2026-07-04
Highlights
PipeParallelalways combines — and every run has a main output — A parallel now always combines its branch outputs into its declaredoutputconcept (with the newnative.Compositeconcept as the ready-made combination vehicle), thecombined_outputfield is deleted from the MTHDS language, and the main-stuff invariant is enforced end to end: every completed pipe run delivers amain_stuff, so downstream surfaces (delivery, graph tracing, telemetry, wire models) can rely on it unconditionally.- Portable, statically validated image generation — A new portable
sizeparameter ("1k"/"2k"/"4k"tiers or exact pixel dimensions) carries the same size intent across providers, Gemini models gain image-to-image editing and extreme banner aspect ratios, and Google image models are now validated against declarative geometry rules at blueprint-load time — unsatisfiable requests fail fast instead of at the provider call.
Added
- Portable image size (
size) forPipeImgGen: Newsizeparameter accepting portable tiers ("1k","2k","4k") or exact pixel dimensions (e.g."2048x1152"). A tier means "this pixel class at my chosenaspect_ratio", mapped to each provider's own grid; an exact size is deterministic (declaringaspect_ratioalongside it is a validation error). Unsatisfiable requests fail as hard validation errors at blueprint-load time, never warn-and-ignore. Whensizeis unset, no size intent is sent and the provider default applies. The MTHDS JSON Schema exposes the field, and an optionalsizedefault is supported in[cogt.img_gen_config.img_gen_param_defaults]. native.Compositeconcept: New native concept backed byCompositeContent— an untyped, named composition holding sub-contents as top-level fields, serving as the default combination vehicle for parallel branches. Supports the full content surface:smart_dump, kajson/transport round-trip, and markdown/HTML rendering.- Gemini image-to-image (img2img) support: The Google img-gen worker now forwards input images to the Gemini API as inline parts, enabling image editing and multi-image composition for the
nano-bananamodels (including the newnano-banana-2-lite). Every img-gen worker now validates input images against the model's declared capability at job start, rejecting img2img on unsupported models with a cleanImgGenParameterErrorbefore any provider call. - Banner aspect ratios: Support for extreme banner formats (
landscape_4_1,landscape_8_1,portrait_1_4,portrait_1_8) from Gemini 3.1 image models. All other image-gen backends reject them with a clean parameter error. - Static validation for Google image models: Google image models now use
rulesblocks (geometry taxonomies likegemini_3_flash) in the backend deck, catching unsupported aspect-ratio and size combinations at blueprint-load time. The Google img-gen factory is keyed by taxonomy instead of hardcoded model names (Breaking: theGoogleImageGenModelname enum is removed — model handles are deck config, not code constants).
Changed
PipeParallelalways combines (Breaking): APipeParallelcontroller now always combines its branch outputs into its declaredoutputconcept and stamps it as the main output. The declaredoutputis strictly validated at author time and must beCompositeor a structured concept whose fields and types match the branchresultnames. Combination replaces the removedcombined_outputfield. Migration: pipes declaring both fields just drop thecombined_outputline;add_each_output-only pipes replace their placeholderoutputwithCompositeor a matching structured concept.add_each_outputkeeps its meaning and now defaults tofalse.- Main-stuff invariant enforced (Breaking): Every pipe run now guarantees a
main_stuff; defensive "maybe there is no main stuff" branches are removed, wire models make the field required (main_stuff_name: stronPipelexPipeRunOutputand the/executeresponse extension), andPipeOutput.optional_main_stuffis replaced byPipeOutput.main_stuff. - Orchestrator SPI delivery split (Breaking):
OrchestratorProtocol.runis now strictly the blocking arm (returning a completedPipelexPipeRunOutput). A newOrchestratorProtocol.starthandles fire-and-forget, returning aPipelexPipeDispatchAck(IDs only).PipelexPipeRunOutput.is_completedis deleted — it is always a completed output now. LLMWorkerInternalAbstractfolded (Breaking): Removed and folded intoLLMWorkerAbstract, which now owns the whole job lifecycle (capability checks, constraints, telemetry). Subclasses extendLLMWorkerAbstractdirectly and implement_gen_text/_gen_object, nothing else.- Type preservation across transport:
Compositecomponents (and their nested lists) now retain strict types across transport boundaries (dump_for_transport/ hydration) via private class markers. PipeParallelhonorsfinal_stuff_code: A requested final stuff code (e.g. from aPipeBatch) is now correctly stamped on the parallel's combined output.- Docs — inference plugins: Rewrote
using-inference-plugins.mdto demonstrate a genuinepipelex.pluginsentry-point package instead of a legacy config workaround. - Linting pipeline (repo-local): in the pipelex repo itself,
plxt lintnow validates.mthdsfiles against the locally generated schema (derived/mthds_schema.json) rather than the released schema bundled withplxt. This is a.pipelex/plxt.tomloverride for this repo only — theplxt.tomltemplate distributed bypipelex init configis unchanged. - Dry-run mocks: Reduced the default dry-run mock list generation from 3 items to 2 to cut dry-run processing time.
- Bumped
mthdsdependency from>=0.6.0to>=0.7.0.
Fixed
PipeConditionpass-through failure: Acontinueoutcome with no pre-existing main stuff now fails loudly and actionably at the pipe level instead of crashing downstream surfaces.- Stale main stuff in parallels: A pipeline ending in an
add_each_output-onlyPipeParallelno longer silently reports the previous step's output as its main result. add_each_outputoptional in the builder spec:PipeParallelSpecnow defaultsadd_each_outputtofalselike the blueprint does, so a generated always-combine spec with justbranchesandoutputno longer fails validation beforeto_blueprint().- Google img-gen size handling: The native Google worker and gateway path now send the requested
image_sizeto the Gemini API instead of hardcoding"1K", making 2K/4K generation reachable. - Img2img support checks: The capability check now keys off the model's declared
inputsrather than requiring aninput_imagesrule, which had falsely reported Gemini models as unsupported. - Routing profile optional routes:
optional_routesdeclared inrouting_profiles.tomlare no longer silently dropped by the factory. - Unknown boot orchestrator fails loud: Requesting a boot orchestrator no installed plugin provides — via
--orchestrator <name>orPipelex.make(boot_orchestrator=...)— now raisesUnknownBootOrchestratorErrorat boot instead of silently falling back to in-process execution. - Failed boot no longer leaks process-global state: A
Pipelex.makethat raises during setup now releases the process-global singletons a partial boot acquired (config, logging, the kajson class registry, template registries), so a failed boot no longer poisons a subsequent boot in the same process. - HuggingFace streaming errors: The provider error-body reader now safely tolerates unread
httpxstreaming responses without crashing withhttpx.ResponseNotRead.
Removed
combined_outputfield (Breaking): Removed from the MTHDS language forPipeParallel; pipes now declare their combination target directly in theoutputfield.- Legacy external plugin setter (Breaking): Removed
set_llm_worker_from_external_pluginfrom the inference manager, fully replaced by thepipelex.pluginsentry point.
Security
- Transformers vulnerability: Bumped
transformerspast CVE-2026-4372 (GHSA-29pf-2h5f-8g72) to resolve a high-severity RCE. To unblock this, thehuggingfaceextra now requireshuggingface_hub>=1.5.0,<2.0.0(Breaking).
[v0.36.0] - 2026-06-30
Highlights
- Orchestration plugin SPI — Pipelex opens its execution path to pluggable orchestrators: the orchestrator that runs a job is now chosen per call by an open
orchestration_modetoken, with the core shipping an in-processdirectorchestrator and the contract ready for plugins to supply distributed backends. - Orchestration plugin contract (
orchestration_mode+DeliveryMode): The contract is built on two independent axes — an openorchestration_modetoken (which orchestrator runs the job —directin core, other modes supplied by plugins) and a closedDeliveryModeenum (the wait-semantics axis —BLOCKING/FIRE_AND_FORGET). An orchestrator plugin implementsOrchestratorProtocol.runwith a requireddelivery: DeliveryModekeyword and declares asupports_fire_and_forget: boolcapability; the orchestrator registries are keyed by theorchestration_modetoken.PipelexPipeRunInputcarriesorchestration_mode+delivery. - Orchestrator-dispatched
/validate: A new per-call bundle-validator seam (BundleValidatorProtocol/BundleValidatorRegistry) makes/validatedispatch byorchestration_modethe way/startruns a pipe —directvalidates in-process, distributed modes dispatch the job to a worker — with a byte-identical verdict across backends. The coredirectplugin registers an in-processDirectBundleValidator. - Honest fire-and-forget delivery: A fire-and-forget
/startrequest is honored only when the resolved orchestrator can do genuine async; an orchestrator that cannot (e.g. the in-processdirectmode) returns a 4xx rather than running the job to completion and falsely acking.
Added
- Explicit graph targets for validation: Graph generation during validation and dry runs now accepts an explicit
pipe_codetarget, so developers can generate graphs for a specific pipe in a bundle even when nomain_pipeis declared. This is wired through the CLI (validate bundle --pipe <target> --graph/--view),dry_run_pipeline,generate_graph_for_bundle,generate_view_for_bundle, andPipelexMTHDSProtocol.validate(extra={"graph_pipe_code": "..."}). - GraphSpec source path enrichment:
GraphSpecartifacts now include the declarationsourcefile path for pipes and concepts inpipe_registryandconcept_registry, powered byLibraryCrate.source_map. - CI/environment heartbeats: Added
WAIT_WITH_HEARTBEATandRUN_WITH_HEARTBEATMakefile macros that emit a periodic heartbeat (default every 20s) to prevent CI runners and sandboxes from timing out during long tasks; applied to theagent-test,pyright,mypy, andpylinttargets. - Developer guidelines: Expanded
python_standards.mdwith rules on filesystem paths (pathlib.Pathoverstr/os.path), data-holder shapes (NamedTuplevs.pydantic.dataclassesvs.BaseModel), keyword-only arguments (enforced viamake cko/make fko), and custom exception placement (exceptions.pyor<topic>_exceptions.py).
Changed
dry_run_pipelinereturn shape:dry_run_pipelinenow returns the fully resolved, domain-qualified pipe reference alongside theGraphSpec.- Graph viewer assets bumped: The CDN-pinned
@pipelex/mthds-uigraph viewer used by the generated ReactFlow HTML is upgraded from0.6.4to0.11.0, with refreshed Subresource Integrity hashes.0.11.0addsPipeStructureto the viewer's recognized pipe types, so graphs containing aPipeStructurenode (e.g. from thepreliminary_textstructuring path) render instead of showing the GraphSpec validation error screen.
Fixed
- Graph generation on bundles without a
main_pipe: Requesting a graph or view via the CLI no longer fails with a missingmain_pipeerror when a valid pipe is targeted with--pipe. - Developer guidelines typo: Fixed a minor spacing typo in
pytest_standards.md.
[v0.35.1] - 2026-06-22
Changed
PipeImgGendocumentation: Rewrote the docs to clarify how inputs are consumed.PipeImgGenhas no dedicated "prompt concept"; it uses apromptstring template into which declaredinputsare injected at runtime —Textvariables are interpolated directly, whileImagevariables (single or lists) are injected as reference images to enable image-to-image and editing workflows. Added examples demonstrating this vision pattern.
Fixed
- Blueprint-stage validation error categorization:
PipeValidationErrors raised during blueprint parsing (e.g.PipeBatchorSubPipeitem name collisions) previously lost theirerror_typebecause Pydantic wrapped them in a genericvalue_error, degrading them to uncategorized residual errors. The categorizer now unwraps them, preserving their structurederror_type,pipe_code,domain_code, andsourcelocators.
Removed
- Native concept
ImgGenPrompt(Breaking): Removed the built-innative.ImgGenPromptconcept. It was structurally identical toText(mapped toTextContent) and added no unique semantics;PipeImgGennever depended on it. Migration: replaceImgGenPrompt(orrefines = "ImgGenPrompt") withTextin your.mthdsfiles. The internalImgGenPromptruntime model, theTemplateCategory.IMG_GEN_PROMPTcategory, andImgGenPromptErrorare unchanged. - Dead validation error type (Breaking): Removed the
PipeValidationErrorType.img_gen_input_not_text_compatibleenum value. It had no raise sites and contradicted the current design, wherePipeImgGenaccepts image inputs as a first-class feature.
[v0.35.0] - 2026-06-18
Added
- Structured validation errors: Bundle validation failures now emit categorized
validation_errors[]items with identity locators, so machine consumers can readerror_typeand locators instead of parsing text. Categories: unresolved concept reference (pipe_validation/unresolved_conceptwithpipe_code,concept_code,field_name; orblueprint_validation/unresolved_conceptwith owningconcept_code), undefined pipe dependency (pipe_validation/unresolved_pipe_dependencywithpipe_codeand the newmissing_pipe_codelocator), and unknown pipe type (blueprint_validation/unknown_pipe_typewithpipe_code). - New error locators and types: Added the
missing_pipe_codelocator field and thePipeValidationErrorTypevaluesunresolved_concept,unresolved_pipe_dependency, andunknown_pipe_type. - String utilities: Added
pluralizeandcount_with_nountopipelex.tools.misc.string_utilsfor correct CLI output grammar (e.g. "1 pipe" instead of "1 pipe(s)"). - Documentation: Documented the 0/1/2 exit-code policy in
docs/under-the-hood/error-model.mdand addedwip/structured-validation-errors-deferred-findings.mdtracking deferred follow-ups.
Changed
- Validate exit-code policy (Breaking): Both
pipelex validateandpipelex-agent validatenow use a three-tier exit code mirroring the hosted/validateAPI:0= valid (including valid-but-not-runnable with--allow-signatures),1= negative verdict (invalid, or valid-but-not-runnable without--allow-signatures),2= no verdict (bad arguments, unresolvable target, or setup/internal errors). Consumers testing zero vs. non-zero are unaffected; machine consumers should rely on the structuredis_validJSON field. - Relocated markdown renderer: Moved
format_validate_markdownfrom CLI internals to the publicpipelex.pipeline.validation_rendermodule so other surfaces (e.g. thepipelex-api/validateroute) can use it without Typer/CLI dependencies, and addedrender_invalid_validation_markdownfor invalid verdicts. - Error class hierarchy:
ConceptLibraryErrornow extendsLibraryLoadingError(instead ofLibraryError) so it can carry per-reference structured items through the existing error cascade. - Strict protocol arguments:
PipelexMTHDSProtocolnow rejectsextraextension arguments, raisingPipelineRequestError, since the local runtime defines no extension arguments. - Bumped
mthdsdependency from>=0.4.1to>=0.5.0.
Fixed
- Dropped
pipe_codeon blueprint errors: The blueprint validation-error categorizer matched the wrong Pydanticlockey (pipesinstead ofpipe), causing categorized items (e.g.missing_input_variable) to silently lose theirpipe_codelocator; it now populates correctly. - CLI output grammar: Validation CLI output now uses the new string utilities, fixing awkward pluralizations (e.g. "Validated 1 pipe(s)" is now "Validated 1 pipe").
[v0.34.0] - 2026-06-17
Highlights
- Structured validation errors — validation failures now return a typed, per-error
validation_errors[]on the error wire instead of a baredetailstring, with the same shape across the HTTP API and the agent CLI. - Structured
validation_errorson the error wire:ErrorReportgains a typedvalidation_errors: list[ValidationErrorItem] | Nonefield.ValidateBundleError.to_error_report()flattens its per-error data onto it via a single shared builder (pipelex/pipeline/validation_errors.py), so the structured error report an HTTP API surfaces carries machine-mappable per-error diagnostics —category,message, identity fields, and asource(declaring file) for cross-file mapping — instead of only adetailstring. The closedValidationErrorCategoryset isblueprint_validation/pipe_factory/pipe_validation/dry_run; a residual dry-run failure (DryRunError/PipeRunError, no structured locator) is projected as onedry_runitem only when no categorized error has data, so an invalid verdict always carries a non-emptyvalidation_errors[](the structured-info invariant) rather than a bare message. The same builder feeds the agent CLI'svalidation_errorsJSON array, so the CLI and API structured shapes cannot drift. The list is surfaced under STRICT disclosure (_STRICT_KEPT_FIELDS) because it describes the caller's own submitted bundle, not server internals. - Changed — agent CLI
validation_errorsshape: thevalidatecommands' error envelope now omits null-valued keys per entry (exclude_none) and gains the previously-droppedsource,field_name, andconcept_codefields. Entries are guaranteed to carrycategoryandmessage; all other keys are present only when populated, so consumers must treat them as optional rather than assume a fixed key set. - Per-content
sourceon the in-memory validate path:PipelexInterpreter.make_pipelex_bundle_blueprint(mthds_source=...)andvalidate_bundle(mthds_sources=...)let a caller attach a logical source to each in-memory bundle string, threaded intoblueprint.source. A sourcelessmthds_contentssubmission previously producedsource=None, breaking cross-file diagnostics; a host (e.g. an HTTP API) can now pass per-item sources so the structuredvalidation_errorscarry a real owning file. The on-disk CLI path is unchanged (it already records real file paths). -
dry_runvalidation category:ValidationErrorCategorygains adry_runvalue. A dry-run residual failure that previously produced a bare-messageValidateBundleErrorwith an emptyvalidation_errors[]now surfaces one structureddry_runitem carrying the message (graph-level, so typically nosource) — closing the structured-info gap that drove consumers to fabricate a category. -
Keyword-only argument enforcement — a mechanical guard enforces the keyword-only argument convention across
pipelex/, end to end — local autofix through the CI gate. - Keyword-only AST guard: A custom AST-based linter (
pipelex-dev check-keyword-only/make cko) that mechanically enforces the keyword-only argument convention acrosspipelex/, wired intomake checkandmake agent-check. - Keyword-only auto-fix: A non-gating
--fixmode (pipelex-dev check-keyword-only --fix/make fix-keyword-only/make fko) that rewrites every mechanically-fixable violation by inserting a bare*as far left as possible (afterself/cls), re-parsing each rewrite before writing and reporting the shapes it can't fix mechanically. It runs early inmake agent-check; the read-only check still runs last and owns the pass/fail gate. - Claude Code hook: A
PostToolUsebash hook (.claude/hooks/check-keyword-only.sh) that runs the guard on edited files for immediate blocking feedback to AI agents. - CI integration: A dedicated
lint-keyword-onlyjob in the GitHub Actions linting workflow to block non-compliant signatures from merging. - Convention documentation: New
docs/contribute/keyword-only-arguments.md, plus updates toCLAUDE.mdandAGENTS.mdestablishing the keyword-only convention as a standing rule.
Added
is_validon the canonical validation report:PipelexValidationReportgainsis_valid: Literal[True] = True, the always-true discriminant of the valid arm of the hosted/validateresponse union (mirrored by pipelex-api'sInvalidReport'sLiteral[False]). It sits besideis_runnable: a sound bundle may still be not-yet-runnable.- Offline CLI unit tests: Coverage for the pipelex-internal logic behind the CLI commands —
doctordiagnostics,runexecution and its sync wrapper, thebuildcodegen cores, the readiness gate,show/which, and the gateway/telemetry/signature error handlers (the spec'd CLI interface stays owned by the conformance suite). - Offline inference & runtime unit tests: Coverage for layers that can break without a provider — structured-output↔instructor mode mapping, model-deck reference checks, the image-gen argument and worker-routing factories, gateway request-shaping and extract parsing, the Mistral factory, the local observer sink, the output renderer, builder spec validation /
to_blueprint(), the pipeline runner's error paths, the TOML config-sync engine, and the storage config validators.
Changed
- [BREAKING] Keyword-only public API: Top-level public surfaces now require keyword arguments after the first parameter. A caller passing a second-or-later argument positionally must switch to keyword form — affected methods include
Pipelex.make(integration_mode, *, ...),Pipelex.setup(integration_mode, *, ...), andPipelexHub.setup_config(config_cls, *, ...). Downstream consumers to check:pipelex-api,pipelex-worker,n8n-nodes-pipelex, cookbook, starter. - Codebase-wide keyword-only refactor: The entire
pipelex/tree (leaf tools, domain core, inference layer, execution path, framework-sensitive packages) now places a bare*after the subject parameter, requiring all later arguments to be named at the call site (e.g.copy_file(src, target_path=dst, overwrite=False)). - Signature subject corrections: Reordered parameters so the true semantic subject is the first positional argument, e.g.
parse_pipe_spec(spec_data, *, pipe_type),hydrate_content(raw_content, *, concept), andwrite_manifest(manifest, *, deck_dir).parse_pipe_specis consumed by the hosted runner API (pipelex-api), updated in lockstep. - [BREAKING] Canonical protocol validation report:
PipelexValidationReportis reworked into the canonical typed shape shared by every backend and moved topipelex/pipeline/validation_report.py— a typedbundle_blueprint(replacing the untyped single-or-listblueprintdump),pipe_io_contractskeyed by namespacedpipe_ref(newpipelex/pipeline/pipe_io_contracts.py),validated_pipes, and thepending_signatures/is_runnableverdict. It is assembled in exactly one place (build_validation_report) with a single shared primary-blueprint rule (select_primary_blueprint). - [BREAKING]
validated_pipeskeypipe_code→pipe_ref: the entry has always carried the namespacedpipe_ref(domain.code) under a key named for the wrong identity; the key now says what the value is. - Protocol
validatenow produces a best-effortgraph_spec: when the batch declares amain_pipe, the local runtime dry-runs it in-process and ships the resultingGraphSpecvia one shared implementation (best_effort_graph_spec); a graph-arm domain failure degrades tograph_spec=Nonewith validation still successful. (dry_run_pipe_in_processmoved topipelex/pipe_run/dry_run_in_process.pyto break an import cycle.) - [BREAKING]
MTHDS_PROTOCOL_VERSIONdeleted: the hardcoded duplicate is gone fromrunner.py; the SDK'sPROTOCOL_VERSION(mthds.protocol.protocol) is the single source of truth, imported directly by consumers including the hosted API. - Additive multi-file library construction: Same-domain
.mthdslibraries can now be built as separate, additive files (forward-declaredPipeSignatureheaders plus concrete definitions in sibling files), enabling parallel top-down construction. APipeSignatureand a same-code concrete pipe reconcile (contracts compared by normalized concept identity) instead of colliding; concept and qualified pipe references resolve against the merged library across sibling and separately-loaded files; domaindescription/system_promptmerge order-independently; and a successfulvalidatereports library-widepending_signaturesplus anis_runnableverdict in both JSON and markdown. - [BREAKING]
PipeSignatureevicted from the executable pipe taxonomy: a signature is a contract, not a way of running, soPipeType.PIPE_SIGNATUREandPipeCategory.PIPE_SIGNATUREare removed (any code matching on them must drop that arm). It stays aPipeAbstractsubclass withpipe_category = None, andis_signatureis now a class fact rather than an enum read. - [BREAKING] Signatures are never a validation error (signatures-as-data): the validator no longer raises when a pipe reaches an unimplemented
PipeSignature. Strict and lenient modes return the same report body — the assembled library's outstanding signatures viapending_signaturesandis_runnable = not pending_signatures.allow_signaturesnarrows to a sweep-mechanics flag (whether signature pipes are mock-run and listed invalidated_pipes); it no longer changes the verdict. The "is this a failure?" decision moves to the consumer: the whole-bundle / whole-library surfaces (pipelex validate,pipelex validate --all,pipelex-agent validate bundle/validate method/validate pipe --all) derive the exit code from the library-wide runnability verdict — strict by default, exiting non-zero onnot is_runnableunless--allow-signatures, while still emitting the success envelope (carryingpending_signatures+is_runnable: false). Single-pipe surfaces make no library-wide runnability claim and never gate: barevalidate pipe <code>, andvalidate bundle/validate methodinvoked with--pipe(the slice can be fully implemented even when unrelated placeholders remain elsewhere). The execute/run path is unchanged — running a stub still raisesPipeSignatureNotExecutableError. - [BREAKING] Host-wiring guards reclassified to
PipelexUnexpectedError:validate_bundle/load_concepts_only's "provide exactly one ofmthds_contents/mthds_file_path" guards (and the existingmthds_sources-length-mismatch guard) now raisePipelexUnexpectedError(→ 500), notValidateBundleError— a caller wiring bug is a programmer error, not a content verdict to be reported as an invalid bundle. The empty-mthds_contentsguard stays caller-facing.
Fixed
- Protocol model deck no longer loses aliases to cross-category collisions:
PipelexModelDeck.aliases/waterfallsare now keyed by model category ({category: {alias: model}}) instead of being flattened withupdate(), which silently kept only the last category's entry for an alias name shared across categories. Breaking for the deck's extension shape. - JSON-Schema rendering failures on the validate surfaces are now structured errors: a pydantic schema-generation failure while building
pipe_io_contractsnow raises the newPipeIOContractError(naming the offending pipe/input/concept) instead of a raw exception. - Protocol
validateteardown can no longer mask the real error: a raising library teardown is suppressed while a body error is propagating, and the validation library id is captured once so the graph arm and the teardown always target the same library. - Empty
mthds_contentsis rejected with a structured error:validate_bundleandselect_primary_blueprintnow raiseValidateBundleErrorinstead of crashing primary-blueprint selection with a rawIndexError; the hand-rolled first-declaring-main_pipeloops inexecution_seams,dry_run_pipeline, andinputs_opsare folded into the singleselect_primary_blueprint. - Structured-info invariant is now total — parse-level failures carry a structured item: a malformed
.mthdsfile (a TOML-syntax error, an empty blueprint, or a bundle-elaborator failure) is raised with only a message and no categorized data, so an invalid verdict previously rode an emptyvalidation_errors[]for the single most common failure mode. The shared builder (build_validation_error_items) gains a last-resortfallback_messageresidual: when no categorized error and nodry_runresidual produced an item, it emits oneblueprint_validationitem carrying the message (nosource, noerror_type— the bundle could not become a blueprint at all). Both surfaces —ValidateBundleError.to_error_report()and the agent CLI'sextract_validation_errors()— pass it, so every invalid verdict now carries a non-emptyvalidation_errors[], never a bare message. - Qualified same-domain pipe references resolve across files: a controller referencing a sibling-file pipe by qualified name (
research.find_key_findings) is now deferred to the merged library like bare references; a reference no file declares is still rejected at load. - Concepts-only loading validates concept references: the
pipelex structures/load_concepts_onlypath now runs the cross-file concept-reference check (batching sibling files into one pass) instead of silently accepting a structure field pointing at an undeclared concept. - Multi-file dependency packages reconcile signatures with their definitions: a dependency package split into a
PipeSignatureheader plus its concrete sibling now goes through the same additive merge instead of colliding on the duplicate code and dropping one declaration by load order. - OpenAI image moderation mapping was inverted:
is_moderated=truesent the less restrictivemoderation="low"andfalsesent"auto"— the mapping now matches the flag (enabled →"auto", disabled →"low").ImgGenSetting.is_moderatedalso defaults toNone, so workers omit the parameter and the provider's own default applies (which also stops force-disabling FAL'senable_safety_checker). - Storage config validation now covers every provider and requires a real
{hash}slot: theuri_formatcheck is enforced uniformly across local / in-memory / S3 / GCP — every placeholder must be a plain supported{name}, a{hash}slot is required (GCP previously accepted the bare substringhash, silently overwriting every stored object), and buckets must set a positivesigned_urls_lifespan_seconds. A misconfigured format now fails fast at Pipelex boot instead of at the first content store. - Mistral chat requests now send the system message before the user message:
make_simple_messagespreviously appended it after the user message, contradicting its own docstring and the OpenAI-typed sibling. - String concept values in bundle specs are constructible again: a bare string in the
ConceptSpec | strunion now validates (no longer crashing themode="before"validator) and passes through to the blueprint as the concept's description instead of intostructure, where the loader rejected it. - LocalObserver JSONL records always carry the true lifecycle event name: a payload's own
event_typekey can no longer overwrite the event name in the written record, which had broken event-type filtering for JSONL consumers. - Tests under
tests/**/build/are no longer silently skipped: pytest's defaultnorecursedirsincludesbuild, so the wholetests/unit/pipelex/cli/commands/build/tree was never collected; the config now overridesnorecursedirsand setstestpaths = ["tests"]. Anything-output option numbering is now deterministic: the output renderer sorts aPipeCondition's possible outputs by pipe code instead of iterating a set, sooutput_option_N/schema_option_Nnumbering is stable across runs.- Documentation examples: Updated code snippets in
docs/under-the-hood/to match the new keyword-only signatures. - Test mock assertions: Migrated mock assertions from
.call_args.argsto.call_args.kwargsto reflect keyword-only calls.
Removed
- [BREAKING]
SignaturesNotAllowedErrordeleted: with signatures no longer a validation error, the strict-mode signature pre-pass (BundleValidator._signature_pre_pass), thesignature_check_errorfield onValidateBundleError, thehandle_signatures_not_allowed_errorCLI renderer, and theSignaturesNotAllowedErrorexception class itself are removed. Code that caughtSignaturesNotAllowedErroron the validate path should read the report'spending_signatures/is_runnableinstead; the execute path'sPipeSignatureNotExecutableErroris unaffected. - Keyword-only migration scaffolding: With the whole
pipelex/tree converted, the temporary baseline file and thepipelex-dev check-keyword-only --regen-baselineflag are removed; the guard now hard-blocks on any new violation rather than burning one down.
[v0.33.0] - 2026-06-11
Breaking Changes
PipelexRunner→PipelexMTHDSProtocol— the runner class now implements the MTHDS Protocol (mthds.protocol.protocol.MTHDSProtocol, mthds 0.4.1). Method renames:execute_pipeline→execute,start_pipeline→start(stillNotImplementedErrorlocally).execute/startcarry the protocol's basic args plus a genericextrapassthrough — server-specific args (a client-supplied run id, callbacks, a storedmethod_id) rideextra, never named params. Response classes:PipelexPipelineExecuteResponse→PipelexRunResultExecute(subclassesRunResultExecute—pipeline_run_id+pipe_output),PipelexPipelineStartResponse→PipelexRunResultStart(subclassesRunResultStart—pipeline_run_idonly).state/created_at/finished_at/main_stuff_name/workflow_idare pipelex extension fields on the protocol's base responses; the run identifier keeps the namepipeline_run_ideverywhere.mthdspin → 0.4.1 — the restructured SDK (mthds.protocol+mthds.runners.api). The agent CLI's API run path usesMthdsAPIClient(mthds.runners.api.client) directly; domain shapes import frommthds.protocol.*, Dict wire models frommthds.runners.api.models.
Changed
--dry-runnow mocks at the cogt leaf instead of swapping out the operators.run_moderides a newCogtRunParamscarrier (derived fromPipeRunParams.run_mode, stamped on every cogt assignment), so a DRY run mocks inside the inference leaf at zero AI cost, with no API keys and no storage IO (the img/extract DRY branches sit above the store step).ContentGeneratorDryis deleted: operators no longer swap generators (the base operator's dry path simply reuses the live path), and the in-process validation scopes pass an inlineContentGenerator. Object mocks are now schema-built; classes with exotic format constraints should declareexamples/mock_format(a re-validation failure surfaces as a typedDryRunObjectFidelityError, and a deterministic mock-build failure as the newDryRunMockBuildError).- Unified dry run —
--mock-inferenceremoved (breaking). There is now exactly one non-live run mode:--dry-run. The mock-inference mode is retired; its capability — non-zero synthetic usage so the cost report renders — survives as an internalis_mock_usagesub-flag of DRY onCogtRunParams(replacingis_mock_inference; setting it on a LIVE run is a validation error). It is exposed on the Python surface (PipelexMTHDSProtocol/execute/prepare_pipe_jobviais_mock_usage=...) and as a hidden test-only CLI trigger, deliberately undocumented. Dry-run leaf coverage was already uniform across every operator, soMockInferenceUnsupportedErrorand its img-gen/extract/search guards are deleted;MockInferenceObjectFidelityErroris renamedDryRunObjectFidelityError(mock-built objects are DRY-only now); themock_inferenceusage sentinel is renamedmock_usage. - Keyless boot (
needs_inference=False) now forces every run to DRY instead of installing a mock generator. Generator selection is purely backend-keyed; the forced-DRY flag is consumed atPipeRunParamsFactory.make_run_params— the single writer ofrun_mode— so every execution entry point is covered, including the runtime bridge.
Removed
dry_run_config.apply_to_jinja2_renderingconfig key: it was dead — PipeCompose renders templates directly and the jinja2 parse check survives in the templating leaf's DRY branch. Remove it from your.pipelex/pipelex.tomloverride if present (config is strict and will reject the unknown key).
Fixed
-
Resubmitting a
pipeline_run_idafter its run finished no longer fails permanently.PipelineManagerwas the one per-run registry with no per-run removal: every run permanently stranded its key, so a second submission of the samepipeline_run_idagainst a long-lived server process raisedPipelineManagerAlreadyExistsError— surfacing as an unrecoverable 500 from the hosted runner API until process restart. The registry entry is now freed on every exit path:execute'sfinallyremoves it after each run (success or failure), andpipeline_run_setupremoves its own registration when setup fails after registering (the caller never learns the id on that path, so setup must self-clean). Serial resubmission of a completed/failed run id now succeeds; only genuinely concurrent same-id runs still collide — deliberately, because the collision raise fires beforeopen_tracerand shields the live direct-mode tracer (keyed by the caller-suppliablepipeline_run_id) fromopen_tracer's stale-key pop-and-replace healing. The hosted API maps the remaining concurrent-duplicate case to 409 Conflict (pipelex-api change). -
dry_run_pipelinenow owns its graph transport — graph generation no longer depends on the host'stracing_config. The function requests a graph explicitly (generate_graph=True) but relied on the host's configured tracing backend as the emit/assemble channel, so a host withtracing_config.is_enabled = false(e.g. pipelex-api's/validatein direct mode, where the web-app's Dry Run button lands) always got "Pipeline execution did not produce a graph spec" and a response withoutgraph_spec. The run now traces through a scopedInMemoryEventLog— the graph comes back under any tracing config, and validation dry-runs stop writing NDJSON/DynamoDB trace events as a side effect when tracing IS enabled. The no-graph contract violation is now a typedDryRunGraphNotProducedError(was a barePipelexError, ambiguous in host logs that record only the exception type) — raised by bothdry_run_pipelineanddry_run_pipe_in_process. - tz-aware datetime payloads no longer fail to decode on hosts without a timezone database — kajson bumped to 0.7.0. kajson ≤ 0.6.0 decoded timezone-aware datetimes via
ZoneInfo(...), which needs the IANA tz database: system tz files or thetzdatapackage. On hosts with neither (slim containers, uv-managed standalone Pythons — including the CI test runner, wheretzdataonly arrived transitively via pandas on Python < 3.11), decoding any aware-datetime payload raisedZoneInfoNotFoundError. Fixed upstream in kajson 0.7.0: its self-sufficient timezone wire format carries the UTC offset (decoding degrades gracefully to a fixed offset instead of raising, and plain UTC decodes with zero tz-database dependence), and kajson now declarestzdataas its own runtime dependency, so a tz database is always available for named zones.
Added
- Protocol
validate/models/versiononPipelexMTHDSProtocol—validatewrapsvalidate_bundle(blueprints + per-pipe structures into the protocolValidationReport);modelswraps the builder'slist_modelsinto aModelDeck;versionreportsprotocol_version0.6.0 with the installed pipelex version.
[v0.32.1] - 2026-06-09
Added
render_cost_report_for_output(pipe_output)submitter helper. A one-arg convenience overrender_run_cost_reportthat unpackspipeline_run_idandtokens_usagesfrom a finishedPipeOutputand derives the--costsgate from the output itself —pipe_output.tokens_usages is Noneis exactly the signal that cost reporting was off for the run, the decision the runner already resolved (with all--costs/--no-costsoverrides applied) and recorded on the output. Embedders and thepipelex runCLI no longer re-derive the three primitive arguments by hand or re-read global config to reconstruct the gate.render_run_cost_reportis unchanged as the low-level primitive for paths where the three values come from different places (the agent CLI'sbuild_cost_summaryJSON envelope, distributed reassembly).
Changed
typeris now capped (>=0.16,<0.27). pipelex subclasses typer'sTyperGroupand overridesmake_context, so it is coupled to typer/click internals and a future typer minor can break the CLI. The cap is tested through 0.26; a new dependency-canary CI job resolves the latest dependencies on a schedule so the bound is bumped deliberately rather than discovered in a user's install.
Fixed
- CLI no longer crashes under newer typer/click. Every
pipelexsubcommand (build,run,validate,init,worker, …) raisedRuntimeError: There is no active click contextand exited 1 when run againsttyper >= 0.26/click >= 8.4— the versions a freshpip install pipelexresolves. The rootapp_callbackfetched the context via the globalclick.get_current_context()instead of thectxTyper already injects; the global context stack isn't populated when a subcommand is dispatched under those versions. It now uses the injectedctx, which is version-robust. The sibling--tracebackflag had the same flaw —is_traceback_requested()read it viaclick.get_current_context(), so under those versions it was silently ignored on handled errors — and is now recorded at parse time in a context-independent flag. A subprocess CLI smoke test (tests/unit/pipelex/cli/test_cli_entrypoint_smoke.py) guards every subcommand against regressing.
[v0.32.0] - 2026-06-09
This cycle reworks cost reporting so it stops leaking. Cost now rides on the run result instead of a side buffer: the success-path registry leak is gone by removal, and a new --costs switch decouples cost collection from --graph. It also extracts the framework-agnostic runtime bridge so any host runtime — not just Mistral Workflows — can embed Pipelex through one boundary.
Added
-
--costs/--no-costs(default on).pipelex run pipe|method|bundlegains a dedicated cost switch that emits usage tracing events and renders the end-of-run cost report. It rides the shared trace-event transport independently of--graph, so--no-graph --costsreports cost without building a graph and--graph --no-costsbuilds a graph with no cost report. It replaces the removed--cost-report(see Changed). -
tokens_usagesonPipeOutput. Newtokens_usages: list[AnyTokensUsage] | Noneandusage_assembly_error: str | Nonefields, mirroringgraph_spec/graph_assembly_error. Cost is now part of the run result and is exposed automatically wherever aPipeOutputis returned, including the Pipelex API response. Render it withCostRegistry.generate_report(tokens_usages=...). -
--mock-inference. A LIVE run that fakes AI calls at the inference leaf with reportable synthetic usage, so cost reporting can be validated cheaply and deterministically without billing tokens. Mutually exclusive with--dry-run. It covers the LLM leaf; image-generation / extract / search under--mock-inferencefail loud withMockInferenceUnsupportedError(pointing at--dry-run) rather than silently calling the real provider. -
Cost report in the agent CLI JSON.
pipelex-agent run ... --with-memoryattaches a best-effort structuredcost_report({total_cost, by_model}, real USD) to its JSON envelope when the run did reportable work and summary aggregation succeeds — treat it as optional (absent for dry runs,--no-costs, the API-runner path, or an aggregation failure). The agent surface stays JSON-only — no Rich table on stderr; compact mode is unchanged.
Changed
-
Mistral Workflows integration extracted into a dedicated package. The optional
pipelex[mistralai-workflows]extra and thepipelex.plugins.mistralai_workflows.*modules have been removed frompipelex. The Mistral Workflows integration now ships separately as its own package,pipelex-mistralai-workflows. The framework-agnostic runtime-bridge core (boundary types,run_pipe_via_bridge,PipelexExecutionMode,ensure_pipelex_booted) has been promoted frompipelex.plugins.mistralai_workflows.*topipelex.runtime_bridge.*so any host runtime — not just Mistral Workflows — can embed Pipelex. No behavior changes; activities, boundary types, and execution modes are identical. -
--cost-reportremoved, folded into--costs. Breaking:--cost-report/--no-cost-reportis gone fromrun pipe|method|bundle. Use--costs(default on) instead. -
Cost reporting is event-sourced; the submitter-side
UsageRegistryis removed. The cost report is rendered fromPipeOutput.tokens_usages, not from an in-process registry.ReportingProtocol(andReportingNoOp) no longer exposeopen_registry/close_registry/generate_report/inject_tokens_usages, and theUsageRegistrymodel is gone. Embedders that rendered cost viaget_report_delegate().generate_report()must render from the returnedpipe_output.tokens_usagesinstead. -
is_log_costs_to_consolenow defaultstrue. With--costson, the CLI prints the cost table at end of run by default (parity with--graphproducing visible output). Per-inference-job console logging is removed — the report renders once at the end, not per call. Library embedders who don't want console output set itfalse. -
Dry runs never emit a cost report; free-model runs still do. Suppression keys on whether the run did reportable work (any tokens or any cost), not on total cost alone: a dry run (zero tokens, zero cost) is suppressed, while a real run on a free / zero-price model (e.g. Ollama) still reports its token usage with a zero total.
Fixed
-
Docs deploy crashed on a fresh runner with
InferenceSetupRequiredError.pipelex-dev generate-error-pages(a prerequisite of everydocs-*make target) bootstrapped Pipelex withneeds_inference=True, so on a CI runner with the gateway enabled but no on-disk service config it hit the first-run inference-setup gate and exited non-zero — breaking theDeploy docsworkflow onmain. The command only introspectsPipelexErrorsubclasses to write markdown and never calls inference, so it now bootstraps withneeds_inference=False. -
UsageRegistrysuccess-path leak. The per-run cost registry was opened during run setup but closed only on the failure path, so every successful run leaked its registry — and in a long-lived process (e.g. the Pipelex API) reusing apipeline_run_idcould collide on the orphaned registry. The registry is removed entirely, so the leak is structurally impossible.
[v0.31.0] - 2026-06-04
This release hardens Pipelex at its edges. The headliners: a full error-handling overhaul that gives every error a stable, RFC 7807-shaped identity and carries it all the way out to webhooks and external surfaces; lenient validation with pipe signatures, so you can sketch and dry-run a whole pipeline top-down before a single pipe is implemented; and a first, experimental cut of CSV tabular support for reading and writing typed lists straight from .csv.
Added
-
Stable error identity (RFC 7807). Every
PipelexErrornow exposestitle()and a stabletype_uri()— a real, dereferenceablehttps://docs.pipelex.com/latest/errors/<error>/URL — and everyErrorReportcarries both as populated fields, so consumers readreport.title/report.type_uridirectly instead of humanizing class names.ErrorReport.to_problem_document()renders anapplication/problem+jsondocument with no web-framework dependency, and a newDisclosureMode(VERBOSE/STRICT) controls how much leaks onto external surfaces:STRICTdrops provider/model attribution and redacts any message that wasn't authored to be caller-facing, keeping only the stable identifiers. -
Structured error payloads on failure webhooks. When a run fails, the delivery webhook now includes an
errorobject — the fullErrorReportas a dict — so receivers can rehydrate it withErrorReport.from_dict(...), render an RFC 7807 response, or route onerror_domain/retryable. AWebhookTarget.payloadthat collides with a Pipelex-reserved key (pipeline_run_id,status,result_url,error) is now rejected at construction. -
Per-class error reference pages. Every
PipelexErrorsubclass now has a generated reference page underdocs/errors/, surfaced in the docs site as "Error Reference" — so atype_uridereferences straight to a populated page. Regenerate with the newpipelex-dev generate-error-pagescommand (make generate-error-pages, aliasmake gep); pages a maintainer claims with a<!-- pipelex:authored -->marker are preserved across runs. -
request_idonJobMetadata. An optional caller-supplied request id, threaded through the run and into the log context. Set it at dispatch withpipeline_run_setup(..., request_id="...")and read it back offjob_metadata.request_id. -
PipeSignature— contract-only pipes for top-down design. A new pipe type (type = "PipeSignature") declares a pipe'sinputs,output, anddescriptionwith no implementation, so an author or agent can sketch a complete pipeline before committing to the operator that will eventually do the work. At dry-run time a signature mints a mock output matching its declared type and multiplicity; at runtime it raisesPipeSignatureNotExecutableError. The optionalsignature_forfield hints which pipe type the stub stands in for. See Signature Pipes. -
Lenient validation with
--allow-signatures.pipelex validate pipe|bundleand everypipelex-agent validatesubcommand take--allow-signatures(default off) to dry-run a pipeline that still containsPipeSignaturestubs. Strict by default: without the flag, validation refuses any pipeline whose dependency graph reaches a signature and raisesSignaturesNotAllowedError, reporting every reachable stub plus the controller chain that leads to it — so you know exactly which pipes are still placeholders. -
CSV tabular support (experimental). Read a
.csvstraight into a typedListContent[YourConcept]: point aninputs.jsonreference at a.csvwhose column headers match the concept's field names, and each row becomes an instance, with cells coerced via Pydantic (birth_year→int, ISO dates →date; an empty cell becomesNone, so the field must be optional). Write a flat-list output back out with the new--save-csv <path>flag onpipelex run pipe|bundle|method. v1 is deliberately narrow — local file paths only (remote URLs with a tabular suffix are rejected), the row concept must be flat (scalar fields only; a nested/list/concept-typed field is rejected with a clear error naming it), and.xlsxis recognized but routed to a "needspipelex[tabular]" message (the Excel backend isn't built yet). See the CSV Input & Output guide. -
--tracebackCLI flag for full stack traces. By default CLI commands print a friendly one-line error;--tracebackalso prints the Rich-rendered stack trace before it. It's position-agnostic —pipelex run --traceback pipe ...andpipelex run pipe ... --tracebackboth work. -
Test tooling for hanging runs. New
make agent-test-debug(aliasmake atd) runs the suite with upfront stale-process cleanup, an outer wall-clock timeout, and live per-test logging — for whenmake agent-testhangs or fails opaquely. Paired with a debugging playbook atdocs/agents/debugging-hanging-pytest-runs.md.
Changed
-
ErrorReportis now a frozen PydanticBaseModel(was a frozen Pydantic dataclass) — still immutable and still round-trips throughto_dict()/from_dict(), but an attempted mutation now raisespydantic.ValidationErrorinstead ofdataclasses.FrozenInstanceError. -
Dry-run and validation consolidated into
BundleValidator. The standalonedry_run_pipe/dry_run_pipesfunctions and the modulespipelex/pipe_run/dry_run.py,dry_run_with_graph.py, anddry_pipe_router.pyare gone; their work now lives inBundleValidator, andvalidate_bundle/BundleValidatorgained theallow_signatures: bool = Falseflag (strict by default). Validation ordering and outputs are unchanged — only the import surface moved. Callers importing frompipelex.pipe_run.dry_runmust switch toBundleValidator. -
validated_pipesnow identifies every pipe by its qualifiedpipe_ref(domain.code). Previouslyvalidate pipereported the bare code whilevalidate bundle/validate allreported the namespaced ref, so the same pipe could appear under two identities depending on which command produced it. Every validate surface now emits the qualified ref, which can't collide across domains. Consumers that parsedpipe_codeexpecting the bare form (e.g. the MTHDS skills) must match on the namespaced ref. -
Gemini deck refresh. Google shut down
gemini-3-pro-preview, so thegemini-3.0-prohandle is removed across thegoogle,portkey, andopenrouterbackends (and the test-profile collections) — usegemini-3.1-pro(→gemini-3.1-pro-preview) instead, now registered onportkeytoo for parity withgoogle. Thegemini-3.0-flash-previewhandle is renamed togemini-3.0-flash. The Pipelex Gateway lists models from its own remote config, so dropgemini-3.0-prothere separately. -
Filesystem path helpers moved to
pathlib.Path. Helpers inpipelex.tools.misc.file_utilsandpipelex.tools.misc.json_utils(save_text_to_path,load_json_from_path,load_binary,copy_file,ensure_directory_exists,get_incremental_file_path, and the rest) now take and returnPathinstead ofstr; path handling isPath-based throughoutpipelex/, converting to/fromstronly at boundaries. Callers passing bare strings must wrap them withPath(...). -
teardown_current_library()renamed toclear_current_library()inpipelex.hub, pairing it cleanly withset_current_library(). -
Dev tooling:
pyrightbumped1.1.408 → 1.1.410(drove two behavior-neutral internal adjustments).
Fixed
-
The generated MTHDS schema now requires
typeon every pipe. In the schema consumed byplxtlint and the VS Code Taplo LSP, each pipe blueprint variant declaredtypewith a literal default — so it was optional, and because the Draft-4 export drops the union discriminator, a pipe table written withouttypematched severaloneOfbranches at once and was rejected with an ambiguous multi-match (worse, a type-less table carrying fields unique to one variant validated silently).typeis now required on every variant, so a type-less pipe table fails with a clear "missing type" and a typed table resolves to exactly one variant. The patched set derives fromPipeBlueprintUnion, so new pipe types are covered automatically. Regenerate withpipelex-dev generate-mthds-schema. -
InputStuffSpecsFactoryErrorwas shadowed by a duplicate class definition.input_stuff_specs_factory.pydeclared a local class with the same name as the canonical one inexceptions.py, leaving two distinct class objects in play so anexcepton one would miss the other. Consolidated to the single canonical class.
Security
- urllib3 floor
>=2.7.0to patch two high-severity issues: CVE-2026-44431 (GHSA-qccp-gfcp-xxvc) forwards sensitive headers across origins on proxied low-level redirects, and CVE-2026-44432 (GHSA-mf9v-mfxr-j63j) bypasses the decompression-bomb safeguards in parts of the streaming API. Floor added to the runtimedependencies. - pymdown-extensions floor
>=10.21.3to patch CVE-2026-46338 (GHSA-62q4-447f-wv8h, medium): a regression inpymdownx.snippetsreintroduced the sibling-prefix path-traversal bypass despiterestrict_base_path. Docs-only; floor added to thedocsextra. - idna floor
>=3.15(lockfile resolves to 3.18) to patch CVE-2026-45409 (GHSA-65pc-fj4g-8rjx, medium): specially crafted inputs toidna.encode()could bypass the CVE-2024-3651 fix. Floor added to the runtimedependencies. - Proactive floor bumps in the same hardening pass, past known-vulnerable releases: pillow
>=12.1.1, protobuf>=6.33.5, python-dotenv>=1.2.2, requests>=2.33.0(runtime); Pygments>=2.20.0(docsextra).
[v0.30.3] - 2026-05-28
Added
claude-4.8-opusmodel added to theanthropicandbedrockbackends. Adaptive thinking mode, supports text / images / pdf in and structured outputs,max_prompt_images = 100,max_tokens = 128000, costs{ input = 5.0, output = 25.0 }per million tokens. Carries thetemperature_unsupportedconstraint likeclaude-4.7-opus. Also available via the Pipelex Gateway.
[v0.30.2] - 2026-05-26
Changed
pipelex-agentmarkdown error envelope no longer includes the## Error sourcestack-frame section. Markdown is the agent / human-facing channel; internal frames likeLibraryError @ pipelex/libraries/library.py:140are noise for an LLM trying to fix a.mthdsfile and forced every consumer (e.g. themthds-pluginsvalidate hook) to strip them. Theerror_sourcefield remains in the JSON envelope (--error-format json) untouched for programmatic consumers — same shape, same cause-chain ordering — so any tooling that parses JSON keeps the full diagnostic surface. The## Detailssection (which carrieserror_domainand other structured fields) is unchanged. No change to error categorization,error_domainvalues, message wording, or stdout/stderr routing.
[v0.30.1] - 2026-05-26
Fixed
pipelex-agentnow silences every Python logger on stderr regardless of user TOML. The agent CLI is machine-consumed: stdout is reserved for the structured success envelope (JSON / markdown) and stderr for the structured error envelope. Free-floatinglog.*calls — alog.debugfromtelemetry_factory.py, alog.warningfromvalidation_error_categorizer.py, or an INFO/WARNING line from any third-party dep (anthropic,httpx,botocore,openai, anything a transitive dep configures) — would corrupt the stderr channel for downstream parsers (mthds-js'sPipelexRunnerdoingJSON.parse(stderr)on the validate hook). Two layers, defense-in-depth:- Layer 1 — pin pipelex's own logs off via config.
make_pipelex_for_agent_cliinjectsconfig_overridesintoPipelex.make()that pindefault_log_level = OFFandpackage_log_levels.pipelex = OFFfrom the very firstlog.configurecall. A user setting[pipelex.log_config.package_log_levels] pipelex = "DEBUG"in~/.pipelex/pipelex.tomlcan no longer leak its own DEBUG/INFO/WARNING lines. - Layer 2 — process-global cutoff that covers every logger. New
silence_logging_for_agent_cli()callslogging.disable(sys.maxsize)— a process-global threshold checked insideLogger.isEnabledForBEFORE any per-logger level. No record gets created for any logger at any level (including custom levels aboveCRITICAL), regardless of which package emits or what level the user configured. Wired into the Typerapp_callbackso every subcommand — includinginitandaccept-gateway-terms, which bypassmake_pipelex_for_agent_cli— silences logging before any command body runs; idempotent per-call invocations remain insidemake_pipelex_for_agent_cliandagent_doctor_cmdas belt-and-braces for direct library callers.
A new e2e regression test pins the contract by setting anthropic, httpx, botocore, openai to DEBUG in the user TOML and asserting both stdout and stderr stay clean.
Changed
-
pipelex-agentno longer accepts--log-level. Log suppression is unconditional by design — there is no verbosity setting on the agent CLI. Thelog_levelparameter is removed frommake_pipelex_for_agent_cli()andapply_agent_cli_output_discipline(), and the correspondingctx.obj["log_level"]plumbing is gone from every caller. For verbose debugging, use the humanpipelexCLI, which honors the user's TOML log config. -
pipelex/cli/commands/doctor_cmd.py::setup_doctor_runtimenowdeep_updateslog_config_overridesinto the loaded config (was a flat-merge that silently replaced nested dicts likepackage_log_levels). With the flat merge, pinningpackage_log_levels.pipelex = OFFfor the agent doctor path would have wiped out all the third-party package levels (anthropic,asyncio,botocore, ...) shipped in the default config. The deep merge preserves them. -
Removed
ctx: typer.Contextfrom 8 agent CLI commands that no longer used it.validate/{pipe,bundle,method}_cmd.py,inputs/{pipe,bundle,method}_cmd.py,models_cmd.py,check_model_cmd.pyhadctx.obj["log_level"]as their only ctx usage; with--log-levelgone, the parameter became dead weight. Therun/commands keepctxbecause they still readctx.obj["runner"]. Test callers (and the now-unusedagent_ctxconftest fixture) updated to match.
[v0.30.0] - 2026-05-25
Fixed
-
console_log_targetpackage default is nowstderr(wasstdout). Logs now stay off the data channel by default, matching the intent of PR #452 ("default to stderr for outputs happening before initialization"). Downstream tooling that parsespipelex/pipelex-agentstdout as JSON (e.g.mthds-js'sPipelexRunner) is no longer at risk of stdout pollution from package-level logs — the bug was latent for stock installs because the agent-CLI JSON paths happen not to log at INFO+, but surfaced for anyone who raisedpackage_log_levels.pipelexto DEBUG or added a setup-time log on the command path. The same flip is applied to the kit template (pipelex/kit/configs/pipelex.toml) thatpipelex initcopies to~/.pipelex/. Note:console_print_targetis intentionally left atstdout— the mainpipelexCLI emits human-facing tables (show backends,show models,which,doctor) via that channel, and downstream piping (pipelex show backends > out.txt) must keep working. -
pipelex-agentnow pins both console targets tostderrregardless of user config.make_pipelex_for_agent_cliinjectsconfig_overridesintoPipelex.make()that forceconsole_log_target = "stderr"andconsole_print_target = "stderr"from the very first log/print fired during init, so a user override of either knob in~/.pipelex/pipelex.tomlcan no longer leak diagnostics onto the agent CLI's JSON data channel. Defense-in-depth post-init calls tolog.redirect_to_stderr()andget_pipelex_hub().set_console_print_target(STDERR)remain. A new adversarial E2E test (tests/e2e/agent_cli/test_stdout_is_clean_json.py::test_models_json_stdout_resists_user_targets_override_to_stdout) pins the contract by overriding both targets tostdoutandpackage_log_levels.pipelextoDEBUGand assertingjson.loads(stdout)still parses.
[v0.29.1] - 2026-05-21
Fixed
pipelex runnow prints the aggregated cost table when[pipelex.reporting_config].is_log_costs_to_console = true, with--cost-report/--no-cost-reportto override per invocation. Thecost-tracking.mdandreporting-config.mddocs both promised a summary cost table at the end of a CLI run, butpipelex/cli/commands/run/_run_core.pynever calledget_report_delegate().generate_report()— the flag only triggeredlog.verbose(...)lines per inference job, which the defaultINFOlog level swallows, so the table never appeared. The CLI now callsgenerate_report()after a successful run when eitheris_log_costs_to_consoleoris_generate_cost_report_file_enabledis true, so the Rich table (one row per model, plus a totals row) prints right before the "✓ Pipeline execution completed successfully" recap — and the CSV export branch finally fires too. The new--cost-report/--no-cost-reporttri-state flag (default unset → use config) lets you force the cost table on for a single invocation (--cost-report) or skip reporting entirely — no Rich table and no CSV file (--no-cost-report) — without touching.pipelex/pipelex.toml. Applies topipelex run bundle,pipelex run pipe, andpipelex run method; works in dry-run mode as well (synthetic usage rows).
[v0.29.0] - 2026-05-20
Added
-
gemini-3.5-flashmodel added to thegooglebackend. Adaptive thinking mode, supports text / images / pdf in and structured outputs,max_prompt_images = 3000, costs{ input = 1.5, output = 9.0 }per million tokens. -
New
PipeStructureoperator that turns text into a structured concept via a single LLM call. Takes oneText-compatible input (or a domain concept thatrefines = "Text"), produces any structured output with the usual multiplicity options (Foo,Foo[],Foo[N]). Useful whenever the source text comes from a PDF extraction, a search result, an upstream pipe, or any non-LLM origin. Documented at building-methods/pipes/pipe-operators/PipeStructure.md. -
Documented
render_jsandinclude_raw_htmlonPipeExtract. Both fields were already shipping onPipeExtractBlueprint; only docs were missing.render_js = trueasks the extraction backend to render JavaScript before fetching web-page content;include_raw_html = truepopulates each extractedPage'sraw_htmlfield with the fetched HTML. Added to building-methods/pipes/pipe-operators/PipeExtract.md. -
Documented
XHIGHvalue onReasoningEffort. The enum already shipped seven levels; theunder-the-hood/reasoning-controls.mdtable listed only six.XHIGHsits betweenHIGHandMAXand maps to provider-specific xhigh values where supported. -
Bounded fan-out concurrency for
PipeBatch. APipeBatchover many items no longer spawns every branch — every coroutine, every deep-copied working memory, every inference call — at once. Branches now run in bounded chunks driven by the new[pipelex.pipeline_execution_config]settingmax_concurrency(default8; set to the literal"unbounded"for unbounded fan-out, the previous behavior). It keeps a large workload (one pipe over thousands of documents) from overwhelming asyncio, memory, and provider rate limits. Results still preserve input order, and a branch failure still propagates (first error by input index wins).PipeParallel, which fans over a fixed pipe-defined branch set, is unchanged. -
Authoritative
error_domain→ HTTP-status mapping.pipelex/base_exceptions.pynow owns the mapping that downstream HTTP APIs (pipelex-relay,pipelex-back-office) need to render anErrorReportas an HTTP response:error_domain_to_http_status()(the pure domain table —INPUT→ 422,CONFIG/RUNTIME/unknown → 500) and theErrorReport.http_statusproperty, which adds a provider-429 passthrough so the API can emit aRetry-Afterheader fromprovider_metadata.retry_after_seconds. The library stays HTTP-agnostic — no web-framework dependency, just the mapping table; downstream FastAPI handlers call the helper instead of reinventing the contract. -
AMBIGUOUSinference-error category for outcome-uncertain failures. NewInferenceErrorCategory.AMBIGUOUSfor failures where the error type is known but the outcome is not — the operation may or may not have committed (e.g. a connection dropped mid-request). It is non-retryable, likeCONFIGURATION/CONTENT/CAPACITY, but semantically distinct fromUNKNOWN, which means the error could not be classified at all. Theazure_restimage-generation worker now raisesAMBIGUOUSfor mid-request transport failures —ReadError/WriteError/RemoteProtocolErrorandReadTimeout/WriteTimeout— so an automatic-retry layer won't re-fire a non-idempotent, billable image submit whose outcome is unknown; pre-request failures (ConnectError/ConnectTimeout/PoolTimeout) stayTRANSIENTand retryable. -
Explicit, uniform Tier 1 transport retry across every inference worker. A new
[cogt]settingtransport_max_retries(default2) is now wired explicitly into every inference SDK client factory — Anthropic, OpenAI / Azure OpenAI, the Portkey-backed gateway clients, Mistral, and Google — instead of each factory silently inheriting whatever retry posture its SDK happens to default to. The two SDK families that default to no transport retry are brought up to the same floor: the Mistral client gets a bounded-backoffRetryConfig(retry_connection_errors=True) and the Google GenAI client getsHttpOptions(retry_options=...). The genuinely SDK-less path — theazure_restimage-generation worker, which talks to Azure over rawhttpx— gets atenacity-based transport-retry wrapper (new modulepipelex/cogt/inference/transport_retry.py) that retries connection failures and transient HTTP statuses (408/409/429/5xx) and honorsRetry-After. When noRetry-Afterheader is present, the fallback backoff uses full jitter (wait_random_exponential) so a burst of failures retried together does not re-fire in lockstep. On a non-idempotent submit-style POST it narrows the retry to failures that prove the server did no billable work — a request that was never delivered, or a 408/429 rejection — withholding an ambiguous 5xx, a 409 conflict, and a post-delivery timeout such as aReadTimeout. Transport retry is now a deliberate, configured, uniform policy rather than a per-provider accident. This is the transport-level floor of the retry model — pipeline execution makes a single attempt on top of it. (Theportkey-aiSDK does not expose a retry knob — it carries its own internal retry — so the gateway'sAsyncPortkeyclient is left as-is; only its underlying OpenAI clients are wired.) -
Offline mode for Pipelex Gateway setup and dry-run. When the gateway is enabled but the remote config service is temporarily unreachable, Pipelex now falls back to a previously primed on-disk cache (
~/.pipelex/cache/remote_config.json, schema-versioned) instead of failing setup outright. Dry-run, validation, andpipelex-agent run bundle --dry-runcomplete normally; only the actual inference call still needs the network at runtime. The cache is primed on every successful fetch and onpipelex initwhile online. When the gateway is disabled (BYOK), no remote fetch is attempted at all — setup is fully offline. A newRemoteConfigStaleWarning(UserWarning) is emitted whenever stale cache is in use; the agent CLI surfaces it on the JSON envelope aswarnings: [{"type": "RemoteConfigStale", ...}]. Telemetry is suppressed (no-op) when running on a cached config so stale model identities don't pollute metrics. The doc/fixture generators (pipelex-dev update-gateway-models,preprocess_test_models_cmd) refuse the cache fallback via a newrequire_fresh=Trueflag, so committed reference docs and test fixtures never bake in stale data. -
GatewayUnknownModelError(pipelex.cogt.exceptions). Raised at setup time when the active model deck references a gateway model handle that isn't present in the (fresh or cached) gateway specs. Carries the model name and the config source (RemoteConfigSource.FRESH|CACHED); the message branches on source so a cached-source failure suggestspipelex initwhile online and a fresh-source failure points at deck/typo fixes. Wired through both the Rich CLI (handle_gateway_unknown_model_errorinerror_handlers.py) and the agent CLI (AGENT_ERROR_HINTS/AGENT_ERROR_DOMAINS). -
RemoteConfigUnavailableError(pipelex.system.pipelex_service.exceptions). User-facing offline-mode error: raised only when the network fetch fails AND no usable cached fallback exists. The message names the cache file path and the two remediation paths (runpipelex initwhile online to prime the cache; or disablepipelex_gatewayinbackends.tomlfor permanent BYOK operation). Distinct from the internalRemoteConfigFetchError, which is kept as the retry-layer exception. -
PIPELEX_REMOTE_CONFIG_URLenvironment variable. Overrides the default remote-config URL. Useful for staging/testing environments; defaults to the production URL when unset.
Changed
-
Inference error handling refactored to Extract / Classify / Render (internal). Every inference worker's SDK-exception block now collapses to
metadata = extract_*_metadata(exc); classification = classify_inference_error(metadata); raise render_*_error(...) from exc. New modules:pipelex/cogt/inference/error_classify.py(single sharedclassify_inference_error()returningClassificationResult(category, user_action_kind, is_model_not_found)),pipelex/cogt/inference/error_render.py(single sharedrender_llm_error/render_img_gen_error/render_extract_error/render_search_error, picking theCogtErrorsubclass from anInferenceErrorFamilytag plus theis_model_not_foundflag), andpipelex/cogt/inference/provider_name.py(theProviderNameenum keying the extract-fn registry).ProviderErrorMetadatagains amessagefield plusis_quota_exhaustion/is_content_policy_violation/is_network_error@propertyaccessors; the per-providerextract_*_metadatafunctions are now the only plugin-local piece — Classify and Render live once. Mistral and the gateway-search worker specialize HTTP 404 toExtractModelNotFoundError/SearchModelNotFoundError; Azure img-gen keeps two worker-specificAMBIGUOUSbranches for mid-request transport failures. Removed: the per-provider*_error_classification.pymodules and their tests,AnthropicCredentialsError,GatewayFactory.classify_error_category/make_user_action_from_portkey_error/make_error_summary_from_portkey_error, and every inline_classify_*_error/_raise_categorized_*worker method. New unit-testtests/unit/pipelex/cogt/inference/test_provider_classification_parity.pywalks everyProviderNameagainst the extract-fn registry + worker-family map, so an unwired new provider fails fast. No user-facing API change — the structuredErrorReportcontract is unchanged. Documented at under-the-hood/error-model.md. -
instructor's structured-output retry no longer re-runs completions on transport errors. Passed a bareint,instructor'smax_retriesbuilds a retry loop whose predicate retries any exception — so the structured-output path (PipeLLM/PipeStructure) was re-running the whole completion on transport / API errors, a second retry loop nested on top of the SDK client's own transport retry. Eachinstructorcall site now passes atenacity.AsyncRetrying(built by the newpipelex/cogt/llm/instructor_retry.pyhelper) whose retry predicate matches only validation failures (pydantic.ValidationError,json.JSONDecodeError, andinstructor's own validation-error types). A transport error now propagates immediately as the raw SDK exception for the worker'sexceptclause to classify — transport retry is the SDK client floor (Tier 1) alone, andinstructor's retry is confined to genuine schema re-ask. As part of this the Google and Mistral structured-generation workers gained anhttpx.TransportErrorexceptclause: those SDKs let raw connection / timeout errors propagate outside their own exception hierarchies, so withinstructorno longer wrapping them they must be caught and classified directly. The Mistral structured path also now gets schema re-ask at all — it previously passed nomax_retries. -
Inference schema-retry setting moved and renamed:
[cogt.llm_config.llm_job_config] max_retries→[cogt.llm_config] schema_reask_max_attempts(breaking). The setting isinstructor's schema re-ask budget for structured-output validation failures. The old namemax_retriesgave no hint of that scope and collided conceptually with the new top-levelcogt.transport_max_retries— which counts retries beyond the initial attempt, whereas this one is a total attempt count (stop_after_attempt). The new name makes both the scope (schema re-ask) and the unit (attempts, not retries) explicit. The single-key[cogt.llm_config.llm_job_config]sub-table is also dropped — the setting now sits directly under[cogt.llm_config]. Projects that override this key in their ownpipelex.tomlmust move and rename it. -
Agent CLI
run/validate/initdefault to markdown output, with independent success/error format options (breaking). These commands previously always emitted JSON; they now accept--format markdown|jsonand default to markdown, matchingmodels/check-model/doctor. A second flag--error-format markdown|jsoncontrols error reporting on stderr independently from success output — it defaults to the value of--format, so--format jsonstill flips both, but the two can now be set separately (e.g.--format markdown --error-format jsonfor human-readable success with machine-parseable errors). Internally, only the error format is carried in aContextVar; the success format is threaded explicitly toagent_success_formatted(). Theinputs/concept/pipe/fmt/lint/accept-gateway-termscommands are unaffected (always JSON / raw passthrough). -
pipelex-agent validate bundlegraph-format option renamed--format→--graph-format(breaking). The--format/-fflag that selected the graph renderer (mermaidflow/reactflow/both) is now--graph-format/-f, freeing--formatto be the uniform markdown/json output-format flag across every agent-CLI command. -
structuring_method = "preliminary_text"onPipeLLMworks again, via build-time elaboration. WhenPipelexInterpreterparses a.mthdsfile with aPipeLLMcarryingstructuring_method = "preliminary_text", the newBundleElaboratorrewrites it before any pipe runs into aPipeSequenceof two synthetic pipes: aPipeLLMproducingText(step 1, inheriting the original prompt + inputs + model) and aPipeStructureproducing the original output (step 2, optionally usingmodel_to_structure). The synthetic codes are tracked in aPipelexBundleBlueprint.elaboration_metadataside-table (excluded from serialization). Output multiplicity is preserved: step 1 always emits a singleText; step 2 emitsFoo,Foo[], orFoo[N]according to the original output. Two LLM calls are issued per invocation. The user-facing pipe code is unchanged, so callers,main_pipe, and the run API keep working as before. Mechanism documented at under-the-hood/build-time-elaboration.md. -
PipeLLMruntime no longer knows aboutstructuring_method. The field is now a pure build-time directive. The runtimePipeLLMclass no longer carriesstructuring_method, the validator that rejected mismatched output concepts has moved toPipeLLMBlueprint(where it fires at parse time), and theNotImplementedErrorpreviously raised at runtime whenpreliminary_textwas selected is gone — the elaborator handles it.PipeLLMSpecexposesstructuring_methodso AI agents authoring via specs can still opt in. -
StructuringMethodenum import path moved. The enum is now defined inpipelex.pipe_operators.llm.pipe_llm_blueprint(it lives next to the blueprint that consumes it) instead ofpipelex.pipe_operators.llm.pipe_llm. Direct importers must update theirfrom pipelex.pipe_operators.llm.pipe_llm import StructuringMethodline tofrom pipelex.pipe_operators.llm.pipe_llm_blueprint import StructuringMethod. -
Retry removed from the gateway workers;
[cogt.tenacity_config]removed (breaking). Thetenacity-based retry insideGatewayExtractWorkerandGatewaySearchWorkeris gone, along with the[cogt.tenacity_config]config block and itsTenacityConfigmodel. Because config models forbid unknown keys, an existing~/.pipelex/pipelex.toml(or any layered override) that still carries[cogt.tenacity_config]will fail to load — remove that block from your config. Transient transport blips are left to the provider SDK clients' own retry; thetenacitylibrary itself is still used elsewhere (FAL job polling, remote-config fetch) and remains a dependency. -
PipeRouter.run()now reportsCogtErrorfailures to the observer. ACogtErrorraised out of pipe execution previously propagated pastrun()without anobserve_after_failing_runnotification (onlyPipeRunErrorwas caught). It is now observed on the failing path, then re-raised as-is — the cause chain is preserved and it is not wrapped intoPipeRouterError(only thePipeRunErrorpath still wraps). -
Provider HTTP 404s now raise dedicated
*ModelNotFoundErroracross LLM, image-gen, extract, and search. A model-or-deployment-not-found 404 from any LLM or image-gen provider, or from the Pipelex Gateway extract / search workers, now raises a dedicated*ModelNotFoundError(LLMModelNotFoundError,ImgGenModelNotFoundError,ExtractModelNotFoundError,SearchModelNotFoundError— allModelNotFoundErrorsubclasses,CONFIGURATIONcategory) instead of a genericLLMCompletionError/ImgGenGenerationError/ExtractJobFailureError/GatewaySearchResponseError. Because these are siblings of the generic errors — not subclasses — a 404 propagates past the operator's genericexcepttoexcept ModelNotFoundErrorinPipeOperator._live_run_pipe, which re-raisesPipeOperatorModelAvailabilityErrorcarrying the unavailablemodel_handle. -
RemoteConfigFetcher.fetch_remote_config()now returns aRemoteConfigResultcarryingconfig,source(fresh|cached), andcached_at, instead of a bareRemoteConfig. Callers unwrap.configfor the payload and may branch on.sourceto know whether the config is fresh or restored from cache. The fetcher accepts a new keyword-onlyrequire_fresh: bool = False— whenTrue, a cached fallback raisesRemoteConfigUnavailableErrorinstead.RemoteConfigValidationErroris never satisfied by the cache (server-side schema breaks must surface loudly). -
ModelManager.setup()andBackendLibrary._load_gateway_model_specs()accept a newgateway_config_source: RemoteConfigSource | Noneparameter. Passed through fromPipelex.setup()so the deck-level gateway membership check can branch its error message onFRESHvsCACHED.GatewayConfigitself staysextra="forbid"and source-free — provenance is plumbed alongside, not baked in. -
RemoteConfigUnavailableErrormessage branches on whether the cache was refused vs absent. Whenrequire_fresh=True(dev-CLI generators) refuses to fall back to an existing cache, the message now reads "the local cache at<path>was refused because a fresh fetch is required" instead of the previously misleading "no local cache is available at<path>". The cache-truly-missing path keeps its original wording.
Fixed
-
Inference-failure
ErrorReports now carrymodelandproviderin production. A real LLM / image-gen / extract / search failure used to surface anErrorReportwithmodel = Noneandprovider = None: the leaf errors (LLMCompletionError,ImgGenGenerationError,ExtractJobFailureError,SearchJobFailureError,ExtractOutputError) carry no model or provider of their own, andCogtError.to_error_report()only duck-typed whatever attributes happened to be set on the exception. Each inference worker family now fillsmodel_handle/backend_namefrom the worker — where both are unambiguously known — at its public-method chokepoint (gen_text/gen_object,gen_image/gen_image_list,extract_pages,search_sourced_answer/search_structured), via the newCogtError.fill_model_and_provider(). The fill never overwrites a value an inner error already set and skips the"unknown"placeholder external plugins report.model_handle/backend_nameare now declared onCogtError(soto_error_report()reads them directly instead ofgetattr), making them uniformlystr | Noneacross the exception hierarchy. -
Two worker error-classification miscategorizations corrected.
LinkupNoResultError(a search or fetch that returned nothing) had no explicit branch in either Linkup worker's_classify_linkup_errorand fell through to theTRANSIENTcatch-all — marking a query that cannot succeed by retrying as retryable. It is now classifiedCONTENT+CHANGE_INPUTin both the search and the extract worker. Behavior change: a no-result search is now non-retryable (CONTENT.is_retryableisFalse), so an automatic-retry layer no longer retries a query that returns nothing on every attempt. Separately, theFileNotFoundErrorbranch in the Docling and pypdfium2 extract workers was classifiedCONFIGURATION— inconsistent with its sibling branches (CONTENT+CHANGE_INPUT) and with the rest of the codebase, whereCONFIGURATIONis reserved for setup problems. A missing input file is a content problem; it is nowCONTENT. This second change does not alter retry behavior —CONFIGURATIONandCONTENTare both non-retryable. -
Wrapped exceptions now surface the underlying inference error's classification.
PipelexError.to_error_report()enriches its report from the__cause__chain, so aPipelineExecutionError— or any wrapper around a transientCogtError— now reportserror_category,retryable,model, andproviderinstead of dropping them. Previously the agent-CLI JSON / markdown error output for a failed pipeline run lost the worker's category and retryability once the error had been wrapped by the pipe operator → router → runner layers, leaving an agent unable to tell a transient failure from a fatal one. -
MTHDS JSON schema no longer leaks the
elaboration_metadataside-table.PipelexBundleBlueprint.elaboration_metadatacarriedField(exclude=True)so it stayed out ofmodel_dump()/model_validate()round-trips, but Pydantic v2'sexclude=Truedoes not affectmodel_json_schema()— soderived/mthds_schema.jsonended up declaring a top-levelelaboration_metadataproperty plus$defs/ElaborationMetadataand$defs/StepRoleentries, even though the side-table is process-local in the reference runtime. Wrapped the field type withSkipJsonSchema[...]so it is hidden from the schema. After regenerating, the three entries are gone from the public schema, matching the spec's silence on them. -
A directory containing a
.pipelex/config dir is now recognized as a project root..pipelexwas added toPROJECT_ROOT_MARKERS, so project-level config (e.g..pipelex/inference/backends.toml) is honored even when the directory has no.git,pyproject.toml, or other source-project marker. Previously such a directory fell through to the global~/.pipelex/config, silently ignoring the project's own overrides — so a backend disabled in the project'sbackends.tomlcould still demand credentials because the global config (where it was enabled) was loaded instead. The home directory remains excluded from project-root detection, so the global~/.pipelex/is unaffected. -
PipeLLMoutputting a concept that refines the nativeJSONconcept no longer crashes withNameError: name 'Any' is not defined. On a LIVE run, such a concept resolves to a structured-output model carrying adict[str, Any]field inherited fromJSONContent.SchemaToModelFactorygenerates that model as source withfrom __future__ import annotations(every annotation becomes a string) and then rebuilds each class to resolve the string annotations. The rebuild namespace was assembled from the exec'd user types plus a hand-listedLiteral, buttyping.Anyis a special form, not atype, so it was filtered out —model_rebuildthen raisedPydanticUndefinedAnnotationevaluating"dict[str, Any]". The rebuild namespace is now the exec namespace itself (minus__builtins__), so it carries exactly the names the generated source was written against and cannot drift as codegen emits other typing constructs. Fixed inpipelex/cogt/content_generation/schema_to_model_factory.py; covers both the sender path (make_from_json_schema) and the cross-process receiver path (make_types_from_source).
[v0.28.0] - 2026-05-13
Changed
- Breaking (rendering): graph viewer assets are no longer bundled into generated HTML. The ReactFlow HTML output now references
@pipelex/mthds-ui(the standalone IIFE bundle + its CSS) andelkjsfromcdn.jsdelivr.netwith pinned versions andsha384Subresource Integrity hashes. Three external requests now load from jsDelivr at view time; the HTML itself is still generated offline by Pipelex — only viewing the rendered graph requires network access. The previousmake sync-graph-ui/make check-graph-ui-syncworkflow and the committedpipelex/graph/reactflow/assets/graph-viewer.{js,css}files have been removed; the manifest-stylepackage.jsonand theGraph UI sync checkGitHub Actions workflow are gone. A single Python module (pipelex/graph/reactflow/standalone_assets.py) is the source of truth for pinned versions and integrity hashes — the template reads them via Jinja2, so a bump touches one file plus the regenerated SRI constants. The newpipelex-dev refresh-graph-ui-sricommand re-fetches the URLs, recomputessha384, and rewrites the constants module; theupdate-graph-uiskill drives that flow. Previously, the "self-contained HTML" was already not offline (elkjs loaded fromunpkg.comwithout integrity), and bumping the vendored bundle meant committing ~2 MB of regenerated JS+CSS on every mthds-ui release — SRI hashes give the same tamper-evidence with none of the diff churn. - Breaking:
@var/@?varsigils must be alone on their own line, and inline@<ident>raises at load time only when<ident>collides with a declared input of the surrounding pipe. The@/@?rewriters wrap the value in a tag-shaped block envelope (<var>...</var>via thetag()filter), so the inline shapes never produced sensible output and are now rejected at load time with a newTemplateSigilSyntaxError— surfaced through pydantic validation with the line number, the offending span, and a migration hint. To stay friendly to coding agents authoring HTML/CSS templates (<style>@media (...) { ... }</style>,@font-face { ... }, Python/Java decorators like@deprecated/@Override), the validator is gated on the surrounding pipe's declaredinputs: an inline@<ident>raises only when the candidate's root identifier matches a declared input (a real typo). Every inline candidate on a line is inspected, so a later collision can't hide behind an earlier CSS at-rule. Other inline@candidates pass through silently. The line-bounded rewriter (alone-on-line@var→{{ var|tag("var") }}, leading/trailing whitespace preserved) is unchanged and remains inputs-agnostic. The strict rule replaces the heuristic regex tightening from the prior CSS-collision fix: there are no residual rewrites for@font-face/@counter-style/@view-transition/@property --x, no special-case lookbehind/lookahead arms. The$varinline sigil is unchanged. API:preprocess_template(template, *, declared_inputs=...)gained a keyword-onlydeclared_inputs: set[str] | Noneparameter (defaultNone= lenient, no validation); a new pair of helpersvalidate_template_sigils(template, declared_inputs)andrewrite_template_sigils(template)exposes the validate and rewrite steps separately.render_template(runtime) callsrewrite_template_sigilsdirectly — templates are already validated at load time, so the render path doesn't need thedeclared_inputscontext. All pipe blueprints (PipeLLMBlueprint,PipeComposeBlueprint,PipeSearchBlueprint,PipeImgGenBlueprint,PipeComposeFactory) and template analyzers (TemplateDocumentAnalyzer,TemplateImageAnalyzer) thread their declared inputs into the validator; the baseTemplateBlueprintandConstructBlueprint-discovery validators remain lenient (no inputs context at that layer — the surrounding pipe's validator catches typos). Migration: for inline values, switch from@varto$var; for block-shaped content, move the sigil onto its own line; for literal@or$characters, use the@@/$$escapes documented below.
Added
@@and$$template escapes. Authors can opt out of sigil interpolation per occurrence:@@varrenders as the literal string@var(no{{ ... }}), and$$varrenders as the literal$var. The escapes are non-overlapping left-to-right (@@@@var→@@var, two literal@s). Use these for any literal@/$the author needs to keep in the rendered output — most commonly@@font-face,@@namespace,@@mediainside CSS<style>blocks, or$$10for a literal dollar amount. Cross-link:wip/template-preprocessor-line-bounded-at.md.TemplateSigilSyntaxError(pipelex/cogt/templating/template_errors.py): raised by the preprocessor when a candidate@/@?sigil is not alone on its line. Pipe blueprints (PipeLLMBlueprint,PipeComposeBlueprint,PipeImgGenBlueprint,PipeSearchBlueprint,TemplateBlueprint,ConstructBlueprint,pipe_compose_factory) and theTemplateBlueprintvalidator catch and re-raise as pydanticValueErrorwith pipe-specific context, so the diagnostic surfaces through normal MTHDS validation errors and IDE/plxt checkdiagnostics.
Fixed
- Template preprocessor:
$<var>no longer substitutes when$is adjacent to a word character on the left (e.g.micro$oft,user$host.com,P@ssw$rd123,a$b$cnow pass through unchanged instead of producing mid-word{{ ... }}substitutions), and no longer emits invalid Jinja for shapes like$name..(now renders{{ name|format() }}..with both trailing dots preserved as literal punctuation). The$arm now mirrors the@candidate pattern's word-boundary lookbehind ((?<!\w)) and uses a strict segmented identifier[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*that rules out a leading digit and consecutive dots structurally. The trailing-dot kludge in the$replacement function is gone (unreachable under the strict identifier shape).$varkeeps its silent pass-through posture for non-candidate shapes — it does not raise like the@arm does. - Project
.pipelex/telemetry.tomlcreated bypipelex initno longer silently disables globally-enabled telemetry. The kit previously shipped onetelemetry.tomltemplate carrying explicitenabled = false/mode = "off"defaults, andpipelex init telemetrycopied it into both~/.pipelex/and the project's.pipelex/. Because the layered loader appends the project base file after~/.pipelex/telemetry_override.toml, a user who enabled Langfuse/PostHog globally in their override still had it turned off in every initialized project. The kit now ships a separatetelemetry.project.tomltemplate with every setting commented out, used only by project-level init. The global init still copies the activetelemetry.toml. As a safety net,telemetry_allowed_modesdefaults (ci=False,cli=True,docker=True,fastapi=True,mcp=True,n8n=True,pytest=False,python=False) now live in theTelemetryConfigPydantic model rather than the TOML template, so a project file that omits the section can't disable custom telemetry for everyone. - Global
pipelex.tomlandtelemetry.tomloverrides no longer silently disappear when a project.pipelex/exists.ConfigLoader.load_config()previously sourced all override files (pipelex_local.toml,pipelex_{env}.toml,pipelex_{run_mode}.toml,pipelex_override.toml,pipelex_temporary_override.toml) from a single "effective config dir" — project.pipelex/if present, else~/.pipelex/. As a result, the user's machine-wide overrides in~/.pipelex/were ignored entirely the moment a project shipped its own.pipelex/.load_telemetry_confighad the same shadowing behavior fortelemetry.tomlandtelemetry_override.toml, which was particularly painful because telemetry holds Langfuse/PostHog/OTLP secrets that users typically set once globally. Both loaders now layer global → project: package defaults → global base → global overrides → project base → project overrides, deep-merged so machine-wide personal preferences keep applying unless explicitly overridden by the project. The unit-testing runmode behavior is preserved:./tests/pipelex*{run_mode}.tomlis still the only run_mode file loaded under unit testing, replacing both layers to keep test runs hermetic. Migration: if a project previously relied on its.pipelex/to fully replace* the user's global config rather than merging over it, the project must now redeclare any keys it wants to set explicitly — silent inheritance from~/.pipelex/is the new default. pipelex build structuresnow emits domain-qualified class names and cross-references.ConceptFactoryregisters each concept's structure class undermake_qualified_structure_class_name(domain, concept_code)(e.g.expense_validator__SpendingLimitCheck), but the CLI generator was passing the bareconcept_codetoStructureGenerator. Generated files therefore containedclass ConceptCode(StructuredContent)and unqualified cross-imports/types, while the registry expected the qualified name.PipeFuncvalidation againstconcept.structure_class_namethen rejected the mismatch withoutput concept expects structure class 'domain__X', but the function return type is 'X', breaking library load for any project that had regenerated structures. Fixed inpipelex/cli/commands/build/structures_cmd.py: the class-definition call sites now callmake_qualified_structure_class_name(blueprint.domain, concept_code);_build_concept_ref_to_class_infoqualifies cross-reference class names while keeping the file stem unqualified so output filenames staydomain__concept_code.py; therefines:branch resolves the refined concept's domain viaQualifiedRef.parse_stripping_cross_packageand qualifies the base-class name for non-native refines, mirroringConceptFactory._handle_refines.pipelex build structurescross-package refines now emit the base-class import. A concept that refines a class defined in another already-installed package (e.g.RefiningConceptwithrefines: some_alias->other_domain.OtherConcept) was generating a file that inherited fromother_domain__OtherConceptwithout importing it.StructureGenerator._validate_executioninjects the base class intoexec_globalsfrom the class registry, so codegen-time validation passed; the failure surfaced only when the generated structures module was later loaded via the normal Python import system, raisingNameError: name 'other_domain__OtherConcept' is not defined. The generator now falls back to the class registry's__module__whenconcept_ref_to_class_infohas no entry for the base class and emits the corresponding import (guarded oncls.__name__ == base_classso we never emit a name the target module won't expose). Regression test intests/unit/pipelex/cli/commands/build/test_structures_cmd_cross_package_refines.pywas tightened to assert the import statement is present.
[v0.27.0] - 2026-05-07
Changed
RunEnvironmentenv var renamed fromENVIRONMENTtoPIPELEX_ENV. The variable that selects the environment-specificpipelex_<env>.tomloverlay (and is stamped on OTel spans asdeployment.environment) is now namespaced to avoid collisions with unrelatedENVIRONMENTvariables already set in deployment environments. Update any shell, CI, or container config that exportedENVIRONMENT=...to exportPIPELEX_ENV=...instead.
[v0.26.4] - 2026-05-06
Fixed
clean_json_content()no longer crashes on nested Pydantic instances inworking_memory_raw. Whenworking_memory_raw(typeddict[str, Any]) held rehydratedBaseModelinstances (e.g.PageContentfromPage[]outputs),clean_json_content()walked only dicts/lists/scalars and letBaseModelinstances reachjson.dumps, which raisedTypeError: Object of type PageContent is not JSON serializable.clean_json_contentnow reduces anyBaseModelit encounters viamodel_dump(serialize_as_any=True)(the canonicalsmart_dumppath) before continuing the recursive walk.
[v0.26.3] - 2026-05-06
Fixed
- OpenAI SDK 2.34.0 compatibility for Portkey/Gateway clients. The new SDK adds both a constructor-time check (
_enforce_credentials) and a request-time_validate_headersguard that reject an emptyapi_key. Pipelex's gateway and Portkey factories were passingapi_key=""because auth is delivered viax-portkey-api-keyandx-portkey-configheaders, not the OpenAIAuthorizationheader. Replaced the empty string with a non-empty placeholder ("unused-auth-via-portkey-headers") ingateway_completions_factory,gateway_responses_factory,portkey_completions_factory, andportkey_responses_factory. Same fix applied toopenai_client_factoryfor the no-auth case (e.g. local Ollama backends), wherebackend.api_keyis intentionally unset. Bumps theopenairequirement to>=2.0.0.
[v0.26.2] - 2026-05-06
Fixed
choicesfields no longer fail validation with'EnumName.MEMBER_NAME'errors. A concept declared withchoices = [...]produces aLiteral[...]field on the dynamic Pydantic class. That schema is round-tripped throughSchemaToModelFactory.make_from_json_schema(used to feed structured-output schemas to LLM providers). Previously the round-trip silently re-emitted the field as a plain PythonEnumclass — e.g.Literal["Strong Match", "Good Match", "Partial Match", "Poor Match"]becameclass Recommendation(Enum): Poor_Match = "Poor Match"; .... LLMs filling that schema then returned the enum's Python repr ("Recommendation.Poor_Match") instead of the literal string ("Poor Match"), which failed Pydantic validation against the original choice set with errors likeInvalid choice errors: 'recommendation': got 'Recommendation.Poor_Match', expected one of 'Strong Match', 'Good Match', 'Partial Match' or 'Poor Match'._generate_source_from_schemanow passesenum_field_as_literal=LiteralType.Alltodatamodel-code-generator, soenum: [strings]schema nodes round-trip asLiteral[...]instead of being regenerated asEnumclasses._exec_source_to_typesnow also exposesLiteralin the rebuild namespace somodel_rebuildresolves the deferred annotations.
[v0.26.1] - 2026-05-05
Changed
- Live-run graph output:
pipelex-agent runnow emits the assembledGraphSpecaslive_run_graph.jsonalongsidelive_run.jsonand the ReactFlow HTML.
[v0.26.0] - 2026-05-04
Highlights
- Distributed tracing — pluggable event-log backends (NDJSON, DynamoDB, in-memory, buffering) emit
TraceEvents that reassemble into a completeGraphSpec. Enabled by default; works in single-process mode too.
Added
Pipeline execution & delivery
PipeRunlayer (pipelex/pipe_run/): newPipeRunProtocolwith the in-processPipeRunimplementation. Wraps pipe execution + delivery in a single orchestration unit.- Delivery framework:
DeliveryAssignmentmodel with webhook (HTTP POST) and storage (S3 / local) variants, run inline after a pipe completes. LibraryCrateIR (pipelex/libraries/library_crate.py,library_crate_factory.py): serializable intermediate representation capturing the exact set of libraries (concepts, pipes, structures) required to execute a job — no shared filesystem assumed.- Schema-based dynamic model construction (
pipelex/cogt/content_generation/schema_to_model_factory.py): rebuilds dynamic Pydantic models from the JSON schema embedded inObjectAssignment, instead of relying on class identity. Cache bounded by an LRU (_SCHEMA_CACHE_MAX_SIZE = 1024); codegen serialized through a file lock to kill thundering-herd duplication when many distinct schemas arrive. Addsdatamodel-code-generator>=0.55.0as a runtime dependency. - Pre-generated
pipeline_run_idsupport:pipeline_run_setup(),PipelineFactory, andPipelineManageraccept an optionalpipeline_run_idparameter for external run-record creation.
Distributed tracing (pipelex/tracing/)
EventLogProtocolwith pluggable backends:NdjsonEventLog,DynamoDBEventLog,InMemoryEventLog,BufferingEventLog. EmitsTraceEvents as pipes start/finish across processes. Configured via[pipelex.tracing_config](backend = "ndjson" | "dynamodb"). Tracing is enabled by default — single-process runs also produce a trace.pipelex[dynamodb]extra:pip install "pipelex[dynamodb]"for the DynamoDB event log backend.writer_idonTraceEvent(default"primary"): every event records which writer (worker / process) produced it, propagated through every backend. Separate writer processes use a distinctwriter_idso multiple writers can emit into the same backend partition without colliding on(workflow_id, sequence). Stamped at construction time (no copy-on-emit). Enables cross-writer dedup and per-writer aggregation.- NDJSON multi-writer key scheme: dedup key is
(workflow_id, writer_id, type, sequence); sort key is(workflow_id, sequence, writer_id)— sequence is primary so the runner'sUsageReportEventdoes not sort before the router'sPipeStartEvent. The file-handle cache key includeswriter_id, so two writers for the same(pipeline_run_id, workflow_id)cannot share a stale handle. - DynamoDB sort key format:
EVENT#{workflow_id}#{writer_id}#{sequence:010d}. ContentGeneratorDryemitsUsageReportEvents: invokesreport_inference_jobwith a syntheticLLMTokensUsageso dry-run mode produces real events observable through the same backend path as live runs.GraphSpecAssembler: rebuilds a completeGraphSpecoffline from a stream ofTraceEvents — equivalence with the liveGraphTraceris pinned by tests.UsageAggregator: aggregates per-pipeline LLM/extract/img-gen usage across workers from the event log.- Hub DI:
PipelexHub.set_event_log()/get_event_log()for dependency injection of custom event log backends.make_event_log()factory selects the backend from config or hub injection; the 3 prior call sites that hardcodedNdjsonEventLognow go through it.
Inference error classification
InferenceErrorCategoryenum (transient,configuration,content,capacity) with per-provider helpers that distinguish quota exhaustion from rate limits and detect content-policy violations — covers OpenAI, Anthropic, Google, Mistral, AWS Bedrock, and Pipelex Gateway.- All inference workers attach error category + user action: every LLM, image-gen, extract, and search worker across all providers raises exceptions with an
InferenceErrorCategoryand actionableuser_actionhint. - Structured
ErrorReport:PipelexError.to_error_report()returns a dataclass with error type, category, retryable flag, user-action hint, model, and provider. CLI error handlers consumeto_error_report()for consistent, structured display. SecurityError(PipelexError): new base class inpipelex.base_exceptionsfor security-policy violations.UnsafeSchemaErrornow extends it (wasContentGenerationError) so security signals are not silently swallowed by domainexcepthandlers.
Documentation
- New "Under the Hood" pages:
pipe-routing-and-execution.mdanddistributed-content-generation.md. Cover routing/dispatch and the dynamic-model serialization story. - New
AGENTS.mdat repo root, generated from the same source asCLAUDE.mdviamake rules.
Other
PipeOutput.graph_assembly_error: optionalstrfield set when graph assembly raises, so consumers can distinguish "graph never produced" from "graph assembly failed". Previously the failure was logged as a warning andgraph_specsilently stayedNone.pipe extractweb URL support with full test coverage intests/integration/pipelex/pipes/pipe_operators/pipe_extract/.needs_inferenceflag on CLI commands: non-inference subcommands (e.g.doctor) skip inference setup, shaving cold-start time.- Environment-specific config:
RunEnvironmentis now loaded from theENVIRONMENTenv var (wasENV). Accepted values:local,dev,staging,prod.
Changed
- Tightened inference quota classification patterns to reduce false positives on auth/setup errors:
- Anthropic: bare
"credit"token replaced with"credit balance","out of credits","insufficient credit". No longer misclassifies"your credit card was declined"or"we will credit your account"as quota exhaustion. - Google: bare
"billing"token replaced with"billing limit","billing quota","billing exceeded", and"billing account". Continues to match real 429-class messages ("Billing account is not active","billing limit reached"); stops matching unrelated billing-mentioning text. - Mistral / Gateway: bare
"billing"likewise narrowed to"billing limit"/"billing quota". Mistral additionally distinguishes"out of credits"vs"insufficient credits". - Removed duplicate
ContentGenerationErrorclass: the unusedpipelex.cogt.content_generation.exceptions.ContentGenerationErrorwas deleted (had zero external imports). Its subclasses re-parented:NeitherUrlNorDataError→PipelexError,UnsafeSchemaError→ newSecurityError. - Storage providers unified:
StorageConfigflattened to inheritance-based config so providers (local,s3) share a single shape across delivery and trace storage. make rulesnow generates bothCLAUDE.mdandAGENTS.mdby default: thepipelex.kit_config.preferred_agent_targetsetting has been renamed topreferred_agent_targetsand is now a list. The default is["claude", "agents"]. Cursor remains exclusive (["cursor"]) and cannot be combined with single-file targets. Downstream projects overriding this setting must rename the key and wrap the value in a list.- Cold start trimmed: heavy SDK imports (
boto3,huggingface_hub, etc.) deferred behindTYPE_CHECKINGor function-local guards across multiple plugins. - Graph viewer updated to mthds-ui v0.3.4: bumped from v0.3.0 — additional polish atop the resizable detail panel, escape-to-close, sticky header, prompt expand/collapse with copy button, concept refinement display.
- Default models: small-vision and creative defaults now point to
gemini-3.0-flash-preview. Addedclaude-4.6-sonnetand Bedrock token-auth support. kajsonupgraded from0.3.1to0.5.0— required for the dynamic-class source registry that backs schema-to-model reconstruction.- README install instructions: replaced step-by-step Claude Code setup with single copy-paste messages for Claude Code and Codex, added manual install section.
Fixed
- Anthropic structured generation no longer flattens all errors to
CONTENT.AnthropicLLMWorker._gen_objectruns requests throughinstructor, which wraps SDK exceptions inInstructorRetryException. The previous handler categorized every wrapped error asCONTENT, so genuineRateLimitError,APITimeoutError,APIConnectionError,PermissionDeniedError, andAuthenticationErrorcases never reached the typed branches — they were reported as content failures (non-retryable) instead ofTRANSIENT/CAPACITY/CONFIGURATION. The handler now unwrapsInstructorRetryException.failed_attempts[-1].exception(with a__cause__/RetryError.last_attemptfallback) and routes recognized SDK exceptions through a shared categorization helper; truly unrecognized errors keep theCONTENTfallback. - Managed-deck detection no longer misclassifies user TOMLs.
_is_managed_deck_filenamepreviously treated any non-x_custom_*.tomlas kit-managed, so a user file likemy_overrides.tomldropped into the deck dir would have been reported (and onpipelex updateoverwritten) as if it were a kit file. Now requires the numbered^\d+_.*\.toml$prefix that the kit actually ships. PipeLLMoutput structure prompt used the unresolved concept ref. Whenis_structure_prompt_enabled,get_output_structure_promptwas called withpipe_run_params.dynamic_output_concept_ref or output_stuff_spec.concept.concept_ref. The first form can be a bare code (no domain), which broke downstream concept resolution. Now passes the already-resolvedoutput_stuff_spec.concept.concept_refdirectly.PIPELEX_NO_DECK_NOTICEsuppression was too lax. Any non-empty value silenced the deck-staleness notice — includingPIPELEX_NO_DECK_NOTICE=0, which users might reasonably expect to enable the notice. Now requires the documentedPIPELEX_NO_DECK_NOTICE=1.- Shipped
.kit_manifest.jsoncarriedkit_version: "0.25.0"for the 0.25.1 release, which would have triggered false stale-detection on fresh installs. Bumped to0.25.1and re-synced intopipelex/kit/configs/. - Stored-XSS guard: HTML escaped in fallback
main_stuff.html. GatewayExtractWorkerteardown: guarded done-callbacks against cancelled tasks to stop noisy teardown errors.- URL checker: 401/403 are now treated as OK for auth-walled URLs.
- Pipeline duplicate guard: registering the same pipeline twice raises explicitly instead of silently shadowing.
Documentation
docs/tools/cli/update.mdno longer claims the deck advisory fires on every CLI invocation. Clarified that it is suppressed forlogin,init,doctor,update, andwhich.
Security
schema_to_modelrejectsx-python-*codegen extensions and restricts__import__to an allowlist.datamodel-code-generatorhonors thex-python-importJSON Schema extension by emitting arbitraryfrom <module> import <name>statements with no sanitization. Combined with the prior gap that_make_restricted_builtins()did not block__import__, an attacker able to plant a craftedobject_class_schema(whereObjectAssignment.object_class_schema: dict[str, Any]round-trips untouched) could cause arbitrary modules to be imported duringexec()of generated code. Two-layer defense added: (1)_reject_unsafe_schema_extensionsraisesUnsafeSchemaErrorif anyx-python-*key is present anywhere in the schema; (2)__import__in the exec namespace is now wrapped to allow onlypydantic,typing,typing_extensions,enum,datetime,decimal,uuid,__future__,collections, andre.- Restricted exec builtins, path sanitization, and atomic fingerprint caching in the schema-to-model pipeline.
- No leaked exception strings on error paths; prefix guards on storage URIs.
[v0.25.2] - 2026-04-30
Fixed
pipelex updateno longer flags user-added deck files for removal. The "managed file" filter accepted any.tomlnot prefixed withx_custom_, so project-local additions likepipelex-cookbook'scookbook.tomlwere reported as "removed upstream" with action "back up + remove". The filter now matches the documented numbered convention only (<digits>_*.toml); any other filename —cookbook.toml,x_custom_*.toml, etc. — is invisible to the update planner.
[v0.25.1] - 2026-04-29
Added
pipelex updatecommand + model-deck staleness detection. New top-level command refreshes the installed model deck (~/.pipelex/inference/deck/) to match the kit shipped with the running pipelex version. Tracks per-file SHA-256 hashes plus the kit version in a.kit_manifest.jsonwritten next to the deck files. Supports--dry-run,--yes(non-interactive),--no-backup(skip.bakfiles for locally-modified deck files), and--local(project-local deck instead of global).- Boot-time deck staleness warn. Every
pipelexCLI invocation prints a one-line yellow advisory when the installed deck's recorded kit version is older than the running pipelex (or when no manifest exists yet). Cost is one file read + one string compare. Suppress withPIPELEX_NO_DECK_NOTICE=1. Skipped automatically forpipelex login,init,doctor,update, andwhich. pipelex doctordeck section. Reports per-file deck status (up_to_date,kit_added,kit_removed,clean_behind,locally_modified) and offerspipelex updateas an auto-fix under--fix.- Manifest written by
pipelex init. Fresh installs land with a current.kit_manifest.jsonso future updates can detect drift cleanly. --dynamic-output-concept/-Oflag onpipelex run. All three subcommands (run bundle,run pipe,run method) accept a concept ref (e.g.document_qa.ReferenceCount) used to resolve a pipe whose output is declared asDynamic. Threaded through_run_core.execute_runtoPipelexRunner.execute_pipeline(dynamic_output_concept_ref=...). Until now, Dynamic-output pipes were only callable from the Python runner.- Line-length-safe wrapping in the structures generator.
pipelex build structuresnow wraps long descriptions so every emitted line stays under the 150-char ruff limit. Long class docstrings become a multi-line triple-quoted block; long Field descriptions become a parenthesized implicit-string-concatenation block (description=("first chunk " "second chunk")). Short descriptions still emit the compact single-line form. New unit tests intests/unit/pipelex/core/concepts/structure_generation/test_structure_generator_wrapping.pycover both lengths and the combined long-everything case. Previously, descriptions above ~140 chars produced files that failedruff checkwith E501.
Changed
- Numbered deck files (
N_*_deck.toml) are pipelex-managed. Each file now carries a header banner explaining that customizations belong inx_custom_*.toml(which pipelex never tracks or overwrites). Local edits to numbered files are preserved with a timestamped.bak.<UTC-timestamp>backup onpipelex updatebut will not survive future updates.
Fixed
-
PipeLLMDynamic-output detection compared the wrong fields.pipe_llm.pycheckedself.output.concept.code == "native.Dynamic", butconcept.codeis the bare code ("Dynamic") not the qualified ref. The check never matched, so when a caller passeddynamic_output_concept_reffor aDynamic-output pipe, the resolver branch was skipped silently: the output structure stayedDynamicContent(an emptyStuffContentsubclass), the LLM produced JSON shaped like the requested concept, and the result deserialized to{}. Detection now usesconcept.code == NativeConceptCode.DYNAMIC and concept.domain_code == SpecialDomain.NATIVE. -
Dynamic-output concept resolution rejected qualified refs. When the runtime override was supplied (e.g.
"document_qa.ReferenceCount"), the previous code calledmake_concept_ref_with_domain(domain_code=self.domain_code, concept_code=output_concept_ref), producing"document_qa.document_qa.ReferenceCount"and a missing-concept lookup. Now usesmake_concept_ref_with_domain_from_concept_ref_or_code, which extracts the domain from the input when it's already qualified and falls back to the pipe's domain only for bare codes. Callers can pass either form.
[v0.25.0] - 2026-04-28
Added
-
GPT-5.5 model support. New
gpt-5.5entry on theopenai,azure_openaiand gateway backends. -
gpt-image-2image generation (OpenAI). New model entry with img-gen routing and constraints onopenai,azure_openai.
Fixed
- PDF input declared on Azure OpenAI and gateway for the GPT-5.4 series.
gpt-5.4,gpt-5.4-mini,gpt-5.4-nano,gpt-5.4-pro(andgpt-5.5) now advertisepdfin theirinputsonazure_openaiand the gateway, matching the existing OpenAI direct entries. Verified end-to-end with live document tests against both backends.
Changed
- Img-gen taxonomies aligned for
gpt-image-2. Convention:gpt_imagefor taxonomies/values shared across all OpenAI GPT Image models (legacy + gpt-image-2);gpt_image_legacywhen the value applies only to gpt-image-1/-1-mini/-1.5 (gpt-image-2 usesunavailablewhere a legacy-only option does not apply). Renames: AspectRatioTaxonomy.OPENAI_GPT_IMAGE_LEGACY→GPT_IMAGE_LEGACY(value"openai_gpt_image_legacy"→"gpt_image_legacy")AspectRatioTaxonomy.OPENAI_GPT_IMAGE_2→GPT_IMAGE_2(value"openai_gpt_image_2"→"gpt_image_2")OutputFormatTaxonomy.GPT→GPT_IMAGE_LEGACY(value"gpt"→"gpt_image_legacy")OutputCompressionTaxonomy.GPT_IMAGE→GPT_IMAGE_LEGACY(value"gpt_image"→"gpt_image_legacy")InputFidelityTaxonomy.OPENAI_IMAGE→GPT_IMAGE_LEGACY(value"openai_image"→"gpt_image_legacy")NumImagesTaxonomy.GPT→GPT_IMAGE(value"gpt"→"gpt_image")InferenceTaxonomy.GPT→GPT_IMAGE(value"gpt"→"gpt_image")- Removed dead
AspectRatioTaxonomy.GPT. -
InputImagesTaxonomy.GPT_IMAGEunchanged (already correct — shared across legacy and gpt-image-2). -
HuggingFace and Fal img-gen workers honor
model_choicerule.huggingface_img_genandfalworkers now pop"model"fromargs_dictinstead of hardcodinginference_model.model_id, mirroring howpromptis already extracted. Themodel_choice = "model_id"rule is now required on every model under these backends; missing it raisesImgGenParameterErrorat call time. Rules added toqwen-image(HF) and to all Fal models (flux-pro,flux-pro/v1.1,flux-pro/v1.1-ultra,flux-2,fast-lightning-sdxl).
[v0.24.1] - 2026-04-22
Security
- lxml floor
>=6.1.0to patch CVE-2026-41066 (GHSA-vfmq-68hx-4jfw): default configuration ofiterparse()andETCompatXMLParser()allowed XXE to local files (resolve_entities=True). lxml 6.1.0 changes the default toresolve_entities='internal'. Transitive viadocling; floor added to thedoclingextra inpyproject.tomlso downstream installs ofpipelex[docling]cannot resolve a vulnerable version. - cryptography floor
>=46.0.7to patch CVE-2026-39892 (GHSA-p423-j2cm-9vmq): non-contiguous Python buffers passed to hashing APIs (e.g.Hash.update()) could read past the end of the buffer on Python >3.11. Transitive viagoogle-auth(pulled bygoogle,gcp-storage,google-genaiextras) andmoto(dev). Floor added to each affected extra inpyproject.toml— previous bump was lockfile-only, which did not protect downstream users resolving fresh from PyPI metadata. - pytest bumped to 9.0.3 to patch CVE-2025-71176 (GHSA-6w46-j5rx-g56g): vulnerable
/tmp/pytest-of-{user}directory handling on UNIX could let a local user cause DoS or gain privileges. Dev-only dependency;pyproject.tomlminimum bumped from>=9.0.2to>=9.0.3. - transformers CVE-2026-1839 (GHSA-69w3-r845-3855) risk-accepted, alert dismissed. The vulnerability requires calling
transformers.Trainer._load_rng_state()with an attacker-controlled checkpoint file. Pipelex only pullstransformerstransitively throughdocling-ibm-modelsfor PDF layout inference; theTrainerclass is never imported or executed. Upgrade path is blocked upstream:docling-ibm-models3.13.0 pinstransformers!=5.0.*,!=5.1.*,!=5.2.*,!=5.3.*,<6.0.0,>=4.42.0, explicitly excluding the patched 5.0.0rc3 release. Revisit whendocling-ibm-modelsadds support fortransformers>=5.4. - Release-publishing GitHub Actions pinned to SHAs:
pypa/gh-action-pypi-publishandsigstore/gh-action-sigstore-pythoninpublish-pypi.ymlare now pinned to full commit SHAs (version kept as a trailing comment) so a compromised tag on a third-party action cannot silently alter a PyPI release. Dependabot keeps them fresh. .github/dependabot.ymladded: declarespipandgithub-actionsecosystems, weekly cadence, with dev and runtime deps grouped to reduce PR noise. Security updates fire immediately regardless of schedule.dependency-review.ymlworkflow added: runs GitHub'sdependency-review-actionon PRs tomain,dev, and release branches. Fails the PR if it introduces a dependency with a moderate-or-higher CVE. Respects the existing transformers (GHSA-69w3-r845-3855) risk-acceptance viaallow-ghsas. Enable as a required status check in branch protection formainto block vulnerable merges.
[v0.24.0] - 2026-04-16
Added
- claude-opus-4-7 model: Registered on anthropic, bedrock, and gateway backends with 128k max output tokens, $5/$25 per MTok pricing, adaptive thinking, and PDF/vision support
XHIGHreasoning effort level: New effort tier across all providers, mapped to Anthropic'sxhigh(recommended for coding/agentic work), OpenAI'sxhigh, and best-available equivalents for Google and MistralTEMPERATURE_UNSUPPORTEDconstraint: New listed constraint for models that reject sampling parameters entirely, checked in both Anthropic and OpenAI completions workers- claude-4.6-sonnet model: Registered on anthropic, bedrock, and gateway backends
- LLM deck cheap presets: Added cheap variants for writing-factual, retrieval, and engineering-code presets, with retrieval tiers from
gemini-2.5-flash-litetoclaude-4.7-opus - Bedrock bearer token authentication: New
bedrock_access_variantconfig option supports"bedrock_token"auth usingAWS_BEARER_TOKEN_BEDROCKenv var, alongside the existing"aws_access"method (default)
Changed
- Anthropic adaptive thinking rejects
reasoning_budget:_build_thinking_params_for_budgetnow raisesLLMCapabilityErrorfor adaptive thinking models, guiding users toreasoning_effortinstead — extended thinking (type: "enabled") is removed on Opus 4.7+ - LLM deck: Updated
best-claudealias toclaude-4.7-opus, switchedimg-gen-prompting-cheapto@default-small-creative, removed deprecated builder presets, standardized cheap preset descriptions - Google
MINIMALreasoning level:ReasoningEffort.MINIMALnow maps to Google'sThinkingLevel.MINIMAL(was previously collapsed toLOW);GoogleThinkingLevelenum gainsMINIMALand the defaultgoogle_config.effort_to_level_mapupdates accordingly
[v0.23.9] - 2026-04-14
Added
- Graph UI asset sync workflow:
package.jsonpins@pipelex/mthds-uito a git tag,make sync-graph-uiclones and builds standalone assets,make check-graph-ui-syncverifies version alignment - CI check:
graph-ui-check.ymlworkflow validates graph viewer assets match the pinned version on PRs to main /update-graph-uiskill: automates bumping the mthds-ui version, syncing assets, and running tests
Changed
- Graph viewer updated to mthds-ui v0.3.0: resizable detail panel, escape-to-close, sticky header, prompt expand/collapse with copy button, concept refinement display
- README install instructions: Replaced step-by-step Claude Code setup with single copy-paste messages for Claude Code and Codex, added manual install section
[v0.23.8] - 2026-04-07
Changed
- Standalone ReactFlow graph rendering: Replaced Jinja2 template-based HTML generation with a single standalone HTML asset, simplifying the graph rendering pipeline and removing the Jinja2 template dependency for ReactFlow output.
[v0.23.7] - 2026-04-06
Added
- Graph tracing for pipe run data: Pipe run data and concept are now included inside the flowchart graph spec, enabling richer visualization of pipe execution results across all pipe types (LLM, extract, compose, search, image gen, sequence, condition, batch, parallel).
- Assignment pipe: New
pipe_assignmentpattern for direct value assignment within pipe execution.
[v0.23.6] - 2026-04-06
Changed
- Sub-pipe input normalization: Silently drop unsupported
inputsfield from step/branch dicts instead of logging a warning.
[v0.23.5] - 2026-04-04
Added
- Gateway config: Introduced
GatewayConfigto bundle gateway model specs with AWS region, propagating it through the backend library so bedrock backends use the correct region. - Config coverage tests: Integration tests that validate one model per Portkey config for each model type (LLM, image gen, extract, search), with
all_configs_gwtest profile andmake ticctarget. - nano-banana-2 model: Added
gemini-3.1-flash-image-previewasnano-banana-2with updated Google image gen costs. - DeepSeek models on bedrock: Added DeepSeek models to the bedrock backend configuration.
Changed
- Image gen deck aliases: Updated aliases to nano-banana model variants and removed
flux-2-pro. - Remote config: Bumped to v08.
- Gateway model docs: Regenerated, removing retired models (claude-3.7-sonnet, deepseek-v3.1, deepseek-v3.2-speciale, flux-2-pro).
Fixed
- deepseek-v3.1 structured output: Removed unsupported
structuredoutput capability from the bedrock deepseek-v3.1 model spec — thebedrock_aioboto3worker does not implement object generation, so structured calls would fail at runtime.
[v0.23.4] - 2026-04-02
Changed
- Pipe spec output alias: Removed
output_typealias fromparse_pipe_spec, keeping onlyoutput_conceptas the single alias for theoutputfield. Simplified the alias resolution logic accordingly.
[v0.23.3] - 2026-04-02
Changed
- Pipe spec output aliases:
parse_pipe_specnow acceptsoutput_conceptandoutput_typeas aliases for theoutputfield, with smart fallback when both alias and canonical field are present.
Fixed
- Gateway terms check: Terms acceptance is now only required for inference operations, not for read-only operations like model spec fetching during validation.
[v0.23.2] - 2026-03-30
Changed
- Claude Code plugin install command: Fixed as →
/plugin install mthds@mthds-pluginsacross README and docs. - Claude Code plugin reload instructions: Added
/reload-pluginsas the primary method to activate the plugin, with exit/reopen as fallback.
[v0.23.1] - 2026-03-30
Changed
- Concept spec:
concept_codereplacesthe_concept_codeas the canonical field name in concept specs and working memory factory. - Shared spec parsing:
concept_cmdandpipe_cmdnow delegate to the sharedparse_concept_specandparse_pipe_spechelpers, removing stale duplicate parsing logic while preserving compatibility and fixing alias/dict-mutation edge cases. concept_ref/pipe_refaliases:parse_concept_specandparse_pipe_specnow acceptconcept_refandpipe_refas input aliases for better AI-agent compatibility.- Replace
pipwithuvin install commands across config files and error messages. - Docs links: Updated mthds.ai links to include
/latest/path.
Fixed
- Concept alias bug: Concept alias handling previously listed
concept_codeas an alias instead ofthe_concept_code, causing valid input to be silently dropped. Fixed by the new sharedparse_concept_spechelper.
[v0.23.0] - 2026-03-29
Added
- Builder Operations module (
pipelex/builder/operations/): New standalone operation functions for the build agent —concept_ops,inputs_ops,models_ops,output_ops,pipe_ops,runner_code_ops,validate_ops. These decouple build logic from CLI commands so it can be reused by agents and the API. dry_run_pipeline(pipelex/pipe_run/dry_run_pipeline.py): New shared entrypoint to dry-run a pipeline from MTHDS contents and produce aGraphSpec. Used by both CLI graph commands and the API.
Changed
mthds_content→mthds_contents: Unified singularmthds_content: str | Noneintomthds_contents: list[str] | NoneacrossPipelexRunner,pipeline_run_setup,validate_bundle, CLI commands, and builder operations. Callers now pass a list of bundle content strings.bundle_uri→bundle_uris: Renamedbundle_uri: str | Nonetobundle_uris: list[str] | NoneacrossPipelexRunner.__init__,pipeline_run_setup,dry_run_pipeline, and all CLI call sites. Multiple bundles can now be loaded simultaneously.- Bump
mthdsdependency to>=0.2.0(from>=0.1.1) to match the updatedRunnerProtocolinterface. - Graph rendering refactor: Extracted dry-run logic from
graph_rendering._dry_run_bundleinto the new shareddry_run_pipelinefunction. - Agent CLI inputs: Refactored
_inputs_coreto delegate tobuilder.operations.inputs_ops.build_inputs_for_pipeinstead of duplicating bundle validation and input rendering logic. - Agent CLI run: Added graph generation support with ReactFlow HTML output and side-effect metadata tracking in
_run_core. - Deduplicate
models_cmd→models_ops:models_cmd.pyis now a thin CLI wrapper delegating tolist_models()andformat_models_markdown()inmodels_ops.py, consistent with other agent CLI commands.
Removed
BuilderLoopand its iterative build-validate-fix cycle (builder_loop.py,builder.py,builder_errors.py). The build-agent CLI now drives spec construction directly.pipelex build pipeCLI command and associated MTHDS workflow files (builder.mthds,agentic_builder.mthds,pipe_design.mthds,concept_fixer.mthds,synthesize_image.mthds).-
pipelex-toolsruntime dependency: Moved to dev-only dependency;plxtis now invoked via subprocess passthrough. -
Talent system: Removed talent enums, config mappings (
talent_preset_mappings), and talent preset tests. Pipe specs accept model presets directly via themodelfield, making the talent indirection unnecessary.
Fixed
- Per-bundle dedup in pipeline run setup: Fixed duplicate bundle loading when the same bundle appears in multiple sources.
- HTTP utils: Use HEAD-first strategy for URL validation to avoid downloading large payloads unnecessarily.
library_dirspassthrough: Fixedlibrary_dirsnot being forwarded in builder operations (inputs_ops,validate_ops).- Dry-run status: Fixed validation status reporting for dry-run results.
[v0.22.0] - 2026-03-25
Added
- MiniMax Backend Support: Added integration for MiniMax models (M2, M2.1, M2.5, M2.7 series including high-speed variants) with an
all_minimaxrouting profile. check-modelAgent CLI Command: Introducedpipelex-agent check-modelto validate model references. Provides fuzzy matching suggestions, cross-collection suggestions, and wrong-sigil hints when an invalid model is provided.- Domain-Qualified Pipe References (
pipe_ref): Added apipe_refproperty (domain.code) as the primary pipe index, allowing pipes with the same code to coexist across different domains. Bare code lookups remain supported as a fallback when unambiguous. - Duplicate Concept Detection: Added validation to warn about duplicate concept declarations across different bundles within the same library.
- Shared TOML Formatter: Extracted a shared
format_toml_stringutility for consistent multi-line string formatting across the MTHDS factory and Agent CLI.
Changed
- Agent CLI Output Formats: Overhauled
pipelex-agentCLI output for LLM agents:conceptandpipecommands now output raw TOML to stdout;modelsanddoctorcommands output Markdown by default (JSON still available via--format json). - Unified
modelField in Pipe Specs: Replaced type-specific talent fields (llm_talent,extract_talent,img_gen_talent,search_talent) with a singlemodelfield accepting model presets directly. Talent mappings removed frompipelex-agent modelsoutput accordingly. - Initialization Checks:
check_is_initializednow additionally verifies the presence ofplxt.toml. - Documentation & Handoffs: Updated Claude Code skills plugin docs, CLI references.
Fixed
- Domain Metadata Conflicts: Loading multiple bundles declaring the same domain with differing descriptions or system prompts now emits a warning and keeps the first declaration instead of throwing an error.
- Cross-Domain Execution Tracking: Pipe controllers and the dry-run engine now track visited pipes using
pipe_refinstead of bare codes, preventing false-positive loop detections when crossing domains.
Removed
assembleAgent CLI Command: Removed thepipelex-agent assemblecommand.
[v0.21.0] - 2026-03-19
Added
- Web Page Extraction:
PipeExtractnow supports extracting content from web pages via the newlinkup-fetchmodel, withrender_jsandinclude_raw_htmlparameters. Added@default-extract-web-pagealias to the extraction model deck. - New AI Models: OpenAI / Azure:
gpt-5.4,gpt-5.4-pro,gpt-5.4-mini,gpt-5.4-nano,gpt-5.2-codex; Mistral:mistral-small-4 - DocumentContent Enhancements: Added
public_url,filename,title, andsnippetfields to support web pages and search citations. - AI Agent Documentation: Integrated
mkdocs-llmstxt-mdplugin to generate/llms.txtand/llms-full.txtfor AI agents. - Claude Code Skills: Added internal
.claude/skills(add-model,test-model) for registering and testing new inference models.
Changed
- Web Fetching → Extract Domain: Moved web fetching from the Search domain into the Extract domain. Replaced
FetchJob,FetchWorkerAbstract, and related classes with native handling inPipeExtractand a newGatewayExtractWorker. SplitLinkupWorkerinto dedicatedLinkupSearchWorkerandLinkupExtractWorker. - Search Results Unification:
SearchResultContentnow usesDocumentContentinstead of the removedSearchSourceContent. - Search Job Refactoring: Encapsulated
SearchJobparameters into a newSearchJobParamsobject; updatedSearchWorkerAbstractsignatures accordingly. - Documentation Build: Replaced inline HTML generation with a
docs/root-index.htmltemplate. Updatedrobots.txtto allow AI crawler access tollms.txt.
Fixed
- Remote Image Fetching: Added error handling (
httpx.HTTPStatusError,httpx.RequestError) inGeneratedContentFactorywhen downloading remote images, with graceful fallback to using the original URL aspublic_url.
Removed
page_image_captionsparameter: Removed fromPipeExtractSpecandExtractJobParams.
[v0.20.13] - 2026-03-16
Removed
- Remove unused
ViewSpecclass and related code from graph/reactflow — dead code that was no longer referenced.
[v0.20.12] - 2026-03-16
Fixed
- Fix Google "Sitemap could not be read" error by adding
Allow: /sitemap.xmltoROOT_ROBOTS_TXT—Disallow: /was blocking Googlebot from fetching the root sitemap even thoughSitemap:pointed to it.
[v0.20.11] - 2026-03-16
Fixed
- Fix
docs-deploy-rootsilently failing due to shell comments breaking the\continuation chain in the Makefile recipe — rootsitemap.xmland updatedrobots.txtwere never deployed in v0.20.10.
[v0.20.10] - 2026-03-16
Fixed
- Fix sitemap double-path bug (
latest/0.20.9/page/) caused bysite_urlincluding/latest/while mike also inserts the version prefix during deployment. - Override canonical URLs,
og:url, and JSON-LDurlto always point to/latest/via template override. - Add root-level
sitemap.xmlgeneration with/latest/URLs todocs-deploy-root.
[v0.20.9] - 2026-03-16
Changed
- Reorganize documentation site architecture and navigation.
- Add SEO meta descriptions to all doc pages.
- Redesign README: lead with value, collapse details.
[v0.20.8] - 2026-03-13
- Add
needs_model_specs=Trueto agent CLI run and models commands.
[v0.20.7] - 2026-03-12
- Bump
mthdsdependency to>=0.1.1.
[v0.20.6] - 2026-03-12
Added
needs_model_specsparameter: New option onPipelex.make()and CLI factories to load real gateway model specs without enabling full inference. Validation commands (pipelex validate,pipelex-agent validate) now fetch live model specs, improving accuracy of pipe/method/bundle validation.
Removed
- Deprecated
pipelex_inferencebackend: Removed all traces of the legacy backend — config files, enum values, migration logic, deprecation warnings, and documentation admonitions. The transition topipelex_gatewayis complete.
Fixed
pipelex init inference --local: Fixed file filter to also copy.mdfiles (e.g. Gateway model lists) to the backends directory, not just.tomlfiles.- Gateway terms persistence: Hardened failure handling — when terms acceptance can't be persisted (e.g. unwritable global directory), gateway is now properly disabled in
backends.tomlas a fallback, preventingGatewayTermsNotAcceptedErrorat runtime.
[v0.20.5] - 2026-03-09
Changed
- Config paths use
pathlib.Path: AllConfigLoaderproperties and methods now returnPathinstead ofstr. Consumer code across the config system (doctor, init, backends, routing, credentials, telemetry, agent CLI) updated accordingly. - Layered config resolution for
pipelex doctorandpipelex init: Config files are now resolved with project-first, global-fallback layering per file. Fixedreplace_backend_fileusing CWD-relative path that broke when run from another directory. - Gateway terms are explicitly global:
update_service_terms_acceptancenow targets~/.pipelex/by default, since gateway terms are a user-level agreement, not project-level. - Tweaks to the
pipelex-agentCLI to play well with the Claude Code plugin and skills.
[v0.20.4] - 2026-03-04
- Improve README.md instructions for Claude Code and MTHDS skills.
[v0.20.3] - 2026-03-04
Fixed
- Rewrote README with updated CV Batch Screening example, corrected CLI command, inputs schema, Python snippet, and pipe descriptions.
[v0.20.2] - 2026-03-04
Fixed
- Fixed removal of the --reset flag from the init command docs.
- Fixed the name of the
PipeSequenceresults within a batch.
[v0.20.1] - 2026-03-03
Changed
- Cost Report Consistency: Renamed
platform_llm_idfield toplatform_model_idinLLMTokenCostReport, aligning with all other report types (ImgGen, Extract, Search, Fetch) that already useplatform_model_id. - Test Coverage: Added
linkupbackend to the coverage test profile.
[v0.20.0] - 2026-03-03
Added
- CLI Authentication:
pipelex logincommand that initiates a browser-based OAuth flow (GitHub/Google) to authenticate with the Pipelex Gateway and save the API key locally. - Search Filtering:
from_date,to_date,include_domains, andexclude_domainsoptions on thePipeSearchoperator, routed through a newGatewaySearchWorker. - Expanded Cost Reporting: Token usage and cost tracking now covers Search, Fetch, Extraction, and Image Generation jobs, in addition to LLMs.
- New Models: Added
gpt-5.3-codex(text, images, pdf inputs) andnano-banana-2.
Changed
- Search Configuration: Renamed Linkup model IDs from
linkup/standardtolinkup-standard(anddeepvariant), simplified presets to$standardand$deep. - Default Pipeline Execution: Changed from
in_memorytolocal. - Default Extraction Model: Changed from
mistral-document-ai-2505toazure-document-intelligence; removedmistral-document-ai-2505from the supported Gateway models list. - Content Handling:
TextAndImagesContentnow supports an optionalraw_htmlfield. - Dev Experience:
Makefilecommands (generate-mthds-schema,update-gateway-models) run in quiet mode by default.
[v0.19.0] - 2026-03-02
Added
- Web Search Integration: Introduced a new
PipeSearchoperator, native support for Linkup as a search backend provider,SearchResultandSearchResultContentconcepts for handling answers with citations, and Model Deck support for search models. - Graph View Generation: Added a
--viewoption topipelex validate bundlethat generates aViewSpecJSON (compatible with ReactFlow) for client-side graph rendering without writing files to disk.
Changed
- Test Configuration: Added a
searchpytest marker, excluded from default test runs. mthdsbumped to>=0.1.0.pipelex-toolsbumped to>=0.2.3.linkup-sdk>=0.12.0added as optional dependency for the Linkup search provider.
[v0.18.6] - 2026-03-01
Added
- GitHub URL support for CLI method targets — All CLI commands accepting a method target (
pipelex validate method,pipelex run method,pipelex build inputs method, etc.) now accept a public GitHub URL (e.g.,https://github.com/org/repo/tree/main/methods/my-method). The repository is cloned automatically, and the method package is discovered and validated. Subdirectory URLs are supported. - Local path support for CLI method targets — Method targets can now also be local filesystem paths pointing to a directory containing a
METHODS.toml. This works for bothpipelexandpipelex-agentCLIs. - Added
clone_default_branch()inmthdspackage for shallow-cloning a git repository's default branch.
[v0.18.5] - 2026-03-01
Changed
pipelex-agent assemblecommand now outputs JSON to stdout by default.
[v0.18.4] - 2026-03-01
Added
- Introduced a lenient loading mode for
InferenceBackendLibraryandRoutingProfileLoader: when enabled, logs warnings instead of raising errors for missing credentials, variable fallback failures, or disabled backends — skipping individual backends gracefully rather than crashing the entire load process. - Added
needs_inferenceparameter toPipelex.make,make_pipelex_for_cli, andmake_pipelex_for_agent_clito control whether full inference setup (credentials, gateway checks, telemetry) is required. - Added
needs_inference_in_pipelexhelper toshared_pytest_pluginsto replace the inverted logic of the previous helper.
Changed
- CLI Robustness:
pipelex build,validate,show,graph,inputs, andwhichcommands now run withneeds_inference=False, allowing them to succeed even when backend credentials are missing or incomplete. - Refactored
Pipelex.make: renameddisable_inferencetoneeds_inference(defaultTrue). WhenFalse, enables lenient backend loading, uses a dummy remote config, disables telemetry, and skipsvalidate_model_deck().
Deprecated
is_inference_disabled_in_pipelexinshared_pytest_plugins— migrate toneeds_inference_in_pipelex.
[v0.18.3] - 2026-02-27
- Updated
pipelex-toolsdependency to0.2.1
[v0.18.2] - 2026-02-27
Added
- Inputs path resolution — Relative file paths (e.g.,
"url": "data/invoice.pdf") insideinputs.jsonare now resolved relative to the inputs file's parent directory, making bundle directories self-contained and portable. Applies to both user and agent CLIs. Handles HTTP, data:, pipelex-storage://, and absolute paths by leaving them unchanged.
Changed
pipelex-agent initdefaults to local project — Theinitcommand now targets the project-level.pipelex/directory by default (at detected project root) instead of auto-detecting. The--localflag has been removed. Use--global/-gto target~/.pipelex/. Errors out if no project root is found without-g.pipelex-agent doctorsupports--global/-g— Thedoctorcommand now accepts--global/-gto check the global~/.pipelex/directory. Without the flag, it auto-detects project.pipelex/if present, else falls back to~/.pipelex/.pipelex-agent init --configimproved help — The--configoption help text now shows the JSON schema with field types upfront for better discoverability.
Fixed
pipelex-agent init -gservice agreement — The--globalflag now correctly writes the gateway service terms acceptance (pipelex_service.toml) to the target directory instead of always writing to the auto-detected config dir.- Deterministic file discovery order —
find_files_in_dirnow sortsrglob/globresults for consistent ordering across platforms and Python versions. On Linux with Python < 3.13,rglobreturned filesystem-order results, which could causetest_validate_allto fail by picking up a test package'sMETHODS.tomlbefore pipelex internal bundles.
[v0.18.1] - 2026-02-25
Fixed
- Fix docs deployment failure caused by shell metacharacters (parentheses) in Makefile
PRINT_TITLEmacro argument fordocs-deploy-roottarget - Fix
mikeunable to findmkdocsbinary by adding venvbin/to PATH in all mike-based Makefile targets
[v0.18.0] - 2026-02-25
Highlights
- Pipelex Gateway — The deprecated
pipelex_inferencebackend is now replaced bypipelex_gateway, featuring remote model configuration fetching so you always have access to the latest models without updating Pipelex.
Getting your API key:
1. Get your API key at app.pipelex.com
2. Add it to your .env file: PIPELEX_GATEWAY_API_KEY=your-key-here
Gateway Supported models — included with the Free API Key - Language Models (LLM): - OpenAI: all models up to GPT-5.2 and Codex - Anthropic: Claude 3.7 Sonnet through Claude 4.5 Haiku/Sonnet/Opus - Google: Gemini 2.0/2.5 Flash, Gemini 2.5 Pro, Gemini 3.0 Flash/Pro - xAI: Grok 3/mini, Grok 4 (+ fast reasoning variants) - Open-source: Mistral Large 3, DeepSeek v3.1/3.2/Speciale, GPT-OSS 20B/120B1, Kimi K2, Phi-4, Qwen3-VL 235B - Document Extraction: Mistral Document AI, Azure Document Intelligence, DeepSeek OCR - Image Generation: GPT-Image 1/1.5, Flux 2 Pro, Nano Banana/Pro
Accepting the Terms of Service:
When you run pipelex init, you'll be prompted to accept the Gateway terms of service. By using Pipelex Gateway, telemetry is automatically enabled and identified by your API key (hashed for security) to monitor service quality and enforce fair usage. We only collect technical data (model names, token counts, latency, error rates)—never your prompts, completions, or business data. See our Privacy Policy.
⚠️ Migration deadline: If you were using pipelex_inference, please migrate soon—the legacy service will be shut down within few days. Get your new Gateway key at app.pipelex.com.
- Execution Graph Visualization System (preview feature) — Comprehensive tracing and visualization for pipeline executions.
CLI: --graph flag on pipelex run generates execution graphs. New pipelex graph render <graph.json> command for post-run rendering.
Viewers: Interactive ReactFlow viewer (reactflow.html) with pan/zoom and node inspector. Mermaid diagrams (mermaidflow.html) with subgraphs and clickable nodes.
Makefile: make view-graph (vg) and make serve-graph (sg) to start a local graph viewer.
- Pydantic Structure Generation — Two new CLI commands bridge Pipelex's declarative concepts with your Python code:
pipelex build structures /library_dir/ — Generates Pydantic models from all concept definitions found in the specified library directory. Now you have your structures as Python code: you can iterate on them, add custom validation functions, or use them as type hints in your code.
pipelex build runner — Now automatically generates both the Python runner file AND the required Pydantic structures. When you run this command, it creates a complete, ready-to-execute Python script that imports the generated structures, so you can immediately use typed objects in your pipeline code.
See the Build Commands documentation for usage examples.
- New Backends & Models:
- Hugging Face Inference — Support for Hugging Face Inference API, including
qwen-imagetext-to-image model. - Google
gemini-3.0-flash-preview - Mistral OCR latest model
mistral-ocr-2512 - Scaleway inference provider support for open-source models
-
Portkey AI backend integration for unified access to multiple models through a single API key
-
Document Support in
PipeLLM— IncludeDocumentobjects (like PDFs) directly in prompts using@variableor$variablesyntax. Supports single documents, multiple documents, and lists, combinable with text and image inputs. -
PipeComposeConstruct Mode — New mode for deterministically buildingStructuredContentobjects without an LLM. Compose fields from working memory variables, fixed values, templates, and nested structures. -
Content Storage System — Configurable storage for generated artifacts (images, extracted pages). Supports
localfilesystem (.pipelex/storage/),in_memory, AWS S3 (pip install pipelex[s3]), and Google Cloud Storage (pip install pipelex[gcp-storage]). Cloud providers support both public URLs and time-limited signed URLs. Content referenced via stablepipelex-storage://URIs. -
Langfuse & OpenTelemetry Observability — New OpenTelemetry-based observability system enables powerful tracing and Evals through Langfuse integration. Also supports OTLP-compatible backends (Datadog, Honeycomb, etc.). Configured via
.pipelex/telemetry.toml. -
Python 3.14 Support — Officially tested and supported.
-
Agent CLI (
pipelex-agent): New machine-first CLI for AI agents with structured JSON output for all commands (build,run,validate,inputs,concept,pipe,assemble,graph,models,doctor). - LLM Reasoning Controls: Unified support for "Thinking" models (Chain of Thought) with
reasoning_effort,reasoning_budget, andthinking_modeparameters. Supports Anthropic Extended Thinking, Google Gemini Thinking, OpenAI Reasoning (o1/o3), and Mistral/Magistral models. Includes new presets:$deep-analysisand$quick-reasoning. - Image-to-Image Generation:
PipeImgGennow supports input images viainput_imagesfield, withInputImagesTaxonomyfor provider-specific handling and variable reference detection ({{ var }},$var,@var) in prompts. - PipeCompose "Construct" Mode: New
constructmode for building structured objects (dictionaries/Pydantic models) directly from variables. - Nested concepts in inline structures: You can now define nested structures for your concepts in your
.plxfiles. Learn more here: Nested Concepts in Inline Structures.
Breaking Changes
- CLI restructure:
method/pipesubcommands —pipelex run,pipelex validate, and allpipelex buildsubcommands (runner,inputs,output) now require an explicitmethodorpipekeyword. For example:pipelex run method my-methodorpipelex run pipe scoring.compute. The oldpipelex run <target>form is no longer supported. The agent CLI (pipelex-agent) follows the same structure.
Added
- Method resolution (
cli/method_resolver.py) — resolves installed method names to pipe codes and library directories. Integrates withmthdsdiscovery module to find methods in~/.mthds/methods/and./.mthds/methods/. run methodcommand — run an installed method by name, optionally overriding the pipe with--pipe.validate methodcommand — validate all bundles in an installed method.build runner/inputs/output methodcommands — generate build artifacts for installed methods.- Persistent Credential Storage (
~/.pipelex/.env):pipelex initnow prompts for missing API keys after backend selection and saves them to~/.pipelex/.envwith0600permissions. Credentials are loaded automatically at startup (global defaults, overridden by project.env). pipelex init credentialsCommand: New standalone focus to re-enter API keys without resetting configuration. Scans enabled backends, detects missing env vars, and prompts only for those.- Package Management System: Introduced a full package manager for MTHDS with
METHODS.tomlmanifests,methods.locklockfile generation, local path and remote Git-based dependency resolution (MVS), a local package cache (~/.mthds/packages), and a newpipelex pkgCLI command group (init,list,add,lock,install,update,publish,search,inspect,graph). - Hierarchical Domains: Support for dot-separated domain namespaces (e.g.,
legal.contracts.shareholder) and cross-package references viaalias->domain.pipesyntax. - PipelexRunner: Introduced the
PipelexRunnerclass as the primary entry point for executing pipelines, replacingPipelexClientand standaloneexecute_pipeline/start_pipelinefunctions. - Linting & Formatting: Integrated
plxt(Pipelex Tools) for formatting and linting.mthdsand.tomlfiles, including CI/CD checks alongsideruff. - JSON Schema: Automatic generation of
mthds_schema.jsonfor standard definition, IDE validation, and auto-completion. - Dev CLI: Added
pipelex-devCLI for internal development tasks (e.g., schema generation). - CSP Nonce Support: Added Content Security Policy nonce support for generated HTML graphs (Mermaid/ReactFlow) to enable secure rendering in VS Code webviews.
- OpenRouter Backend: Added OpenRouter as an inference backend with 337 chat model definitions and 14 image generation models.
- Builder Auto-Repair: Self-healing capabilities including auto-generation of undeclared concepts, multiplicity mismatch fixes, and pruning of unreachable pipes/unused concepts.
- Concept Field Features: Added
choicessupport (compiles toLiteraltypes/Enums) and explicitlisttype withitem_type/item_concept_ref. - PipeFunc Execution Error Context: When a
@pipe_funcfunction fails during execution, the error message now includes detailed context: the function name, actual input values from working memory, expected output type, and the original error with its type. This makes debugging PipeFunc errors much easier. pipelex build outputCLI Command: New command to generate example output JSON for a pipe, complementing the existingpipelex build inputscommand. Shows the expected output structure based on the pipe's output concept type, with multiplicity support. For pipes withnative.Anythingoutput (e.g.,PipeConditionwith different mapped pipe outputs), displays all possible outputs from mapped pipes.- Telemetry System: Introduced anonymous usage tracking and exception capture for CLI commands (
graph render), reporting to both user-configured and Pipelex analytics endpoints. - PipeExtract Operator Validation: Added strict input validation that raises configuration errors for incompatible input types or when document-specific parameters are used with image inputs.
- PipeCondition Output Auto-Fix in Builder Loop: The pipe builder now automatically fixes
PipeConditionoutput concept errors during validation. If all mapped pipes have the same output, thePipeConditionoutput is set to that concept; otherwise it's set tonative.Anything. - PipeFunc Return Type Validation: Added validation to ensure that a
PipeFuncfunction's return type matches the output concept's structure class. - URL Validation on
ImageContentandDocumentContent: Both models validate external resources (HTTP/HTTPS URLs via HEAD request, local file paths via existence check) through avalidate_resources()method called during pipeline execution (validate_before_run) rather than at model instantiation. Internal URIs (data:,pipelex-storage://) skip validation entirely. Validation is skipped in dry-run mode where inputs use mock URLs. - Literal Type Support in Dry Run Mocks:
DryRunFactorynow detectsLiteraltype annotations (includingOptional[Literal[...]]) and generates valid mock values by randomly picking from the allowed choices instead of producing invalid random strings. - Literal Type Support in
pipelex build inputs/pipelex build output: The concept representation generator now handlesLiteralfields by picking a random value from the allowed choices, and generates mock URL patterns forurlfields. - Literal Error Handling in Validation Messages: Pydantic validation error formatting now recognizes
literal_errortypes and displays them as "Invalid choice errors" with the actual value and expected options. PipeRunErrorCatching in Bundle Validation:validate_bundlenow catchesPipeRunErrorduring dry run and wraps it inValidateBundleErrorwith a clear message.ValidationErrorCatching in Pipeline Execution:execute_pipelinenow catches PydanticValidationErrorfrom input construction, formats the errors, and raises aPipeExecutionErrorwith a clear message.- Broader Error Handling in CLI
pipelex run: The CLI run command now catchesPipelexErrorin addition toPipelineExecutionError, providing better error messages for failures that occur outside the pipeline execution itself. - Content Filenames: Added
filenamefield toImageContentandDocumentContent, with auto-population from local file paths via newextract_filename_from_urihelper. - Batch Validation Error Type: Introduced
PipeValidationErrorType.BATCH_ITEM_NAME_COLLISIONfor naming conflicts in batch operations. - Documentation: Added naming convention rules to
builder.plxandpipe_design.plx(batch input lists should be plural, item names singular). --library-dirCLI Option:--library-dir/-Loption forpipelex run,pipelex validate, andpipelex buildsubcommands (one-shot-pipe,partial-pipe) to specify additional directories for searching pipe definitions. Can be specified multiple times.- Automatic File Loading: The core pipeline execution functions (
pipelex.execute_pipeline,pipelex.start_pipeline) can now directly load a pipeline from a file path via a newbundle_uriparameter. - Dry Run Mode:
pipelex run --dry-runexecutes pipeline logic without API calls, useful for validating structure and generating orchestration graphs. Combine with--mock-inputsto generate mock data for missing required inputs. | with_imagesJinja2 Filter: Explicitly extract and include all nested images from complex data structures (e.g.,Pageobjects or custom concepts withImagefields). Renders the object's text representation while making associated images available to the LLM.- System Prompt Media Support: Reference images and documents in
system_promptusing the same$variableand@variablesyntax as the userprompt. - Pipelex Gateway Service: Terms of service management via
.pipelex/pipelex_service.tomland interactive acceptance flow inpipelex initandpipelex init agreement. - Gateway Available Models Documentation: Auto-generated reference of all LLM, Document Extraction, and Image Generation models available through the Gateway.
- Configurable Retry Logic: Exponential backoff for inference API calls, configurable in
pipelex.tomlunder[cogt.tenacity_config] - Context Manager Support: The
Pipelexclass now supportswith Pipelex.make(): ...for graceful shutdown - Validation Improvements:
- Pipelex Bundle concept keys: prevent bundles from re-creating a native concept
PipeSequence: output multiplicity must match the last step's output multiplicityPipeFunc: output multiplicity must match the function return type (ListContentsubclass for multiplicity=true)- Rendering Protocols: Three new
@runtime_checkableprotocols (ImageRenderable,TagRenderable,TextFormatRenderable) to formalize the interaction between data types and Jinja2 filters. - Unified URI Handling System: New
pipelex.tools.urimodule providing type-safe parsing for HTTP/HTTPS URLs, local file paths, file URIs,pipelex-storage://URIs, and base64 data URLs. - Automatic Input Data Storage: Pipeline pre-processing step that converts large
data:URLs in anImageContentorDocumentContentintopipelex-storage://URIs for improved performance, by storing the data with the configured storage provider. Configurable viais_normalize_data_urls_to_storageinpipelex.toml. pipelex build inputsCommand: New CLI command to generate example input JSON files for pipes. Supports--library-dir(-L) to specify library directories.- Pipe Code Syntax Validation: Bundle validation now checks that pipe codes and
main_pipevalues use valid snake_case syntax, with proper error categorization (INVALID_PIPE_CODE_SYNTAX).
Changed
- CI Runner Optimization: Split self-hosted runners into dedicated test (D32) and lint (D4) pools with pre-baked Docker image (Python 3.10-3.14, UV, dependency cache) for faster job startup.
- MTHDS Light Client Extraction: The light client protocol (runner, pipeline models, pipe output abstractions) has been extracted from pipelex into the new
mthdspackage on PyPI. Pipelex now depends onmthds>=0.0.1and implements itsRunnerProtocol. - Global/Local Config Split:
pipelex initnow creates configuration in~/.pipelex/(global) by default. Usepipelex init --localto create project-level overrides in{project_root}/.pipelex/. Config loading merges: package defaults → global → project → overrides. - IDE Extension Detection: Extension check now uses
code --list-extensions/cursor --list-extensionsfor reliable detection instead of folder scanning. Shows separate marketplace links for VS Code (Microsoft Marketplace) and Cursor (Open VSX Registry). - Quieter
pipelex init: Removed verbose file listing and reset messages from config initialization output. pipelex initHelp Text: Detailed focus option descriptions now shown inpipelex init --helpexplaining each focus (all,config,credentials,inference,routing,telemetry,agreement).- File Extension: Pipeline definitions now use
.mthdsinstead of.plx; the project refers to "Methods" (MTHDS) rather than "Pipelex workflows". - Syntax: In
PipeParalleldefinitions,parallelsfield renamed tobranches;plx_configinpipelex.tomlrenamed tomthds_config. - Documentation: Comprehensive update to reflect
.mthdsfile format, package management, and new project structure. - Model Deck Updates: Default premium model now
claude-4.6-opus; added Mistral models (mistral-small-3.2,mistral-large,magistralseries) andgpt-5placeholders. - Jinja2 Rendering: Image objects now replaced with placeholders (e.g.,
[Image 1]) during text generation; async filters only registered in async environments. - Backend Configurations: Added
effort_to_level_mapandeffort_to_budget_mapsfor reasoning translation; disabled Google Vertex AI by default. - Dependencies: Updated
pypdfium2,anthropic, andmistralaiversion constraints. pipelex run --dry-run: No longer pretty prints the main_stuff output, matching the expected behavior for dry runs where no actual inference occurs.pipelex build structuresCommand: Now uses a lightweight loading mechanism that only processes domains and concepts, skipping pipe loading and validation entirely. This fixes the chicken-and-egg problem where structure generation would fail due to pipe validation errors before the structures were even created. Added--force/-fflag to regenerate all structures without checking if classes already exist.- Test Profile System: Refactored integration tests to use a new configuration system (
.pipelex/test_profiles.toml) withdev,ci, andfullprofiles for controlling which AI models are used in parametrized tests, replacing runtime filtering and hardcoded model lists. pipelex run --graphFlag: Now acts as an override forpipelex.tomlsettings instead of defaulting totrue.- Default Image Generation Models: Updated in
base_deck.toml:base-img-gen:flux-2-pro,best-img-gen:nano-banana-pro,fast-img-gen:gpt-image-1-mini - Remote Configuration: Updated service URL to version 3.
- GatewayExtractWorker: Now checks model capabilities before attempting image captioning.
- Change the output validation of
PipeCondition: If all mapped pipes have the same output concept,PipeCondition's output MUST be that same concept. If mapped pipes have different output concepts,PipeCondition's output MUST be the native conceptAnything. - CLI: Changed
pipelex validate alltopipelex validate --all(or-a). - StructuredContent.rendered_html(): Now recursively calls
rendered_html()on nestedStuffContentfields instead of using json2html conversion. Also skipsNonevalues and uses HTML table format. - Batch Pipe Validation: Enforced stricter naming rules for batch specs—
input_item_namemust differ frominput_list_nameand not shadow existing input keys, with clearer error messages suggesting plural/singular conventions. - Jinja2 Integration Refactored to Protocol-Based Approach: Replaced the
Jinja2Registrysingleton and handler functions with a decoupled protocol-based system, eliminating circular dependencies between the template layer and core domain logic. StuffArtefactRedesigned as Delegation Adapter: Now a lightweight, immutable adapter that delegates attribute access directly to underlyingStuffandStuffContentobjects, improving performance and providing more intuitive field access.- Image Extraction Moved to Content Types:
StructuredContent,ListContent,ImageContent, andTextAndImagesContentnow implement theImageRenderableprotocol, replacing centralized handler logic. - ⚠️ Breaking: User override config renamed from
pipelex_super.tomltopipelex_override.toml. - Image Generation Architecture: Refactored to taxonomy-based approach. Standardizes parameter translation (
aspect_ratio,quality,output_format) to provider-specific APIs. - Document Extraction Improvements:
pypdfium2extractor now extracts embedded images from PDFs. Response parsing uses dedicated Pydantic schemas for validation. - Default Model Change:
extract_text_from_visualsdeck now defaults toazure-document-intelligence pipelex_inferencereplaced bypipelex_gateway: See Highlights for migration details. NewPIPELEX_GATEWAY_API_KEYenvironment variable; default routing profiles updated topipelex_gateway_first.-
Telemetry System Split: Now two separate streams: 1. Pipelex Gateway telemetry for service monitoring (never collects prompts/completions/business data) 2. Custom telemetry to user-configured backends 3. Config updated accordingly (
telemetry.toml):- Renamed
[posthog]to[custom_posthog]to distinguish user's PostHog from Pipelex Gateway telemetry - Added new
[custom_portkey]section withforce_debug_enabledandforce_tracing_enabledsettings
- Renamed
-
Main Configuration Overrides Updated (
.pipelex/pipelex.toml): pipelex_override.toml(final override) renamed frompipelex_super.tomltopipelex_override.tomland moved from repo root to.pipelex/directorytelemetry_override.toml(personal telemetry settings)-
is_generate_cost_report_file_enableddefault changed fromtruetofalse -
Documentation:
- Clarified Setup (first run) vs Configuration (TOML reference), added a Setup overview page, and added contributor docs for configuration defaults/overrides.
- Added the "Under the Hood" page documenting the execution graph tracing system.
pipelex init: Now creates a documentedtelemetry.tomltemplate instead of prompting for preferences- Model Catalog Updated: Latest models (gpt-5.1, claude-4.5-opus, gemini-3.0-pro, etc.) and updated waterfalls in
base_deck.toml - Model Constraints Refactored: From simple lists to structured
valued_constraintsdictionaries (e.g.,valued_constraints = { fixed_temperature = 1 }) - OpenAI Responses API: New implementation now differentiates between
openai_completionsandopenai_responses - CLI Initialization: Commands refactored to use centralized
Pipelexinitialization factory for improved error handling pipelex doctor: Enhanced to detect outdatedtelemetry.tomlformats and suggest fixes--output-dirOption: Therunner,structures, andinputsCLI commands now accept this option- Cost Report: Now displays a note clarifying that it only includes LLM costs
descriptionField Now Required: InPipeAbstract,PipeBlueprint, andPipeSpecclasses.- Configuration: New
[pipelex.pipeline_execution_config.graph_config]section inpipelex.tomlfor fine-grained control over graph generation, data embedding, and rendering options. - CLI: All
pipelexcommands now accept--no-logoto suppress the Pipelex banner in the terminal — useful to reduce tokens.
Fixed
find_project_rootHome Directory Bug: The project root walker no longer considers the home directory (~) as a project root, even if it contains stray marker files likepackage.json.- Python 3.10 Compatibility: Fixed
datetime.UTCimport (Python 3.11+) to usedatetime.timezone.utc. - Graph Rendering: Fixed dashed edge rendering for
PipeBatchandPipeParallelrelationships. - Image Generation Response Parsing: Hardened image response parsing to handle varied provider response formats more robustly.
- Helpful Error for
get_stuff_as(ListContent[T]): When users incorrectly callget_stuff_as("name", ListContent[Something])instead ofget_stuff_as_list("name", Something), the error message now explicitly suggests usingget_stuff_as_list(). - PipeFunc
ListContent[T]Validation: Fixed validation rejecting validListContent[T]return types for array outputs (T[]). Previously, a function returningListContent[Expense]would fail validation foroutput = "Expense[]"with a misleading error. The validation now correctly extracts and validates the generic type parameter from Pydantic's metadata. - PipeFunc Class Name Matching: Fixed validation failing when the return type class and concept structure class are logically the same but loaded from different contexts. The validation now uses class name matching as a fallback, allowing
ListContent[Expense]to matchExpense[]even if theExpenseclass objects differ. - Fixed
PipeImgGennot properly convertingImageContentto custom subclasses (e.g.,Receipt(ImageContent)). The pipe now usessmart_dump()beforemodel_validate()to correctly instantiate the output concept's structure class. - Corrected output directory creation logic in
pipelex runto properly respect the--no-graphflag and configuration settings. - Fixed a bug when trying to print HTML content in a TextContent object.
- Fixed the Pipelex CLI for generating structures, inputs, runner files.
- Fixed
@pipe_funcdecorated functions showing "function not found" instead of explaining why the function is ineligible (e.g., missing return type annotation). - Fixed PipeLLM with list output (e.g.,
output = "Item[]") not producingListContentwhen run inside a nested PipeSequence withbatch_over. - Duplicate Pipe Error Message: When a pipe code is declared in multiple
.plxfiles (or twice in the same file), the error message now shows which bundle file(s) contain the conflicting declarations instead of a misleading message about "running the same pipe twice in the same pipeline". - Fixed
pipelex build runnerandpipelex build inputsgenerating string placeholders (e.g.,"number_int | float") instead of numeric values for Number concepts withint | floatunion type fields. - Fixed structure generation failing with
PydanticUserErrorwhen a concept structure references native concepts (e.g.,native.Html). The generator now properly resolves native concept refs to their content classes (e.g.,HtmlContent) with correct imports. - Nested Image Handling: Images nested within structured data are now properly replaced with
[Image N]tokens. The| with_imagesfilter andImageRegistrysystem correctly extract images from complex nested structures. PipeConditionValidation: Output multiplicity validation now works correctly.- Error Reporting:
PipeComposevalidation errors now include formatted details and failing field values. - Duplicate Pipeline Registration: Running a pipeline from a file that was also part of a pre-loaded library (via
PIPELEXPATH) no longer causes a duplicate domain registration error. The system now tracks absolute paths of loaded library files and skips files already loaded. pipelex build structures: Corrected output file naming and resolved import path generation.ConceptFactory.make_from_blueprint: Now correctly handles native concepts.
Removed
- Legacy Client & Execution Modules: Removed
PipelexClient, protocol files, and standalonepipelex.pipeline.execute/pipelex.pipeline.startmodules (replaced byPipelexRunnerandmthdspackage). - Legacy Config: Removed
plx_config.pyand.plx-specific configuration references. pipelex kitCommand: The kit commands have been removed from the main CLI. They are now internal tools for Pipelex contributors only, available viapipelex-dev kit rules.pipelex kit migrationsCommand: Removed entirely.pipelex kit remove-rulesCommand: Removed entirely.- PLX Syntax Agent Rules: Removed
write_pipelex.mdandrun_pipelex.mdagent rules. These PLX syntax guides are no longer installed in client projects. [pipelex.kit_config]Configuration: Removed from client project configuration (.pipelex/pipelex.toml).openai_utilsModule: Removedpipelex.plugins.openai.openai_utils; logic now in centralized image preparation utilities.- Pipeline Tracking feature: Removed entirely, including the
pipelex/pipeline/trackmodule,PipelineTrackercomponents, related configuration, tracker calls in pipe controllers, and associated documentation. FlowGenerator: The old flow generator has been removed.
Security
- CSP Nonce Support: Added Content Security Policy nonce for generated HTML graph outputs.
Deprecated
pipelex_inferencebackend in favor ofpipelex_gateway(marked as "🛑 Legacy" in configuration template)
For Contributors
- Technical Documentation: Added a new "Under the Hood" page documenting the
StuffArtefactdelegation pattern and image rendering architecture. - Enhanced Testing: Added extensive unit and integration tests for the protocol-based rendering system, including nested image extraction and filter error conditions.
- Agent Rules: Added
pipelex_standards.mdoutlining standards for the Pipelex configuration system, also included as rules for AI development agents. - Agent Rules: New target
make agent-checkfor faster linting. - ⚠️ Breaking — Content Handling Overhaul:
GeneratedImagereplaced by internalGeneratedImageRawDetails;ImageContentis now standard (withoutbase_64field).PipeExtractoutputsPageContentlist directly. Content persistence now handled automatically by storage system. - ⚠️ Breaking — Image Prompt Representation: Redesigned
PromptImagemodels—consolidatedPromptImagePathandPromptImageUrlintoPromptImageUri; now uses Pydantic discriminated union for URI, base64, and raw bytes sources. - Centralized Image Preparation: Moved image fetching and base64 conversion logic to
pipelex.cogt.image.prompt_image_utils, simplifying LLM provider plugins (Anthropic, Google, Mistral, OpenAI). - Unified Resource Loading: Updated all file/URL reading components (PDF renderers, document extractors) to use the new URI handling system, replacing the legacy
pipelex.tools.misc.path_utilsmodule. - Async HTTP Fetching: Renamed
fetch_file_from_url_httpx_asynctofetch_file_from_url_httpx; removed redundant synchronous version. PreparedImageAbstraction: New models (PreparedImageHttpUrl,PreparedImageBase64) representing images ready for LLM provider APIs.- Pipelex Gateway Model Management: New CLI commands (
pipelex-dev update-gateway-models,pipelex-dev check-gateway-models) and correspondingmaketargets (ugm,cgm) to generate and verify gateway model catalog. CI now validates this documentation is up-to-date. - Test Suite Pre-flight Check: Verifies Gateway terms acceptance before running tests, providing clear error messages.
- Content Rendering:
StuffContent.rendered_*methods now provide both synchronous and asynchronous variants.
Migration Notes
- Telemetry configuration migration: If you have an existing
telemetry.toml, rename: [posthog]→[custom_posthog][posthog.tracing]→[custom_posthog.tracing][posthog.tracing.capture]→[custom_posthog.tracing.capture]- Or run
pipelex init telemetry --resetto regenerate the file with the new structure
Refactored
- Anthropic Backend: Internal streaming for standard completions to prevent SDK timeouts, configurable structured output timeout (
structured_output_timeout_seconds), improved error mapping, and increased Bedrock Claudemax_tokens(8K → 64K) with removal ofmax_output_tokens_limitconstraint. - ⚠️ Breaking — Pipe I/O Specification: The output (and inputs) of a pipe is now a
StuffSpecobject that holds the concept and the multiplicity. - Naming Convention: Renamed
domaintodomain_codewhere relevant. - Dry Run Methods: Refactored the dry run methods of the
PipeAbstractclass.
[v0.18.0b4] - 2026-02-23
Added
- Persistent Credential Storage (
~/.pipelex/.env):pipelex initnow prompts for missing API keys after backend selection and saves them to~/.pipelex/.envwith0600permissions. Credentials are loaded automatically at startup (global defaults, overridden by project.env). pipelex init credentialsCommand: New standalone focus to re-enter API keys without resetting configuration. Scans enabled backends, detects missing env vars, and prompts only for those.- Package Management System: Introduced a full package manager for MTHDS with
METHODS.tomlmanifests,methods.locklockfile generation, local path and remote Git-based dependency resolution (MVS), a local package cache (~/.mthds/packages), and a newpipelex pkgCLI command group (init,list,add,lock,install,update,publish,search,inspect,graph). - Hierarchical Domains: Support for dot-separated domain namespaces (e.g.,
legal.contracts.shareholder) and cross-package references viaalias->domain.pipesyntax. - PipelexRunner: Introduced the
PipelexRunnerclass as the primary entry point for executing pipelines, replacingPipelexClientand standaloneexecute_pipeline/start_pipelinefunctions. - Linting & Formatting: Integrated
plxt(Pipelex Tools) for formatting and linting.mthdsand.tomlfiles, including CI/CD checks alongsideruff. - JSON Schema: Automatic generation of
mthds_schema.jsonfor standard definition, IDE validation, and auto-completion. - Dev CLI: Added
pipelex-devCLI for internal development tasks (e.g., schema generation). - CSP Nonce Support: Added Content Security Policy nonce support for generated HTML graphs (Mermaid/ReactFlow) to enable secure rendering in VS Code webviews.
- OpenRouter Backend: Added OpenRouter as an inference backend with 337 chat model definitions and 14 image generation models.
Changed
- CI Runner Optimization: Split self-hosted runners into dedicated test (D32) and lint (D4) pools with pre-baked Docker image (Python 3.10-3.14, UV, dependency cache) for faster job startup.
- MTHDS Light Client Extraction: The light client protocol (runner, pipeline models, pipe output abstractions) has been extracted from pipelex into the new
mthdspackage on PyPI. Pipelex now depends onmthds>=0.0.1and implements itsRunnerProtocol. - Global/Local Config Split:
pipelex initnow creates configuration in~/.pipelex/(global) by default. Usepipelex init --localto create project-level overrides in{project_root}/.pipelex/. Config loading merges: package defaults → global → project → overrides. - IDE Extension Detection: Extension check now uses
code --list-extensions/cursor --list-extensionsfor reliable detection instead of folder scanning. Shows separate marketplace links for VS Code (Microsoft Marketplace) and Cursor (Open VSX Registry). - Quieter
pipelex init: Removed verbose file listing and reset messages from config initialization output. pipelex initHelp Text: Detailed focus option descriptions now shown inpipelex init --helpexplaining each focus (all,config,credentials,inference,routing,telemetry,agreement).- File Extension: Pipeline definitions now use
.mthdsinstead of.plx; the project refers to "Methods" (MTHDS) rather than "Pipelex workflows". - Syntax: In
PipeParalleldefinitions,parallelsfield renamed tobranches;plx_configinpipelex.tomlrenamed tomthds_config. - Documentation: Comprehensive update to reflect
.mthdsfile format, package management, and new project structure.
Fixed
find_project_rootHome Directory Bug: The project root walker no longer considers the home directory (~) as a project root, even if it contains stray marker files likepackage.json.- Python 3.10 Compatibility: Fixed
datetime.UTCimport (Python 3.11+) to usedatetime.timezone.utc. - Graph Rendering: Fixed dashed edge rendering for
PipeBatchandPipeParallelrelationships. - Image Generation Response Parsing: Hardened image response parsing to handle varied provider response formats more robustly.
Removed
- Legacy Client & Execution Modules: Removed
PipelexClient, protocol files, and standalonepipelex.pipeline.execute/pipelex.pipeline.startmodules (replaced byPipelexRunnerandmthdspackage). - Legacy Config: Removed
plx_config.pyand.plx-specific configuration references.
Security
- CSP Nonce Support: Added Content Security Policy nonce for generated HTML graph outputs.
[v0.18.0b3] - 2026-02-11
Highlights
- Agent CLI (
pipelex-agent): New machine-first CLI for AI agents with structured JSON output for all commands (build,run,validate,inputs,concept,pipe,assemble,graph,models,doctor). - LLM Reasoning Controls: Unified support for "Thinking" models (Chain of Thought) with
reasoning_effort,reasoning_budget, andthinking_modeparameters. Supports Anthropic Extended Thinking, Google Gemini Thinking, OpenAI Reasoning (o1/o3), and Mistral/Magistral models. Includes new presets:$deep-analysisand$quick-reasoning. - Image-to-Image Generation:
PipeImgGennow supports input images viainput_imagesfield, withInputImagesTaxonomyfor provider-specific handling and variable reference detection ({{ var }},$var,@var) in prompts. - PipeCompose "Construct" Mode: New
constructmode for building structured objects (dictionaries/Pydantic models) directly from variables. - Nested concepts in inline structures: You can now define nested structures for your concepts in your
.plxfiles. Learn more here: Nested Concepts in Inline Structures.
Added
- Builder Auto-Repair: Self-healing capabilities including auto-generation of undeclared concepts, multiplicity mismatch fixes, and pruning of unreachable pipes/unused concepts.
- Concept Field Features: Added
choicessupport (compiles toLiteraltypes/Enums) and explicitlisttype withitem_type/item_concept_ref. - PipeFunc Execution Error Context: When a
@pipe_funcfunction fails during execution, the error message now includes detailed context: the function name, actual input values from working memory, expected output type, and the original error with its type. This makes debugging PipeFunc errors much easier. pipelex build outputCLI Command: New command to generate example output JSON for a pipe, complementing the existingpipelex build inputscommand. Shows the expected output structure based on the pipe's output concept type, with multiplicity support. For pipes withnative.Anythingoutput (e.g.,PipeConditionwith different mapped pipe outputs), displays all possible outputs from mapped pipes.- Telemetry System: Introduced anonymous usage tracking and exception capture for CLI commands (
graph render), reporting to both user-configured and Pipelex analytics endpoints. - PipeExtract Operator Validation: Added strict input validation that raises configuration errors for incompatible input types or when document-specific parameters are used with image inputs.
- PipeCondition Output Auto-Fix in Builder Loop: The pipe builder now automatically fixes
PipeConditionoutput concept errors during validation. If all mapped pipes have the same output, thePipeConditionoutput is set to that concept; otherwise it's set tonative.Anything. - PipeFunc Return Type Validation: Added validation to ensure that a
PipeFuncfunction's return type matches the output concept's structure class. - URL Validation on
ImageContentandDocumentContent: Both models validate external resources (HTTP/HTTPS URLs via HEAD request, local file paths via existence check) through avalidate_resources()method called during pipeline execution (validate_before_run) rather than at model instantiation. Internal URIs (data:,pipelex-storage://) skip validation entirely. Validation is skipped in dry-run mode where inputs use mock URLs. - Literal Type Support in Dry Run Mocks:
DryRunFactorynow detectsLiteraltype annotations (includingOptional[Literal[...]]) and generates valid mock values by randomly picking from the allowed choices instead of producing invalid random strings. - Literal Type Support in
pipelex build inputs/pipelex build output: The concept representation generator now handlesLiteralfields by picking a random value from the allowed choices, and generates mock URL patterns forurlfields. - Literal Error Handling in Validation Messages: Pydantic validation error formatting now recognizes
literal_errortypes and displays them as "Invalid choice errors" with the actual value and expected options. PipeRunErrorCatching in Bundle Validation:validate_bundlenow catchesPipeRunErrorduring dry run and wraps it inValidateBundleErrorwith a clear message.ValidationErrorCatching in Pipeline Execution:execute_pipelinenow catches PydanticValidationErrorfrom input construction, formats the errors, and raises aPipeExecutionErrorwith a clear message.- Broader Error Handling in CLI
pipelex run: The CLI run command now catchesPipelexErrorin addition toPipelineExecutionError, providing better error messages for failures that occur outside the pipeline execution itself. - Content Filenames: Added
filenamefield toImageContentandDocumentContent, with auto-population from local file paths via newextract_filename_from_urihelper. - Batch Validation Error Type: Introduced
PipeValidationErrorType.BATCH_ITEM_NAME_COLLISIONfor naming conflicts in batch operations. - Documentation: Added naming convention rules to
builder.plxandpipe_design.plx(batch input lists should be plural, item names singular).
Changed
- Model Deck Updates: Default premium model now
claude-4.6-opus; added Mistral models (mistral-small-3.2,mistral-large,magistralseries) andgpt-5placeholders. - Jinja2 Rendering: Image objects now replaced with placeholders (e.g.,
[Image 1]) during text generation; async filters only registered in async environments. - Backend Configurations: Added
effort_to_level_mapandeffort_to_budget_mapsfor reasoning translation; disabled Google Vertex AI by default. - Dependencies: Updated
pypdfium2,anthropic, andmistralaiversion constraints. pipelex run --dry-run: No longer pretty prints the main_stuff output, matching the expected behavior for dry runs where no actual inference occurs.pipelex build structuresCommand: Now uses a lightweight loading mechanism that only processes domains and concepts, skipping pipe loading and validation entirely. This fixes the chicken-and-egg problem where structure generation would fail due to pipe validation errors before the structures were even created. Added--force/-fflag to regenerate all structures without checking if classes already exist.- Test Profile System: Refactored integration tests to use a new configuration system (
.pipelex/test_profiles.toml) withdev,ci, andfullprofiles for controlling which AI models are used in parametrized tests, replacing runtime filtering and hardcoded model lists. pipelex run --graphFlag: Now acts as an override forpipelex.tomlsettings instead of defaulting totrue.- Default Image Generation Models: Updated in
base_deck.toml:base-img-gen:flux-2-pro,best-img-gen:nano-banana-pro,fast-img-gen:gpt-image-1-mini - Remote Configuration: Updated service URL to version 3.
- GatewayExtractWorker: Now checks model capabilities before attempting image captioning.
- Change the output validation of
PipeCondition: If all mapped pipes have the same output concept,PipeCondition's output MUST be that same concept. If mapped pipes have different output concepts,PipeCondition's output MUST be the native conceptAnything. - CLI: Changed
pipelex validate alltopipelex validate --all(or-a). - StructuredContent.rendered_html(): Now recursively calls
rendered_html()on nestedStuffContentfields instead of using json2html conversion. Also skipsNonevalues and uses HTML table format. - Batch Pipe Validation: Enforced stricter naming rules for batch specs—
input_item_namemust differ frominput_list_nameand not shadow existing input keys, with clearer error messages suggesting plural/singular conventions.
Fixed
- Helpful Error for
get_stuff_as(ListContent[T]): When users incorrectly callget_stuff_as("name", ListContent[Something])instead ofget_stuff_as_list("name", Something), the error message now explicitly suggests usingget_stuff_as_list(). - PipeFunc
ListContent[T]Validation: Fixed validation rejecting validListContent[T]return types for array outputs (T[]). Previously, a function returningListContent[Expense]would fail validation foroutput = "Expense[]"with a misleading error. The validation now correctly extracts and validates the generic type parameter from Pydantic's metadata. - PipeFunc Class Name Matching: Fixed validation failing when the return type class and concept structure class are logically the same but loaded from different contexts. The validation now uses class name matching as a fallback, allowing
ListContent[Expense]to matchExpense[]even if theExpenseclass objects differ. - Fixed
PipeImgGennot properly convertingImageContentto custom subclasses (e.g.,Receipt(ImageContent)). The pipe now usessmart_dump()beforemodel_validate()to correctly instantiate the output concept's structure class. - Corrected output directory creation logic in
pipelex runto properly respect the--no-graphflag and configuration settings. - Fixed a bug when trying to print HTML content in a TextContent object.
- Fixed the Pipelex CLI for generating structures, inputs, runner files.
- Fixed
@pipe_funcdecorated functions showing "function not found" instead of explaining why the function is ineligible (e.g., missing return type annotation). - Fixed PipeLLM with list output (e.g.,
output = "Item[]") not producingListContentwhen run inside a nested PipeSequence withbatch_over. - Duplicate Pipe Error Message: When a pipe code is declared in multiple
.plxfiles (or twice in the same file), the error message now shows which bundle file(s) contain the conflicting declarations instead of a misleading message about "running the same pipe twice in the same pipeline". - Fixed
pipelex build runnerandpipelex build inputsgenerating string placeholders (e.g.,"number_int | float") instead of numeric values for Number concepts withint | floatunion type fields. - Fixed structure generation failing with
PydanticUserErrorwhen a concept structure references native concepts (e.g.,native.Html). The generator now properly resolves native concept refs to their content classes (e.g.,HtmlContent) with correct imports.
Removed
pipelex kitCommand: The kit commands have been removed from the main CLI. They are now internal tools for Pipelex contributors only, available viapipelex-dev kit rules.pipelex kit migrationsCommand: Removed entirely.pipelex kit remove-rulesCommand: Removed entirely.- PLX Syntax Agent Rules: Removed
write_pipelex.mdandrun_pipelex.mdagent rules. These PLX syntax guides are no longer installed in client projects. [pipelex.kit_config]Configuration: Removed from client project configuration (.pipelex/pipelex.toml).
[v0.18.0b2] - 2026-01-20
Highlights
- Pipelex Gateway — The deprecated
pipelex_inferencebackend is now replaced bypipelex_gateway, featuring remote model configuration fetching so you always have access to the latest models without updating Pipelex.
Getting your API key:
1. Get your API key at app.pipelex.com
2. Add it to your .env file: PIPELEX_GATEWAY_API_KEY=your-key-here
Gateway Supported models — included with the Free API Key - Language Models (LLM): - OpenAI: all models up to GPT-5.2 and Codex - Anthropic: Claude 3.7 Sonnet through Claude 4.5 Haiku/Sonnet/Opus - Google: Gemini 2.0/2.5 Flash, Gemini 2.5 Pro, Gemini 3.0 Flash/Pro - xAI: Grok 3/mini, Grok 4 (+ fast reasoning variants) - Open-source: Mistral Large 3, DeepSeek v3.1/3.2/Speciale, GPT-OSS 20B/120B1, Kimi K2, Phi-4, Qwen3-VL 235B - Document Extraction: Mistral Document AI, Azure Document Intelligence, DeepSeek OCR - Image Generation: GPT-Image 1/1.5, Flux 2 Pro, Nano Banana/Pro
Accepting the Terms of Service:
When you run pipelex init, you'll be prompted to accept the Gateway terms of service. By using Pipelex Gateway, telemetry is automatically enabled and identified by your API key (hashed for security) to monitor service quality and enforce fair usage. We only collect technical data (model names, token counts, latency, error rates)—never your prompts, completions, or business data. See our Privacy Policy.
⚠️ Migration deadline: If you were using pipelex_inference, please migrate soon—the legacy service will be shut down within few days. Get your new Gateway key at app.pipelex.com.
- Execution Graph Visualization System (preview feature) — Comprehensive tracing and visualization for pipeline executions.
CLI: --graph flag on pipelex run generates execution graphs. New pipelex graph render <graph.json> command for post-run rendering.
Viewers: Interactive ReactFlow viewer (reactflow.html) with pan/zoom and node inspector. Mermaid diagrams (mermaidflow.html) with subgraphs and clickable nodes.
Makefile: make view-graph (vg) and make serve-graph (sg) to start a local graph viewer.
- Pydantic Structure Generation — Two new CLI commands bridge Pipelex's declarative concepts with your Python code:
pipelex build structures /library_dir/ — Generates Pydantic models from all concept definitions found in the specified library directory. Now you have your structures as Python code: you can iterate on them, add custom validation functions, or use them as type hints in your code.
pipelex build runner — Now automatically generates both the Python runner file AND the required Pydantic structures. When you run this command, it creates a complete, ready-to-execute Python script that imports the generated structures, so you can immediately use typed objects in your pipeline code.
See the Build Commands documentation for usage examples.
- New Backends & Models:
- Hugging Face Inference — Support for Hugging Face Inference API, including
qwen-imagetext-to-image model. - Google
gemini-3.0-flash-preview - Mistral OCR latest model
mistral-ocr-2512 - Scaleway inference provider support for open-source models
-
Portkey AI backend integration for unified access to multiple models through a single API key
-
Document Support in
PipeLLM— IncludeDocumentobjects (like PDFs) directly in prompts using@variableor$variablesyntax. Supports single documents, multiple documents, and lists, combinable with text and image inputs. -
PipeComposeConstruct Mode — New mode for deterministically buildingStructuredContentobjects without an LLM. Compose fields from working memory variables, fixed values, templates, and nested structures. -
Content Storage System — Configurable storage for generated artifacts (images, extracted pages). Supports
localfilesystem (.pipelex/storage/),in_memory, AWS S3 (pip install pipelex[s3]), and Google Cloud Storage (pip install pipelex[gcp-storage]). Cloud providers support both public URLs and time-limited signed URLs. Content referenced via stablepipelex-storage://URIs. -
Langfuse & OpenTelemetry Observability — New OpenTelemetry-based observability system enables powerful tracing and Evals through Langfuse integration. Also supports OTLP-compatible backends (Datadog, Honeycomb, etc.). Configured via
.pipelex/telemetry.toml. -
Python 3.14 Support — Officially tested and supported.
Added
--library-dirCLI Option:--library-dir/-Loption forpipelex run,pipelex validate, andpipelex buildsubcommands (one-shot-pipe,partial-pipe) to specify additional directories for searching pipe definitions. Can be specified multiple times.- Automatic File Loading: The core pipeline execution functions (
pipelex.execute_pipeline,pipelex.start_pipeline) can now directly load a pipeline from a file path via a newbundle_uriparameter. - Dry Run Mode:
pipelex run --dry-runexecutes pipeline logic without API calls, useful for validating structure and generating orchestration graphs. Combine with--mock-inputsto generate mock data for missing required inputs. | with_imagesJinja2 Filter: Explicitly extract and include all nested images from complex data structures (e.g.,Pageobjects or custom concepts withImagefields). Renders the object's text representation while making associated images available to the LLM.- System Prompt Media Support: Reference images and documents in
system_promptusing the same$variableand@variablesyntax as the userprompt. - Pipelex Gateway Service: Terms of service management via
.pipelex/pipelex_service.tomland interactive acceptance flow inpipelex initandpipelex init agreement. - Gateway Available Models Documentation: Auto-generated reference of all LLM, Document Extraction, and Image Generation models available through the Gateway.
- Configurable Retry Logic: Exponential backoff for inference API calls, configurable in
pipelex.tomlunder[cogt.tenacity_config] - Context Manager Support: The
Pipelexclass now supportswith Pipelex.make(): ...for graceful shutdown - Validation Improvements:
- Pipelex Bundle concept keys: prevent bundles from re-creating a native concept
PipeSequence: output multiplicity must match the last step's output multiplicityPipeFunc: output multiplicity must match the function return type (ListContentsubclass for multiplicity=true)- Rendering Protocols: Three new
@runtime_checkableprotocols (ImageRenderable,TagRenderable,TextFormatRenderable) to formalize the interaction between data types and Jinja2 filters. - Unified URI Handling System: New
pipelex.tools.urimodule providing type-safe parsing for HTTP/HTTPS URLs, local file paths, file URIs,pipelex-storage://URIs, and base64 data URLs. - Automatic Input Data Storage: Pipeline pre-processing step that converts large
data:URLs in anImageContentorDocumentContentintopipelex-storage://URIs for improved performance, by storing the data with the configured storage provider. Configurable viais_normalize_data_urls_to_storageinpipelex.toml. pipelex build inputsCommand: New CLI command to generate example input JSON files for pipes. Supports--library-dir(-L) to specify library directories.- Pipe Code Syntax Validation: Bundle validation now checks that pipe codes and
main_pipevalues use valid snake_case syntax, with proper error categorization (INVALID_PIPE_CODE_SYNTAX).
Fixed
- Nested Image Handling: Images nested within structured data are now properly replaced with
[Image N]tokens. The| with_imagesfilter andImageRegistrysystem correctly extract images from complex nested structures. PipeConditionValidation: Output multiplicity validation now works correctly.- Error Reporting:
PipeComposevalidation errors now include formatted details and failing field values. - Duplicate Pipeline Registration: Running a pipeline from a file that was also part of a pre-loaded library (via
PIPELEXPATH) no longer causes a duplicate domain registration error. The system now tracks absolute paths of loaded library files and skips files already loaded. pipelex build structures: Corrected output file naming and resolved import path generation.ConceptFactory.make_from_blueprint: Now correctly handles native concepts.
Changed
- Jinja2 Integration Refactored to Protocol-Based Approach: Replaced the
Jinja2Registrysingleton and handler functions with a decoupled protocol-based system, eliminating circular dependencies between the template layer and core domain logic. StuffArtefactRedesigned as Delegation Adapter: Now a lightweight, immutable adapter that delegates attribute access directly to underlyingStuffandStuffContentobjects, improving performance and providing more intuitive field access.- Image Extraction Moved to Content Types:
StructuredContent,ListContent,ImageContent, andTextAndImagesContentnow implement theImageRenderableprotocol, replacing centralized handler logic. - ⚠️ Breaking: User override config renamed from
pipelex_super.tomltopipelex_override.toml. - Image Generation Architecture: Refactored to taxonomy-based approach. Standardizes parameter translation (
aspect_ratio,quality,output_format) to provider-specific APIs. - Document Extraction Improvements:
pypdfium2extractor now extracts embedded images from PDFs. Response parsing uses dedicated Pydantic schemas for validation. - Default Model Change:
extract_text_from_visualsdeck now defaults toazure-document-intelligence pipelex_inferencereplaced bypipelex_gateway: See Highlights for migration details. NewPIPELEX_GATEWAY_API_KEYenvironment variable; default routing profiles updated topipelex_gateway_first.-
Telemetry System Split: Now two separate streams: 1. Pipelex Gateway telemetry for service monitoring (never collects prompts/completions/business data) 2. Custom telemetry to user-configured backends 3. Config updated accordingly (
telemetry.toml):- Renamed
[posthog]to[custom_posthog]to distinguish user's PostHog from Pipelex Gateway telemetry - Added new
[custom_portkey]section withforce_debug_enabledandforce_tracing_enabledsettings
- Renamed
-
Main Configuration Overrides Updated (
.pipelex/pipelex.toml): pipelex_override.toml(final override) renamed frompipelex_super.tomltopipelex_override.tomland moved from repo root to.pipelex/directorytelemetry_override.toml(personal telemetry settings)-
is_generate_cost_report_file_enableddefault changed fromtruetofalse -
Documentation:
- Clarified Setup (first run) vs Configuration (TOML reference), added a Setup overview page, and added contributor docs for configuration defaults/overrides.
- Added the "Under the Hood" page documenting the execution graph tracing system.
pipelex init: Now creates a documentedtelemetry.tomltemplate instead of prompting for preferences- Model Catalog Updated: Latest models (gpt-5.1, claude-4.5-opus, gemini-3.0-pro, etc.) and updated waterfalls in
base_deck.toml - Model Constraints Refactored: From simple lists to structured
valued_constraintsdictionaries (e.g.,valued_constraints = { fixed_temperature = 1 }) - OpenAI Responses API: New implementation now differentiates between
openai_completionsandopenai_responses - CLI Initialization: Commands refactored to use centralized
Pipelexinitialization factory for improved error handling pipelex doctor: Enhanced to detect outdatedtelemetry.tomlformats and suggest fixes--output-dirOption: Therunner,structures, andinputsCLI commands now accept this option- Cost Report: Now displays a note clarifying that it only includes LLM costs
descriptionField Now Required: InPipeAbstract,PipeBlueprint, andPipeSpecclasses.- Configuration: New
[pipelex.pipeline_execution_config.graph_config]section inpipelex.tomlfor fine-grained control over graph generation, data embedding, and rendering options. - CLI: All
pipelexcommands now accept--no-logoto suppress the Pipelex banner in the terminal — useful to reduce tokens.
Removed
openai_utilsModule: Removedpipelex.plugins.openai.openai_utils; logic now in centralized image preparation utilities.- Pipeline Tracking feature: Removed entirely, including the
pipelex/pipeline/trackmodule,PipelineTrackercomponents, related configuration, tracker calls in pipe controllers, and associated documentation. FlowGenerator: The old flow generator has been removed.
Deprecated
pipelex_inferencebackend in favor ofpipelex_gateway(marked as "🛑 Legacy" in configuration template)
For Contributors
- Technical Documentation: Added a new "Under the Hood" page documenting the
StuffArtefactdelegation pattern and image rendering architecture. - Enhanced Testing: Added extensive unit and integration tests for the protocol-based rendering system, including nested image extraction and filter error conditions.
- Agent Rules: Added
pipelex_standards.mdoutlining standards for the Pipelex configuration system, also included as rules for AI development agents. - Agent Rules: New target
make agent-checkfor faster linting. - ⚠️ Breaking — Content Handling Overhaul:
GeneratedImagereplaced by internalGeneratedImageRawDetails;ImageContentis now standard (withoutbase_64field).PipeExtractoutputsPageContentlist directly. Content persistence now handled automatically by storage system. - ⚠️ Breaking — Image Prompt Representation: Redesigned
PromptImagemodels—consolidatedPromptImagePathandPromptImageUrlintoPromptImageUri; now uses Pydantic discriminated union for URI, base64, and raw bytes sources. - Centralized Image Preparation: Moved image fetching and base64 conversion logic to
pipelex.cogt.image.prompt_image_utils, simplifying LLM provider plugins (Anthropic, Google, Mistral, OpenAI). - Unified Resource Loading: Updated all file/URL reading components (PDF renderers, document extractors) to use the new URI handling system, replacing the legacy
pipelex.tools.misc.path_utilsmodule. - Async HTTP Fetching: Renamed
fetch_file_from_url_httpx_asynctofetch_file_from_url_httpx; removed redundant synchronous version. PreparedImageAbstraction: New models (PreparedImageHttpUrl,PreparedImageBase64) representing images ready for LLM provider APIs.- Pipelex Gateway Model Management: New CLI commands (
pipelex-dev update-gateway-models,pipelex-dev check-gateway-models) and correspondingmaketargets (ugm,cgm) to generate and verify gateway model catalog. CI now validates this documentation is up-to-date. - Test Suite Pre-flight Check: Verifies Gateway terms acceptance before running tests, providing clear error messages.
- Content Rendering:
StuffContent.rendered_*methods now provide both synchronous and asynchronous variants.
Migration Notes
- Telemetry configuration migration: If you have an existing
telemetry.toml, rename: [posthog]→[custom_posthog][posthog.tracing]→[custom_posthog.tracing][posthog.tracing.capture]→[custom_posthog.tracing.capture]- Or run
pipelex init telemetry --resetto regenerate the file with the new structure
Refactored
- Anthropic Backend: Internal streaming for standard completions to prevent SDK timeouts, configurable structured output timeout (
structured_output_timeout_seconds), improved error mapping, and increased Bedrock Claudemax_tokens(8K → 64K) with removal ofmax_output_tokens_limitconstraint. - ⚠️ Breaking — Pipe I/O Specification: The output (and inputs) of a pipe is now a
StuffSpecobject that holds the concept and the multiplicity. - Naming Convention: Renamed
domaintodomain_codewhere relevant. - Dry Run Methods: Refactored the dry run methods of the
PipeAbstractclass.
[v0.17.6] - 2026-02-14
Added
- Claude Code GitHub Actions: Added
claude.ymlworkflow for interactive Claude Code assistance on issues and PR comments, andclaude-code-review.ymlworkflow for automated code review on pull requests.
[v0.17.5] - 2026-01-16
- Added target
make docs-deploy-404to deploy the 404.html file to the gh-pages root for versionless URL redirects.
[v0.17.4] - 2026-01-16
Added
- Added the
mikedependency to support mutiple docs versions.versionplugin added to the MkDocs configuration, make targets and CI scripts.
[v0.17.3] - 2025-12-01
Fixed
- Fixed the issue with the
find_files_in_dirforce including virtual environment directories: Now it force includes thepipelex.builderdirectory. - Fixed a bug with the comparison of Concept structures.
[v0.17.2] - 2025-12-01
Added
- New AI models support: Added GPT-5.1, Claude 4.5 Opus, and Gemini 3 Preview to the available models.
- Codex Cloud support: Added support for running Pipelex in Codex Cloud environments with appropriate configuration and testing capabilities.
- Enhanced file discovery: Added
force_include_dirsparameter to thefind_files_in_dirfunction. This allows specific directories to be force included in the search even when they are nested within excluded directories. For example, you can now exclude.venvwhile still including.venv/lib/python3.11/site-packages/pipelexfor loading Pipelex libraries from installed packages. - Added validation of the PipeLLM inputs at the blueprint level.
- Added a xfailed test for
PipeCondition: if one of the outcome of the pipe iscontinue, it does nothing, but the main stuff still points towards the last step. Therefore when trying to get the main stuff out of the working memory as a specific type, it fails.
Changed
- Backend fallback now only activates when explicitly opted-in, giving users more control over model selection.
- Renamed and improved the Azure Image Generation SDK implementation.
- Enhanced language spec examples, operator details, and added Viewpoint documentation.
Fixed
- Fixed kit rules to be idempotent and work correctly across multiple executions.
[v0.17.1] - 2025-11-27
Fixed
- Fixed a bug in the
find_files_in_dirfunction.
[v0.17.0] - 2025-11-27
Highlights
- Previously, in the pipelex config files (
.tomlfiles in the.pipelex/directory, such as.pipelex/pipelex.toml, but also the routing profiles files, backends, etc.), when an array was overridden, the new array was concatenated to the old array. Now, the new array overrides the old array.
Fixed
- Relaxed concept structure field naming restrictions: Users can now use field names like
content,stuff_code,stuff_name, andconceptin their concept structures without conflicts. Internal metadata fields in stuff artefacts now use underscore prefixes (_stuff_name,_content_class,_concept_code,_stuff_code,_content) to avoid collisions with user-defined fields. Reserved field names (Pydantic BaseModel attributes likemodel_config,model_fields, etc.) and field names starting with underscore remain forbidden with improved error messages that clearly specify which fields are problematic.
Changed
- Modified the GHA
version-check.ymlso that the check of the version is only applying to release branches. - Removed the
pyproject.tomlfile from the build. - No more implicit concepts. A concept reference has a domain and a code. If there is no domain, it should be a native concept, or it is declared in the same bundle.
Refactored
- The
find_files_in_dirfunction was coded in 3 different places, now it's inpipelex/tools/misc/file_utils.py, and acceptsexcluded_dirs. - Refactored the Pipe factories: Centralized everything in the
PipeFactoryclass.
[v0.16.0] - 2025-11-25
Highlights
- Library manager now supports multiple libraries. You can now have multiple libraries in your project, each with its own set of concepts, pipes, and stuffs. You can run the same pipe at the same times as much as you want, with different inputs. Side effets: Unit tests now run in 30s.
Fixed
- Fixed some issues with inputs of pipes: The validation methods was not detecting misconceptions with implicit concepts.
Changed
- Improved pipe builder by auto-fixing errors, forcing consistency in the inputs and outputs of the pipes.
Refactor
- PipeCondition: Moved the expression/expression_template choosing to the factory.
- Moved a lot of validation to blueprints instead of pipe instances.
- Refactored the Blueprint validation errors, and validation functions.
- Refactored the PipelexInterpreter validation errors.
- Refactored the pipe builder validation loop.
- Reorganized the unit tests, and added new ones.
- Reorganized the config files.
- Refactored methods
execute_pipelineandstart_pipeline. - Moved
dev_clitocli.dev_cli.
[v0.15.7] - 2025-11-18
Fixed
- Fixed issue with
get_console()function returningNoneif Pipelex is not initialized. Now always defaults tostderrif not set.
[v0.15.6] - 2025-11-18
Contributors
- Welcome to our new contributor @0x090909 (yup, that's his github username) for his work on Groq support in PR #445! 🎉
Added
- Improved configuration repair: New
--fixoption forpipelex doctorcommand that interactively detects and repairs outdated or invalid backend configuration files using latest templates from the Pipelex kit. - Developer CLI & tooling: New internal
pipelex-devCLI for project maintenance withcheck-config-synccommand to verify user-facing configuration templates (.pipelex/) are synchronized with package's internal kit configs. Includesmake check-config-synccommand and CI check (lint-check.yml) to enforce synchronization. - Enhanced test infrastructure: Integration tests now automatically parameterized to run against all supported backend routing profiles. Tests are intelligently skipped at collection time if a model is not supported by the active backend profile, with a summary of skipped tests provided at session end.
- New routing profiles: Added
all_groqandall_pipelex_inferencerouting profiles. - Vision support flag: Added
is_vision_supportedproperty toLLMWorkerAbstractclass for explicit checks of model vision capabilities. - New type of
StuffContent:JSONContentto support an arbitrary JSON object as input or output of a pipe. - Azure image generation: Support for image generation models via Azure OpenAI backend using
gpt-image-1.
Changed
- Unified structured output: Complete overhaul of structured generation settings. Replaced global configuration setting with new
structure_methodparameter in backend.tomlfiles (configurable at backend level in[defaults]or per individual model). ExpandedStructureMethodenum to include dozens of modes supported byinstructor, enabling fine-grained control over provider-specific features like OpenAI Structured Outputs or Anthropic Tools, and various JSON-based modes. - Groq integration: Updated to use standard
openaiSDK, simplifying integration. - Default configurations: All official backend providers now enabled by default after
pipelex init. Default prompting style changed fromtickstoxml. - Code & test organization: Unit test suite reorganized from
tests/unit/coreand other directories into unifiedtests/unit/pipelex/structure. Integration test fixtures modularized fromconftest.pyinto separate files withintests/integration/pipelex/fixtures/. - Console output settings: Added
console_print_targetandconsole_log_targetsettings inpipelex.tomlfor redirecting output tostdoutorstderr, with CLI and logging refactored to use centralized console instance. This makes it easier to support MCP communication based on stdio.
Fixed
- Improved Pydantic validation error messages when loading backend configurations to clearly indicate the specific file and model containing the error.
Removed
- Perplexity backend: Default configuration for Perplexity AI backend (
perplexity.toml) removed from kit (it was obsolete, it will come back). - Groq plugin: Dedicated
pipelex/plugins/groqplugin removed (now uses standardopenaiSDK). - Global instructor config: Global
is_openai_structured_output_enabledsetting, replaced by per-modelstructure_methodapproach.
[v0.15.4] - 2025-11-12
Added
- Enhanced
pipelex buildCommand: Now generates a self-contained directory (e.g.,results/pipeline_01/) containingbundle.plx,inputs.json,run_{pipe_code}.py,bundle_view.html, andbundle_view.svg. New CLI options:--output-name (-o)for custom base name,--output-dirfor custom directory, and--no-extrasto generate only the.plxfile. - CLI Readiness Check: Verifies that a virtual environment is active for development installations.
- Model Deck Presets: Added
llm_for_creativityandcheap_llm_for_creativitymodel waterfalls, plus[cogt.model_deck_config]section inpipelex.tomlfor configuring model fallback behavior. - WIP: Groq Inference Backend Support: Integrated full support for the Groq API with configuration file (
.pipelex/inference/backends/groq.toml), model specifications, costs, capabilities, new model aliases (base-groq,fast-groq,vision-groq), and routing profile (all_groq).
Changed
- CLI Output and Visualization: Overhauled command-line output with rich, table-based layouts for pipeline components. Final output of
pipelex runis now pretty-printed and adapts to content type. - Documentation: Updated "Get Started" and "Build Reliable AI Workflows" to reflect new directory-based build output and CLI options.
- Internal Code Refactoring: Reorganized exception hierarchy into dedicated
exceptions.pyfiles per module, centralized validation logic intovalidation.pymodules, addedValueErrorto blueprints, and removed unused exceptions for improved maintainability. - Updated pytest to
>=9.0.1to support their newpyproject.tomlconfig format.
Fixed
- Adjusted default temperature for
llm_for_testing_gen_objectpreset from0.5to0.1for more deterministic structured data generation. - Corrected
LLM_FOR_VISUAL_DESIGNskill inpipe_llm_specto point tocheap_llm_for_creativitypreset. - Standardized input variable names in
pipe_llm_vision.plxfromimageA/imageBtoimage_a/image_b.
Removed
- Deleted
pipelex/core/validation_errors.pyfile as part of exception hierarchy refactoring.
[v0.15.3] - 2025-11-07
Fixed
- Fixed weird import issues with
posthogandStrEnum
[v0.15.2] - 2025-11-07
Fixed
- Fixed resetting routing profile when calling with
--resetflag inpipelex init
[v0.15.1] - 2025-11-07
Fixed
- Bumped OpenAI dependency to
>=1.108.1to support their breaking change: "change optional parameter type fromNotGiventoOmit" get_selected_backend_keys()now correctly considers backends enabled by default (like before v0.15.0)
[v0.15.0] - 2025-11-07
Highlights
This release dramatically simplifies onboarding with interactive CLI setup, comprehensive documentation relaunch, and intelligent model fallbacks, making Pipelex more accessible and resilient than ever.
Added
- Model Waterfalls: Define prioritized model lists in
base_deck.toml(e.g.,smart_llm = ["gpt-4o", "claude-4.5-sonnet", "grok-3"]). Pipelex automatically falls back to the next model if the preferred one is unavailable. - Advanced Routing Profiles: New capabilities in
routing_profiles.toml:fallback_order(Global fallback sequence specifying which backends to try if a model isn't found) andoptional_routes(Routes that activate only when their target backend is enabled) - New Models: Anthropic
claude-4.5-haiku(Pipelex Inference, Anthropic, and Bedrock backends) and Azure OpenAIo3 - Comprehensive Documentation Relaunch: Complete restructure under
/home/with new "Get Started" guides forpipelex buildand manual workflows, plus in-depth sections on Domains, Bundles, Concepts, and Pipe lifecycle. - Enhanced CLI:
pipelex initnow interactively guides backend selection and automatically configures routing profiles, including primary backend and fallback order. Addedpipelex init routingfocus. - Enhanced CLI: Improved error reporting across all commands (
build,validate,run,show) with clear, actionable feedback for configuration errors, missing models, and invalid presets. - Enhanced CLI:
pipelex doctornow validates model deck configuration. - New Routing Profiles: Full suite of
all_*profiles (e.g.,all_openai,all_anthropic,all_google) to route all requests to a single provider.
Changed
- BREAKING: for inline concept structures, the fields are now optional by default: the
requiredproperty defaults tofalse. Explicitly setrequired = trueto make fields mandatory, which we discourage as it increases risks of hallucinations. - LLM Presets Overhaul: Rationalized and renamed default presets in
base_deck.toml. Single-model aliases replaced with waterfall aliases. Key renames:llm_for_complex_reasoning→engineering-structured,llm_to_answer_hard_questions→llm_to_answer_questions,llm_to_write_questions→llm_for_writing_cheap. Removed redundant older presets. - Stricter Configuration Validation: Pipelex validates model deck on startup and raises errors if presets reference unavailable models.
Fixed
- Local OpenAI-Compatible Endpoints: OpenAI plugin now handles empty API keys, enabling seamless integration with local servers like Ollama.
Removed
- Old Documentation Structure: Previous
/pages/directory documentation removed in favor of new structure.
[v0.14.3] - 2025-10-29
Added
- Image generation models via BlackBoxAI backend:
flux-pro,flux-pro/v1.1,flux-pro/v1.1-ultra(Black Forest Labs),fast-lightning-sdxl(ByteDance), andnano-banana(Google). Implemented using newopenai_alt_img_genSDK worker with chat completion-style API. - Language model:
claude-4.5-sonnet(Anthropic) via BlackBoxAI backend. - Routing profile:
all_blackboxaiprofile routes all supported model requests to BlackBoxAI backend.
Changed
- Model aliases in
base_deck.toml:base-img-gen→flux-pro/v1.1-ultra,best-img-gen→nano-banana,llm_for_large_codebasenow includesclaude-4.5-sonnet. - Configuration file:
BLACKBOX_RULES.mdrenamed to.blackboxrules.
Fixed
- Image generation schema:
ImgGenJobParams.seedfield now explicitly defined withdefault=None. - CLI bundle validation:
pipelex validatecommand now accepts bundle path (.plxfile) which are in the package and already loaded and performs dry run on all pipes in the bundle.
[v0.14.2] - 2025-10-29
Chaged
- Improved pipe builder.
Added
- CLI to generate inputs JSON.
[v0.14.1] - 2025-10-27
Added
- Tutorial GIF on the README.md file.
[v0.14.0] - 2025-10-27
Added
pipelex doctorcommand: Diagnoses and fixes common configuration issues including missing files, invalid telemetry settings, and unset environment variables for enabled backends.- Interactive backend selection in
pipelex init: Multi-select menu for enabling/disabling inference backends (OpenAI, Anthropic, Amazon Bedrock, etc.). - JSON input support:
pipelex run --inputsflag accepts a JSON file path for passing structured data to pipelines. pretty_printmethods: Added toPipeSpec,ConceptSpec, andStuffobjects for readable debugging output.- VS Code debug configuration: "Debug run pipe" launch configuration for debugging pipeline executions.
display_nameattribute: Added to all inference backends inbackends.tomlfor better UI presentation.- Documentation headers: All default
.tomlconfiguration files now include headers with links to documentation and support channels.
Changed
pipelex initredesign: Transformed into a unified, interactive setup wizard with rich terminal UI for configuration files, backend selection, and telemetry preferences. Telemetry is now configured here instead of via first-run prompt.README.mdrewrite: Complete overhaul featuring a simplified 5-step quick-start guide highlighting thepipelex buildcommand.- Documentation updates: "Quick Start" guide renamed to "Writing Workflows" with simplified content. Python examples updated to use JSON input method, removing manual
StuffandWorkingMemoryobject creation boilerplate. Developer guides and AI assistant rules now recommendpipelex validateovermake validate. Added instructions emphasizing.venvactivation before running commands. - Error handling improvements: Pipelines now validate required inputs upfront and fail early with
PipeRunInputsError.pipelex runprints full rich-formatted exception tracebacks on error. - Default enabled backends: Amazon Bedrock, Google AI, and Google Vertex AI are now enabled by default.
- Naming consistency: "AWS Bedrock" renamed to "Amazon Bedrock" throughout codebase, configuration, and documentation.
Fixed
- Some documentation links were broken.
[v0.13.2] - 2025-10-25
Added
- Added the
n8ndocumentation page for the n8n-nodes-pipelex package. - Added optional telemetry system with first-run interactive prompt offering three modes: off (no data collected), anonymous (usage data without identification), and identified (usage data with user identification). Automatically respects
DO_NOT_TRACKenvironment variable and redacts sensitive data (prompts, responses, file paths, URLs). Configuration stored in.pipelex/telemetry.toml. - Added telemetry documentation: user-friendly setup guide and comprehensive configuration reference.
Changed
- Updated the
PipelexClientand changed the route of the API calls tov1/pipeline/executeandv1/pipeline/start. - Changed the parameter
input_memorytoinputsin the documentaton.
[v0.13.1] - 2025-10-22
Changed
- Changed the
pydanticdependency from==2.10.6to>=2.10.6,<3.0.0to avoid compatibility issues.
[v0.13.0] - 2025-10-21
Highlights
This release focuses on making Pipelex more accessible and easier to use, with major improvements to the CLI, simplified syntax for multiplicity, and a complete documentation overhaul:
- New CLI commands: Run pipelines directly with
pipelex run, generate Python runners withpipelex build runner, and inspect your AI backend configuration withpipelex show backends - Simplified pipeline inputs: The new
inputsparameter replacesinput_memoryand accepts strings, lists, or content objects directly - no more complex dictionary structures - Getting started faster: Completely rewritten quick-start guide and new documentation sections help you go from installation to your first pipeline in minutes
Added
- CLI command
pipelex run: Top-level command to execute pipelines directly from the CLI. Can run pipes from the package or from any.plxbundle file, with options to provide inputs from a JSON file and save the output - CLI command
pipelex build runner: Generates Python script with imports and example input structures for any pipe - CLI command
pipelex show backends: Displays configured AI providers, their status, and active routing rules - Model presets: Added task-oriented presets including
llm_to_write_questions,llm_to_code,llm_for_basic_vision,llm_for_visual_analysis - Documentation: Complete quick-start guide rewrite, new guides for "Understanding Multiplicity", "API Guide", "Executing Pipelines with Inputs", and updated README with video demo
- Migration guide: Updated guide at
pipelex/kit/migrations/migrate_0.11.0_0.12.x.md
Changed
- Unified bracket notation for multiplicity: Single items use
"Concept", variable lists use"Concept[]", fixed-count lists use"Concept[3]". Applies to bothinputsandoutputfields in.plxfiles - Pipeline input format:
input_memoryparameter renamed toinputs; now accepts strings, lists of strings,StuffContentobjects, or explicit concept dictionaries instead ofCompactMemory - Bundle
main_pipeattribute: Pipelex bundles (.plxfiles) now support amain_pipeattribute to designate the primary entry point of the bundle. Used bypipelex runandpipelex build runnercommands to simplify execution - Model preset names:
llm_to_reason→llm_for_complex_reasoning,base_ocr_mistral→extract_text_from_visuals,base_extract_pypdfium2→extract_text_from_pdf,base_img_gen→gen_image_basic,fast_img_gen→gen_image_fast,high_quality_img_gen→gen_image_high_quality - Unified model parameter:
PipeExtractandPipeImgGennow usemodelparameter for consistency across all operator pipes PipeExtractoperator: Output is now consistently validated to be thePageconcept, simplifying its usage for document processing- CLI improvements:
pipelex runandpipelex validatenow auto-detect pipe code vs.plxbundle files;pipelex validatepromoted to top-level command with improved error reporting and syntax-highlighted code snippets - CLI reorganization: Main command-line interface restructured for better usability with improved help texts and more logical command order
- Python API:
Pipelex.make()now accepts dependency injection arguments directly - Python coding standards: Updated internal coding standards to recommend declaring variables with a type but no default value to better leverage linters for bug detection
- Default configuration: Azure and AWS inference backends now disabled by default in template configuration
Fixed
- Structure generation: Special characters (double quotes, backslashes) in concept field descriptions or default values no longer produce invalid Python code
Removed
- Legacy multiplicity syntax:
nb_output,multiple_outputparameters, and complex input dictionary syntax withmultiplicityfield - Pipe-specific model parameters:
ocrparameter fromPipeExtractandimg_genparameter fromPipeImgGen prompt_template_to_structureandsystem_prompt_to_structureconfigurations at the pipe and domain level- Project Name discovery from Configuration
- Temporary design document for the new inference backend system (feature now fully implemented and documented)
[v0.12.0] - 2025-10-15
Highlights
Moving fast and breaking things:
- Added the new builder pipeline system for auto-generating Pipelex bundles from user briefs
- it's a pipeline to generate pipelines, and it works!
- the pipeline definitions are in
pipelex_libraries/pipelines/base_library/builder/ - removed the previous draft which was named
meta_pipeline.plx
Breaking changes... for good!
We tried to group all the renamings we wanted to do which impact our language, so that you get one migration to apply and then we will be way more stable in the future releases.
This is all in the spirit of making Pipelex a declarative language, where you express what you want to do, and the system will figure out how to do it. So our focus inwas to make the Pipelex language easier to understand and use for non-technical users, and at the same time use more consistent and obvious words that developers are used to.
💡 Pro tip: To make migration easier, pass the migration guide to your favorite SWE agent (Cursor, Claude Code, github copilot, etc.) and let it handle the bulk of the changes!
- Removed centralized
pipelex_librariesfolder system - Pipelines are now auto-discovered from anywhere in your project—no special directory required
- No config path parameters needed in
Pipelex.make()or CLI commands (just callPipelex.make()) - Custom functions require
@pipe_func()decorator for auto-discovery - Structure classes auto-discovered (must inherit from
StructuredContent) - Configuration stays at repository root in
.pipelex/directory -
See migration guide for details on reorganizing your project structure
-
General changes
-
renamed
definitionfields todescriptionacross all cases -
Renamed PipeJinja2 to PipeCompose
- the fact that our templating engine is Jinja2 is a technnical detail, not fundamental to the language, especially since we included a pre-processor enabling insertion of variables in prompts using
@variableor$variable, in addition to the jinja2 syntax{{ variable }} - renamed
jinja2field totemplatefor the same reason -
for more control, instead of providing a string for the
templatefield, you can also use a nestedtemplatesection withtemplate,categoryandtemplating_stylefields -
Renamed PipeOCR to PipeExtract
- this is to account for various text extraction techniques from images and docs, including but not only OCR; e.g. we now have integrated the
pypdfium2package which can extract text and images from PDF, when it's actually real text (not an image), and soon we'll add support for other document extraction models solutions - removed obligation to name your document input
ocr_input, it can now be named whatever you want as long as it's a single input and it's either anImageor aPDFor some concept refining PDF or Image - renamed
ocr_page_contents_from_pdftoextract_page_contents_from_pdf - renamed
ocr_page_contents_and_views_from_pdftoextract_page_contents_and_views_from_pdf - introduced model settings and presets for extract models like we had for LLMs
-
renamed
ocr_modeltomodelfor choice of model, preset, or explicit setting and introducedbase_ocr_mistralas an alias tomistral-ocr -
PipeLLM field renames
- image inputs must now be tagged in the prompt like all other inputs; you can just drop their names at the beginning or end of the prompt, or you can reference them in meaningful sentences to guide the Visual LLM, e.g. "Analyze the colors in $some_photo and the shapes in $some_painting."
- renamed
prompt_templatefield toprompt - renamed
llmfield tomodel -
renamed
llm_to_structurefield tomodel_to_structure -
PipeImgGen field renames
- renamed
img_genfield tomodelfor choice of model, preset, or explicit setting - removed some technical settings such as
nb_stepsfrom the pipe attributes, instead you can set these as model settings or model presets -
introduced model settings and presets for image generation models like we had for LLMs
-
PipeCondition field renames
- renamed
pipe_maptooutcomes -
renamed
default_pipe_codetodefault_outcomeand it's now a required field, because we need to know what to do if the expression doesn't match any key in the outcomes map; if you don't know what to do in that case, then it's a failure and you can use thefailvalue -
Configuration file changes (
.pipelex/directory) - Renamed parameter
llm_handletomodelacross all LLM presets in deck files - Renamed parameter
img_gen_handletomodelacross all image generation presets in deck files - Renamed parameter
ocr_handletomodelin extraction presets - Renamed
ocrsection toextractthroughout configuration files - Renamed
ocr_configtoextract_configinpipelex.toml - Renamed
base_ocr_pypdfium2tobase_extract_pypdfium2 - Renamed
is_auto_setup_preset_ocrtois_auto_setup_preset_extract - Renamed
nb_ocr_pagestonb_extract_pages - Updated pytest marker from 'ocr' to 'extract'
Added
- Added
cheap-gptmodel alias forgpt-4o-mini - Added
cheap_llm_for_visionpreset usinggemini-2.5-flash-lite - Added
llm_for_testing_visionandllm_for_testing_vision_structuredpresets for vision testing - Added
is_dump_text_prompts_enabledandis_dump_response_text_enabledconfiguration flags to have the console display everything that goes in and out of the LLMs - Added
generic_templatessection inllm_configwith structure extraction prompts - Added useful error messages with migration configuration maps pin-pointing the fields to rename for config and plx files
- Added improved error message for
PipeFuncwhen function not found in registry, mentioning@pipe_func()decorator requirement since v0.12.0 - Added pytest filterwarnings to ignore deprecated class-based config warnings
- Added
Flowclass that represents the flow of pipe signatures - Added
pipe-buildercommandflowto generate flow view from pipeline brief - Added
FlowFactoryclass to create Flow from PipelexBundleSpec or PLX files - Added
sort_pipes_by_dependencies()function for topological sorting of pipes - Added
pipe_sorter.pymodule for pipe dependency sorting utilities - Added
search_for_nested_image_fields_in_structure_class()method to Concept class - Added
image_field_search.pymodule with utilities to search for image fields in structure classes - Added
pipe_dependenciesproperty to PipeBlueprint and controller blueprints - Added
ordered_pipe_dependenciesproperty to PipeBlueprint for ordered dependencies - Added
get_native_concept()function to hub - Added
get_pipes()function to hub - Added
remove_concepts_by_codes()method to ConceptLibraryAbstract - Added
remove_pipes_by_codes()method to PipeLibraryAbstract - Added template preprocessing with
preprocess_template()function - Added better dependency checking for optional SDK packages (anthropic, mistralai, boto3, aioboto3)
- Added
MissingDependencyErrorexception for missing optional dependencies - Added
library_utils.pymodule with utility functions for PLX file discovery usingimportlib.resources - Added
class_utils.pymodule withare_classes_equivalent()andhas_compatible_field()functions - Added comprehensive unit tests for
CostRegistry,WorkingMemory, andModuleInspector - Added
ScanConfigclass with configurable excluded directories for library scanning - Added CSV export capabilities to
CostRegistrywithsave_to_csv()andto_records()methods - Added default configuration template in
pipelex/kit/configs/pipelex.toml
Changed
- Replaced package
tomlbytomliwhich is more modern and faster - Updated Gemini 2.0 model from
gemini-2.0-flash-exptogemini-2.0-flashwith new pricing (input: $0.10, output: $0.40 per million tokens) - Updated Gemini 2.5 Series comment from '(when available)' to stable release
- Updated
best-claudefromclaude-4-sonnettoclaude-4.5-sonnetacross all presets - Updated kajson dependency from version
0.3.0to0.3.1 - Updated httpx dependency to
>=0.23.0,<1.0.0for broader compatibility - Cleanup env example and better explain how to set up keys in README and docs
- Changed Gemini routing from
googlebackend topipelex_inferencebackend - BREAKING: Major module reorganization - moved
tools/config/,tools/exceptions.py,tools/environment.py,tools/runtime_manager.pytosystem/package structure (system/configuration/,system/exceptions.py,system/environment.py,system/runtime.py) - BREAKING: Reorganized registry modules from
tools/tosystem/registries/(affectsclass_registry_utils,func_registry,func_registry_utils,registry_models) - BREAKING: Split
pipelex.core.stuffs.stuff_contentmodule into individual files per content type (affects imports:StructuredContent,TextContent,ImageContent,ListContent,PDFContent,PageContent,NumberContent,HtmlContent,MermaidContent,TextAndImagesContent) - BREAKING: Renamed package
pipelex.pipe_workstopipelex.pipe_runand movedPipeRunParamsclasses into it - BREAKING: Cost reporting changed from Excel (xlsx) to CSV format using native Python csv module instead of pandas
- Renamed
ConfigManagertoConfigLoader - Renamed
PipelexRegistryModelstoCoreRegistryModels - Renamed
PipelexTestModelstoTestRegistryModels - Renamed
generate_jinja2_context()togenerate_context()inWorkingMemoryandContextProviderAbstract - Renamed
ConceptProviderAbstracttoConceptLibraryAbstract - Renamed
DomainProviderAbstracttoDomainLibraryAbstract - Renamed
PipeProviderAbstracttoPipeLibraryAbstract - Renamed
PipeInputSpectoInputRequirements - Renamed
PipeInputSpecFactorytoInputRequirementsFactory - Renamed
pipe_input.pytoinput_requirements.py - Renamed
pipe_input_factory.pytoinput_requirements_factory.py - Renamed
pipe_input_blueprint.pytoinput_requirement_blueprint.py - Changed hub methods from
get_*_provider()toget_*_library()pattern - Changed hub methods from
set_*_provider()toset_*_library()pattern - Changed
PipeLLMvalidation to check all inputs are in required variables - Updated
LLMPromptSpecto handle image collections (lists/tuples) in addition to single images - Changed Mermaid diagram URL generation from
/img/to/svg/endpoint - Changed
PipeLLMPromptTemplate.make_llm_prompt()to private method_make_llm_prompt() - Updated pipe-builder prompts to include concept specs for better context
- Updated
PipelexBundleSpec.to_blueprint()to sort pipes by dependencies before creating bundle - Changed exception base class from
PipelexErrortoPipelexErrorthroughout codebase - Updated Makefile pyright target to use
--pythonpathflag correctly - Enhanced
LibraryManagerto useimportlib.resourcesfor reliable PLX file discovery across all installation modes (wheel, source, relative path) - Simplified
FuncRegistryUtilsto exclusively register functions with@pipe_funcdecorator (removeddecorator_namesandrequire_decoratorparameters) - Updated
ReportingManagerto get config directly instead of via constructor parameter - Updated PipeFunc documentation to reflect
@pipe_func()decorator requirement and auto-discovery from anywhere in project - Added warnings about module-level code execution during auto-discovery to PipeFunc and StructuredContent documentation
Fixed
- Fixed Makefile target
pyrightto use correct pythonpath flag - Fixed bug with inputs of the
PipeLLMwhere image inputs couldn't be used and tagged in prompts - Fixed image input handling in
LLMPromptSpecto support both single images and image collections - Fixed template preprocessing to handle jinja2 templates correctly
- Fixed hard dependencies by moving imports to function scope in model_lists.py
- Updated README badge URL to point to main branch instead of feature/pipe-builder branch
Removed
- Removed centralized
pipelex_librariesfolder system andpipelex init librariescommand - Removed config path parameters from
Pipelex.make()(relative_config_folder_path,config_folder_path,from_file) - Removed Gemini 1.5 series models:
gemini-1.5-pro,gemini-1.5-flash, andgemini-1.5-flash-8b - Removed
base_templates.tomlfile (generic prompts moved topipelex.toml) - Removed
gpt-5-minifrom possible models in pipe-builder - Removed useless functions in
LLMJobFactory:make_llm_job_from_prompt_factory(),make_llm_job_from_prompt_template(),make_llm_job_from_prompt_contents() - Removed
add_or_update_pipe()method from PipeLibrary - Removed
get_optional_library_manager()method from PipelexHub - Removed
get_optional_domain_provider()andget_optional_concept_provider()methods from hub - Removed unused test fixtures (apple, cherry, blueberry, concept_provider, pretty) from conftest.py
- Removed some Vision/Image description pipes from the base library, because we doubt they were useful as they were
- Removed pandas and openpyxl dependencies (including stubs: pandas-stubs, types-openpyxl)
- Removed Excel file generation for cost reports and
to_dataframe()method fromCostRegistry - Removed
should_warn_if_already_registeredparameter fromfunc_registry.register_function() - Removed
decorator_namesandrequire_decoratorparameters fromFuncRegistryUtilsmethods - Removed
_find_plx_files_in_dir()and_get_pipelex_plx_files_from_dirs()methods fromLibraryManager(refactored tolibrary_utilsmodule) - Removed hardcoded excluded directories from
ClassRegistryUtilsandFuncRegistryUtils(now useScanConfig) - Removed
are_classes_equivalent()andhas_compatible_field()methods fromClassRegistryUtils(moved toclass_utilsmodule)
[v0.11.0] - 2025-10-01
Highlights
- New pipe builder pipeline to generate Pipes based on a brief in natural language: use the cli
pipelex build pipe "Your task"to build the pipe. - New observer system: inject your own class to observe and trace all details before and after each pipe run. We also provide a local observer that dumps the payloads to local JSONL files = new-line delilmited json, i.e. one json object per line.
- Full refactoring of OCR and Image Generation to use the same patterns as
LLMworkers and pipes.
Added
- Added
claude-4.5-sonnetto the model deck. - Added a badge on the
README.mdto display the number of tests. - Added new test cases for environment variable functions
- Added new documentation for
PipeFuncon how to register functions. - Added
pipelex show models [BACKEND_NAME]command to list available models from a specific backend.
Changed
- Renamed
llm_deckterminology tomodel_deckthroughout codebase and documentation, now that it's also used for OCR and Image Generation models - Renamed
is_gha_testingproperty tois_ci_testingin RuntimeManager - Refactored
all_env_vars_are_set()function to only accept a list of keys, single string support now usesis_env_var_set() - Modified
any_env_var_is_placeholder()to use new placeholder detection logic - Updated test environment setup to use dynamic placeholder generation instead of hardcoded values
Fixed
- Fixed logic error in
any_env_var_is_placeholder()function - now correctly returns False when no placeholders are found
Removed
- Removed
get_rooted_path()andget_env_rooted_path()utility functions which were not used - Removed hardcoded placeholder dictionary and
ENV_DUMMY_PLACEHOLDER_VALUEconstant in test setup - Removed function
run_pipe_codein pipe router because it was not relevant (used mostly in tests) - Remove the use of
PipeComposeinPipeCondition, to only use jinja2 directly, through theContentGenerator - Remove the template libraries from the pipelex libraries.
- Removed
claude-3.5-sonnetandclaude-3.5-sonnet-v2from the model deck.
[v0.10.2] - 2025-09-18
Added
- Unified OCR system using model handles instead of separate OcrHandle enum
- ModelType enum supporting LLM and TEXT_EXTRACTOR types
- Enhanced error handling in library loading with better validation messages
- Config template management with
config-templateandcftMakefile targets to update templates from the.pipelex/directory
Changed
- ⚠️ Breaking changes:
- Renamed
ocr_handletoocr_modelinPipeExtractblueprint, so you'll need to update your PLX code accordingly - Updated .env.example file with slightly modified key names (more standard).
- OCR system now uses InferenceModelSpec with unified model handles
- Renamed
get_llm_deck()toget_model_deck()and updated parameter names fromllm_handletomodel_handle - Simplified OCR worker factory using plugin SDK matching
- Enhanced plugin system compatibility with InferenceModelSpec
- Improved error messages throughout system
- Improved management of placeholder environment variables for unit tests
Removed
- Legacy OCR classes: OcrHandle, OcrPlatform, OcrEngine, OcrEngineFactory
- Obsolete configuration fields and setup methods
- PipelexFileError exception class
[v0.10.1] - 2025-09-17
Changed
- Enabled all backends, still required to pass all unit tests.
- A few tweaks to the base model deck.
[v0.10.0] - 2025-09-17
Highlights
New Inference Backend Configuration System — We've completely redesigned how LLMs are configured and accessed in Pipelex, making it more flexible and easier to get started:
- Get started in seconds with Pipelex Inference: Use a single API key to access all major LLM providers (OpenAI, Anthropic, Google, Mistral, and more)
- Flexible backend configuration: Configure multiple inference backends (Azure OpenAI, Amazon Bedrock, Vertex AI, etc.) through simple TOML files in
.pipelex/inference/ - Smart model routing: Automatically route models to the right backend using routing profiles with pattern matching
- User-friendly aliases: Define shortcuts like
best-claude→claude-4.1-opuswith optional fallback chains - Cost-aware model specs: Each model includes detailed pricing, capabilities, and constraints for better cost management
For complete details, see the Inference Backend Configuration documentation.
Added
- New inference backend configuration system in
.pipelex/inference/directory - Support for 10+ inference backends: OpenAI, Anthropic, Azure OpenAI, Amazon Bedrock, Mistral, Vertex AI, XAI, BlackboxAI, Perplexity, Ollama, and Pipelex Inference
- Model routing profiles with pattern matching (
*model*,model*,*model) - Model aliases with waterfall fallback chains
- Environment variable and secret substitution in TOML configs (
${VAR}and${secret:KEY}) - Comprehensive model specifications with detailed cost categories
- Unified plugin SDK registry for all backends
- CI environment detection with automatic placeholder API keys for testing
- Improved
pipelex init configcommand to copy entire configuration template directory structure to.pipelex/with smart file handling (skips existing files, shows clear progress messages) - Added
FuncRegistryUtilsto register functions in a pipelex folder that have a specific signature. - Added
mistral-mediumandmistral-medium-2508to the Mistral backend configuration. - Added
gemini-2.5-flashto the VertexAI backend configuration.
Changed
- LLM configuration moved from
pipelex_libraries/llm_deck/to.pipelex/inference/deck/ - LLM handles simplified to direct model names or user-defined aliases
- Model deck completely redesigned with inference models, aliases, and presets
- Plugin system refactored to use backend-specific TOML configuration
- Token categories renamed to cost categories with expanded types
Fixed
- Improved error messages for missing environment variables
- Enhanced TOML configuration validation
- More robust model routing and backend selection
Removed
- Legacy LLM model library system (
llm_integrations/directory) - Platform-specific configuration classes (AnthropicConfig, OpenAIConfig, etc.)
- Deprecated LLM engine blueprint and factory classes
- Old LLM platform and family enumerations
Security
- Enhanced secret management with secure fallback patterns
- Improved API key handling through centralized backend configuration
[v0.9.5] - 2025-09-12
Highlights
- Pinned
instructorto version<1.10.0to avoid errors withmypy
Added
- Added
PIPELEX_INFERENCELLM family enum value - Added support for
PIPELEX_INFERENCEin OpenAI LLM worker - Added Azure OpenAI platform support for Grok models (
grok-3andgrok-3-mini) - Added debug logging for
PipeParalleloutput contents - Added
TOMLfile filtering in LLM model library loading - Added error handling for Unicode decode errors in LLM model library
- Added new test model configurations for
pipelexandvertex_aiplatforms
Changed
- Improved error messages in
StuffFactoryto include concept code and stuff name - Disabled
is_gen_object_supportedfor all Grok models (grok-3,grok-3-mini,grok-3-fast) - Updated test configurations to use different LLM models and platforms
- Modified
Jinja2filter to use defaultTagStyle.TICKSinstead of raising error - Added proper error handling for Unicode decode errors when loading model libraries
- Improved error handling in Anthropic plugin tests with specific
AuthenticationErrorhandling - Image handling in
AnthropicFactorynow converts image URLs tobase64data URLs with proper MIME type prefix - Put back Discord link in
README.md
Fixed
- Pinned
instructorto version<1.10.0to avoid errors withmypy
[v0.9.4] - 2025-09-06
Added
- Added support for BlackboxAI models
[v0.9.3] - 2025-09-06
Added
- Better support for BlackboxAI IDE
- VS Code extensions recommendations file with Pipelex, Ruff, and MyPy extensions
- File association for .plx files in VS Code settings
[v0.9.2] - 2025-09-05
Fixed
- Fix the rules of all agents.
Added
- Added agent rule for copilot
- Added a rule to forbidden structuring basic text concepts
[v0.9.1] - 2025-09-05
Fixed
- Fixed many inconsistencies in the documentation.
[v0.9.0] - 2025-09-02
Refacto
- Changed the pipeline file extension from
.tomlto.plx: Updated the LibraryManager in consequence.
Fixed
- Fixed the
structuring_methodbehavior in thePipeLLMpipe: Putting it topreliminary_text, thePipeLLMwill always generate text before generating the structure -> Reliability increased by a lot.
Fixed
- Fixed a bug in the
needed_inputsmethod of thePipeSequencepipe.
Changed
dry_run_pipenow returns aDryRunOutputobject instead of astrwith additional information.- Updated
cocodedependency from versionv0.0.10tov0.0.15.
Added
- Added the
FuncRegistryUtilsclass to register functions in the library.
[v0.8.1] - 2025-08-27
Bugfix
- Bugfix: Fixed the
PipeFuncoutput concept code and structure class name in the dry run.
[v0.8.0] - 2025-08-27
Refactor
- Refactored the concepts: Blueprints are now more explicit, and hold only concept strings or code. Pipes hold concept instances.
- Organized code: Created subfolders for controller and operator pipes.
- Say goodbye to
PipeLLMPrompt. - Removed the
PipeComposeandPipeLLMPromptfrom thePipeLLM.
Added
- Added a lot of unit tests.
- Loading the library can now be done from toml file or from
PipelexBundleBlueprint.
Fixed
- Backported
backports.strenumto>=1.3.0to support Python 3.10 now in dependencies and not in optional dependencies.
[v0.7.0] - 2025-08-20
Refactor
- Refactored the Blueprints. Introduces the
PipelexInterpreterthat interprets the Pipelex language and creates the Pipelex Blueprints (and vice versa) - Modified the way we declare pipes. Use the field
type = "PipeLLM"instead of fieldPipeLLM. (Same for all pipes) - Refactored the
LibraryManager. - Refactored CLI commands and added new ones. Modified CLI command structure:
pipelex init- Initialization commandspipelex init libraries [DIRECTORY]- Initialize pipelex libraries (createspipelex_librariesfolder)pipelex init config- Initialize pipelex configuration (createspipelex.toml)
pipelex validate- Validation and dry-run commandspipelex validate all -c pipelex/libraries- Validate all libraries and dry-run all pipespipelex validate pipe PIPE_CODE- Dry run a single pipe by its code
pipelex show- Show and list commandspipelex show config- Show the pipelex configurationpipelex show pipes- List all available pipes with descriptionspipelex show pipe PIPE_CODE- Show a single pipe definition
pipelex migrate- Migration commandspipelex migrate run- Migrate TOML files to new syntax (with--dry-runand--backupsoptions)
pipelex build- Build artifacts like pipeline blueprintspipelex build draft PIPELINE_NAME- Generate a draft pipelinepipelex build blueprint PIPELINE_NAME- Generate a pipeline blueprint
- Organized
concept,pipe,working_memory,stufffiles into folders.
Changed
- Allow
aiofilesversion>=23.2.1 - GHA Cla assistant fixed with Github App
Added
- New LLM families
LLMFamily.GPT_5,LLMFamily.GPT_5_CHATandLLMFamily.CLAUDE_4_1 - Added support for Claude 4.1 and GPT 5 models (inc. mini, nano, chat)
- New Pipe that generates pipe. Pipe code:
build_blueprint - New tests. Especially for the
PipelexInterpreter. - Migration files and cli commands to migrate Pipelex language to new syntax.
- Introduces
PipelexBundle, which correspond to the python paradigm of the Pipelex TOML syntax.
[v0.6.10] - 2025-08-02
Added
- New test file for source code manipulation functions (tests/cases/source_code.py)
- New integration test for PipeFunc functionality (tests/integration/pipelex/pipes/pipe_operator/pipe_func/test_pipe_func.py)
- New package structure file for pipe_func tests (init.py)
- Simplified input memory creation for native concepts (Text, Image, PDF) in pipeline execution
- Added Pipeline requests link to GitHub issue template config
Changed
- Updated pipeline execution documentation and examples to use input_memory instead of working_memory
- Renamed pipeline from 'extract_page_contents_from_pdf' to 'ocr_page_contents_from_pdf'
- Renamed pipeline from 'extract_page_contents_and_views_from_pdf' to 'ocr_page_contents_and_views_from_pdf'
- Updated cocode dependency from version 0.0.6 to 0.0.9
Fixed
- Fixed typo in pipeline description ('aspage views' to 'as full page views')
Removed
- Removed WorkingMemoryFactory and StuffFactory imports from pipeline execution examples
- Removed working memory creation code from pipeline examples
[v0.6.9] - 2025-07-26
Changed
Simplified input memory:
- The concept code can now be provided with arg named
conceptin addition toconcept_code - You can pass a simple string to create a
Textstuff
[v0.6.8] - 2025-07-25
Added
- New method
make_stuff_using_concept_name_and_search_domainsinStuffFactoryfor creating stuff using concept names and search domains. - New method
make_stuff_from_stuff_content_using_search_domainsinStuffFactoryfor creating stuff from stuff content using search domains. - New method
make_from_implicit_memoryinWorkingMemoryFactoryfor creating working memory from implicit memory. - New method
create_mock_contentinWorkingMemoryFactoryfor creating mock content for requirements.
Changed
- Refactored
PipeInputto useInputRequirementandTypedNamedInputRequirementclasses instead of plain strings for input specifications. - Updated
WorkingMemoryFactoryto handlePipelineInputsinstead ofCompactMemory. - Replaced
ExecutePipelineExceptionwithPipelineInputErrorinexecute_pipelinefunction. - Updated
PipeBatch,PipeCondition,PipeParallel,PipeSequence,PipeFunc,PipeImgGen,PipeCompose,PipeLLM, andPipeExtractclasses to useInputRequirementfor input handling. - Updated
PipeInputcreation in various test files to usemake_from_dictmethod. - Updated
pyproject.tomlto excludepypdfium2version4.30.1. - Updated
Jinja2TemplateCategoryto handle HTML and Markdown templates differently.
Fixed
- Corrected error messages in
StuffFactoryandStuffContentFactoryto provide more detailed information about exceptions.
[v0.6.7] - 2025-07-24
Removed
- Removed the
structure_classesparameter from thePipelexclass.
[v0.6.6] - 2025-07-24
Added
- Added a new method
verify_content_typein theStuffclass to verify and convert content to the expected type. - Added
cocode==0.0.6to the development dependencies inpyproject.toml.
Changed
- Updated
Stuffclass methods to use the newverify_content_typemethod for content verification. - Updated
vertexai.tomlto change LLM IDs from preview models to released models:gemini-2.5-proandgemini-2.5-flash.
Removed
- Removed
reinitlibraries,rl,v, andinittargets from the Makefile.
[v0.6.5] - 2025-07-21
Fixed
- In the documentation, fixed the use of
execute_pipeline.
[v0.6.4] - 2025-07-19
- Fixed the
README.mdlink to the documentation
[v0.6.3] - 2025-07-18
Changed
- Enhanced
Stuff.content_as()method with improved type validation logic - now attempts model validation whenisinstancecheck fails
[v0.6.2] - 2025-07-18
Added
- New
dry-run-pipecli command to dry run a single pipe by its code - New
show-pipecli command to display pipe definitions from the pipe library - New
dry_run_single_pipe()function for running individual pipe dry runs
Changed
- Updated
init-librariescommand to accept a directory argument and createpipelex_librariesfolder in specified location - Updated
validatecommand to use-cflag for the config folder path
[v0.6.1] - 2025-07-16
- Can execute pipelines with
input_memory: It is aCompactMemory: Dict[str, Dict[str, Any]]
[v0.6.0] - 2025-07-15
Changed
- Enhanced
Pipelex.make()method: Complete overhaul of the initialization method with new path configuration options and robust validation: - Added
relative_config_folder_pathandabsolute_config_folder_pathparameters for flexible config folder specification - The
from_fileparameter controls path resolution: ifTrue(default), relative paths are resolved relative to the caller's file location; ifFalse, relative to the current working directory (useful for CLI scenarios) - Renamed Makefile targets like
make doctomake docsfor consistency
Added
- Added github action for inference tests
load_json_list_from_pathfunction inpipelex.tools.misc.file_utils: Loads a JSON file and ensures it contains a list.- Added issue templates
- Updated Azure/OpenAI integrations, using dated deployment names systematically
[v0.5.2] - 2025-07-11
- log a warning when dry running a
PipeFunc - Update Readme.md
[v0.5.1] - 2025-07-09
Fixed
- Fixed the
ConceptFactory.make_from_blueprintmethod: Concepts defined in single-line format no longer automatically refineTextContentwhen a structure class with the same name exists ConceptFactory.make_concept_from_definitionis nowConceptFactory.make_concept_from_definition_str
Added
- Bumped
kajsontov0.3.0: IntroducingMetaSingletonfor better singleton management - Unit tests for
ConceptLibrary.is_compatible_by_concept_code
[v0.5.0] - 2025-07-01
Highlights
Vibe Coding an AI workflow becomes a reality — Create AI workflows from natural language without writing code: the combination of Pipelex's declarative language, comprehensive Cursor rules, and robust validation tools enables AI assistants to autonomously iterate on pipelines until all errors are resolved and workflows are ready to run.
Added
- Complete Dry Run & Static Validation System - A comprehensive validation framework that catches configuration and pipeline errors before any expensive inference operations.
- WorkingMemoryFactory Enhancement: New
make_for_dry_run()method creates working memory with realistic mock objects for zero-cost pipeline testing - Enhanced Dry Run System: Complete dry run support for all pipe controllers (
PipeCondition,PipeParallel,PipeBatch) with mock data generation usingpolyfactory - Comprehensive Static Validation: Enhanced static validation with configurable error handling for missing/extraneous input variables and domain validation
- TOML File Validation: Automatic detection and prevention of trailing whitespaces, formatting issues, and compilation blockers in pipeline files
- Pipeline Testing Framework: New
dry_run_all_pipes()method enables comprehensive testing of entire pipeline libraries - Enhanced Library Loading: Improved error handling and validation during TOML file loading with proper exception propagation
Configuration
- Dry Run Configuration: New
allowed_to_fail_pipessetting allows specific pipes (like infinite loop examples that fail on purpose) to be excluded from dry run validation - Static Validation Control: Configurable error reactions (
raise,log,ignore) for different validation error types
Documentation & Development Experience
- Cursor Rules Enhancement: Comprehensive pipe controller documentation covering
PipeSequence,PipeCondition,PipeBatch, andPipeParallel, improved PipeOperator documentation forPipeLLM,PipeOCR - Pipeline Validation CLI: Enhanced
pipelex validate all -c pipelex/librariescommand with better error reporting and validation coverage - Improved Error Messages: Better formatting and context for pipeline configuration errors
Changed
- Error Message Improvements: Updated PipeCondition error messages to reference
expression_templateinstead of deprecatedexpression_jinja2
[v0.4.11] - 2025-06-30
- LLM Settings Simplification: Streamlined LLM choice system by removing complex
for_object_direct,for_object_list, andfor_object_list_directoptions. LLM selection now uses a simpler fallback pattern: specific choice → text choice → overrides → defaults. - Image Model Updates: Renamed
image_bytesfield tobase_64inPromptImageTypedBytesfor better consistency. Updated to useCustomBaseModelbase class to benefit from bytes truncation when printing.
[v0.4.10] - 2025-06-30
- Fixed a bad import statement
[v0.4.9] - 2025-06-30
Highlights
Plugin System Refactoring - Complete overhaul of the plugin architecture to support external LLM providers.
Added
- External Plugin Support: New
LLMWorkerAbstractbase class for integrating custom LLM providers, and we don't mean only an OpenAI-SDK-based LLM with a custom endpoint, now the implementation can be anything, as long as it implements theLLMWorkerAbstractinterface. - Plugin SDK Registry: Better management of SDK instances with proper teardown handling
- Enhanced Error Formatting: Improved Pydantic validation error messages for enums
Changed
- Plugin Architecture: Moved plugin system to dedicated
pipelex.pluginspackage - LLM Workers: Split into
LLMWorkerInternalAbstract(for built-in providers) andLLMWorkerAbstract(for external plugins) - Configuration: Plugin configs moved from main
pipelex.tomlto separatepipelex_libraries/plugins/plugin_config.toml(⚠️ breaking change) - Error Handling: Standardized credential errors with new
CredentialsErrorbase class
[v0.4.8] - 2025-06-26
- Added
StorageProviderAbstract - Updated the changelog of
v0.4.7: MovedAdded StorageProviderAbstracttov0.4.8
[v0.4.7] - 2025-06-26
- Added an API serializer: introducing the
compact_memory, a new way to encode/decode the working memory as json, for the API. - When creating a Concept with no structure specified and no explicit
refines, set it to refinenative.Text JobMetadata: addedjob_name. Removedtop_job_idandwfidPipeOutput: addedpipeline_run_id
[v0.4.6] - 2025-06-24
- Changed the link to the doc in the
README.md: https://docs.pipelex.com
[v0.4.5] - 2025-06-23
Changed
- Test structure overhaul: Reorganized test directory structure for better organization:
- Tests now separated into
unit/,integration/, ande2e/directories - Created
tests/cases/package for pure test data and constants - Created
tests/helpers/package for test utilities - Cleaned up test imports and removed empty
__init__.pyfiles - Class registry refactoring: Updated kajson from 0.1.6 to 0.2.0, adapted to changes in Kajson's class registry with new
ClassRegistryUtils(better separation of concerns) - Dependency updates:
- Added pytest-mock to dev dependencies for improved unit testing
Added
- Coverage commands: New Makefile targets for test coverage analysis:
make cov: Run tests with coverage reportmake cov-missing(ormake cm): Show coverage with missing lines- Test configuration: Set
xfail_strict = truein pytest config for stricter test failure handling - Pydantic validation errors: Enhanced error formatting to properly handle model_type errors
Fixed
- External links: Removed broken Markdown target="_blank" syntax from MANIFESTO.md links
- Variable naming consistency: Fixed redundant naming in OpenAI config (openai_openai_config → openai_config)
- Makefile optimization: Removed parallel test execution (
-n auto) from codex-tests, works better now
Tests
- Unit tests added: New comprehensive unit tests for:
ClassRegistryUtilsFuncRegistryModuleInspector- File finding utilities
[v0.4.4] - 2025-06-20
Fixed
- Changed the allowed base branch names in the GHA
guard-branches.yml:doc->docs - Fixed
kajsondependency (see kajson v0.1.6 changelog)
Cursor rules
- Added Cursor rules for coding best practices and standards (including linting methods). Added TDD (Test Driven Development) rule on demand.
- Various changes
Documentation
- Added documentation for referencing images in PipeLLM.
- Fixed typos
Refactor
- Removed the
imagesfield from PipeLLM - images can now be referenced directly in theinputs - Moved the list-pipes CLI function to the
PipeLibraryclass.
[v0.4.3] - 2025-06-19
Fixed
- Removed deprecated Gemini 1.5 models: Removed
gemini-1.5-flashandgemini-1.5-profrom the VertexAI integration as they are no longer supported - Fixed multiple import statements across the codebase
Documentation
- Enhanced MkDocs search: Added search functionality to the documentation site
- Proofreading improvements: Fixed various typos and improved clarity across documentation
Refactor
- Mini refactor: changed kajson dependency to
kajson==0.1.5(instead of>=) to tolerate temporary breaking changes from kajson
[v0.4.2] - 2025-06-17
- Fixed the inheritance config manager method (Undocumented feature, soon to be removed)
- Fixed the
deploy-doc.ymlGitHub Action - Grouped the mkdocs dependencies in a single group
docsin thepyproject.tomlfile
[v0.4.1] - 2025-06-16
- Changed discord link to the new one: https://go.pipelex.com/discord
- Added
hello-worldexample in thecookbook-examplesof the documentation.
[v0.4.0] - 2025-06-16
Highlights
Complete documentation overhaul:
- MkDocs setup for static web docs generation
- Material for MkDocs theme, custom styling and navigation
- Other plugins: meta-manager, glightbox
- GitHub Pages deployment, mapped to docs.pipelex.com
- Added GHA workflows for documentation deployment and validation
- Added to docs:
- Manifesto explaining the Pipelex viewpoint
- The Pipelex Paradigm explaining the fundamentals of Pipelex's solution
- **Cookbook examples** presented and explained, commented code, some event with mermaid flow charts
- And plenty of details about using Pipelex and developing for Pipelex, from structured generation to PipeOperators (LLM, Image generation, OCR…) to PipeControllers (Sequence, Parallel, Batch, Condition…), workflow optimization, workflow static validation and dry run… there's still work to do, but we move fast!
- Also a major update of Cursor rules
Tooling Improvements
- Pipeline tracking: restored visual flowchart generation using Mermaid
- Enhanced dry run configuration: added more granular control with
nb_list_items,nb_extract_pages, andimage_urls - New feature flags: better control over pipeline tracking, activity tracking, and reporting
- Improved OCR configuration: handle image file type for Mistral-OCR, added
default_page_views_dpisetting - Enhanced LLM configuration: better prompting for structured generation with automatic schema insertion for two-step structuring: generate plain text and then structure via Json
- Better logging: Enhanced log truncation and display for large objects like image bytes (there are still cases to deal with)
Refactor
Concept system refactoring
- Improved concept code factory with better domain handling, so you no longer need the
nativedomain prefix for native domains, you can just call them by their names:Text,Image,PDF,Page,Number… - Concept
refinesattribute can now be a string for single refined concepts (the most common case)
Breaking Changes
- File structure changes: documentation moved from
doc/todocs/ - Configuration changes: some configuration keys have been renamed or restructured
StuffFactory.make_stuff()argumentconcept_coderenamed toconcept_strto explicitly support concepts without fully qualified domains (e.g.,TextorPDFimplicitlynative)- Some method signatures have been updated
Tests
- Added Concept refinement validation:
TestConceptRefinesValidationFunctionandTestConceptPydanticFieldValidationensure proper concept inheritance and field validation
[v0.3.2] - 2025-06-13
- Improved automatic insertion of class structure from BaseModel into prompts, based on the PipeLLM's
output_concept. New unit test included. - The ReportingManager now reports costs for all pipeline IDs when no
pipeline_run_idis specified. - The
make_from_strmethod from theStuffFactoryclass now usesTextcontext by default.
[v0.3.1] - 2025-06-10
Added
- New pytest marker
dry_runnablefor tests that can run without inference. - Enhanced
maketargets with dry-run capabilities for improved test coverage: make test-xdist(ormake t): Runs all non-inference tests plus inference tests that support dry-runs - fast and resource-efficientmake test-inference(ormake ti): Runs tests requiring actual inference, with actual inference (slow and costly)- Parallel test execution using
pytest-xdist(-n auto) enabled for: - GitHub Actions workflows
- Codex test targets
Changed
- Domain validation is now less restrictive in pipeline TOML: the
descriptionattribute is nowOptional
[v0.3.0] - 2025-06-09
Highlights
- Structured Input Specifications: Pipe inputs are now defined as a dictionary mapping a required variable name to a concept code (
required_variable->concept_code). This replaces the previous singleinputfield and allows for multiple, named inputs, making pipes more powerful and explicit. This is a breaking change. - Static Validation for Inference Pipes: You can now catch configuration and input mistakes in your pipelines before running any operations. This static validation checks
PipeLLM,PipeExtract, andPipeImgGen. Static validation for controller pipes (PipeSequence, PipeParallel…) will come in a future release. - Configure the behavior for different error types using the
static_validation_configsection in your settings. For each error type, choose toraise,log, orignore. - Dry Run Mode for Zero-Cost Pipeline Validation: A powerful dry-run mode allows you to test entire pipelines without making any actual inference calls. It's fast, costs nothing, works offline, and is perfect for linting and validating pipeline logic.
- The new
dry_run_configlets you control settings, like disabling Jinja2 rendering during a dry run. - This feature leverages
polyfactoryto generate mock Pydantic models for simulated outputs. - Error handling for bad inputs during
run_pipehas been improved and is fully effective in dry-run mode. - One limitation: currently, dry running doesn't work when the pipeline uses a PipeCondition. This will be fixed in a future release.
Added
native.AnythingConcept: A new flexible native concept that is compatible with any other concept, simplifying pipe definitions where input types can vary.- Added dependency on
polyfactoryfor mock Pydantic model generation in dry-run mode.
Changed
- Refactored Cognitive Workers: The abstraction for
LLM,ImgGen, andOcrworkers has been elegantly simplified. The old decorator-based approach (..._job_func) has been replaced with a more robust pattern: a public base method now handles pre- and post-execution logic while calling a private abstract method that each worker implements. - The
b64_image_bytesfield inPromptImageByteswas renamed tobase_64for better consistency.
Fixed
- Resolved a logged error related to the pipe stack when using
PipeParallel. - The pipe tracker functionality has been restored. It no longer crashes when using nested object attributes (e.g.,
my_object.attribute) as pipe inputs.
Tests
- A new pytest command-line option
--pipe-run-modehas been added to switch betweenliveanddryruns (default isdry). All pipe tests now respect this mode. - Introduced the
pipelex_apipytest marker for tests related to the Pipelex API client, separating them from generalinferenceorllmtests. - Added a
make test-pipelex-apitarget (shorthand:make ta) to exclusively run these new API client tests.
Removed
- The
llm_job_func.pyfile and the associated decorators have been removed as part of the cognitive worker refactoring.
[v0.2.14] - 2025-06-06
- Added a feature flag for the
ReportingManagerin the config:
[pipelex]
[pipelex.feature_config]
is_reporting_enabled = true
- Moved the reporting config form the
cogtconfig to the Pipelex config.
[v0.2.13] - 2025-06-06
- Added Discord badge on the Readme. Join the community! -> https://go.pipelex.com/discord
- Added a client for the Pipelex API. Join the waitlist -> https://www.pipelex.com/signup
- Removed the
run_pipe_codefunction. Replaced byexecute_pipelineinpipelex.pipeline.execute. - Added llm deck
llm_for_img_to_text. - Renamed
InferenceReportManagertoReportingManager: It can report more than Inference cost. RenamedInferenceReportDelegatetoReportingProtocol. - Added an injection of dependency for
ReportingManager - pipelex cli: fixed some bugs
[v0.2.12] - 2025-06-03
- pipelex cli: Split
pipelex initinto 2 separate functions:pipelex init-librariesandpipelex init-config - Fixed the inheritance config manager method
- Rename Mission to Pipeline
- Enable to start a pipeline and let in run in the background, getting it's run id, but not waiting for the output
Makefile: avoid defaulting pytest to verbose. Setup targetmake test-xdist= Run unit tests withxdist, make it the default for shorthandmake t. The oldmake tis nowmake tp(test-with-prints)- Added
mistral-small-3.1andqwen3:8b - Fix template pre-processor: don't try and substitute a dollar numerical like $10 or @25
- Refactor with less "OpenAI" naming for non-openai stuff that just uses the OpenAI SDK
[v0.2.11] - 2025-06-02
- HotFix for v0.2.10 👇 regarding the new pipelex/pipelex_init.toml`
[v0.2.10] - 2025-06-02
Highlights
Python Support Expansion - We're no longer tied to Python 3.11! Now supporting Python 3.10, 3.11, 3.12, and 3.13 with full CI coverage across all versions.
Major Model Additions - Claude 4 (Opus & Sonnet), Grok-3, and GPT-4 image generation are now in the house.
Pipeline Base Library update
- New pipe -
ocr_page_contents_and_views_from_pdftransferred from cookbook to base library (congrats on the promotion!). This pipe extracts text, linked images, AND page_view images (rendered pages) - it's very useful if you want to use Vision in follow-up pipes
Added
- Template preprocessor - New
@?token prefix for optional variable insertion - if a variable doesn't exist, we gracefully skip it instead of throwing exceptions - Claude 4 support - Both Opus and Sonnet variants, available through Anthropic SDK (direct & Bedrock) plus Bedrock SDK. Includes specific max_tokens limit reduction to prevent timeout/streaming issues (temporary workaround)
- Grok-3 family support - Full support via OpenAI SDK for X.AI's latest models
- GPT-4 image generation - New
gpt-image-1model through OpenAI SDK, available via PipeImgGen. Currently saves local files (addressing in next release) - Gemini update - Added latest
gemini-2.5-proto the lineup - Image generation enhancements - Better quality controls, improved background handling options, auto-adapts to different models: Flux, SDXL and now gpt-image-1
Refactored
- Moved subpackage
pluginto the same level ascogtwithin pipelex for better visibility - Major cleanup in the unit tests, hierarchy significantly flattened
- Strengthened error handling throughout inference flows and template preprocessing
- Added
make test-quiet(shorthandtq) to Makefile to run tests without capturing outputs (i.e. without pytest-soption) - Stopped using Fixtures for
pipe_routerandcontent_generator: we're now always getting the singleton frompipelex.hub
Fixed
- Perplexity integration - Fixed breaking changes from recent updates
Dependencies
- Added pytest-xdist to run unit tests in parallel on multiple CPUs. Not yet integrated into the Makefile, so run it manually with
pytest -n auto(without inference) orpytest -n auto -m "inference"(inference only). - Swapped pytest-pretty for pytest-sugar - because readable test names > pretty tables
- Updated instructor to v1.8.3
- All dependencies tested against Python 3.10, 3.11, 3.12, and 3.13
Tests
- TestTemplatePreprocessor
- TestImgGenByOpenAIGpt
- TestImageGeneration
- TestPipeImgGen
[v0.2.9] - 2025-05-30
- Include
pyproject.tomlinside the project build. - Fix
ImgGenEngineFactory: image generation (imgg) handle required format isplatform/model_name - pipelex cli: Added
list-pipesmethod that can list all the available pipes along with their descriptions. - Use a minimum version for
uvinstead of a fixed version - Implement
AGENTS.mdfor Codex - Add tests for some of the
tools.misc - pipelex cli: Rename
pipelex run-setuptopipelex validate all -c pipelex/libraries
[v0.2.8] - 2025-05-28
- Replaced
poetrybyuvfor dependency management. - Simplify llm provider config: All the API keys, urls, and regions now live in the
.env. - Added logging level
OFF, prevents any log from hitting the console
[v0.2.7] - 2025-05-26
- Reboot repository
[v0.2.6] - 2025-05-26
- Refactor: use
ActivityManagerProtocol, renameBaseModelTypeVar
[v0.2.5] - 2025-05-25
- Add custom LLM integration via OpenAI sdk with custom
base_url
[v0.2.4] - 2025-05-25
- Tidy tools
- Tidy inference API plugins
- Tidy WIP feature
ActivityManager
[v0.2.2] - 2025-05-22
- Simplify the use of native concepts
- Include "page views" in the outputs of Ocr features
[v0.2.1] - 2025-05-22
- Added
OcrWorkerAbstractandMistralOcrWorker, along withPipeExtractfor OCR processing of images and PDFs. - Introduced
MissionManagerfor managing missions, cost reports, and activity tracking. - Added detection and handling for pipe stack overflow, configurable with
pipe_stack_limit. - More possibilities for dependency injection and better class structure.
- Misc updates including simplified PR template, LLM deck overrides, removal of unused config vars, and disabling of an LLM platform id.
[v0.2.0] - 2025-05-19
- Added OCR, thanks to Mistral
- Refactoring and cleanup
[v0.1.14] - 2025-05-13
- Initial release 🎉