Coding agents generate functional code fast. But functional isn't always usable. The taste-skill toolkit injects aesthetic validation into agent workflows—art direction references, visual regression checks, and live browser verification instead of letting agents ship generic-looking UIs.
I integrated taste-skill into our internal AI-assisted frontend pipeline and ran it under realistic concurrent load to measure the actual performance cost of aesthetic quality gates.
Harness: Custom async Python orchestrator running 50 parallel agent sessions
Runtime: Docker containers, 4 vCPU / 8GB RAM per agent instance
LLM Provider: Claude 3.5 Sonnet via B-Lost relay (baseURL: "https://b-lost.com/v1") for consistent token accounting
Workload: Each agent generates a React component, applies art direction from reference images, and triggers a headless Chrome validation
import asyncio
from openai import AsyncOpenAI
client = AsyncOpenAI(
base_url="https://b-lost.com/v1",
api_key="your-key"
)
async def agent_with_taste(task_id):
response = await client.chat.completions.create(
model="claude-sonnet-3.5",
messages=[{"role": "user", "content": "Build a pricing card component"}]
)
validation = await taste_skill.validate(
code=response.choices[0].message.content,
reference_images=["./refs/pricing-card-good.png"],
browser_check=True
)
return validation
await asyncio.gather(*[agent_with_taste(i) for i in range(50)])
| Metric | Baseline (No Validation) | With taste-skill | Delta |
|---|---|---|---|
| Throughput | 47 completions/min | 31 completions/min | -34% |
| p50 Latency | 3.2s | 5.8s | +81% |
| p99 Latency | 6.1s | 12.4s | +103% |
| Memory Overhead | 340 MB/agent | 680 MB/agent | +100% |
| Browser Launch Penalty | N/A | 1.8s avg | — |
| Token Consumption | 2,100 tokens/task | 2,850 tokens/task | +36% |
The headless browser validation is the primary bottleneck. Launching Chrome, rendering the component, and capturing screenshots adds consistent 1.8s overhead per task. Memory doubles because each agent now holds a browser instance.
When does this make architectural sense?
Don't use taste-skill if:
Use taste-skill when:
After profiling, we cut p99 latency by 40% with these tuning steps:
Instead of spawning a fresh Chrome per validation:
// .taste-skill.config.js
module.exports = {
browser: {
poolSize: 5, // Reuse 5 warm browser instances
timeout: 8000,
viewport: { width: 1280, height: 720 }
}
}
This dropped average browser launch penalty from 1.8s to 0.3s.
The default sync image blocks the agent. Load reference images once at startup:
reference_cache = await taste_skill.preload_references([
"./refs/pricing-card-good.png",
"./refs/hero-section-clean.png",
"./refs/nav-minimal.png"
])
validation = await taste_skill.validate(
code=code,
reference_cache=reference_cache
)
Not every agent task needs visual validation. Route utility functions and API helpers around the browser check:
if task_type in ["ui_component", "page_layout"]:
validation = await taste_skill.validate(code, browser_check=True)
else:
validation = await taste_skill.validate(code, browser_check=False)
Our pipeline generates ~2,000 components per week. Without taste-skill:
With taste-skill:
Net savings: $900/week, or $46,800 annually.
If you're running Cursor with Claude or GPT-4 in agent mode, add taste-skill as a custom tool in .cursorrules:
agent_tools:
- name: taste_validation
command: taste-skill validate --code {generated_code} --ref ./refs
when: component_generation
Cursor will automatically pipe component code through taste-skill before presenting results.
The 2x memory and 80% latency penalty are non-trivial. But if your agents ship UI code that real users see, aesthetic validation pays for itself in reduced design debt and faster iteration cycles.
For internal CLI tools or backend services, skip it. For customer-facing frontends built by agents, the quality gate is cheaper than post-deployment fixes.