Omics-OS Docs

Plugin Contract

API contract for agent packages in the Lobster ecosystem

Plugin Contract

Reference Document: This page provides detailed reference for the plugin contract API.

For step-by-step agent creation, see Creating Agent Packages.

This document defines the formal API contract that all Lobster agent packages must follow. Following this contract ensures your agent package integrates seamlessly with the Lobster ecosystem.

Entry Point Groups

Agent packages register components via Python entry points in pyproject.toml. Lobster discovers these automatically at runtime. There are seven entry point groups organized into two categories.

Agent and Service Groups

lobster.agents

Register agent configurations (AGENT_CONFIG objects):

[project.entry-points."lobster.agents"]
my_agent = "my_package.agents.my_agent:AGENT_CONFIG"

The entry point value must resolve to an AgentRegistryConfig instance.

lobster.services

Register service classes for shared functionality:

[project.entry-points."lobster.services"]
my_service = "my_package.services.my_service:MyService"

Services should implement the ServiceProtocol (see Package Structure).

lobster.agent_configs

Register agent LLM configurations for model settings:

[project.entry-points."lobster.agent_configs"]
my_agent = "my_package.config.agent_configs:MY_AGENT_CONFIG"

Omics Plugin Groups

These groups enable the modular omics plugin architecture. They allow new omics types and data sources to be added without modifying core. See Entry Points for the full guide.

lobster.adapters

Register modality adapter factories for data loading.

lobster.providers

Register database provider classes for data access.

lobster.download_services

Register download service classes for database retrieval.

lobster.queue_preparers

Register queue preparation classes for accession mapping.

lobster.omics_types

Register OmicsTypeConfig instances for omics type metadata and detection configuration.

AgentRegistryConfig

All agents must define an AGENT_CONFIG instance using AgentRegistryConfig:

from lobster.config.agent_registry import AgentRegistryConfig

AGENT_CONFIG = AgentRegistryConfig(
    name="my_agent",
    display_name="My Agent",
    description="What this agent does",
    factory_function="my_package.agents.my_agent.my_agent",
    handoff_tool_name="handoff_to_my_agent",
    handoff_tool_description="When to delegate to this agent",
    tier_requirement="free",  # All official agents are free. Use "premium"/"enterprise" for custom packages.
    package_name="lobster-my-domain",  # PyPI package name
    service_dependencies=[],  # Required services
)

Required Fields

FieldTypeDescription
namestrUnique identifier (snake_case)
display_namestrHuman-readable name for UI
descriptionstrAgent's purpose and capabilities
factory_functionstrModule path to factory function

Optional Fields

FieldTypeDefaultDescription
handoff_tool_namestrNoneTool name for supervisor handoff
handoff_tool_descriptionstrNoneWhen to use this agent
child_agentsList[str]NoneAgents this can delegate to
supervisor_accessibleboolNoneOverride supervisor access inference
tier_requirementstr"free"Required subscription tier
package_namestrNonePyPI package providing this agent
service_dependenciesList[str]NoneRequired services

Factory Function Signature

All agent factories must follow this standardized signature:

from pathlib import Path
from typing import List, Optional

from langgraph.graph.state import CompiledGraph

from lobster.core.data_manager_v2 import DataManagerV2
from lobster.config.callback_handler import CallbackHandler


def agent_factory(
    data_manager: DataManagerV2,
    callback_handler: Optional[CallbackHandler] = None,
    agent_name: str = "default_agent_name",
    delegation_tools: Optional[List] = None,
    workspace_path: Optional[Path] = None,
    **kwargs,
) -> CompiledGraph:
    """Create agent as compiled LangGraph.

    Args:
        data_manager: DataManagerV2 instance for data operations.
        callback_handler: Optional callback for streaming responses.
        agent_name: Name for this agent instance (for logging/attribution).
        delegation_tools: List of tools for delegating to child agents.
        workspace_path: Optional workspace path override.
        **kwargs: Agent-specific parameters (subscription_tier, etc.).

    Returns:
        CompiledGraph ready for invocation.
    """
    # Implementation
    ...

Use delegation_tools, not handoff_tools. The parameter was renamed in Phase 2 for semantic clarity.

AGENT_CONFIG Placement Rule

Critical: AGENT_CONFIG must be defined at the TOP of your agent file (e.g., my_agent.py), BEFORE any heavy imports.

# my_package/agents/my_agent/my_agent.py

# =============================================================================
# AGENT_CONFIG FIRST (before heavy imports)
# =============================================================================
from lobster.config.agent_registry import AgentRegistryConfig

AGENT_CONFIG = AgentRegistryConfig(
    name="my_agent",
    display_name="My Agent",
    description="Specialized agent for domain analysis",
    factory_function="my_package.agents.my_agent.my_agent.my_agent",
    handoff_tool_name="handoff_to_my_agent",
    handoff_tool_description="Delegate domain-specific tasks",
    tier_requirement="free",
    package_name="lobster-my-domain",
    service_dependencies=[],
)

# =============================================================================
# Heavy imports AFTER (only loaded when factory is called)
# =============================================================================
from pathlib import Path
from typing import List, Optional
# ... rest of imports

def my_agent(...):
    """Factory function."""
    ...

The __init__.py file should only import and re-export:

# my_package/agents/my_agent/__init__.py
from my_package.agents.my_agent.my_agent import AGENT_CONFIG, my_agent

__all__ = ["AGENT_CONFIG", "my_agent"]

This prevents circular import issues during entry point discovery.

PEP 420 Namespace

Never create lobster/__init__.py. Agent packages must use PEP 420 implicit namespace packages to merge with the core lobster namespace.

Correct structure:

my-package/
  lobster/                    # NO __init__.py here!
    agents/                   # NO __init__.py here!
      my_domain/
        __init__.py           # Exports only (imports from my_agent.py)
        my_agent.py           # AGENT_CONFIG at top + factory
        prompts.py

This allows multiple packages to contribute to the lobster namespace without conflicts.

Version Compatibility

Declare minimum lobster-ai version in pyproject.toml:

[project]
name = "lobster-my-domain"
version = "1.0.0"
dependencies = [
    "lobster-ai~=1.0.0",  # Compatible release (allows 1.0.x patches)
]

At runtime, Lobster validates that plugins are compatible with the installed version. Incompatible plugins are skipped with a warning.

Error Handling

ComponentConflictError

Raised when a custom agent name conflicts with a core agent:

from lobster.core.component_registry import ComponentConflictError

# This error is raised automatically when:
# 1. Your agent name matches a core agent name
# 2. Two plugins define the same agent name

Prevention: Use unique, descriptive agent names prefixed with your domain.

Version Incompatibility

When version compatibility fails, the plugin is logged as a warning and skipped:

WARNING: Skipping incompatible plugin my_agent from lobster-my-domain: Requires lobster-ai>=0.5.0, found 0.4.4

Contract Validation

You can validate your package follows the contract using the contract validation test:

# From lobster directory
pytest tests/test_plugin_contract.py -v

Or implement similar tests in your own package:

import inspect
from my_package.agents.my_agent import AGENT_CONFIG, my_agent

def test_agent_config_fields():
    """Verify AGENT_CONFIG has required fields."""
    assert AGENT_CONFIG.name
    assert AGENT_CONFIG.display_name
    assert AGENT_CONFIG.description
    assert AGENT_CONFIG.factory_function

def test_factory_signature():
    """Verify factory follows standard signature."""
    sig = inspect.signature(my_agent)
    params = list(sig.parameters.keys())

    assert "data_manager" in params
    assert "delegation_tools" in params
    assert "handoff_tools" not in params  # Deprecated

Summary Checklist

Before publishing your agent package:

  • AGENT_CONFIG defined at top of agent file (e.g., my_agent.py), before heavy imports
  • __init__.py imports and re-exports AGENT_CONFIG from agent file
  • No lobster/__init__.py or lobster/agents/__init__.py (PEP 420 namespace)
  • Factory signature matches standard (use delegation_tools)
  • Entry points configured in pyproject.toml
  • Minimum lobster-ai~=1.0.0 version declared
  • Unique agent name (no conflicts with core)
  • Contract validation tests pass

On this page