Lazy Agent Instantiation¶
Plugins should be "safe to load" regardless of the user's environment. You should defer the instantiation of heavy objects—especially LLM agents that require API keys—until they are actually needed.
If you instantiate an agent in the tool's __init__, it might fail if the user hasn't configured an API key or model for that tool. This prevents the entire toolkit from starting or listing other tools.
Pattern: Private Property Instantiation¶
Instantiate your agents lazily inside the execute method or via a private property.
from aifred_tk.core.llm import build_agent_from_settings, AgentRunner
class MyTool(Tool):
def __init__(self, settings: Dynaconf):
self._settings = settings
self._agent: AgentRunner[MyResultModel] | None = None
def _get_agent(self) -> AgentRunner[MyResultModel]:
if self._agent is None:
# This will fail if no LLM is configured for this tool,
# but only when the tool is actually RUN.
self._agent = build_agent_from_settings(
self.tool_id,
self._settings,
output_type=MyResultModel,
system_prompt=MY_SYSTEM_PROMPT
)
return self._agent
def execute(self, args: ToolArgs) -> ToolResult:
# Agent is built only when the tool is executed
agent = self._get_agent()
# ...
This ensures that aifred-tk can still start and list all available tools even if one plugin is misconfigured.