Skip to content

Concepts & Glossary

Build a mental model of Agentomatic before writing your first line of code. This page covers every core abstraction, shows how a request flows end-to-end, and helps you choose the right pattern for your agent.


🧩 Core Concepts

Every Agentomatic application is built from a handful of composable primitives. Learn these once and everything else clicks into place.

Agent

A self-contained unit of AI logic that processes requests and returns responses. An agent can be as simple as a single function or as complex as a multi-step execution graph with branching, loops, and tool calls.

from agentomatic.agents import BaseGraphAgent

class MyAgent(BaseGraphAgent[MyState]):
    """A class-based agent β€” all logic in one file."""
    ...

Think of it as…

A micro-service with exactly one job. It receives input, does smart work (often involving an LLM), and returns structured output.


Node

A single processing step within an agent's execution graph. Each node receives the current state, performs work (LLM call, tool use, data transform), and returns the updated state.

def retrieve_docs(self, state: MyState) -> dict:
    """Node: fetch relevant documents from the knowledge base."""
    state.documents = self.retriever.search(state.query)
    return {"documents": state.documents}

Nodes are the atoms of your agent β€” keep them small and focused.


State

The data structure passed between nodes during a single execution run. It acts as shared memory for the entire graph.

from __future__ import annotations
from dataclasses import dataclass, field

@dataclass
class MyState:
    query: str = ""
    documents: list[str] = field(default_factory=list)
    answer: str = ""
# State is just a plain dictionary
state = {
    "query": "",
    "documents": [],
    "answer": "",
}

Immutability in Practice

Nodes return a dict of updated fields. The framework merges these updates into the current state β€” you never need to mutate state in-place.


Graph

The directed flow of nodes that defines an agent's logic. Nodes are connected by edges (linear) or conditional edges (branching).

graph LR
    START(["β–Ά START"]) --> A["retrieve_docs"]
    A --> B["generate_response"]
    B --> C{"needs_followup?"}
    C -- yes --> A
    C -- no --> END_(["⏹ END"])

    style START fill:#e8f5e9,stroke:#43a047
    style END_ fill:#ffebee,stroke:#e53935

Graphs are built declaratively inside build_graph() (class-based) or graph_fn() (functional). The framework compiles them into an optimised execution plan.


Manifest

An AgentManifest dataclass that declares an agent's identity β€” name, slug, description, framework, and version. The registry reads the manifest to know what agents exist and how to route to them.

from agentomatic.core.manifest import AgentManifest

manifest = AgentManifest(
    name="Search Bot",
    slug="search_bot",
    description="Knowledge-base search with citations.",
    framework="langgraph",
    version="1.0.0",
)

Class-based agents generate their manifest automatically

If you use BaseGraphAgent, the manifest is derived from class attributes. You only write one explicitly when using the functional pattern.


Thread

A conversation session with persistent history. Each thread has a unique thread_id and stores messages across multiple requests, enabling multi-turn dialogue.

# Client-side: continue a conversation
response = client.post(
    "/agents/search_bot/chat",
    json={
        "message": "Tell me more about that last point.",
        "thread_id": "abc-123",   # ← same thread
    },
)

Threads are stored in the configured storage backend (SQLite, PostgreSQL, or in-memory).


Platform

The AgentPlatform β€” the FastAPI server that hosts, discovers, and serves all agents. Created with a single call:

from agentomatic import AgentPlatform

platform = AgentPlatform.from_folder("./agents")
platform.run()  # πŸš€ FastAPI is live

The platform handles middleware (auth, rate limiting, CORS), health checks, and the Studio debugger β€” you focus on agent logic.


Discovery

The automatic process where the registry scans your agents/ folder at startup, imports each agent module, reads its manifest (or introspects the BaseGraphAgent subclass), and registers it with REST endpoints.

flowchart LR
    A["agents/"] --> B["Registry Scan"]
    B --> C{"agent.py?"}
    C -- yes --> D["Class-Based\nBaseGraphAgent"]
    C -- no --> E{"__init__.py?"}
    E -- yes --> F["Functional\nmanifest + graph_fn"]
    D --> G["Register\n26 REST Endpoints"]
    F --> G

    style G fill:#e3f2fd,stroke:#1565c0

Zero configuration

Drop a new folder into agents/, restart the server, and your agent is live β€” complete with docs, streaming, threads, and Studio integration.


Studio

The visual debugger (React frontend) that ships with Agentomatic. Studio shows graph topology, execution state, node timings, and time-travel debugging so you can step through each node's input/output.

# Launch the platform with Studio enabled
agentomatic run --studio

See Agentomatic Studio for the full guide.


Endpoint

One of the 26 auto-generated REST API routes per agent. Every registered agent automatically receives endpoints for:

Category Example Routes
Execution /invoke, /stream, /batch
Chat /chat, /chat/stream
Threads /threads, /threads/{id}/history
Introspection /config, /schema, /graph, /health
Management /feedback, /state, /metrics

No boilerplate

You never write a route. The platform generates them from your agent class and serves an OpenAPI spec at /docs.


Task & Execution Modes

A unit of work tracked by the platform's task engine. The same resource can be invoked in several execution modes β€” sync (wait for the result), streaming (SSE), async (submit now, poll later), batch (many inputs), or A2A. Async/batch calls return a TaskRecord with a status (queued β†’ running β†’ succeeded/failed/cancelled) and live progress, pollable at /api/v1/tasks/{id}.

# Submit an async job, then poll it
curl -X POST /api/v1/my_agent/invoke/async -d '{"query": "long job"}'
curl /api/v1/tasks/task_abc123    # β†’ {"status": "running", "progress": {...}}

Think of it as…

A background job with a receipt. Perfect for long-running work (e.g. document ingestion) where a UI submits, then shows a progress bar. See Tasks & Execution Modes.


Plugin

A classical ML model wrapped as a deployable resource (BaseMLPlugin). Drop it in plugins/ and it's auto-discovered with /predict endpoints β€” callable sync, async, or as a task, and usable as a pipeline step. Use it to serve scikit-learn, PyTorch, or any model alongside your LLM agents. See ML Plugins.


Pipeline

A declarative graph that chains resources β€” agents, plugins, endpoints, ingestors, transforms, loops, and sub-pipelines β€” with explicit data-passing between steps. Defined in YAML under pipelines/, with conditionals, retries, timeouts, rollback/compensation, and optional schema enforcement. See Pipelines.


Ingestor

A user-defined ingestion/RAG job packaged as a resource (BaseIngestor). Agentomatic handles the ops (discovery, endpoints, task tracking, progress); you bring the implementation by reusing any library (PDF→markdown, splitters, embedders, vector stores). Drop it in ingestion/. See Ingestion & RAG.


πŸ”€ How a Request Flows

Every request β€” whether REST, streaming, or chat β€” follows the same path through the system:

sequenceDiagram
    participant C as Client
    participant F as FastAPI
    participant M as Middleware
    participant R as Router
    participant A as Agent
    participant G as Graph Engine

    C->>F: POST /agents/search_bot/invoke
    F->>M: Auth Β· Rate Limit Β· CORS
    M->>R: Route to agent
    R->>A: agent.invoke(payload)
    A->>A: input_to_state(payload)
    A->>G: Execute graph
    loop Each Node
        G->>G: node(state) β†’ updated state
    end
    G-->>A: Final state
    A->>A: state_to_output(state)
    A-->>R: Structured response
    R-->>F: HTTP response
    F-->>C: 200 OK + JSON body
Step What Happens
1. Middleware Auth tokens are validated, rate limits are checked, CORS headers are set.
2. Router The platform routes to the correct agent by slug.
3. input_to_state() Your raw request payload is transformed into the agent's state dataclass.
4. Graph Execution Nodes run in topological order. Conditional edges choose branches dynamically.
5. state_to_output() The final state is transformed into your response schema.

βš–οΈ Two Patterns: Class-Based vs Functional

Agentomatic supports two ways to define agents. Both are fully auto-discovered and receive the same 26 REST endpoints.

Choosing a Pattern

flowchart TD
    Q["Starting a new agent?"] --> A{"Need typed state,\nML lifecycle, or\nmulti-node graphs?"}
    A -- Yes --> B["βœ… Class-Based\n(Recommended)"]
    A -- No --> C{"Quick prototype\nor single-node\nlogic?"}
    C -- Yes --> D["βœ… Functional"]
    C -- No --> B

    style B fill:#c8e6c9,stroke:#388e3c
    style D fill:#fff9c4,stroke:#f9a825

Side-by-Side Comparison

agents/search_bot/agent.py
from __future__ import annotations

from dataclasses import dataclass, field

from agentomatic.agents import BaseGraphAgent
from agentomatic.agents.graph import GraphBuilder


@dataclass
class SearchState:
    query: str = ""
    documents: list[str] = field(default_factory=list)
    answer: str = ""


class SearchBot(BaseGraphAgent[SearchState]):
    name = "Search Bot"
    description = "Knowledge-base search with citations."

    def build_graph(self, builder: GraphBuilder) -> None:
        builder.add_node("retrieve", self.retrieve_docs)
        builder.add_node("generate", self.generate_response)
        builder.add_edge("retrieve", "generate")
        builder.set_entry_point("retrieve")
        builder.set_finish_point("generate")

    def retrieve_docs(self, state: SearchState) -> dict:
        state.documents = ["doc1", "doc2"]
        return {"documents": state.documents}

    def generate_response(self, state: SearchState) -> dict:
        state.answer = f"Based on {len(state.documents)} docs..."
        return {"answer": state.answer}

    def input_to_state(self, payload: dict) -> SearchState:
        return SearchState(query=payload.get("query", ""))

    def state_to_output(self, state: SearchState) -> dict:
        return {"answer": state.answer}

Why class-based?

  • Typed state β€” catch bugs at development time
  • ML lifecycle β€” compile() β†’ fit() β†’ evaluate() β†’ transform()
  • Self-contained β€” one file, one class, one import
  • Graph viz β€” Studio renders your build_graph() topology
agents/search_bot/__init__.py
from __future__ import annotations

from agentomatic.core.manifest import AgentManifest

manifest = AgentManifest(
    name="Search Bot",
    slug="search_bot",
    description="Knowledge-base search with citations.",
    framework="langgraph",
    version="1.0.0",
)


def retrieve_docs(state: dict) -> dict:
    """Node: fetch relevant documents."""
    state["documents"] = ["doc1", "doc2"]
    return state


def generate_response(state: dict) -> dict:
    """Node: produce an answer from documents."""
    state["answer"] = f"Based on {len(state['documents'])} docs..."
    return state


def graph_fn():
    """Build and return the LangGraph StateGraph."""
    from langgraph.graph import StateGraph

    g = StateGraph(dict)
    g.add_node("retrieve", retrieve_docs)
    g.add_node("generate", generate_response)
    g.add_edge("retrieve", "generate")
    g.set_entry_point("retrieve")
    g.set_finish_point("generate")
    return g.compile()

When to use functional

  • Quick prototypes or single-node agents
  • Gradual migration from raw LangGraph code
  • Scripts that don't need typed state or ML lifecycle

Feature Matrix

Feature Class-Based Functional
Typed @dataclass state βœ… ❌
ML lifecycle (compile/fit/evaluate) βœ… ❌
build_graph() with GraphBuilder βœ… ❌
input_to_state() / state_to_output() βœ… ❌
Auto-generated 26 endpoints βœ… βœ…
Studio graph visualization βœ… βœ…
Custom config (config.py) βœ… βœ…
Custom schemas (schemas.py) βœ… βœ…
Prompt management (prompts.json) βœ… βœ…
Tool definitions (tools.py) βœ… βœ…

πŸ“ Key Files at a Glance

Every agent lives in a subfolder under agents/. Here's what each file does:

File Pattern Purpose
agent.py Class-Based Your BaseGraphAgent subclass β€” nodes, graph, state transforms
__init__.py Functional Module-level manifest + node_fn / graph_fn
config.py Both Pydantic settings model β€” LLM params, feature flags, thresholds
schemas.py Both Custom request/response models (overrides auto-generated ones)
prompts.json Both Versioned prompt templates with variable interpolation
tools.py Both LangChain-compatible tool definitions for tool-calling agents
api.py Both Custom FastAPI routers (add or override auto-generated routes)
.env.example Both Environment variable blueprint for your agent
README.md Both Agent-level documentation

Only one file is required

Class-based: agent.py is the only mandatory file. Functional: __init__.py with a manifest is the only mandatory file. Everything else is optional β€” add files as your agent grows.

agents/
β”œβ”€β”€ search_bot/
β”‚   β”œβ”€β”€ agent.py         ← REQUIRED (class-based)
β”‚   β”œβ”€β”€ config.py        ← optional
β”‚   β”œβ”€β”€ schemas.py       ← optional
β”‚   β”œβ”€β”€ tools.py         ← optional
β”‚   β”œβ”€β”€ prompts.json     ← optional
β”‚   └── README.md        ← optional
β”‚
└── echo_bot/
    β”œβ”€β”€ __init__.py      ← REQUIRED (functional)
    └── config.py        ← optional

πŸ—ΊοΈ What's Next?

You now have the vocabulary to navigate every part of Agentomatic. Pick your path:

Goal Page
Run your first agent in 60 seconds Quick Start
Step-by-step agent tutorial Your First Agent
Deep dive into class-based agents Class-Based Agents
File conventions & discovery Agent Structure & Discovery
Patterns & recipes Cookbook & Recipes
Visual debugging with Studio Agentomatic Studio
Configure LLMs & middleware Configuration

Recommended Reading Order

Concepts (you are here) β†’ Quick Start β†’ Your First Agent β†’ Class-Based Agents β†’ Cookbook