pip install mellea, Ollama running locally (or an
OpenAI-compatible endpoint).
When a single prompt grows too long or asks the LLM to do too many things at
once, quality degrades. m decompose analyses the prompt, extracts its
constraints, and produces a Python script of ordered m.instruct() calls — one
per subtask — that you can run immediately or refine with types and requirements.
When to use m decompose
Usem decompose when:
- A prompt contains multiple distinct tasks (write, classify, translate, summarise) that you would benefit from separating.
- You want to add typed return values or
@generativewrappers to each step. - You need to assign different requirements to different parts of the pipeline.
- You are prototyping a pipeline and want a structured starting point to edit.
m.instruct() call, use instruct()
directly.
Step 1: Write your prompt to a file
Create a plain-text file that describes the full task. Include all constraints and requirements as part of the description —m decompose extracts them:
party_plan.txt.
Tip: The more explicit your constraints in the prompt file, the more
accurately m decompose assigns them to individual subtasks. Phrases like
“must”, “must not”, “at least”, and “ordered by” are reliably extracted as
constraints.
Step 2: Run the decompose command
./output/:
m_decomp_result.py— a runnable Python script with onem.instruct()call per subtask, in dependency orderm_decomp_result.json— the full decomposition: subtask list, extracted constraints, dependency graph, and Jinja2 prompt templates
Note: The--out-dirdirectory must already exist.m decomposedoes not create it.
What the pipeline does
m decompose runs these steps internally, in order:
- Parses the prompt into a list of subtasks, each tagged with a short identifier
- Extracts all constraints and requirements from the prompt text
- Decides for each constraint whether validation should be done with code
(
"code") or with an LLM judge ("llm") - Generates a Jinja2 prompt template for each subtask
- Assigns constraints to the subtasks they apply to
- Writes the output Python script with
m.instruct()calls in dependency order
All CLI options
| Flag | Default | Description |
|---|---|---|
--prompt-file | (interactive) | Path to a text file containing the task prompt. Omit to enter the prompt interactively. |
--out-dir | (required) | Path to the directory for output files. Must exist. |
--out-name | m_decomp_result | Base name for the output .py and .json files. |
--model-id | mistral-small3.2:latest | Model to use for the decomposition. |
--backend | ollama | Inference backend: ollama or openai. |
--backend-endpoint | — | URL endpoint. Required when --backend openai. |
--backend-api-key | — | API key. Required when --backend openai. |
--backend-req-timeout | 300 | Request timeout in seconds. |
--input-var | — | Repeatable. Declares a user input variable name (uppercase Python identifier). |
Step 3: Review the generated Python file
Openoutput/m_decomp_result.py. For the birthday party prompt above, the
generated script looks roughly like this:
m.instruct() call. Subtasks that depend on earlier
outputs receive them through user_variables. The file runs as-is:
Note: Generated output varies — LLM responses depend on model and temperature.
Step 4: Refine the generated code
The generated script is a starting point. Common refinements:Add typed returns with @generative
Replace an instruct() call with a @generative function to get typed output
and IDE support:
Add requirements to a subtask
Attach plain-English requirements to enforce constraints thatm decompose left
as prose:
Step 5: Use —input-var for dynamic variables
When your prompt refers to values that change at runtime (a customer name, a product ID, a date), declare them with--input-var. Variable names must be
valid Python identifiers, uppercase, and contain only alphanumeric characters
and underscores:
CHILD_NAME and
PARTY_DATE as user_variables, ready for you to wire up at call time.
Warning:--input-varnames must be uppercase Python identifiers (e.g.CHILD_NAME, notchild-nameorchildName). The command rejects names that contain hyphens, start with a digit, or use mixed case.
Step 6: Choose the right model for decomposition
The decomposition quality depends heavily on the model. The default,mistral-small3.2:latest, handles most prompts well. For more complex prompts
with many interdependent constraints, a larger model produces clearer subtask
boundaries:
Tip: Run m decompose run --help to see the current defaults and all
available flags.
What the output JSON contains
The.json file gives you the full structured decomposition if you want to
process it programmatically:
depends_on (a list of tag values), a ready-to-use
prompt_template, and the constraints that apply to it. Each constraint carries
a validation_strategy — "code" for deterministic checks (word count, length)
and "llm" for quality checks that require LLM-as-a-judge evaluation.
Next steps
- Generative Functions — add
@generative, typed returns, and context steering to the generated pipeline - Enforce Structured Output — constrain
subtask outputs to Pydantic models or
Literalvalues