Component
What's a Component?
A Component is the basic executable unit in GLLM Core. It wraps a piece of async business logic and standardizes how that logic is:
Discovered via a single async entrypoint (
@mainor fallbacks).Executed through a uniform
run(**kwargs)method.Observed via structured input/output events.
Analyzed so pipelines and orchestrators can understand its input contract.
At a high level:
You implement a subclass of
Component.You mark one async method with
@mainto declare the entrypoint.Pipelines never call your method directly. They call
component.run(**kwargs).Input schemas can be generated from the
@mainsignature, enabling validation and argument construction.
This gives GLLM Core a uniform abstraction over heterogeneous logic: pipelines don't need to know whether a component is talking to an LLM, a database, an API, or anything else.
Installation
Quickstart
Define Your First Component
Key points:
Subclass
Component.Define a single async method (here
format).Mark it with
@mainto tell the system: "this is the entrypoint".
Execute the Component Uniformly
You never call await formatter.format(...) from orchestration code. Instead, you always call await formatter.run(**kwargs):
The Component base class emits start/finish events.
Logging is performed via the component's
_logger.Pipelines can treat every component the same way.
Use the Generated Input Schema
The design for Components includes an input_params property that exposes a Pydantic model mirroring the @main signature:
This gives you:
Type-checked construction of arguments.
Easy validation and error reporting.
A single source of truth: the
@mainsignature.
The @main Decorator
@main DecoratorThe @main decorator marks one async method on a Component subclass as the canonical entrypoint. Architecturally, it enables:
Entry-point abstraction: pipelines don't need to know method names.
Schema generation: the
@mainsignature drivesinput_params.Future interoperability: the same entrypoint can later be wrapped as an MCP-compliant
Tool.
From the docs and specs:
Component.get_main()resolves the entrypoint by honoring@main,__main_method__, or falling back to_run.Component.input_paramsgenerates a Pydantic model from the resolved main method.Component.run(**kwargs)executes the resolved main coroutine and emits events.
@main Method Resolution
@main Method ResolutionThe entrypoint resolution is conceptually:
Prefer an explicitly decorated
@mainmethod on the subclass.If none is decorated, look for a class-level
__main_method__override.As a compatibility fallback, use
_run.
This resolution is cached (via a resolver such as MainMethodResolver) so the cost of introspection is paid once per class.
Using @main with Abstract Classes
@main with Abstract ClassesThe @main decorator works seamlessly with abstract base classes, allowing you to define a common entrypoint signature that subclasses can implement. This is particularly useful when building component hierarchies with shared interfaces.
Example: Abstract Base Component
Key behaviors:
The
@maindecorator is inherited: BothUpperCaseProcessorandLowerCaseProcessorinherit the@mainmarking fromBaseProcessor.process.Subclasses implement the abstract method: Each subclass provides its own implementation of
process.Uniform execution: All subclasses can be executed via
run(**kwargs):
Shared input schema: Both subclasses generate the same
input_paramsmodel based on the abstract signature:
Example: Overriding @main in Subclasses
@main in SubclassesIf a subclass needs a different entrypoint, it can define its own @main method:
Important notes:
Most derived
@mainwins: When a subclass defines its own@mainmethod, it takes precedence over inherited@mainmethods.Abstract methods must still be implemented: Even if you override
@main, you must implement all abstract methods from the parent class.Schema generation uses the resolved main: The
input_paramsproperty always reflects the signature of the resolved@mainmethod, not the abstract one.
Component Lifecycle and Runtime Behavior
The Component base class provides a logger and a standard event flow:
run(**kwargs)Formats an input event with the component name and arguments.
Logs it via
_logger.Optionally emits it through an
EventEmitterif one is passed inkwargs.
Calls the resolved main coroutine (or
_runin the current implementation).Formats and logs an output event containing the result.
Binary payloads (e.g., bytes) are handled via binary_handler_factory so logs show sizes or summaries instead of raw bytes.
Designing Good Component APIs
Prefer Clear, Typed Parameters
When defining your @main method:
Use explicit type hints for all parameters.
Provide sensible defaults where appropriate.
Reserve
**kwargsfor truly open-ended options.
Example:
With the planned input_params behavior, this will:
Generate a
DataProcessorParamsmodel.Enforce types for
dataandlimit.Allow extra fields (because of
**options) viaextra="allow".
When to Use **kwargs
**kwargsUse **kwargs when:
You truly don't know all the options ahead of time.
You want to forward arbitrary parameters to downstream systems.
Avoid it when:
You can name and type your parameters precisely.
You want strict validation and clear API docs.
Backwards Compatibility with Legacy _run Components
_run ComponentsIf you have existing components that only implement _run, they continue to work:
See Migrating from the old Component for a guide to move from the old _run-style Components to the newer one.
Last updated