xml-pipeline/handlers/hello.py
dullfig 9ab6df85e1 Rebrand Nextra → OpenBlox
Update all documentation and code comments to reference OpenBlox
(https://openblox.ai) instead of Nextra.

Also updated references to reflect that WebSocket server is now
part of the OSS core (added in previous commit).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 20:31:13 -08:00

129 lines
4.2 KiB
Python

"""
hello.py — Multi-agent hello world handlers for testing the message pump.
This module demonstrates a multi-agent flow:
user -> greeter -> shouter -> user
Payload classes:
- Greeting: Initial request with a name
- GreetingResponse: Greeter's response
- ShoutedResponse: Shouter's ALL CAPS version
Handlers:
- handle_greeting: Receives Greeting, sends GreetingResponse to shouter
- handle_shout: Receives GreetingResponse, sends ShoutedResponse to original sender
Usage in organism.yaml:
listeners:
- name: greeter
payload_class: handlers.hello.Greeting
handler: handlers.hello.handle_greeting
- name: shouter
payload_class: handlers.hello.GreetingResponse
handler: handlers.hello.handle_shout
"""
from dataclasses import dataclass
from third_party.xmlable import xmlify
from xml_pipeline.message_bus.message_state import HandlerMetadata, HandlerResponse
@xmlify
@dataclass
class Greeting:
"""Incoming greeting request."""
name: str
@xmlify
@dataclass
class GreetingResponse:
"""Greeter's response - will be forwarded to shouter."""
message: str
original_sender: str # Track who started the conversation
@xmlify
@dataclass
class ShoutedResponse:
"""Shouter's ALL CAPS response - sent back to original sender."""
message: str
async def handle_greeting(payload: Greeting, metadata: HandlerMetadata) -> HandlerResponse:
"""
Handle an incoming Greeting and forward GreetingResponse to shouter.
Flow: console-router -> greeter -> shouter -> response-handler
Demonstrates TodoUntil pattern:
1. Register a watcher for ShoutedResponse from shouter
2. Send GreetingResponse to shouter
3. When ShoutedResponse appears, eyebrow is raised
4. On next invocation, greeter sees nudge and can close the todo
NOTE: This handler uses platform.complete() for LLM calls.
The system prompt is managed by the platform (from organism.yaml).
The handler cannot see or modify the prompt.
"""
from xml_pipeline.platform import complete
from xml_pipeline.message_bus.todo_registry import get_todo_registry
# Check for any raised todos and close them
todo_registry = get_todo_registry()
if metadata.todo_nudge:
# We have raised todos - check and close them
raised = todo_registry.get_raised_for(metadata.thread_id, metadata.own_name or "greeter")
for watcher in raised:
todo_registry.close(watcher.id)
# Register a todo watcher - we want to know when shouter responds
todo_registry.register(
thread_id=metadata.thread_id,
issuer=metadata.own_name or "greeter",
wait_for="ShoutedResponse",
from_listener="shouter",
description=f"waiting for shouter to process greeting for {payload.name}",
)
# Use platform.complete() for LLM call
# The platform assembles: system prompt (from registry) + peer schemas + history + user message
# The handler only provides the user message - no prompt building!
llm_response = await complete(
agent_name=metadata.own_name or "greeter",
thread_id=metadata.thread_id,
user_message=f"Greet {payload.name} enthusiastically. Respond with ONLY a short greeting sentence.",
temperature=0.9,
)
# Return clean dataclass + target - pump handles envelope
return HandlerResponse(
payload=GreetingResponse(
message=llm_response,
original_sender="response-handler",
),
to="shouter",
)
async def handle_shout(payload: GreetingResponse, metadata: HandlerMetadata) -> HandlerResponse:
"""
Handle GreetingResponse by shouting it back to original sender.
Flow: greeter -> shouter -> original_sender (response-handler)
"""
# Return clean dataclass + target - pump handles envelope
return HandlerResponse(
payload=ShoutedResponse(message=payload.message.upper()),
to=payload.original_sender,
)
async def handle_response_print(payload: ShoutedResponse, metadata: HandlerMetadata) -> None:
"""
Print the final response to the console.
Note: TUI console is available in OpenBlox. This handler uses simple stdout.
"""
print(f"\033[36m[response] {payload.message}\033[0m")