Install any skill in seconds. Free to start, no credit card required.
Get Started Free →awslabs/agui-author
Author live dashboard UI from an agent via the `emit_ui` MCP tool. Emit one of six allow-listed components (approval_card, choice_prompt, diff_summary, progress, metric, agent_card) with JSON props and it renders in any AG-UI client watching the fleet.
Passed 17 of 19 test cases with the skill, and 6 of 19 without it.
and 14 more in the full report
13 fixed7 passed either way2 still failing0 broke
Tokens, turns and time describe resource use, not a dollar price.
One of 12 test cases the skill fixed. Same model, same prompt, with and without the skill.
Which environment variable on the CAO server enables the AG-UI generative UI surface?
| Checked | Without skill | With skill |
|---|---|---|
| Names CAO_AGUI_ENABLED or CAO_MCP_APPS_ENABLED. | Missed | Passed |
The instructions your model reads when the skill loads.
CAO exposes an AG-UI stream (GET /agui/v1/stream) that any dashboard —
CopilotKit, the AG-UI Dojo, or a plain EventSource — renders
without CAO-specific code. As an agent you can push a declarative UI intent
onto that stream with the emit_ui MCP tool. The operator sees a rendered card,
not raw text — and because every provider's intents render uniformly, they can't
tell (and don't need to) which CLI agent produced which card.
The surface must be enabled on the server (CAO_AGUI_ENABLED=true or
CAO_MCP_APPS_ENABLED=true — the two surfaces share one event source). When it
is disabled, emit_ui returns {"ok": false, "reason": "AG-UI surface disabled…"}
— treat that as a no-op, not an error.
You may emit only a closed allow-list of named components with JSON props.
There is no HTML, no script, no eval, no iframe. The intent is validated
server-side against the allow-list before it reaches the stream:
iframe, script) is refused — the tool
raises a ValueError; nothing is rendered.props must be JSON-serializable and are bounded to 8 KB — an oversized
or non-serializable payload is rejected at the emit_ui boundary (HTTP 400,
the tool raises a ValueError), so a bad payload never reaches the bus.emit_ui(component: str, props: dict) -> {"ok", "event_id", "component"}
component must be one of: approval_card, choice_prompt, diff_summary,
progress, metric, agent_card.
test cases passed, vs 6 / 19 without
More skills from the same source and nearby in the registry, with their headline benchmark lift.