Skip to main content

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:

  1. Local Testing - Learn advanced testing techniques
  2. Build APKG - Package your agent for deployment
  3. Deploy to PAR - Deploy to production
  4. 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!