Connection lost. Reconnecting… attempt 1 of 8
Paused. Your work is held on the server.
Could not reconnect.
This session has expired on the server.
An unhandled error has occurred.
Sedna.UI
v0.31.0 · main

Steps and approvals

tier 2 — classes

What an agent thought, which tools it ran, what it means to do next, and what it asks permission for. The person stays in charge: every step can be opened and read, and nothing that writes happens before somebody says yes. All of it is markup the app writes, in the app's words, with no script. A run that spans many steps, branches and hand-offs is a workflow.

Reasoning

details.reasoning folds away the thinking behind an answer. It is a native <details>, so it opens from the keyboard and with scripting off; .reasoning-chevron turns as it opens, and .reasoning-body hangs the text off a rule under it. The summary says how long the agent thought, which is what most readers want to know without opening it.

Thought for 4 s

The question is about one night and one region, so the sync log for that window comes first. If the sync timed out, something else held the tables; the nightly maintenance jobs are the usual suspects.

Check the runbook for the timeout, then confirm against the lock history.

<details class="reasoning" style="max-width: 520px">
    <summary><i class="ri-arrow-right-s-line reasoning-chevron"></i><span>Thought for 4 s</span></summary>
    <div class="reasoning-body">
        <p>The question is about one night and one region, so the sync log for that window comes first. If the sync timed out, something else held the tables; the nightly maintenance jobs are the usual suspects.</p>
        <p>Check the runbook for the timeout, then confirm against the lock history.</p>
    </div>
</details>

Steps

ol.agent-steps is the tool calls behind an answer, in order. Each <li> carries data-state — pending, running, done or failed, the same words as .steps — an .agent-step-icon, and a details.agent-step that opens on what the step sent and what came back. .agent-step-meta is the count and the time, on the end. A running step's marker is a small orb.

Show the call, not a description of it. The .code-block inside is what lets a reader check the agent's work; a failed step keeps the error in its own words.

  1. Searched the runbook for “sync timeout”4 results · 1.2 s
    search(index: "runbook", query: "sync timeout", limit: 4)
  2. Read 3 log files on build-runner-042.4 s
    02:14:07 sync  ERROR  timed out after 600 s waiting for lock on orders
    02:25:31 maint INFO   vacuum finished on orders (681 s)
  3. Opened a shell on orders-console-01Permission denied
    ssh orders-console-01: the agent's role may not open a shell here
  4. Querying src-db-14 for locks held over 60 s0.8 s
    SELECT relation, mode, duration FROM lock_history WHERE duration > interval '60 s';
  5. Draft a new maintenance window

    Not started.

<ol class="agent-steps" style="max-width: 560px">
    <li data-state="done">
        <span class="agent-step-icon"><i class="ri-check-line"></i></span>
        <details class="agent-step">
            <summary><span class="agent-step-label"><i class="ri-search-line"></i><span>Searched the runbook for &ldquo;sync timeout&rdquo;</span></span><span class="agent-step-meta">4 results &middot; 1.2 s</span></summary>
            <pre class="code-block"><code>search(index: "runbook", query: "sync timeout", limit: 4)</code></pre>
        </details>
    </li>
    <li data-state="done">
        <span class="agent-step-icon"><i class="ri-check-line"></i></span>
        <details class="agent-step" open>
            <summary><span class="agent-step-label"><i class="ri-file-text-line"></i><span>Read 3 log files on build-runner-04</span></span><span class="agent-step-meta">2.4 s</span></summary>
            <pre class="code-block"><code>02:14:07 sync  ERROR  timed out after 600 s waiting for lock on orders
02:25:31 maint INFO   vacuum finished on orders (681 s)</code></pre>
        </details>
    </li>
    <li data-state="failed">
        <span class="agent-step-icon"><i class="ri-close-line"></i></span>
        <details class="agent-step">
            <summary><span class="agent-step-label"><i class="ri-terminal-box-line"></i><span>Opened a shell on orders-console-01</span></span><span class="agent-step-meta">Permission denied</span></summary>
            <pre class="code-block"><code>ssh orders-console-01: the agent's role may not open a shell here</code></pre>
        </details>
    </li>
    <li data-state="running">
        <span class="agent-step-icon"><span class="orb orb--sm" data-orb="working" role="img" aria-label="Running"></span></span>
        <details class="agent-step">
            <summary><span class="agent-step-label"><i class="ri-database-2-line"></i><span>Querying src-db-14 for locks held over 60 s</span></span><span class="agent-step-meta">0.8 s</span></summary>
            <pre class="code-block"><code>SELECT relation, mode, duration FROM lock_history WHERE duration &gt; interval '60 s';</code></pre>
        </details>
    </li>
    <li data-state="pending">
        <span class="agent-step-icon"></span>
        <details class="agent-step">
            <summary><span class="agent-step-label"><i class="ri-edit-line"></i><span>Draft a new maintenance window</span></span></summary>
            <p class="text-muted text-sm">Not started.</p>
        </details>
    </li>
</ol>

Plan

ul.agent-plan is what the agent means to do and how far it got: data-state on each item is done, current or skipped, or nothing for a step still to come. Mark the current one aria-current="step" too. A .progress above it gives the same count at a glance.

Plan2 of 5
  • Find when the sync stopped
  • Find what held the lock
  • Draft a new maintenance window
  • Ask for approval
  • Restart the sync by hand
<div class="card" style="max-width: 400px">
    <div class="card-head"><strong>Plan</strong><span class="text-muted text-sm text-nums">2 of 5</span></div>
    <div class="card-body sedna-col sedna-gap-3">
        <div class="progress" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" aria-label="Plan progress"><div class="progress-bar" style="width: 40%"></div></div>
        <ul class="agent-plan">
            <li data-state="done"><span class="agent-plan-mark"><i class="ri-check-line"></i></span><span class="agent-plan-label">Find when the sync stopped</span></li>
            <li data-state="done"><span class="agent-plan-mark"><i class="ri-check-line"></i></span><span class="agent-plan-label">Find what held the lock</span></li>
            <li data-state="current" aria-current="step"><span class="agent-plan-mark"><span class="orb orb--sm" data-orb="working" role="img" aria-label="In progress"></span></span><span class="agent-plan-label">Draft a new maintenance window</span></li>
            <li><span class="agent-plan-mark"></span><span class="agent-plan-label">Ask for approval</span></li>
            <li data-state="skipped"><span class="agent-plan-mark"><i class="ri-subtract-line"></i></span><span class="agent-plan-label">Restart the sync by hand</span></li>
        </ul>
    </div>
</div>

Asking before it acts

.agent-approval on a .card is the agent asking permission. .agent-approval-change is the change itself — what, from, to — and chips under it say what kind of change it is. Approve is .btn--go.btn--solid, because it lets the action out; taking control back is .btn--warn; deny is quiet. The library's own meanings, so an approval reads the same as every other outward action in the app.

Once the reader answers, data-state="approved" or "denied" swaps .agent-approval-actions for .agent-approval-result, which names who answered and when. Keep an undo there while the change can still be taken back.

Change a scheduleOps agent asks before it writes
src-db-14 · vacuum.start02:0003:30
Writes 1 setting Reversible
Approved by Alex Fischer
Change a scheduleOps agent asks before it writes
src-db-14 · vacuum.start02:0003:30
Approved by Alex Fischer at 09:31
<div class="sedna-row-wrap sedna-gap-3" style="align-items: start">
    <div class="card agent-approval" style="width: 380px">
        <div class="card-head">
            <div class="agent-approval-head">
                <span class="agent-approval-icon"><i class="ri-shield-check-line"></i></span>
                <span class="agent-approval-title"><strong>Change a schedule</strong><span>Ops agent asks before it writes</span></span>
            </div>
        </div>
        <div class="card-body sedna-col sedna-gap-3">
            <div class="agent-approval-change"><span>src-db-14 &middot; vacuum.start</span><s>02:00</s><i class="ri-arrow-right-line" aria-label="to" role="img"></i><strong>03:30</strong></div>
            <div class="chip-set">
                <span class="chip"><i class="ri-edit-line"></i><span class="chip-label">Writes 1 setting</span></span>
                <span class="chip"><i class="ri-loop-left-line"></i><span class="chip-label">Reversible</span></span>
            </div>
        </div>
        <div class="card-foot">
            <div class="agent-approval-actions">
                <button class="btn btn--ghost" type="button">Deny</button>
                <button class="btn btn--warn sedna-push" type="button">Take over</button>
                <button class="btn btn--go btn--solid" type="button"><i class="ri-check-line"></i><span>Approve</span></button>
            </div>
            <div class="agent-approval-result">
                <i class="ri-checkbox-circle-fill"></i><span>Approved by Alex Fischer</span>
            </div>
        </div>
    </div>

    <div class="card agent-approval" data-state="approved" style="width: 380px">
        <div class="card-head">
            <div class="agent-approval-head">
                <span class="agent-approval-icon"><i class="ri-shield-check-line"></i></span>
                <span class="agent-approval-title"><strong>Change a schedule</strong><span>Ops agent asks before it writes</span></span>
            </div>
        </div>
        <div class="card-body">
            <div class="agent-approval-change"><span>src-db-14 &middot; vacuum.start</span><s>02:00</s><i class="ri-arrow-right-line" aria-label="to" role="img"></i><strong>03:30</strong></div>
        </div>
        <div class="card-foot">
            <div class="agent-approval-actions">
                <button class="btn btn--ghost" type="button">Deny</button>
                <button class="btn btn--go btn--solid" type="button"><i class="ri-check-line"></i><span>Approve</span></button>
            </div>
            <div class="agent-approval-result">
                <i class="ri-checkbox-circle-fill"></i><span>Approved by Alex Fischer at 09:31</span>
                <button class="btn btn--sm btn--ghost sedna-push" type="button">Undo</button>
            </div>
        </div>
    </div>
</div>