A tiny, free‑tier clone of Strands Agents Harness‑SDK
Welcome to another official UVF IT build guide! In the next 45 minutes you’ll spin up a minimal Python‑only agent harness that mimics the core of Strands Agents Harness‑SDK – no paid APIs, just the standard library and SQLite.
We’ll scaffold a Flask app, define a simple agent model, expose a tiny REST API, run it locally, and verify it works – perfect for beginners eager to experiment with AI‑agent patterns.
pip. The real Harness SDK supports advanced model‑driven pipelines; our clone only stores a single JSON payload in SQLite.python -m venv venv then venv\Scripts\activate; on macOS/Linux use source venv/bin/activate.Create a fresh virtual environment so our dependencies stay isolated from any other Python work you have. Then install Flask (the lightweight web framework) and SQLAlchemy (the ORM that will talk to SQLite). This gives us a tiny but functional stack to host our agent harness.
We also set up a basic folder layout: a top‑level app.py for the Flask entry point and a models.py that will later hold our data definitions. All files live in the same directory for simplicity.
python -m venv venv
# Activate the environment
# Windows:
# venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate
# Upgrade pip and install required packages
pip install --upgrade pip
pip install Flask SQLAlchemy
# Create project skeleton
mkdir harness_clone && cd harness_clone
touch app.py models.pyOur clone only needs to remember an identifier for each agent and a JSON‑encoded snapshot of its internal state. SQLAlchemy makes this trivial: we declare a Python class that maps to a SQLite table, and SQLAlchemy handles the CRUD operations for us.
The state column uses the JSON type when available (SQLite supports it via sqlite_json in newer versions) but falls back to a plain Text field, ensuring the code runs everywhere.
models.py
from sqlalchemy import Column, Integer, String, Text, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import json
Base = declarative_base()
class Agent(Base):
__tablename__ = 'agents'
id = Column(Integer, primary_key=True, autoincrement=True)
identifier = Column(String, unique=True, nullable=False)
# Store JSON as text; SQLAlchemy will give us a string we can json.loads()
state = Column(Text, nullable=False, default='{}')
def get_state(self):
return json.loads(self.state)
def set_state(self, data):
self.state = json.dumps(data)
# Helper to create a SQLite DB in the current folder
engine = create_engine('sqlite:///agents.db')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)In this step we expose a tiny REST API that lets you create and list agents. The /agents endpoint accepts a JSON payload with a name and optional state, stores it in a local SQLite file, and returns the new record's ID. We also add a very simple HTML page at the root URL that pulls the list of agents from the database and renders them as plain text, so you can see the data without any front‑end framework.
app.py
import json, sqlite3
from flask import Flask, request, g, jsonify, render_template_string
app = Flask(__name__)
DB = 'agents.db'
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect(DB)
db.execute('CREATE TABLE IF NOT EXISTS agents (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, state TEXT)')
return db
@app.teardown_appcontext
def close_connection(exc):
db = getattr(g, '_database', None)
if db is not None:
db.close()
@app.route('/agents', methods=['GET', 'POST'])
def agents():
db = get_db()
if request.method == 'POST':
data = request.get_json() or {}
name = data.get('name', 'unnamed')
state = json.dumps(data.get('state', {}))
cur = db.execute('INSERT INTO agents (name, state) VALUES (?,?)', (name, state))
db.commit()
return jsonify({'id': cur.lastrowid, 'name': name, 'state': json.loads(state)})
rows = db.execute('SELECT id, name, state FROM agents').fetchall()
agents = [{'id': r[0], 'name': r[1], 'state': json.loads(r[2])} for r in rows]
return jsonify(agents)
@app.route('/')
def index():
db = get_db()
rows = db.execute('SELECT id, name, state FROM agents').fetchall()
items = []
for r in rows:
state = json.loads(r[2])
items.append(f"<li>{r[0]}: {r[1]} – {json.dumps(state)}</li>")
html = "<h1>Agents</h1><ul>" + "".join(items) + "</ul>"
return render_template_string(html)
if __name__ == '__main__':
app.run(debug=True)Now we start the Flask development server. The first request will automatically create the SQLite database file (agents.db) if it doesn't exist, so you don't need any manual setup. Running in debug mode gives you live reloads while you experiment.
export FLASK_APP=app.py
export FLASK_ENV=development
flask runWith the server running, use curl to POST a new agent and watch the JSON response contain an id. Then open a browser at http://127.0.0.1:5000/ to see the simple HTML list showing the agent you just created. Feel free to add more fields to the agents table or replace the HTML with a richer UI as you grow the clone.
curl -X POST http://127.0.0.1:5000/agents \
-H "Content-Type: application/json" \
-d '{"name":"demo","state":{"msg":"hello"}}'| Check | Command / Why it matters |
|---|---|
| Virtual environment activated and Flask installed | pip list | grep Flask |
| Server starts without errors | flask run (should show * Running on http://127.0.0.1:5000/) |
| POST request returns JSON with an id | curl -X POST http://127.0.0.1:5000/agents -H "Content-Type: application/json" -d '{"name":"demo","state":{"msg":"hello"}}' (response contains \"id\":1) |
| Browser at http://127.0.0.1:5000/ shows the new agent | Open URL and see "1: demo – {\"msg\":\"hello\"}" |
Your minimal harness is up and running. The real Strands SDK adds model‑driven pipelines, remote execution, and rich UI – you now have the skeleton to explore those features on your own.