Advanced: This page is for developers who need to go beyond the standardThe@generative,instruct(), andm.chat()API. If you are getting started with Mellea, see the Quick Start first.
Component Protocol is the fundamental unit of composition in Mellea. Every
high-level API call — m.instruct(), @generative, m.chat() — is backed by a
Component that formats its input for the LLM and parses the output into a typed
result. This page shows you how to implement the protocol yourself.
When to build a custom component
Use the standard API in most cases. Build a customComponent when:
- You need a domain-specific prompt structure that cannot be expressed as a
@generativedocstring or aninstruct()template. - You need deterministic, reusable parsing logic across many call sites — not ad-hoc post-processing.
- You want to unit-test prompt formatting and output parsing in isolation, without a real backend.
- You are building a reusable library component that other developers will import.
- You need to feed a
ModelOutputThunkfrom one LLM call directly into the formatted input of another (lazy composition).
@generative or instruct() covers your use case with
less boilerplate.
The Component Protocol
Component is a Protocol generic over S, the return type produced when the
component parses LLM output:
_parse:
| Method | Signature | Purpose |
|---|---|---|
parts() | -> list[Component | CBlock] | Returns child components and CBlock content blocks |
format_for_llm() | -> TemplateRepresentation | str | Formats the component for LLM consumption |
_parse() | (computed: ModelOutputThunk) -> S | Parses LLM output into the return type S |
parse() | (computed: ModelOutputThunk) -> S | Public wrapper — catches exceptions as ComponentParseError |
parts(), format_for_llm(), and _parse(). You do not override
parse() — the base implementation calls _parse() and wraps any exception in a
ComponentParseError so callers always get a consistent error type.
Type parameter
Component[S] is parameterised by S: the Python type your _parse method
returns. For example, Component[str] returns a plain string, while
Component[list[str]] returns a list. The type parameter is enforced at static
analysis time by mypy.
Minimal example: FeedbackForm
The following component formats a structured feedback request and parses the model’s response into a Python dictionary.m.act() to get a result:
MelleaSession.act() — the session method is a thin wrapper
around the same functional API:
Using TemplateRepresentation for Jinja2-based rendering
For components that need model-specific prompt formatting, return aTemplateRepresentation from format_for_llm() instead of a plain string.
TemplateRepresentation is a dataclass with these fields:
| Field | Type | Purpose |
|---|---|---|
obj | Any | The component instance (typically self) |
args | dict | Variables passed to the Jinja2 template |
tools | dict | None | Tool definitions available in the template |
template | str | None | Inline Jinja2 template string |
template_order | list[str] | None | Template file names to look up; "*" means the class name |
images | list | None | Image blocks to include |
templates/prompts/ directory,
traversing subdirectories that match the model ID before falling back to
default/. See Mellea Core Internals for
the full lookup order.
mellea/templates/prompts/default/FeedbackFormTemplate.jinja2:
template= for one-off components where a separate file is
unnecessary:
Registering with act()
You do not need to register or annotate a custom component. Pass it directly tom.act() or mfuncs.act():
mfuncs.aact():
Testing custom components
BecauseComponent is a Protocol, you can test formatting and parsing without a
real backend. Create a ModelOutputThunk with a known value to exercise _parse
directly.
Note:ModelOutputThunkaccepts avaluekeyword argument in tests. Check the current constructor signature inmellea/core/base.pyif the import path changes in a future release. Tip: Keep_parsepure — no I/O, no side effects. This makes it trivial to unit test and means failures are always the model’s fault, not your parsing code.
Next steps
- Mellea Core Internals — understand
CBlock,ModelOutputThunk, and the full abstraction stack that custom components plug into. - Write Custom Verifiers — combine custom components with requirement validation to build structured output pipelines with automatic retry.