Hello Agent Example
Create your first AI agent in under 5 minutes! This tutorial walks you through building a simple "Hello Agent" that responds to messages and demonstrates all three communication surfaces.
What You'll Build
A simple agent that:
- 👋 Greets users with personalized messages
 - 🧠 Responds intelligently to different types of input
 - 🌐 Exposes REST API for HTTP requests
 - 🔗 Supports A2A communication via gRPC
 - 🎨 Provides a web UI for interactive testing
 
Prerequisites
- PAK installed - Installation Guide
 - Python 3.11+ - Required for modern Python features
 - 5 minutes - That's it!
 
Step 1: Create Your Agent
Start by creating a new agent project:
# Create the hello-agent project
pixell init hello-agent
# Navigate to the project
cd hello-agent
This creates a complete agent structure:
hello-agent/
├── agent.yaml              # Agent manifest
├── README.md               # Project documentation
├── .env.example           # Environment variables template
├── requirements.txt        # Python dependencies
├── src/
│   ├── main.py            # Main entry point
│   ├── a2a/               # A2A service implementation
│   │   └── service.py
│   └── rest/              # REST API routes
│       └── routes.py
└── ui/
    └── index.html         # Web UI
Step 2: Configure Your Agent
Edit the agent.yaml manifest:
name: hello-agent
version: 0.1.0
description: A simple greeting agent that responds to messages
author: Your Name
entry_point: src/main.py
# Agent capabilities
capabilities:
  - greeting
  - conversation
  - personalization
# API endpoints
endpoints:
  rest:
    - path: /greet
      method: POST
      description: Get a personalized greeting
    - path: /chat
      method: POST
      description: Chat with the agent
  a2a:
    - service: GreetingService
      methods: [Greet, Chat]
  ui:
    - path: /
      description: Interactive web interface
Step 3: Implement the Agent Logic
Edit src/main.py:
import os
import json
from typing import Dict, Any
class HelloAgent:
    def __init__(self):
        self.name = "Hello Agent"
        self.version = "0.1.0"
        
    def greet(self, name: str = "World") -> str:
        """Generate a personalized greeting."""
        greetings = [
            f"Hello, {name}! 👋",
            f"Hi there, {name}! How are you today?",
            f"Greetings, {name}! Nice to meet you!",
            f"Hey {name}! Welcome to the future of AI agents! 🤖"
        ]
        
        # Simple hash-based selection for consistency
        index = hash(name) % len(greetings)
        return greetings[index]
    
    def chat(self, message: str, context: Dict[str, Any] = None) -> str:
        """Respond to chat messages."""
        message_lower = message.lower()
        
        if any(word in message_lower for word in ["hello", "hi", "hey"]):
            name = context.get("name", "friend") if context else "friend"
            return self.greet(name)
        
        elif any(word in message_lower for word in ["how", "what", "who"]):
            return "I'm a Hello Agent! I love greeting people and having conversations. What would you like to know?"
        
        elif any(word in message_lower for word in ["bye", "goodbye", "see you"]):
            return "Goodbye! It was nice chatting with you! 👋"
        
        else:
            return f"I heard you say: '{message}'. That's interesting! Tell me more about it."
# Global agent instance
agent = HelloAgent()
def get_agent():
    """Get the agent instance."""
    return agent
Step 4: Implement REST API
Edit src/rest/routes.py:
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from ..main import get_agent
router = APIRouter()
class GreetRequest(BaseModel):
    name: str = "World"
class ChatRequest(BaseModel):
    message: str
    context: dict = {}
@router.post("/greet")
async def greet(request: GreetRequest):
    """Get a personalized greeting."""
    try:
        agent = get_agent()
        greeting = agent.greet(request.name)
        return {
            "greeting": greeting,
            "agent": agent.name,
            "version": agent.version
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
@router.post("/chat")
async def chat(request: ChatRequest):
    """Chat with the agent."""
    try:
        agent = get_agent()
        response = agent.chat(request.message, request.context)
        return {
            "response": response,
            "agent": agent.name,
            "version": agent.version
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
@router.get("/health")
async def health():
    """Health check endpoint."""
    return {
        "status": "healthy",
        "agent": "hello-agent",
        "version": "0.1.0"
    }
@router.get("/capabilities")
async def capabilities():
    """Get agent capabilities."""
    return {
        "capabilities": [
            "greeting",
            "conversation", 
            "personalization"
        ],
        "endpoints": {
            "rest": ["/greet", "/chat", "/health", "/capabilities"],
            "a2a": ["GreetingService.Greet", "GreetingService.Chat"],
            "ui": ["/"]
        }
    }
Step 5: Implement A2A Service
Edit src/a2a/service.py:
from pixell_runtime.proto import agent_pb2, agent_pb2_grpc
from ..main import get_agent
class GreetingService(agent_pb2_grpc.AgentServiceServicer):
    def __init__(self):
        self.agent = get_agent()
    
    def Health(self, request, context):
        """Health check for A2A communication."""
        return agent_pb2.HealthResponse(
            status="healthy",
            message="Hello Agent is running"
        )
    
    def DescribeCapabilities(self, request, context):
        """Describe agent capabilities."""
        return agent_pb2.CapabilitiesResponse(
            capabilities=[
                "greeting",
                "conversation",
                "personalization"
            ],
            description="A simple greeting agent that responds to messages"
        )
    
    def Invoke(self, request, context):
        """Handle A2A invoke requests."""
        try:
            # Parse the request
            message = request.message
            context_dict = dict(request.context) if request.context else {}
            
            # Route based on message content
            if message.startswith("greet:"):
                name = message.split(":", 1)[1].strip()
                response = self.agent.greet(name)
            else:
                response = self.agent.chat(message, context_dict)
            
            return agent_pb2.InvokeResponse(
                response=response,
                success=True,
                metadata={"agent": "hello-agent", "version": "0.1.0"}
            )
        except Exception as e:
            return agent_pb2.InvokeResponse(
                response=f"Error: {str(e)}",
                success=False,
                metadata={"error": str(e)}
            )
    
    def Ping(self, request, context):
        """Ping endpoint for connectivity testing."""
        return agent_pb2.PingResponse(
            message="pong",
            timestamp=request.timestamp
        )
Step 6: Create Web UI
Edit ui/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello Agent</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
        }
        .container {
            background: white;
            border-radius: 10px;
            padding: 30px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.1);
        }
        h1 {
            color: #333;
            text-align: center;
            margin-bottom: 30px;
        }
        .input-group {
            margin-bottom: 20px;
        }
        label {
            display: block;
            margin-bottom: 5px;
            font-weight: 600;
            color: #555;
        }
        input, textarea {
            width: 100%;
            padding: 12px;
            border: 2px solid #e1e5e9;
            border-radius: 6px;
            font-size: 16px;
            transition: border-color 0.3s;
        }
        input:focus, textarea:focus {
            outline: none;
            border-color: #667eea;
        }
        button {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 6px;
            font-size: 16px;
            cursor: pointer;
            transition: transform 0.2s;
        }
        button:hover {
            transform: translateY(-2px);
        }
        .response {
            margin-top: 20px;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 6px;
            border-left: 4px solid #667eea;
        }
        .error {
            border-left-color: #dc3545;
            background: #f8d7da;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🤖 Hello Agent</h1>
        <p style="text-align: center; color: #666; margin-bottom: 30px;">
            A simple AI agent that greets and chats with you!
        </p>
        
        <div class="input-group">
            <label for="name">Your Name (for greeting):</label>
            <input type="text" id="name" placeholder="Enter your name" value="World">
        </div>
        
        <div class="input-group">
            <label for="message">Message:</label>
            <textarea id="message" rows="3" placeholder="Type your message here...">Hello!</textarea>
        </div>
        
        <button onclick="sendMessage()">Send Message</button>
        <button onclick="getGreeting()">Get Greeting</button>
        
        <div id="response" class="response" style="display: none;">
            <strong>Agent Response:</strong>
            <div id="responseText"></div>
        </div>
    </div>
    <script>
        async function sendMessage() {
            const message = document.getElementById('message').value;
            const name = document.getElementById('name').value;
            
            if (!message.trim()) {
                alert('Please enter a message');
                return;
            }
            
            try {
                const response = await fetch('/chat', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        message: message,
                        context: { name: name }
                    })
                });
                
                const data = await response.json();
                showResponse(data.response);
            } catch (error) {
                showError('Failed to send message: ' + error.message);
            }
        }
        
        async function getGreeting() {
            const name = document.getElementById('name').value;
            
            try {
                const response = await fetch('/greet', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({ name: name })
                });
                
                const data = await response.json();
                showResponse(data.greeting);
            } catch (error) {
                showError('Failed to get greeting: ' + error.message);
            }
        }
        
        function showResponse(text) {
            const responseDiv = document.getElementById('response');
            const responseText = document.getElementById('responseText');
            
            responseText.textContent = text;
            responseDiv.className = 'response';
            responseDiv.style.display = 'block';
        }
        
        function showError(text) {
            const responseDiv = document.getElementById('response');
            const responseText = document.getElementById('responseText');
            
            responseText.textContent = text;
            responseDiv.className = 'response error';
            responseDiv.style.display = 'block';
        }
    </script>
</body>
</html>
Step 7: Test Your Agent
Start the development server:
# Start the agent
pixell run-dev
Your agent is now running! Test it in multiple ways:
1. REST API Testing
# Health check
curl http://localhost:8000/health
# Get a greeting
curl -X POST http://localhost:8000/greet \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice"}'
# Chat with the agent
curl -X POST http://localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Hello! How are you?", "context": {"name": "Bob"}}'
2. Web UI Testing
Open your browser to: http://localhost:8000/ui
- Enter your name
 - Type a message
 - Click "Send Message" or "Get Greeting"
 - See the agent's response!
 
3. A2A gRPC Testing
# Python A2A client test
import grpc
from pixell_runtime.proto import agent_pb2, agent_pb2_grpc
# Connect to A2A service
channel = grpc.insecure_channel('localhost:8001')
stub = agent_pb2_grpc.AgentServiceStub(channel)
# Test health
response = stub.Health(agent_pb2.HealthRequest())
print(f"Health: {response.status}")
# Test invoke
request = agent_pb2.InvokeRequest(
    message="Hello from A2A!",
    context={"name": "Developer"}
)
response = stub.Invoke(request)
print(f"Response: {response.response}")
Step 8: Build and Package
Once you're satisfied with your agent:
# Validate the agent
pixell validate
# Build the APKG
pixell build
# Inspect the package
pixell inspect dist/hello-agent-0.1.0.apkg
What You've Learned
✅ Agent Structure - How to organize agent code
✅ REST API - HTTP endpoints for web integration
✅ A2A Communication - gRPC for agent-to-agent communication
✅ Web UI - Interactive user interface
✅ Testing - Multiple ways to test your agent
✅ Packaging - Building APKG files for deployment
Next Steps
Now that you have a working agent:
- Local Testing - Learn advanced testing techniques
 - Build APKG - Package your agent for deployment
 - Deploy to PAR - Deploy to production
 - Web Agent Example - Build a more complex agent
 
Customization Ideas
Try these enhancements to make your agent more interesting:
1. Add Memory
class HelloAgent:
    def __init__(self):
        self.memory = {}
    
    def chat(self, message: str, context: Dict[str, Any] = None) -> str:
        user_id = context.get("user_id", "anonymous")
        
        # Store conversation in memory
        if user_id not in self.memory:
            self.memory[user_id] = []
        
        self.memory[user_id].append(message)
        
        # Reference previous messages
        if len(self.memory[user_id]) > 1:
            return f"I remember you said: '{self.memory[user_id][-2]}'. Now you're saying: '{message}'. That's interesting!"
        
        return self.greet(context.get("name", "friend"))
2. Add External APIs
import requests
def get_weather(self, location: str) -> str:
    """Get weather information."""
    # Add weather API integration
    return f"The weather in {location} is sunny and 72°F"
3. Add File Processing
def process_file(self, file_path: str) -> str:
    """Process uploaded files."""
    # Add file processing logic
    return f"I processed the file: {file_path}"
Congratulations! 🎉 You've built your first AI agent with PAK. Ready to learn more? Check out Local Testing for advanced development techniques!