Ceylon Minimal Playground Tutorial
Installation
First, install Ceylon and its dependencies:
pip install ceylon loguru
Basic Concepts
Ceylon is a framework for building distributed systems. The minimal approach uses:
- BasePlayground: Coordinates message passing between agents
- Worker: An agent that can send and receive messages
- Message Handlers: Functions that process specific types of messages
Simple Example
Here's a minimal example showing the core functionality:
import asyncio
from dataclasses import dataclass
from loguru import logger
from ceylon import Worker, AgentDetail
from ceylon.base.playground import BasePlayGround
# Define a message type
@dataclass
class SimpleMessage:
content: str
# Create playground and agent
playground = BasePlayGround(name="minimal_demo")
agent = Worker("worker1")
# Define message handler
@agent.on(SimpleMessage)
async def handle_message(message: SimpleMessage, sender: AgentDetail, time: int):
logger.info(f"From {sender.name} received: {message.content}")
async def main():
async with playground.play(workers=[agent]) as active_playground:
message = SimpleMessage(content="Hello from worker1!")
await active_playground.broadcast_message(message)
if __name__ == "__main__":
asyncio.run(main())
Breaking Down the Components
1. Message Types
Messages are defined using dataclasses:
@dataclass
class SimpleMessage:
content: str
2. Playground and Agent
Create instances at module level:
playground = BasePlayGround(name="minimal_demo")
agent = Worker("worker1")
3. Message Handler
Use the @agent.on
decorator to handle specific message types:
@agent.on(SimpleMessage)
async def handle_message(message: SimpleMessage, sender: AgentDetail, time: int):
logger.info(f"From {sender.name} received: {message.content}")
4. Message Broadcasting
Send messages through the playground:
await active_playground.broadcast_message(message)
Common Use Cases
-
System Monitoring
- Agents sending status updates
- Collecting metrics
-
Event Processing
- Handling events in distributed systems
- Event broadcasting
-
Simple Communication
- Message passing between components
- Basic coordination
Best Practices
-
Message Design
- Keep message classes simple
- Use dataclasses for message definitions
- Include only necessary fields
-
Handler Organization
- One handler per message type
- Clear handler naming
- Focused handler functionality
-
Resource Management
- Use async context managers
- Proper cleanup in handlers
- Handle errors appropriately
Common Extensions
- Add multiple message types:
@dataclass
class StatusMessage:
status: str
@agent.on(StatusMessage)
async def handle_status(message: StatusMessage, sender: AgentDetail, time: int):
logger.info(f"Status from {sender.name}: {message.status}")
- Add multiple agents:
agent1 = Worker("worker1")
agent2 = Worker("worker2")
async with playground.play(workers=[agent1, agent2]) as active_playground:
# Your code here
Troubleshooting
-
Messages not being received
- Check handler decorator matches message type
- Verify playground has started properly
- Ensure agent is in workers list
-
Type errors
- Verify message class matches handler
- Check dataclass field types
- Ensure proper async/await usage
Next Steps
- Explore more complex message types
- Add multiple agents
- Implement different message patterns
- Add error handling
- Explore other Ceylon features
Resources
- Ceylon Documentation: https://docs.ceylon.ai
- GitHub Repository: https://github.com/ceylon-ai/ceylon