High-level components for building conversational agent UIs.
Install
mkdir -p .claude/skills/castella-agent-ui && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/11071" && unzip -o skill.zip -d .claude/skills/castella-agent-ui && rm skill.zipInstalls to .claude/skills/castella-agent-ui
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Build chat interfaces and agent management UIs with Castella. Create chat components, display tool calls, manage multiple agents, and build agent hubs.Key capabilities
- →Create chat interfaces
- →Display tool calls
- →Manage agent hubs
- →Render message history
How it works
It provides high-level Python components that connect to A2A agents to render chat windows, message lists, and tool call visualizations.
Inputs & outputs
When to use castella-agent-ui
- →Building agent hubs
- →Displaying tool calls
- →Managing chat history
- →Creating custom chat windows
About this skill
Castella Agent UI Components
High-level components for building conversational interfaces and agent management UIs.
When to use: "create a chat UI", "AgentChat", "chat with agent", "display tool calls", "multi-agent chat", "AgentHub", "message history", "MultiAgentChat"
Quick Start (3 Lines)
Create a chat UI connected to an A2A agent:
from castella.agent import AgentChat
chat = AgentChat.from_a2a("http://localhost:8080")
chat.run()
Installation
uv sync --extra agent # Agent UI + A2A + A2UI support
AgentChat
High-level chat component with minimal setup:
from castella.agent import AgentChat
# Connect to A2A agent
chat = AgentChat.from_a2a("http://localhost:8080")
chat.run()
# Or use custom handler function
chat = AgentChat(
handler=lambda msg: f"Echo: {msg}",
title="Echo Bot",
system_message="Welcome! How can I help?",
)
chat.run()
Parameters
AgentChat(
a2a_client=None, # A2AClient instance
handler=None, # Custom handler: (str) -> str
title="Agent Chat", # Window title
placeholder="Type...", # Input placeholder
system_message=None, # Initial system message
show_agent_card=True, # Show agent card for A2A
width=700, # Window width
height=550, # Window height
)
Factory Methods
# From A2A agent URL
chat = AgentChat.from_a2a("http://localhost:8080")
# From A2A client
from castella.a2a import A2AClient
client = A2AClient("http://localhost:8080")
chat = AgentChat.from_a2a(client)
Chat Components
Build custom chat UIs with lower-level components.
ChatContainer
Complete chat UI (messages + input):
from castella.agent import ChatContainer, ChatMessageData
from castella.core import ListState
messages = ListState([])
def on_send(text: str):
messages.append(ChatMessageData(role="user", content=text))
# Get response from agent...
response = get_response(text)
messages.append(ChatMessageData(role="assistant", content=response))
container = ChatContainer(
messages,
on_send=on_send,
title="My Chat",
placeholder="Type a message...",
)
ChatMessage
Display a single message:
from castella.agent import ChatMessage, ChatMessageData
msg = ChatMessageData(
role="assistant", # "user", "assistant", or "system"
content="Hello! How can I help you today?",
)
widget = ChatMessage(msg)
ChatInput
Text input with send button:
from castella.agent import ChatInput
input_widget = ChatInput(
placeholder="Type a message...",
on_send=lambda text: print(f"Sent: {text}"),
)
ChatView
Scrollable message list:
from castella.agent import ChatView
from castella.core import ScrollState
scroll_state = ScrollState()
view = ChatView(messages, scroll_state=scroll_state)
ChatMessageData
Message data structure:
from castella.agent import ChatMessageData, ToolCallData
msg = ChatMessageData(
role="assistant",
content="Let me check the weather for you.",
tool_calls=[
ToolCallData(
id="call_1",
name="get_weather",
arguments={"location": "Tokyo"},
result="Sunny, 22°C",
)
],
)
Tool Call Visualization
ToolCallView
Display a single tool call:
from castella.agent import ToolCallView
tool = ToolCallView(
name="get_weather",
arguments={"location": "Tokyo"},
result="Sunny, 22°C",
)
ToolHistoryPanel
Display history of tool calls:
from castella.agent import ToolHistoryPanel
from castella.core import ListState
tool_calls = ListState([...])
panel = ToolHistoryPanel(tool_calls)
Agent Card Display
AgentCardView
Show agent information:
from castella.agent import AgentCardView
from castella.a2a import A2AClient
client = A2AClient("http://agent.example.com")
card_view = AgentCardView(
client.agent_card,
show_skills=True,
compact=False,
)
AgentListView
Display multiple agents:
from castella.agent import AgentListView
agent_list = AgentListView(
agents=[client1.agent_card, client2.agent_card],
on_select=lambda card: print(f"Selected: {card.name}"),
)
MultiAgentChat
Tabbed interface for multiple agents:
from castella.agent import MultiAgentChat
from castella.a2a import A2AClient
chat = MultiAgentChat({
"weather": A2AClient("http://localhost:8081"),
"travel": A2AClient("http://localhost:8082"),
"restaurant": A2AClient("http://localhost:8083"),
})
chat.run()
Each agent gets its own chat tab with independent message history.
AgentHub
Agent discovery and management dashboard:
from castella.agent import AgentHub
from castella.a2a import A2AClient
# Create hub
hub = AgentHub(title="Agent Hub")
# Add agents
hub.add_agent("http://localhost:8081")
hub.add_agent(A2AClient("http://localhost:8082"))
hub.run()
Or initialize with agents:
hub = AgentHub(agents=[
A2AClient("http://agent1.example.com"),
A2AClient("http://agent2.example.com"),
])
Features:
- Left panel: List of agents with add/remove
- Right panel: Chat with selected agent
- URL input to add new agents at runtime
Scroll Position Pattern
Important pattern for chat UIs - set scroll before adding message:
class ChatComponent(Component):
def __init__(self):
super().__init__()
self._messages = ListState([])
self._messages.attach(self)
self._scroll_state = ScrollState()
# DON'T attach scroll state
def _send_message(self, text: str):
# Add user message
self._messages.append(ChatMessageData(role="user", content=text))
# Get response...
response = get_response(text)
# Set scroll BEFORE adding response (so re-render picks it up)
self._scroll_state.y = 999999
self._messages.append(ChatMessageData(role="assistant", content=response))
Lazy State Attachment
For components created before App exists (like AgentHub):
class MyComponent(Component):
def __init__(self):
super().__init__()
self._state = State(0)
self._states_attached = False
# DON'T attach here - App may not exist yet
def view(self):
# Attach lazily when view() is called
if not self._states_attached:
self._state.attach(self)
self._states_attached = True
return Text(str(self._state()))
Message Markdown Support
Messages support Markdown formatting:
msg = ChatMessageData(
role="assistant",
content="""
# Weather Report
**Tokyo**: Sunny, 22°C
| Day | High | Low |
|-----|------|-----|
| Mon | 24°C | 18°C |
| Tue | 22°C | 17°C |
""",
)
Best Practices
- Use ScrollState without attaching for chat scroll
- Set scroll position before adding new messages
- Use Markdown for rich message content
- Handle loading states for async responses
- Use ListState.append() for new messages
- Use lazy state attachment for hub-style components
Reference
references/components.md- Component API referencereferences/data_classes.md- ChatMessageData, ToolCallData typesscripts/- Executable examples (simple_chat.py, multi_agent.py, agent_hub.py)
When not to use it
- →Applications without A2A agents
Prerequisites
Limitations
- →Limited to Castella component ecosystem
How it compares
It offers pre-built, agent-aware UI components specifically for A2A architectures instead of generic web frameworks.
Compared to similar skills
castella-agent-ui side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| castella-agent-ui (this skill) | 0 | 7mo | Review | Intermediate |
| textual | 143 | 9mo | Review | Intermediate |
| qt-qml | 0 | 5mo | No flags | Intermediate |
| pyside6-qml-views | 0 | 5mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
textual
KyleKing
Expert guidance for building TUI (Text User Interface) applications with the Textual framework. Invoke when user asks about Textual development, TUI apps, widgets, screens, CSS styling, reactive programming, or testing Textual applications.
qt-qml
sleepyvani
>
pyside6-qml-views
sleepyvani
Use this skill when creating QML view files, designing QML component hierarchies, building layouts, styling QML controls, creating reusable QML components, implementing QML navigation / page switching, or working with QML resources. Covers QML file structure, component patterns, Material/Controls st
anywidget-marimo
diegosouzapw
Toolkit for generating custom widgets from scratch for Marimo.
nano-image-generator
solidSpoon
Generate images using Nano Banana Pro (Gemini 3 Pro Preview). Use when creating app icons, logos, UI graphics, marketing banners, social media images, illustrations, diagrams, or any visual assets. Triggers include phrases like 'generate an image', 'create a graphic', 'make an icon', 'design a logo', 'create a banner', or any request needing visual content.
dashboard-view-builder
gitwalter
Building and managing premium statistical dashboards, RAG explorer UIs, warehouse log monitors, and real-time visualization centers.