Deep Dive: Create and Publish Teachers
What Is a Teacher?
1
Understand the Teacher Methods
Required Methods
Method
What it does
Optional Methods
Method
What it does
Default
Method Signatures
from typing import Dict, List
from amesa_core import AgentTeacher
class MyTeacher(AgentTeacher):
# Required — called once at startup; result is cached
async def filtered_sensor_space(self) -> List[str]:
...
# Required — called every step; return a float
async def compute_reward(self, transformed_sensors: Dict, action, sim_reward: float) -> float:
...
# Required — called every step; return True when the agent has succeeded
async def compute_success_criteria(self, transformed_sensors: Dict, action) -> bool:
...
# Required — called every step; return the action to send to the simulator
async def transform_action(self, transformed_sensors: Dict, action):
...
# Optional — called every step; return True to end the episode as a failure
async def compute_termination(self, transformed_sensors: Dict, action) -> bool:
return False
# Optional — called every step; return a modified sensors dict
async def transform_sensors(self, sensors, action) -> Dict:
return sensors2
Write Your Teacher
Option A: Custom Teacher
# temperature_teacher/teacher.py
from typing import Dict, List
from amesa_core import AgentTeacher
class TemperatureTeacher(AgentTeacher):
"""
Trains an agent to maintain process temperature near a setpoint.
Reward: negative absolute error from target (closer = higher reward)
Success: temperature within TOLERANCE of target
Termination: temperature more than FAIL_DISTANCE from target
"""
TARGET = 80.0 # desired temperature
TOLERANCE = 2.0 # success band: ±2 degrees
FAIL_DISTANCE = 20.0 # terminate if this far from target
def __init__(self):
# __init__ must take no required arguments
# self.* state is wiped at every episode reset — do not store cross-episode data here
pass
async def filtered_sensor_space(self) -> List[str]:
# Declare which sensors the RL policy observes
# Only these sensor names will be visible during training
return ["temperature", "heater_output"]
async def compute_reward(self, transformed_sensors: Dict, action, sim_reward: float) -> float:
error = abs(transformed_sensors["temperature"] - self.TARGET)
return -error # reward = 0 at target; decreases with distance
async def compute_success_criteria(self, transformed_sensors: Dict, action) -> bool:
error = abs(transformed_sensors["temperature"] - self.TARGET)
return error <= self.TOLERANCE
async def compute_termination(self, transformed_sensors: Dict, action) -> bool:
error = abs(transformed_sensors["temperature"] - self.TARGET)
return error >= self.FAIL_DISTANCE
async def transform_action(self, transformed_sensors: Dict, action):
# Clamp heater output to valid range [0.0, 1.0]
return max(0.0, min(1.0, action))
async def transform_sensors(self, sensors, action) -> Dict:
# No pre-processing needed — pass sensors through unchanged
# Note: action is always None here; do not write logic that depends on it
return sensorsOption B: Goal-Based Teacher (Less Code)
Goal Class
Use when you want to...
# temperature_teacher/teacher.py
from typing import Dict
from amesa_core.orchestration.agent.goals.coordinated_goal import CoordinatedGoal
from amesa_core.orchestration.agent.goals.maintain_goal import MaintainGoal
class TemperatureTeacher(CoordinatedGoal):
"""
Goal-based teacher: maintain temperature near setpoint using MaintainGoal.
CoordinatedGoal handles compute_reward, compute_success_criteria,
and compute_termination automatically.
"""
def __init__(self):
temperature_goal = MaintainGoal(
"temperature",
"Maintain process temperature near setpoint",
target=80.0,
stop_distance=2.0,
)
super().__init__([temperature_goal])
async def transform_action(self, transformed_sensors: Dict, action):
return max(0.0, min(1.0, action))
async def transform_sensors(self, sensors, action) -> Dict:
return sensors3
Create the Artifact Directory
Using the CLI Scaffold (Recommended)
amesa agent new \
--name temperature-teacher \
--type teacher \
--description "Maintains process temperature near setpoint" \
--location ./temperature-teacher/
temperature_teacher/
__init__.py ← empty; required
teacher.py ← your AgentTeacher subclass goes here
pyproject.toml ← artifact metadata; CLI reads this on publishCreating Manually
mkdir -p temperature-teacher/temperature_teacher
touch temperature-teacher/temperature_teacher/__init__.py
touch temperature-teacher/temperature_teacher/teacher.py
touch temperature-teacher/pyproject.tomlNaming Rules
Layer
Convention
Example
4
Configure pyproject.toml
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.backends.legacy:build"
[project]
name = "temperature-teacher"
version = "0.1.0"
description = "Maintains process temperature near setpoint"
dependencies = [
"amesa-core",
]
[amesa]
type = "agent-teacher"
entrypoint = "temperature_teacher.teacher:TemperatureTeacher"Field Reference
Field
Where
Required
Description
Entrypoint Format
Part
Value in this example
5
Updating a Published Teacher
[project]
version = "0.2.0" # ← increment before re-publishingamesa agent publish ./temperature-teacher/