Echo Environment#
A simple test environment that echoes back messages. Perfect for testing the env APIs as well as demonstrating environment usage patterns.
Quick Start#
The simplest way to use the Echo environment is through the EchoEnv class. The client is async by default:
import asyncio
from echo_env import EchoAction, EchoEnv
async def main():
# Create environment from Docker image
client = await EchoEnv.from_docker_image("echo-env:latest")
async with client:
# Reset
result = await client.reset()
print(f"Reset: {result.observation.echoed_message}")
# Send multiple messages
messages = ["Hello, World!", "Testing echo", "Final message"]
for msg in messages:
result = await client.step(EchoAction(message=msg))
print(f"Sent: '{msg}'")
print(f" โ Echoed: '{result.observation.echoed_message}'")
print(f" โ Length: {result.observation.message_length}")
print(f" โ Reward: {result.reward}")
asyncio.run(main())
For synchronous usage, use the .sync() wrapper:
from echo_env import EchoAction, EchoEnv
with EchoEnv(base_url="http://localhost:8000").sync() as client:
result = client.reset()
result = client.step(EchoAction(message="Hello!"))
print(result.observation.echoed_message)
The EchoEnv.from_docker_image() method handles:
Starting the Docker container
Waiting for the server to be ready
Connecting to the environment
Container cleanup when the context manager exits
Building the Docker Image#
Before using the environment, you need to build the Docker image:
# From project root
docker build -t echo-env:latest -f envs/echo_env/server/Dockerfile .
Environment Details#
Action#
EchoAction: Contains a single field
message(str) - The message to echo back
Observation#
EchoObservation: Contains the echo response and metadata
echoed_message(str) - The message echoed backmessage_length(int) - Length of the messagereward(float) - Reward based on message length (length ร 0.1)done(bool) - Always False for echo environmentmetadata(dict) - Additional info like step count
Reward#
The reward is calculated as: message_length ร 0.1
โHiโ โ reward: 0.2
โHello, World!โ โ reward: 1.3
Empty message โ reward: 0.0
Advanced Usage#
Connecting to an Existing Server#
If you already have an Echo environment server running, you can connect directly:
from echo_env import EchoAction, EchoEnv
# Async usage
async with EchoEnv(base_url="http://localhost:8000") as client:
result = await client.reset()
result = await client.step(EchoAction(message="Hello!"))
# Sync usage
with EchoEnv(base_url="http://localhost:8000").sync() as client:
result = client.reset()
result = client.step(EchoAction(message="Hello!"))
Note: When connecting to an existing server, closing the client will NOT stop the server.
Development & Testing#
Direct Environment Testing#
Test the environment logic directly without starting the HTTP server:
# From the server directory
python3 envs/echo_env/server/test_echo_env.py
This verifies that:
Environment resets correctly
Step executes actions properly
State tracking works
Rewards are calculated correctly
Running the Full Example#
Run the complete example that demonstrates the full workflow:
python3 examples/local_echo_env.py
This example shows:
Creating an environment from a Docker image
Resetting and stepping through the environment
Automatic cleanup with
close()
Project Structure#
echo_env/
โโโ __init__.py # Module exports
โโโ README.md # This file
โโโ client.py # EchoEnv client implementation
โโโ models.py # Action and Observation models
โโโ server/
โโโ __init__.py # Server module exports
โโโ echo_environment.py # Core environment logic
โโโ app.py # FastAPI application
โโโ test_echo_env.py # Direct environment tests
โโโ Dockerfile # Container image definition