npx claudepluginhub joshuaoliphant/claude-plugins --plugin hexagonal-agentsThis skill uses the workspace's default tool permissions.
Build web applications where an AI agent serves as the UI layer, dynamically generating HTML in response to user messages. The agent sits at the center of a hexagonal architecture — tools handle data (ports), FastAPI/HTMX handle transport (adapters), and a skill file teaches the agent its entire UI vocabulary.
references/architecture.mdreferences/component_library.mdreferences/debugging.mdreferences/enhanced_ux.mdreferences/eval_patterns.mdreferences/multi_agent_patterns.mdreferences/saved_views.mdreferences/sdk_reference.mdreferences/sqlite_persistence.mdscripts/init_hexagonal_app.pytemplates/agent.py.templatetemplates/main.py.templatetemplates/skill_ui.md.templatetemplates/tools.py.templateGenerates interactive, semantic HTML prototypes for human+AI agent use with Tailwind+DaisyUI (Tier A) or React+shadcn/ui+Vite (Tier B). Includes Playwright previews for iteration.
Designs agent-native applications with agent tool parity, atomic primitives, context injection, agent-UI communication, and mobile checkpoint patterns. Use for agentic systems, tool surfaces, and agent-aware UIs.
Deploys websites, apps, AI agents to Agentuity production. Creates new projects, migrates Express/Next.js/Vite apps, restructures code, and manages full deploy workflows.
Share bugs, ideas, or general feedback.
Build web applications where an AI agent serves as the UI layer, dynamically generating HTML in response to user messages. The agent sits at the center of a hexagonal architecture — tools handle data (ports), FastAPI/HTMX handle transport (adapters), and a skill file teaches the agent its entire UI vocabulary.
uv init, uv add, uv run uvicornclaude_agent_sdk package. Provides ClaudeSDKClient, ClaudeAgentOptions, TextBlock, @tool, create_sdk_mcp_server.ANTHROPIC_API_KEY environment variable.Browser (static shell + HTMX)
│ POST /agent {message: "..."}
▼
FastAPI (HTTP Adapter)
│ agent.process(message)
▼
Agent (ClaudeSDKClient)
│ System prompt = skill file
│ Calls tools for data, generates HTML
▼
Tools (MCP Server)
│ Pure data operations → JSON
Tools are the agent's interface to data. Each tool:
@tool("list_items", "Get all items. Returns array of items with id, name, status.", {})
async def list_items(args: dict[str, Any]) -> dict[str, Any]:
items = load_items()
return {"content": [{"type": "text", "text": json.dumps({"items": items, "count": len(items)})}]}
Return format: {"content": [{"type": "text", "text": json.dumps(data)}]}. Errors: add "is_error": True.
Tool names in allowed_tools must follow: mcp__{server_key}__{tool_name}
The skill file (app/skills/ui.md) teaches the agent how to generate UI. Critical requirements:
hx-post, hx-target, hx-vals.Every button: <button hx-post="/agent" hx-target="#content" hx-vals='{"message":"action"}'>
Every form: <form hx-post="/agent" hx-target="#content"> with hidden message input.
For the complete design system (colors, typography, spacing) and full component library (cards, lists, forms, alerts, empty states, etc.):
→ references/component_library.md
For detailed hexagonal architecture explanation and SDK API details:
→ references/architecture.md
→ references/sdk_reference.md
Load any stored feedback preferences before starting:
python ${PLUGIN_ROOT}/scripts/feedback_manager.py hexagonal-agents show-feedback
If feedback entries exist, apply them throughout app scaffolding:
Locate the init script within this skill's directory and run it:
uv run {skill_root}/scripts/init_hexagonal_app.py my-app-name --domain items
Where {skill_root} is the installed path of this skill (e.g., the directory containing this SKILL.md). Alternatively, create the project structure manually following the layout below.
Creates:
my-app-name/
├── pyproject.toml
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI application
│ ├── agent.py # Agent wrapper
│ ├── tools.py # MCP tool definitions
│ └── skills/
│ └── ui.md # UI skill file
└── data/ # Created at runtime
Edit app/tools.py. Create an MCP server with CRUD operations:
def create_tools_server():
return create_sdk_mcp_server(
name="app_tools", version="1.0.0",
tools=[list_items, get_item, create_item, update_item, delete_item]
)
Edit app/skills/ui.md to teach the agent its UI vocabulary. Structure:
# Application UI Skill
## Critical Output Rules (raw HTML only, never markdown)
## Design System (colors, typography)
## Component Patterns (with full HTML examples)
## Available Tools (when to call each)
## Response Patterns (user intent → tool → UI)
Use components from references/component_library.md.
The agent wrapper (app/agent.py) connects everything:
class Agent:
def __init__(self):
self.tools_server = create_tools_server()
self._allowed_tools = ["mcp__app_tools__list_items", ...]
async def _ensure_connected(self):
skill_content = SKILL_PATH.read_text()
options = ClaudeAgentOptions(
system_prompt=skill_content,
mcp_servers={"app_tools": self.tools_server},
allowed_tools=self._allowed_tools,
permission_mode="acceptEdits",
)
self.client = ClaudeSDKClient(options=options)
await self.client.connect()
async def process(self, message: str) -> str:
await self._ensure_connected()
await self.client.query(message)
html_parts = []
async for msg in self.client.receive_response():
for block in msg.content:
if isinstance(block, TextBlock):
html_parts.append(block.text)
return self._clean_html("\n".join(html_parts))
The FastAPI app (app/main.py) serves the base template and handles agent messages:
@app.post("/agent", response_class=HTMLResponse)
async def handle_message(request: Request):
form_data = await request.form()
message = str(form_data.get("message", "")).strip()
# Append extra form fields to message
extra_fields = [f"{k}={v}" for k, v in form_data.items() if k != "message" and v]
if extra_fields:
message = f"{message} [{', '.join(extra_fields)}]"
html = await agent.process(message)
return html
Before considering the app ready, verify:
To adapt for a new domain:
_allowed_tools listA running hexagonal agent web application:
cd my-app-name
export ANTHROPIC_API_KEY=your_key_here
uv run uvicorn app.main:app --reload
# Open http://localhost:8000
As the app matures:
→ references/multi_agent_patterns.md — Specialized agents communicating via semantic messages
→ references/saved_views.md — Progressive UI caching to reduce latency and API costs
→ references/sqlite_persistence.md — Migrate from JSON to SQLite for ACID compliance
→ references/enhanced_ux.md — Animated loading states and visual feedback
→ references/eval_patterns.md — Systematic testing with pydantic-evals
For common issues (agent outputs markdown instead of HTML, tools not being called, HTMX not working, blank responses):
→ references/debugging.md