Agent: factory
1. Behavior and Context
In the jazzmine architecture, build_agent acts as the "Assembly Line." An agent turn requires coordination between many disparate components (Enhancer, Selector, Summarizer, Orchestrator).
- Dependency Wiring: It consumes a long list of dependencies and correctly injects them into the ToolOrchestrator and the Agent core.
- Interface Adaptation: It implements a critical adapter pattern: it wraps the framework's BaseLLM into a specialized llm_caller closure. This closure ensures that the ToolOrchestrator receives the exact data it needs (text + usage + latency) in a format compatible with its telemetry requirements.
- Default Injection: It ensures that optional safety and logging features (like SecurityGuard and AgentLogger) are initialized with functional "No-Op" defaults if the user does not provide them.
2. Purpose
- Simplification: Reducing the boilerplate code needed to start a production-grade agent.
- Flexibility: Enabling the use of a specialized "Coding LLM" for writing sandbox scripts while using a "Reasoning LLM" for user interaction.
- Decoupling: Allowing the ToolOrchestrator to remain agnostic of the specific LLM provider used by the framework.
- Security by Default: Automatically applying the NOOP_GUARD if no security policy is specified, ensuring the agent logic always has a security interface to call.
3. High-Level API
The build_agent Function
This function is the main entry point for developers.
Example: Building an Agent with Dual LLMs
python
from jazzmine.core.agent import build_agent, AgentConfig
from jazzmine.core.llm import OpenAICompatibleLLM
# 1. Main reasoning model (GPT-4o)
main_llm = OpenAICompatibleLLM(model="gpt-4o", api_key="...")
# 2. Specialized coding model (DeepSeek Coder)
coder_llm = OpenAICompatibleLLM(
model="deepseek-coder",
api_key="...",
base_url="https://api.deepseek.com"
)
# 3. Use the factory to wire everything
agent = build_agent(
config=AgentConfig(name="Aria", personality="...", agent_id="v1"),
llm=main_llm,
script_gen_llm=coder_llm, # Use the coder for sandboxes
message_store=store,
wm_store=working_mem,
enhancer=enhancer,
episodic_memory=episodic,
semantic_memory=semantic,
flow_selector=selector,
summarizer=summarizer,
tool_registry=registry,
pool=sandbox_pool,
security_guard=my_guard
)5. Detailed Functionality
build_agent(...) [Function]
Parameters:
| Parameter | Type | Description |
|---|---|---|
| config | AgentConfig | Static identity and operational policy. |
| llm | BaseLLM | The primary model for reasoning and chat. |
| script_gen_llm | Optional[BaseLLM] | Model used for script writing. Defaults to llm. |
| message_store | MessageStore | Persistent database for chat/traces. |
| wm_store | WorkingMemoryStore | State manager for active conversations. |
| enhancer | MessageEnhancer | Semantic pre-processor. |
| flow_selector | FlowSelector | Two-stage skill resolver. |
| summarizer | ConversationSummarizer | Background memory maintenance. |
| tool_registry | ToolRegistry | Registry of Python functions and sandboxes. |
| pool | SandboxPool | Fleet manager for warm Docker containers. |
| security_guard | Optional[SecurityGuard] | Input/Output safety filter. |
| logger | Optional[AgentLogger] | Structured logging interface. |
The llm_caller Adapter [Internal]
Inside the factory, an asynchronous closure is created:
python
async def llm_caller(prompt: str) -> LLMCallResult: ...Functionality:
- Isolation: It targets the script_gen_llm, ensuring code-generation prompts do not interfere with the chat history of the main_llm.
- Telemetry Capture: It wraps the call in a time.monotonic() block to measure latency.
- Normalization: It converts the standard LLMResponse into an LLMCallResult, which the orchestrator uses to build the detailed AttemptRecord in the audit trail.
6. Error Handling
- Component Mismatch: Since the factory is the "Linker," errors here usually manifest as TypeError or AttributeError if a provided component does not adhere to the expected interface (e.g., providing a sync store where an async one is expected).
- Security Safety: If the security_guard parameter is None, the factory injects NOOP_GUARD. This ensures that Agent.chat() can always call self.security.check_input() without checking for None, preventing runtime crashes.
7. Remarks
- Inversion of Control: By using this factory, the Agent class does not need to know how to build a ToolOrchestrator. This allows for independent testing of the orchestration logic vs. the chat logic.
- LLM Specialization: Supply a different, cheaper, or code-specialized model (e.g., DeepSeek-Coder-V2 or Llama-3-70B-Instruct) to the script_gen_llm parameter to independently optimize cost and quality for sandbox execution without affecting the primary agent personality.