Persisting States with Databases and Callbacks
Introduction: Why Database Persistence Matters
In the previous lesson, you built a FastAPI server that exposes AI agents through REST endpoints, storing agent states in a Python dictionary. This worked well for learning the basics, but had a critical flaw: when your server restarts, all agent states disappear. For Factor 6 — Launch / Pause / Resume with simple APIs to work reliably, an agent that was paused yesterday must still be resumable today. Database persistence solves this by storing states on disk. In this lesson, you'll replace in-memory storage with SQLite using SQLAlchemy and implement progress callbacks that save state after each agent step, enabling real-time progress tracking for clients. This persistent foundation is what makes the pause and resume endpoints you'll build in the next lesson truly practical.
Setting Up SQLAlchemy with SQLite
To begin working with a database, you need to create a connection engine and configure where the database file will be stored. SQLAlchemy provides this through the create_engine function, which takes a connection string specifying the database type and location:
The db_path variable uses Path to construct an absolute path to a file named agent_states.db inside a data directory. The mkdir(parents=True, exist_ok=True) call ensures the directory exists before SQLite tries to create the database file. The connection string sqlite:///{db_path} tells SQLAlchemy to use SQLite with the specified file path, and setting echo=False prevents SQLAlchemy from logging all SQL statements to the console. The declarative_base() function creates a base class that all your database models will inherit from, while sessionmaker creates a factory for database sessions that represent transaction boundaries. With this foundation in place, you can now define how agent states will be stored.
