Skip to content

Scaffolding Templates

agentomatic logo

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

# Launches a guided questionnaire to pick template and configure
agentomatic init my_agent

Requires questionary

Install with pip install questionary for the interactive prompt experience.

# Specify template directly
agentomatic init my_agent --template basic

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).

agentomatic init my_agent --template basic
# or: agentomatic init my_agent --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.

agentomatic init my_agent --template full
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.

agentomatic init knowledge_bot --template rag
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.

agentomatic init assistant --template chatbot
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.

agentomatic init researcher --template deepagent
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.

agentomatic init simple --template custom
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.

agentomatic init helper --template legacy_dict
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.

agentomatic init my_classifier --template plugin
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.

agentomatic init analyzer --template basic
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