ShippedDeveloper tooling · 2025

Python library

ChainComposer

ChainComposer came out of Academic Metrics, where five LLM stages needed structured parsers, fallback paths, and named outputs carried into later prompts. LCEL could express that machinery, but every new workflow meant rebuilding the same construction pattern. ChainComposer kept LCEL underneath and reduced each stage to one declarative call.

My role

Independent open-source project

ChainComposer wordmark over a connected-node background
Developer tooling
Era
LangChain 0.3 / LCEL
Authoring
Hours → ~5 minutes
Runtime
LCEL Runnable pipelines
01

Why it existed

Academic Metrics was not a toy example bolted on after the fact. Its classifier was the original proving ground: method extraction, sentence analysis, summarization, recursive taxonomy classification, and theme recognition run across three managers with outputs carried forward by name.

LangChain 0.3's LCEL supplied expressive prompt, model, parser, and Runnable primitives. It did not supply this opinionated application pattern. Once I extracted that repeated construction into ChainComposer, assembling a new multi-stage workflow went from hours of wiring and debugging to roughly five minutes of declaring layers.

02

Explicit data flow

Each layer declares its prompts, parser, output model, and the key under which its result enters shared chain state. Later layers can consume that value without burying the workflow in callback code.

03

Structured output with a fallback path

Layers can parse JSON or validate against Pydantic models, while an optional fallback parser preserves useful output when a provider misses the preferred format. Errors remain visible through chain logging and inspection APIs.

Before / after

The abstraction was the product.

LCEL could express every step. The recurring cost was constructing and debugging the same prompt, parser, fallback, and state machinery before building the actual workflow. ChainComposer paid that cost once; scaling the pattern across Academic Metrics' five LLM stages became layer declarations.

Raw LCEL

Build the machinery first

This is the compact version for one intermediate stage. Reusing it cleanly means extracting another helper—which is already the beginning of an orchestration library.

prompt = ChatPromptTemplate.from_messages([
    ("system", METHOD_EXTRACTION_SYSTEM_MESSAGE),
    ("human", HUMAN_MESSAGE_PROMPT),
])

primary = (
    prompt
    | llm
    | JsonOutputParser(
        pydantic_object=MethodExtractionOutput,
    )
)
fallback = prompt | llm | StrOutputParser()

method_layer = primary.with_fallbacks(
    [fallback],
    exceptions_to_handle=PARSE_ERRORS,
)
pipeline = RunnablePassthrough.assign(
    method_json_output=method_layer,
)
state = pipeline.invoke(inputs)

ChainComposer

Declare the workflow

Prompt construction, parser policy, the fallback path, and the named state handoff become one layer contract. Additional stages use the same call.

composer = ChainComposer(
    model="gpt-4o-mini",
    api_key=api_key,
)

composer.add_chain_layer(
    system_prompt=METHOD_EXTRACTION_SYSTEM_MESSAGE,
    human_prompt=HUMAN_MESSAGE_PROMPT,
    parser_type="json",
    fallback_parser_type="str",
    pydantic_output_model=MethodExtractionOutput,
    output_passthrough_key_name="method_json_output",
)

state = composer.run(inputs)

Connected work

Engineering choices

The decisions that shaped it.

The implementation details matter because each one closes a specific failure mode or keeps an important boundary visible.

01

Wrap LCEL, do not replace it

Every layer still compiles to ordinary Runnable pipelines; the library removes repeated construction without inventing another execution engine.

02

Name every handoff

Each output enters shared state under an explicit key, so the next prompt's inputs remain visible and inspectable.

03

Treat parsers as policy

Output format, validation, and fallback behavior are configured per layer instead of being scattered through control flow.

Where it landed

A PyPI package extracted from a working classifier that reduced my repeat pipeline setup from hours to roughly five minutes while leaving LCEL visible underneath.

Next case study

SaltCast

Keep reading