Service Catalog
This document provides a comprehensive catalog of all services in the AgentMap clean architecture, their responsibilities, interfaces, and usage examples.
Service Categories
- Core Services - Essential business logic services
- Infrastructure Services - Technical and external integration services
- Configuration Services - Configuration management services
- Storage Services - Data persistence services
- Validation Services - Data validation services
- Execution Services - Workflow execution services
Core Services
GraphBuilderService
Purpose: Builds graph models from CSV files
Dependencies:
- CSVGraphParserService
- LoggingService
Key Methods:
def build_from_csv(self, csv_path: Path, graph_name: str = None) -> Graph:
"""Build a graph model from CSV file"""
def build_from_dataframe(self, df: pd.DataFrame, graph_name: str) -> Graph:
"""Build a graph model from pandas DataFrame"""
Usage Example:
graph_builder = container.graph_builder_service()
graph = graph_builder.build_from_csv(Path("workflow.csv"))
CompilationService
Purpose: Compiles graph models into executable LangGraph StateGraphs
Dependencies:
- GraphAssemblyService
- GraphBuilderService
- GraphBundleService
- LoggingService
Key Methods:
def compile_graph(self, graph_name: str, csv_path: Path = None,
state_schema: Type = None) -> CompiledGraph:
"""Compile a graph from CSV or cache"""
def compile_from_model(self, graph: Graph, state_schema: Type = None) -> CompiledGraph:
"""Compile a graph model directly"""
Usage Example:
compilation = container.compilation_service()
compiled = compilation.compile_graph("MyWorkflow", Path("workflow.csv"))
GraphRunnerService
Purpose: Orchestrates graph execution with tracking and policies
Dependencies:
- CompilationService
- ExecutionTrackingService
- ExecutionPolicyService
- StateAdapterService
- LoggingService
Key Methods:
def run_graph(self, graph_name: str, initial_state: Dict[str, Any],
csv_path: Path = None) -> ExecutionResult:
"""Execute a graph with full tracking"""
def run_compiled_graph(self, compiled_graph: CompiledGraph,
initial_state: Dict[str, Any]) -> ExecutionResult:
"""Execute a pre-compiled graph"""
Usage Example:
runner = container.graph_runner_service()
result = runner.run_graph("MyWorkflow", {"input": "data"})
print(f"Success: {result.success}")
print(f"Duration: {result.duration}s")
AgentFactoryService
Purpose: Creates and configures agent instances with dependency injection
Dependencies:
- AgentRegistryService
- LoggingService
- LLMService (optional)
- StorageManager
- NodeRegistryService
Key Methods:
def create_agent(self, node: Node) -> BaseAgent:
"""Create an agent with all required services injected"""
def create_agent_by_type(self, agent_type: str, name: str,
context: Dict = None) -> BaseAgent:
"""Create an agent by type with services"""
Usage Example:
factory = container.agent_factory_service()
agent = factory.create_agent(node)
# Agent has all services injected based on protocols
GraphAssemblyService
Purpose: Assembles graph models into LangGraph StateGraphs
Dependencies:
- AgentFactoryService
- FunctionResolutionService
- StateAdapterService
- LoggingService
Key Methods:
def assemble_graph(self, graph: Graph, state_schema: Type = None) -> StateGraph:
"""Assemble a graph model into LangGraph"""
def assemble_with_agents(self, graph: Graph, agents: Dict[str, BaseAgent],
state_schema: Type = None) -> StateGraph:
"""Assemble with pre-created agents"""
Usage Example:
assembly = container.graph_assembly_service()
state_graph = assembly.assemble_graph(graph_model, StateSchema)
compiled = state_graph.compile()
Infrastructure Services
LoggingService
Purpose: Provides structured logging throughout the application
Dependencies: None (base infrastructure service)
Key Methods:
def get_class_logger(self, obj: Any) -> Logger:
"""Get a logger for a class instance"""
def get_agent_logger(self, agent_name: str) -> Logger:
"""Get a logger specifically for an agent"""
def set_level(self, level: str):
"""Set global logging level"""
Usage Example:
class MyService:
def __init__(self, logging_service: LoggingService):
self.logger = logging_service.get_class_logger(self)
self.logger.info("Service initialized")
StateAdapterService
Purpose: Adapts state between different formats (dict, Pydantic, etc.)
Dependencies:
- LoggingService
Key Methods:
def adapt_initial_state(self, state: Any, schema: Type = None) -> Dict[str, Any]:
"""Adapt initial state to required format"""
def extract_value(self, state: Any, key: str, default: Any = None) -> Any:
"""Extract value from state regardless of format"""
Usage Example:
adapter = container.state_adapter_service()
adapted = adapter.adapt_initial_state({"input": "data"}, StateSchema)
FunctionResolutionService
Purpose: Resolves function references for dynamic routing
Dependencies:
- LoggingService
Key Methods:
def resolve_function(self, func_ref: str) -> Optional[Callable]:
"""Resolve a function reference like 'func:my_router'"""
def register_function(self, name: str, func: Callable):
"""Register a function for resolution"""
Usage Example:
resolver = container.function_resolution_service()
router_func = resolver.resolve_function("func:custom_router")
Configuration Services
AppConfigService
Purpose: Manages application configuration with defaults
Dependencies:
- ConfigService
Key Methods:
def get_csv_path(self) -> Optional[Path]:
"""Get configured CSV path"""
def get_llm_config(self, provider: str) -> Dict[str, Any]:
"""Get LLM provider configuration"""
def get_prompts_config(self) -> Dict[str, Any]:
"""Get prompts configuration"""
Usage Example:
config = container.app_config_service()
csv_path = config.get_csv_path()
openai_config = config.get_llm_config("openai")
StorageConfigService
Purpose: Manages storage service configuration
Dependencies:
- ConfigService
Key Methods:
def get_provider_config(self, storage_type: str, provider: str) -> Dict[str, Any]:
"""Get configuration for a storage provider"""
def get_default_provider(self, storage_type: str) -> str:
"""Get default provider for storage type"""
Usage Example:
storage_config = container.storage_config_service()
csv_config = storage_config.get_provider_config("csv", "local")
Storage Services
StorageManager
Purpose: Manages and provides access to all storage services
Dependencies:
- StorageConfigService
- Various storage service implementations
Key Methods:
def get_service(self, storage_type: str, provider: str = None) -> StorageService:
"""Get a storage service by type and provider"""
def register_service(self, storage_type: str, provider: str, service: StorageService):
"""Register a custom storage service"""
Usage Example:
storage_manager = container.storage_manager()
csv_service = storage_manager.get_service("csv")
json_service = storage_manager.get_service("json", "cloud")
CSVStorageService
Purpose: Handles CSV file operations with pandas
Key Methods:
def read(self, collection: str, document_id: Any = None,
format: str = "dict", id_field: str = None) -> Any:
"""Read CSV data in various formats"""
def write(self, collection: str, data: Any, document_id: Any = None,
mode: WriteMode = WriteMode.WRITE) -> StorageResult:
"""Write data to CSV"""
Usage Example:
csv_service = storage_manager.get_service("csv")
data = csv_service.read("users", format="records")
result = csv_service.write("users", new_data)
JSONStorageService
Purpose: Handles JSON document storage
Key Methods:
def read(self, collection: str, document_id: str = None,
path: str = None) -> Any:
"""Read JSON documents or paths"""
def write(self, collection: str, data: Any, document_id: str = None,
mode: WriteMode = WriteMode.WRITE, path: str = None) -> StorageResult:
"""Write JSON documents"""
Usage Example:
json_service = storage_manager.get_service("json")
doc = json_service.read("configs", "app_config")
result = json_service.write("configs", {"debug": True}, "app_config")
Validation Services
ValidationService
Purpose: Orchestrates all validation operations
Dependencies:
- CSVValidationService
- ConfigValidationService
- ValidationCacheService
- LoggingService
Key Methods:
def validate_csv(self, csv_path: Path) -> ValidationResult:
"""Validate a CSV file"""
def validate_config(self, config_path: Path = None) -> ValidationResult:
"""Validate configuration files"""
Usage Example:
validator = container.validation_service()
result = validator.validate_csv(Path("workflow.csv"))
if not result.is_valid:
for error in result.errors:
print(f"Error: {error.message}")
Execution Services
ExecutionTrackingService
Purpose: Tracks workflow execution metrics and history
Dependencies:
- AppConfigService
- LoggingService
Key Methods:
def create_tracker(self, graph_name: str) -> ExecutionTracker:
"""Create a new execution tracker"""
def get_tracking_enabled(self) -> bool:
"""Check if tracking is enabled"""
Usage Example:
tracking = container.execution_tracking_service()
tracker = tracking.create_tracker("MyWorkflow")
tracker.start()
# ... execution ...
tracker.complete(final_state)
summary = tracker.get_summary()
ExecutionPolicyService
Purpose: Evaluates execution success based on configured policies
Dependencies:
- AppConfigService
- LoggingService
Key Methods:
def evaluate_success(self, execution_summary: ExecutionSummary,
graph_name: str = None) -> bool:
"""Evaluate if execution was successful"""
def get_policy_type(self) -> str:
"""Get configured policy type"""
Usage Example:
policy = container.execution_policy_service()
success = policy.evaluate_success(execution_summary, "MyWorkflow")
Service Registration in DI Container
All services are registered in the DI container with proper dependency injection:
class Container:
# Infrastructure services (no dependencies)
def logging_service(self) -> LoggingService:
return self._get_or_create('_logging_service', LoggingService)
# Services with dependencies
def graph_builder_service(self) -> GraphBuilderService:
return self._get_or_create('_graph_builder_service',
lambda: GraphBuilderService(
csv_parser_service=self.csv_graph_parser_service(),
logging_service=self.logging_service()
)
)
# Optional services with graceful degradation
def llm_service(self) -> Optional[LLMService]:
try:
return self._get_or_create('_llm_service',
lambda: LLMService(
config=self.app_config_service(),
logger=self.logging_service()
)
)
except Exception:
return None
Service Lifecycle
- Creation: Services are created lazily when first requested
- Caching: Services are cached in the container (singleton pattern)
- Dependency Injection: Dependencies are automatically injected
- Graceful Degradation: Optional services return None if unavailable
- Cleanup: Services can implement cleanup methods if needed
Best Practices
- Always inject dependencies - Never create services directly
- Use type hints - Clear interfaces with proper typing
- Handle None returns - Optional services may not be available
- Log appropriately - Use injected loggers for debugging
- Test with container - Use real DI container in tests
Adding New Services
To add a new service:
- Create service class with constructor injection
- Add to appropriate module (services/your_service.py)
- Register in DI container (di/containers.py)
- Add to this catalog with documentation
- Write tests following patterns
Example:
# 1. Create service
class MyNewService:
def __init__(self, dep_service: DependencyService, logging_service: LoggingService):
self.dep = dep_service
self.logger = logging_service.get_class_logger(self)
def do_something(self) -> Result:
self.logger.debug("Doing something")
return Result()
# 2. Register in container
class Container:
def my_new_service(self) -> MyNewService:
return self._get_or_create('_my_new_service',
lambda: MyNewService(
dep_service=self.dependency_service(),
logging_service=self.logging_service()
)
)
This catalog will be updated as new services are added to the system.