Scaffolding Templates¶
Agent Scaffolding and Project Generation
Agentomatic ships with 14 templates for rapid agent creation. Each template generates a complete, runnable agent package with the right files, structure, and boilerplate for your use case.
๐ Quick Start¶
Both commands create the agent folder at agents/my_agent/ with all necessary files.
๐ Template Comparison¶
| Template | Framework | Graph | Config | Tools | Custom API | Best For |
|---|---|---|---|---|---|---|
basic |
Built-in | โ | โ | โ | โ | Quick prototyping and learning |
full |
Built-in | โ | โ | โ | โ | Production agents with all overrides |
rag |
Built-in | โ | โ | โ | โ | Knowledge bases, Q&A over documents |
chatbot |
Built-in | โ | โ | โ | โ | Conversational agents with memory |
deepagent |
LangGraph | โยน | โ | โ | โ | Autonomous planning with sub-agents |
custom |
Custom | โ | โ | โ | โ | Framework-agnostic, minimal deps |
legacy_dict |
LangGraph | โ | โ | โ | โ | Legacy functional agent (3 files) |
plugin |
N/A | โ | โ | โ | โ | ML Model Plugins with REST endpoints |
ยน Deep agent uses agent.py with create_deep_agent() instead of build_graph()
All class-based templates use AgentGraph
Templates basic, full, rag, and chatbot generate BaseGraphAgent subclasses that use agentomatic's built-in AgentGraph runtime โ no LangGraph dependency required.
๐ Generated Files by Template¶
basic โ Minimal Agent¶
The simplest starting point โ a class-owned BaseGraphAgent (also
available as --template class).
agents/my_agent/
โโโ __init__.py # AgentManifest card
โโโ agent.py # BaseGraphAgent subclass
โโโ llm.py # Stack-aware LLM helpers
โโโ prompts.json # v1/v2 prompt templates
โโโ langgraph.json # LangGraph Studio config
โโโ .env.example # Environment variable template
โโโ README.md # Agent documentation
Class-agent layout
basic / class emit agent.py + llm.py โ not the legacy
graph.py / nodes.py layout (use --template legacy_dict for that).
full โ All Override Files¶
Includes every possible override file. Ideal for production agents that need full control.
agents/my_agent/
โโโ __init__.py # AgentManifest card
โโโ agent.py # BaseGraphAgent subclass (+ get_graph export)
โโโ llm.py # Stack-aware LLM helpers
โโโ config.py # Pydantic config (MyAgentConfig)
โโโ schemas.py # Custom request/response models
โโโ tools.py # Tool definitions
โโโ api.py # Optional custom FastAPI router
โโโ dataset.jsonl # Sample train/eval data
โโโ train.py / eval.py / optimize.py / predict.py
โโโ search_space.yaml # PromptFitter search space
โโโ Makefile
โโโ prompts.json
โโโ langgraph.json # Points at ./agent.py:get_graph
โโโ .env.example
โโโ README.md
Generated config.py
"""Configuration for My Agent agent."""
from pydantic import BaseModel, Field
class MyAgentConfig(BaseModel):
"""Agent-specific configuration."""
prompt_version: str = Field("v1", description="Active prompt version")
temperature: float = Field(0.1, ge=0.0, le=2.0)
max_tokens: int = Field(2048, ge=1)
enable_memory: bool = Field(True, description="Enable conversation memory")
Generated schemas.py
"""Custom schemas for my_agent."""
from pydantic import BaseModel, Field
class MyAgentRequest(BaseModel):
"""Custom request model."""
query: str = Field(..., description="User query")
context: dict = Field(default_factory=dict)
class MyAgentResponse(BaseModel):
"""Custom response model."""
answer: str
confidence: float = Field(0.0, ge=0.0, le=1.0)
sources: list[str] = Field(default_factory=list)
Generated api.py
"""Custom API router for my_agent.
If this file exports a `router`, it REPLACES the auto-generated endpoints.
Remove this file to use auto-generated endpoints instead.
"""
from fastapi import APIRouter
router = APIRouter()
@router.get("/status")
async def status() -> dict:
"""Custom status endpoint."""
return {"agent": "my_agent", "custom_router": True}
Custom Router Override
When api.py is present and exports a router, all 12 auto-generated endpoints are dropped. Remove api.py to restore the default REST API.
rag โ Retrieval-Augmented Generation¶
A two-stage pipeline (retrieve โ generate) pre-configured for knowledge-base Q&A.
agents/knowledge_bot/
โโโ __init__.py # AgentManifest with RAG keywords
โโโ agent.py # BaseGraphAgent: retrieve โ generate
โโโ llm.py # Stack-aware LLM helpers
โโโ config.py # Pydantic config
โโโ tools.py # Search tool stubs
โโโ prompts.json
โโโ langgraph.json # ./agent.py:get_graph
โโโ .env.example
โโโ README.md
Class-agent RAG
The rag template is a BaseGraphAgent with retrieve + generate
nodes โ not the legacy graph.py / nodes.py layout.
chatbot โ Conversational Agent¶
Optimized for multi-turn conversations with memory support.
agents/assistant/
โโโ __init__.py # AgentManifest with chat keywords
โโโ agent.py # BaseGraphAgent conversational agent
โโโ llm.py # Stack-aware LLM helpers
โโโ config.py # Pydantic config
โโโ prompts.json
โโโ langgraph.json # ./agent.py:get_graph
โโโ .env.example
โโโ README.md
Class-agent chatbot
The chatbot template is a BaseGraphAgent subclass with prompt-backed
conversation, not the legacy graph.py / nodes.py layout.
deepagent โ Deep Agent with Planning¶
Uses the deepagents package for autonomous planning, tool usage, and sub-agent delegation.
agents/researcher/
โโโ __init__.py # Manifest + graph_fn + node_fn
โโโ agent.py # Deep agent definition with tools
โโโ config.py # Pydantic config
โโโ prompts.json # v1/v2 prompt templates
โโโ .env.example # Environment variable template
โโโ README.md # Agent documentation
Generated agent.py
"""Deep Agent definition for researcher.
Uses LangChain's `deepagents` harness for planning, tools,
subagent delegation, and context management.
"""
from functools import lru_cache
def internet_search(query: str, max_results: int = 5) -> str:
"""Search the internet for information."""
# TODO: Replace with real search (Tavily, SerpAPI, etc.)
return f"Search results for: {query} ({max_results} results)"
@lru_cache(maxsize=1)
def create_agent():
"""Create and compile the deep agent."""
from deepagents import create_deep_agent
return create_deep_agent(
model="openai:gpt-4o",
system_prompt=(
"You are Researcher, "
"an expert AI assistant. Be thorough and accurate."
),
tools=[internet_search],
)
Dependency
The deepagent template requires the deepagents package: pip install deepagents
custom โ Framework-Agnostic¶
The most minimal template. Pure Python with no LangGraph dependency โ ideal for simple API wrappers or custom frameworks.
agents/simple/
โโโ __init__.py # Manifest + node_fn (framework="custom")
โโโ prompts.json # v1/v2 prompt templates
โโโ .env.example # Environment variable template
โโโ README.md # Agent documentation
Generated custom __init__.py
"""Agent: simple (framework-agnostic)."""
from __future__ import annotations
from typing import Any
from agentomatic import AgentManifest
manifest = AgentManifest(
name="simple",
slug="agent-simple",
description="Simple agent",
intent_keywords=["simple"],
framework="custom",
)
async def node_fn(state: dict[str, Any]) -> dict[str, Any]:
"""Process the request directly โ no graph framework needed."""
query = state.get("current_query", "")
return {
"response": f"Hello from simple! You asked: {query}",
"agent_type": "agent-simple",
}
legacy_dict โ Legacy Functional Agent¶
The classic agentomatic pattern using __init__.py with manifest + node_fn. Ideal for quick utilities or migrating existing LangGraph code.
agents/helper/
โโโ __init__.py # Manifest + node_fn entrypoint
โโโ .env.example # Environment config
โโโ README.md # Agent documentation
Generated __init__.py
"""Agent: helper (legacy functional pattern)."""
from __future__ import annotations
from typing import Any
from agentomatic import AgentManifest
manifest = AgentManifest(
name="helper",
slug="agent-helper",
description="Helper agent",
intent_keywords=["helper", "assist"],
framework="custom",
)
async def node_fn(state: dict[str, Any]) -> dict[str, Any]:
"""Process the user's request and return a response."""
query = state.get("current_query", "")
return {
"response": f"Processed: {query}",
"agent_type": "helper",
"suggestions": [],
}
When to use legacy_dict
Use this template when you want the simplest possible agent โ a single async function with no graph, no class, no state management. Perfect for wrappers around external APIs.
plugin โ ML Model Plugin¶
Wrap a classical ML model (scikit-learn, XGBoost, etc.) as a REST endpoint using BaseMLPlugin.
agents/my_classifier/
โโโ agent.py # BaseMLPlugin subclass
โโโ .env.example # Environment config
โโโ README.md # Plugin documentation
Generated agent.py
"""ML Plugin: my_classifier."""
from __future__ import annotations
from typing import Any
from pydantic import BaseModel, Field
from agentomatic.plugins import BaseMLPlugin
class PredictInput(BaseModel):
features: list[float] = Field(..., description="Input feature vector")
class PredictOutput(BaseModel):
prediction: float = Field(..., description="Model prediction")
confidence: float = Field(0.0, description="Prediction confidence")
class MyClassifierPlugin(BaseMLPlugin[PredictInput, PredictOutput]):
plugin_name = "my_classifier"
plugin_description = "Classification model plugin"
plugin_version = "1.0.0"
def load_model(self) -> Any:
"""Load and return the trained model."""
# Example: return joblib.load("model.pkl")
return None
def predict(self, model: Any, input_data: PredictInput) -> PredictOutput:
"""Run prediction on the loaded model."""
return PredictOutput(
prediction=0.0,
confidence=0.95,
)
ML Plugin Features
Plugins get automatic REST endpoints (/predict, /health, /model-card) and can be deployed alongside agents in the same platform. See ML Plugins for the full guide.
This is the basic template pattern
The code below shows the class-based agent structure generated by agentomatic init analyzer --template basic. All class-based templates (basic, full, rag, chatbot) generate this pattern.
agents/analyzer/
โโโ __init__.py # AgentManifest + node_fn for auto-discovery
โโโ agent.py # BaseGraphAgent subclass with build_graph()
โโโ llm.py # LLM configuration
โโโ prompts.json # Prompt templates
โโโ dataset.jsonl # Sample training/test dataset
โโโ train.py # ML-like training script
โโโ .env.example # Environment config
โโโ README.md # Agent documentation
Generated agent.py
"""Class-based agent: analyzer."""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any
from agentomatic.agents import BaseGraphAgent
@dataclass
class AnalyzerState:
"""Agent state โ per-run transient data."""
request: str = ""
context: list[str] = field(default_factory=list)
output: dict[str, Any] = field(default_factory=dict)
class AnalyzerAgent(BaseGraphAgent[AnalyzerState]):
"""ML-like class agent for analyzer.
Usage::
agent = AnalyzerAgent(llm=my_llm)
result = agent.transform({"request": "Hello"})
"""
agent_name = "analyzer"
agent_description = "Analyzer agent"
def __init__(self, *, llm: Any = None) -> None:
super().__init__()
self.llm = llm
self.system_prompt = "You are a helpful assistant."
# --- Graph Definition ---
def build_graph(self):
"""Wire the execution graph."""
g = self.new_graph()
g.add_node("process", self.process)
g.add_node("generate", self.generate)
g.set_entry_point("process")
g.add_edge("process", "generate")
g.set_finish_point("generate")
return g.compile()
# --- Node Methods ---
def process(self, state: AnalyzerState) -> AnalyzerState:
"""Process the input request."""
state.context = [f"Processed: {state.request}"]
return state
def generate(
self, state: AnalyzerState,
) -> AnalyzerState:
"""Generate the final output."""
state.output = {
"response": f"Result for: {state.request}",
"agent_type": "analyzer",
}
return state
# --- State Conversion ---
def input_to_state(
self, input_data: dict[str, Any],
) -> AnalyzerState:
return AnalyzerState(
request=input_data.get("request", ""),
)
def state_to_output(
self, state: AnalyzerState,
) -> dict[str, Any]:
return state.output
Generated dataset.jsonl
{"id": "analyzer_001", "split": "train", "input": {"request": "Help me with task planning"}, "expected_output": {"response": "Here is a plan..."}, "metadata": {"domain": "general", "difficulty": "easy"}}
{"id": "analyzer_002", "split": "train", "input": {"request": "Summarize this document"}, "expected_output": {"response": "Summary: ..."}, "metadata": {"domain": "general", "difficulty": "medium"}}
{"id": "analyzer_003", "split": "test", "input": {"request": "Analyze the risks"}, "expected_output": {"response": "Risks identified: ..."}, "metadata": {"domain": "general", "difficulty": "hard"}}
Generated train.py (flat TrainCliSettings + staged comment)
Scaffolded class agents use a flat script: settings โ agent โ
train_and_report (full abstraction). The same file
includes a commented staged Keras-like example
(load_data โ build_default_metrics โ compile_agent โ fit_agent โ
evaluate_agent) for full control โ both tiers share the same primitives.
from agentomatic.optimize import TrainCliSettings, print_train_result, train_and_report
from agents.analyzer.agent import AnalyzerAgent
cli = TrainCliSettings.parse() # AGENTOMATIC_* env + --help CLI flags
result = train_and_report(
agent,
config=cli.to_train_config(
agent_name="analyzer",
agent_dir=HERE,
stacks_dir=ROOT / "stacks",
env_path=ROOT / ".env",
required_keys=["response"],
judge_dimensions=["relevance", "accuracy", "structure"],
),
)
print_train_result(result)
Matching eval.py uses EvalCliSettings โ evaluate_and_report โ
print_eval_result. See Prompt Optimization for both
tiers and the full knob table.
No LangGraph Required
Class agents use the built-in AgentGraph runtime. Wire your graph in build_graph() using new_graph() โ no need for langgraph or StateGraph.
๐ค Which Template Should I Use?¶
flowchart TD
A["What are you building?"] --> B["Simple API wrapper<br/>or utility?"]
A --> C["Multi-step pipeline?"]
A --> D["Conversational<br/>chatbot?"]
A --> E["Knowledge base<br/>Q&A?"]
A --> F["Autonomous<br/>researcher?"]
A --> G2["Wrap an ML model?"]
A --> H2["Legacy LangGraph<br/>code?"]
B -->|Yes| G["custom"]
C -->|Simple pipeline| H["basic"]
C -->|Need all overrides| I["full"]
D -->|Yes| J["chatbot"]
E -->|Yes| K["rag"]
F -->|Yes| L["deepagent"]
G2 -->|Yes| N["plugin"]
H2 -->|Yes| O["legacy_dict"]
style G fill:#f3e5f5
style H fill:#e8f5e9
style I fill:#e3f2fd
style J fill:#fff3e0
style K fill:#fce4ec
style L fill:#e0f2f1
style N fill:#fbe9e7
style O fill:#f1f8e9
| If you need... | Use template |
|---|---|
| Quick prototype, minimum files | basic |
| Full control over API, schemas, tools | full |
| Document retrieval + answer generation | rag |
| Multi-turn conversation with memory | chatbot |
| Autonomous planning with tools | deepagent |
| No framework dependency, pure Python | custom |
| Legacy functional agent (dict-based) | legacy_dict |
| Wrap a classical ML model | plugin |
๐ Common Files¶
All templates (except custom and deepagent) include these common files:
| File | Purpose |
|---|---|
prompts.json |
Two prompt versions (v1 concise, v2 detailed) with system and user templates |
langgraph.json |
LangGraph Studio config (./agent.py:get_graph for class agents, ./graph.py:get_graph for legacy) |
.env.example |
Template for agent-specific env vars (LLM settings, feature flags) |
README.md |
Auto-generated documentation with quick start commands and file reference |
Common prompts.json Content¶
{
"v1": {
"system": "You are a helpful AI assistant. Be concise and accurate.",
"user_template": "{query}"
},
"v2": {
"system": "You are an advanced AI assistant. Provide detailed, well-structured responses with examples when helpful.",
"user_template": "Please help with the following: {query}"
}
}
Common .env.example Content¶
# my_agent agent configuration
# Copy to .env and fill in values
# LLM Settings
MY_AGENT_LLM_PROVIDER=ollama
MY_AGENT_LLM_MODEL=mistral:7b
MY_AGENT_TEMPERATURE=0.1
MY_AGENT_MAX_TOKENS=2048
# Feature Flags
MY_AGENT_ENABLE_MEMORY=true
MY_AGENT_ENABLE_STREAMING=true
๐งช After Scaffolding¶
Once your agent is generated, start the platform and test:
# Start the platform
agentomatic run
# Test your agent
curl -X POST http://localhost:8000/api/v1/my_agent/invoke \
-H "Content-Type: application/json" \
-d '{"query": "Hello, world!"}'
# Check health
curl http://localhost:8000/api/v1/my_agent/health
# View in Swagger docs
open http://localhost:8000/docs