Create a Plugin
Create a Plugin
Goal: Build a custom plugin for document processing
This guide provides an overview of plugin development. For detailed guides, see the plugin-type-specific pages below.
Install the SDK
pip install bizsupply-sdkThe bizsupply-sdk package provides all base classes, models, and CLI tools for plugin development.
Plugin Types
| Type | Purpose | Guide |
|---|---|---|
| Classification | Categorize documents with labels | Create a Classification Plugin |
| Extraction | Extract structured data from documents | Create an Extraction Plugin |
| Source | Ingest documents from external systems | Create a Source Plugin |
| Benchmark | Score documents and compare metrics | Create a Benchmark |
| Aggregation | Create relationships between documents | Contact support |
CRITICAL: Plugin Requirements
All plugins MUST follow these requirements or they will fail:
| Requirement | Details | If Violated |
|---|---|---|
| Install SDK | pip install bizsupply-sdk | Import errors |
| Import base class | from bizsupply_sdk import ClassificationPlugin | NameError |
| Inherit base class | class MyPlugin(ClassificationPlugin): | Registration fails |
| Type-specific method | classify(), extract(), or fetch() | Runtime error |
| Async method | async def classify(...) | Runtime error |
| Correct return type | str | None, ExtractionResult, or AsyncIterator[DocumentInput] | Job fails |
| Await async calls | await self.prompt_llm(...) | Timeout/hang |
Quick Start
1. Choose Your Plugin Type
- Need to categorize documents? -> Classification Plugin
- Need to extract data fields? -> Extraction Plugin
- Need to pull from external sources? -> Source Plugin
2. Scaffold with the CLI
Use bizsupply init to generate a starting template:
bizsupply init classification --name my_classifier
bizsupply init extraction --name my_extractor
bizsupply init source --name my_source
bizsupply init benchmark --name my_benchmarkOr copy the template from the dedicated plugin guides.
3. Validate Your Plugin
bizsupply validate my_plugin.py4. Register via API
curl -X POST "https://api.bizsupply.com/api/v1/plugins" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My Plugin",
"description": "What this plugin does",
"code": "... your plugin code as string ..."
}'Or using form data:
curl -X POST "https://api.bizsupply.com/api/v1/plugins" \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "name=My Plugin" \
-F "description=What this plugin does" \
-F "code_file=@your_plugin.py"Plugin Structure
Every plugin follows this basic structure:
from bizsupply_sdk import ClassificationPlugin
class MyPlugin(ClassificationPlugin):
"""Your plugin description."""
# Optional: Define configurable parameters
configurable_parameters = [
{
"parameter_name": "my_param",
"parameter_type": "str",
"default_value": "default",
"description": "What this parameter does",
},
]
async def classify(
self,
document,
file_data,
mime_type,
available_labels,
current_path,
configs,
):
"""Classify at a single hierarchy level."""
result = await self.prompt_llm(
prompt=f"Select from: {available_labels}",
file_data=file_data,
mime_type=mime_type,
)
return result.get("category") if result else NoneKey Points:
- Plugin type is determined by the base class you inherit from
- All configuration is defined as class attributes (no separate manifest file)
- Each plugin type has its own method:
classify(),extract(), orfetch() - The Engine handles persistence, document fetching, and ontology traversal
Common Mistakes
No Base Class or Missing Import
# WRONG - no import, no base class
class MyPlugin:
async def classify(self, ...):
pass
# CORRECT
from bizsupply_sdk import ClassificationPlugin
class MyPlugin(ClassificationPlugin):
async def classify(self, document, file_data, mime_type, available_labels, current_path, configs):
...Using Old execute() Method
# WRONG - execute() is the old v1.0 API
async def execute(self, context: PluginContext):
...
# CORRECT - use type-specific method
async def classify(self, document, file_data, mime_type, available_labels, current_path, configs):
...Missing Async/Await
# WRONG
result = self.prompt_llm(prompt="...") # Returns coroutine!
# CORRECT
result = await self.prompt_llm(prompt="...")Reference Documentation
- Plugin Interface Specification - Complete contract
- Plugin Service API - Available service methods
Next Steps
Choose your plugin type and follow the dedicated guide:
- Classification Plugin - Categorize documents
- Extraction Plugin - Extract structured data
- Source Plugin - Ingest from external sources
- Benchmark - Score documents and compare metrics
After creating your plugin:
- Use Plugins - Execute in a pipeline
- Create an Ontology - Define extraction schemas
- Create a Prompt - LLM instruction templates
Updated 2 months ago