This document provides guidelines for AI coding agents working on the Plugboard project. Following these instructions ensures contributions are consistent with the project's architecture, conventions, and style.
Plugboard is an event-driven framework in Python for simulating and orchestrating complex processes with interconnected stateful components. Typical users are data scientists and engineers.
Component: The fundamental building block for modeling logic (see plugboard/component/).
- Lifecycle:
__init__→init→step(repeated) →destroy. - I/O declaration: Use class-level
io: IOControllerattribute. Use this to specify inputs, outputs and events associated with a component. - Business logic: Implement in the
stepmethod. - Asynchronous: All lifecycle methods (
init,step,destroy) must beasync.
Process: Orchestrates execution of components (see plugboard/process/)
- Manages collections of components and their interconnections.
LocalProcess: Runs all components in a single process.- Supports distributed execution via other process types, e.g.
RayProcess.
Connector: Defines communication channels between components (see plugboard/connector/).
- Links outputs to inputs:
component_name.output_name→component_name.input_name. - Various connector types available for different execution contexts.
State Management: Tracks component and process status (see plugboard/state/).
- Critical for monitoring and distributed execution.
- Uses
StateBackendabstraction.
Configuration: Flexible process definition.
- Python-based: Direct component instantiation.
- YAML-based: Declarative configuration for CLI execution (
plugboard process run ...). - Relies on the Pydantic objects defined in
plugboard-schemas.
- Package Manager: Uses
uvfor dependency management. - Dependencies: Defined in
pyproject.toml. - Python Version: Requires Python 3.12 or higher.
- You can delegate to the
testagent in.github/agentsto update/add tests. - Framework:
pytest - Location:
tests/directory - Commands:
uv run pytest tests/path/to/teststo run a specific test file or folder.make test- Run all tests.make test-integration- Run integration tests.
- Best Practice: Always include tests with new features.
- You can delegate to the
lintagent in.github/agentsto resolve linting issues. - Tools:
ruff- Formatting and linting.mypy- Static type checking.
- Commands:
make lint- Check for issues.make format- Auto-format code.
- Requirement: All code must be fully type-annotated.
- Framework: Built with
typer. - Location:
plugboard/cli/. - Usage:
plugboard --help.
- Entire framework built on
asyncio. - All I/O operations must be async.
- All component lifecycle methods must be async.
- Uses
that-dependsfor DI. - Container setup:
plugboard/utils/DI.py. - Access logger:
self._logger = DI.logger.resolve_sync().bind(...).
- Prefer immutable structures:
msgspec.Struct(frozen=True). - Use Pydantic models for validation where needed.
When creating components:
- Inherit from
plugboard.component.Component. - Always call
super().__init__()in__init__. - Declare I/O via class-level
ioattribute. - Implement required async methods.
- Use type hints throughout.
Example:
import typing as _t
from plugboard.component import Component, IOController as IO
from plugboard.schemas import ComponentArgsDict
class MyComponent(Component):
io = IO(inputs=["input_a"], outputs=["output_x"])
def __init__(
self,
param: float = 1.0,
**kwargs: _t.Unpack[ComponentArgsDict]
) -> None:
super().__init__(**kwargs)
self._param = param
async def step(self) -> None:
# Business logic here
self.output_x = self.input_a * self._param- Event system for component communication.
- Define events by inheriting from
plugboard.events.Event. - Add handlers with
@Event.handlerdecorator. - Emit events via
self.io.queue_event()or return from handlers.
- Minimal Changes: Make surgical, focused changes.
- Type Safety: Maintain full type annotations.
- Testing: Add tests for new functionality.
- Documentation: Update docstrings and docs for public APIs. You can delegate to the
docsagent in.github/agentsto maintain the project documentation. - Async Discipline: Never use blocking I/O operations.
- Immutability: Prefer immutable data structures.
- Logging: Use structured logging via
structlog. - Error Handling: Use appropriate exception types from
plugboard.exceptions.
- Create class inheriting from
Component. - Define
iowith inputs/outputs. - Implement
__init__with proper signature. - Implement async
stepmethod. - Add tests in
tests/. - Update documentation if public API.
- Understand impact on existing components.
- Ensure backward compatibility where possible.
- Update type stubs if needed.
- Run full test suite.
- Update relevant documentation.
- Define event class with data model.
- Declare in component's
io(input_events/output_events). - Implement handlers with decorators.
- Use
EventConnectorBuilderfor wiring.
- Repository: https://github.com/plugboard-dev/plugboard
- Documentation: https://docs.plugboard.dev
- Issue Tracker: GitHub Issues
- Discussions: GitHub Discussions