running output pending
{"path":"CHANGELOG.md"}Waiting for the host response.
Preview the live recipe, then copy HTML or Install. CSS is composition-only: copy the listed component stylesheets.
Preview
{"actionId":"write-release-notes-01","path":"release-notes.md","content":"# Release notes\n\n- Added agent-ui recipes"}The file proposal is ready; the host has not written anything yet.
approval required
write-file · release-notes.md · actionId=write-release-notes-01 · exact action shown
Why this is safe
Draft only touches a new markdown file outside production paths and secret stores.
Code
<section class="au-tool-call" data-au-state="waiting" aria-label="Release notes tool call">
<header class="au-tool-call__header"><span class="au-tool-call__name">write-file</span><span class="au-tool-call__status">waiting</span></header>
<pre class="au-tool-call__args">{"actionId":"write-release-notes-01","path":"release-notes.md"}</pre>
<p class="au-tool-call__output">The file proposal is ready; the host has not written anything yet.</p>
</section>
<section class="au-approval-gate" data-au-state="waiting" data-action-id="write-release-notes-01" aria-labelledby="approval-title">
<header class="au-approval-gate__header">
<div>
<p class="au-approval-gate__eyebrow">approval required</p>
<h2 class="au-approval-gate__title" id="approval-title">Write release-notes.md?</h2>
</div>
</header>
<p class="au-approval-gate__action">write-file · release-notes.md · exact action shown</p>
<form class="au-approval-gate__footer" method="post">
<button class="au-btn au-btn--ghost" type="submit" name="decision" value="reject">Keep editing</button>
<button class="au-btn au-btn--primary" type="submit" name="decision" value="approve">Approve write</button>
</form>
</section>recipes.css in docs; product hosts copy component CSS only.Install
<link rel="stylesheet" href="tokens.css">
<link rel="stylesheet" href="themes.css">
<link rel="stylesheet" href="components/button/button.css">
<link rel="stylesheet" href="components/tool-call/tool-call.css">
<link rel="stylesheet" href="components/approval-gate/approval-gate.css">
<link rel="stylesheet" href="host-chrome.css">Arguments and output are rendered as text. The component does not parse markup, execute commands, or imply that a waiting call succeeded.
running output pending
{"path":"CHANGELOG.md"}Waiting for the host response.
success output received
{"path":"CHANGELOG.md","offset":0,"limit":30}Found 3 headings in the selected range.
error host rejected output
{"path":"release-notes.md"}Permission denied; write aborted by the host.
cancelled host stopped call
{"actionId":"write-release-notes-01"}The host cancelled this call before execution.
# agent-ui / recipe / tool-approval
recipe: tool-approval
purpose: Show exact tool args/output and require a human decision before host-owned execution.
install:
- tokens.css
- tool-call.css
- approval-gate.css
- button.css (actions)
tool_call_states: running | waiting | success | error | cancelled
approval_gate_states: waiting | success | error | cancelled
no_javascript: Exact arguments, output, action ID, and native decision form remain visible. Host receives the normal POST.
accessibility: Label both regions; expose status as text; use concrete button labels; status dots are decorative only.
security: Escape arguments and output. Bind approval to an immutable action ID plus exact serialized tool name and arguments.
host_owns: validation, authorization, execution, audit, and invalidation of stale approvals.
rules:
- Approved UI still needs host validation before anything runs.
- Prefer an optional __rationale that explains why the action is safe.
- For a policy choice before acting, stack approval-gate with ask-user-question.When the agent needs a policy choice before acting, stack an approval-gate (why paused + exact action) with an ask-user-question (bounded options). The host still owns authorization and whether work resumes.
approval-gate header and action line state the pause. ask-user-question options carry the judgement. Pair with question resume for the answered → resumed handoff. Message copy / regenerate footers stay host button actions inside chat-message.
Compose the tool call and approval gate when the next action has a meaningful consequence. Keep the trust boundary in the host.