Your First Agent¶
Build a production-ready agent from scratch — step by step, with every line explained.
What You'll Build¶
In this tutorial, you'll create a knowledge base search agent that:
- Receives a user query via REST API
- Retrieves relevant documents from a knowledge base
- Generates a grounded response using an LLM
- Returns structured output with citations and suggestions
By the end, you'll understand the full agent lifecycle — from folder structure to Studio debugging.
graph LR
A["User Query"] --> B["retrieve_docs"]
B --> C["generate_response"]
C --> D["Structured Response<br/>(answer + citations)"]
Step 1: Create the Agent Folder¶
Use the CLI to scaffold a new agent:
This creates a complete agent package:
agents/search_bot/
├── __init__.py # ← Optional: Python package init
├── agent.py # ← REQUIRED: Contains your BaseGraphAgent subclass
├── config.py # ← Agent settings (Pydantic model)
├── schemas.py # ← Custom request/response schemas
├── tools.py # ← LangChain-compatible tools
├── api.py # ← Custom routers (override auto-generated routes)
├── prompts.json # ← Versioned prompt templates
├── langgraph.json # ← LangGraph Studio local settings
├── .env.example # ← Environment blueprint
└── README.md # ← Agent documentation
Only agent.py is required
The only mandatory file is agent.py containing your agent class. Everything else is optional — add files as your agent grows in complexity.
Step 2: Declare the Agent Class¶
Agentomatic uses a modern, ML-inspired class pattern for agents. Open agents/search_bot/agent.py:
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any
from agentomatic.agents import BaseGraphAgent
@dataclass
class SearchBotState:
"""Agent state — per-run transient data."""
request: str = ""
citations: list[dict[str, Any]] = field(default_factory=list)
output: dict[str, Any] = field(default_factory=dict)
class SearchBotAgent(BaseGraphAgent[SearchBotState]):
"""Knowledge base search assistant."""
agent_name = "search_bot"
agent_description = "Knowledge base search assistant."
agent_framework = "graph_agent"
def __init__(self, *, llm: Any = None) -> None:
super().__init__()
self.llm = llm
self.system_prompt = "You are a helpful assistant."
def build_graph(self):
"""Wire the execution graph."""
g = self.new_graph()
g.add_node("retrieve", self.retrieve)
g.add_node("generate", self.generate)
g.set_entry_point("retrieve")
g.add_edge("retrieve", "generate")
g.set_finish_point("generate")
return g.compile()
# --- Node Methods ---
def retrieve(self, state: SearchBotState) -> SearchBotState:
# Simulate retrieval
state.citations = [
{"content": f"Document about {state.request}", "source": "knowledge_base"}
]
return state
def generate(self, state: SearchBotState) -> SearchBotState:
context = "\n".join(d.get("content", "") for d in state.citations)
state.output = {
"response": f"Based on the knowledge base: Answer to '{state.request}' using context: {context}",
"agent_type": "search_bot",
"citations": state.citations,
}
return state
# --- State Conversion ---
def input_to_state(self, input_data: dict[str, Any]) -> SearchBotState:
return SearchBotState(request=input_data.get("current_query", ""))
def state_to_output(self, state: SearchBotState) -> dict[str, Any]:
return state.output
Understanding the Class Pattern¶
- State: The
@dataclassdefines what variables are tracked during execution. - Metadata:
agent_name,agent_description, andagent_frameworkare automatically extracted by Agentomatic's registry to build the API endpoints. __init__: The perfect place to inject dependencies (like database clients or LLMs).build_graph: Uses agentomatic's built-inGraphBuilderto wire your steps together into an execution graph.- Nodes: Plain Python methods (like
retrieveandgenerate) that take the state and return the updated state. - I/O Conversion:
input_to_stateandstate_to_outputmap the REST API's JSON payload to your typed state.
Agentomatic automatically discovers this class, instantiates it, and serves it over the API and Studio!
Step 3: Run and Test¶
Start your platform:
Test your agent:
Expected response:
{
"response": "Based on the knowledge base: Answer to 'What is machine learning?' using context: Document about What is machine learning?",
"agent_type": "search_bot",
"citations": [{"content": "Document about What is machine learning?", "source": "knowledge_base"}],
"thread_id": null,
"suggestions": [],
"duration_ms": 12.5
}
Step 4: Enable Studio Debugging¶
See your agent's graph topology and execution flow in the visual debugger:
Then open http://localhost:8000/studio/ in your browser. You'll see:
- Graph View — Visual representation of your
retrieve → generatepipeline - State Panel — Inspect the state at each node during execution
- History — Time-travel through past executions
SSE Streaming
Try the streaming endpoint to see real-time execution:
Step 5: Add Multi-Turn Conversations¶
Enable persistent chat by adding a storage backend:
from agentomatic import AgentPlatform
from agentomatic.storage import SQLAlchemyStore
store = SQLAlchemyStore("sqlite:///./data/agents.db")
platform = AgentPlatform.from_folder(
"agents/",
store=store,
)
app = platform.build()
Now use the /chat endpoint with a thread_id for multi-turn conversations:
# First message
curl -X POST http://localhost:8000/api/v1/search_bot/chat \
-H "Content-Type: application/json" \
-d '{"content": "What is ML?", "thread_id": "session-1"}'
# Follow-up (same thread_id — agent remembers context)
curl -X POST http://localhost:8000/api/v1/search_bot/chat \
-H "Content-Type: application/json" \
-d '{"content": "Give me more details", "thread_id": "session-1"}'
Common Mistakes¶
Pitfalls to avoid
1. Forgetting to return state from node methods
# ❌ Wrong — returns None
def retrieve(self, state):
state.citations = [...]
# ✅ Correct
def retrieve(self, state):
state.citations = [...]
return state
2. Wrong key in input_to_state
The REST API maps query → current_query in the state dict:
3. Missing response key in output
state_to_output() must return a dict with at minimum a "response" key:
4. Forgetting super().__init__() in custom __init__
What's Next?¶
Now that you have a working agent, explore these topics to build production-ready systems:
| Topic | Link | When You Need It |
|---|---|---|
| Add more nodes & conditional routing | Class-Based Agents | Complex multi-step workflows |
| Copy-paste recipes | Cookbook & Recipes | Common patterns ready to use |
| Custom request/response schemas | Input & Output Schemas | Domain-specific API contracts |
| Versioned prompts | Prompt Management | A/B testing prompt variants |
| Persistent conversations | Storage Backends | Multi-turn chat with history |
| Visual debugging | Agentomatic Studio | Graph visualization & time-travel |
| ML lifecycle | Class-Based Agents — ML Pipeline | Optimize, evaluate, and deploy |
| Deploy to production | Configuration | Auth, rate limiting, CORS |