Show What the Design Agent Rejected Before Asking a Human to Approve It

# ai# design# a11y# productmanagement
Show What the Design Agent Rejected Before Asking a Human to Approve ItHaley

Teams are using design agents to produce polished UI options, but most approval screens still show...

Teams are using design agents to produce polished UI options, but most approval screens still show only the selected option. That hides the decision's real risk: the agent often discards the accessible alternative, the conservative option, or the one that would have failed more slowly. The current rush to give AI design taste is producing beautiful screenshots and silent regressions. Approving a single recommendation without seeing those discards is a decision made with missing evidence.

A concrete failure: a product designer asks an agent to simplify a settings screen. The agent proposes a two-level menu because it shortens the route. The approval card shows the before/after and a confidence score. The reviewer approves. Two releases later, a keyboard-only user reports the old skip-to-main shortcut no longer exists. The agent had generated and rejected a flattened layout that preserved that shortcut, but the rejection never appeared in the approval UI. The consequence lands on the reviewer's queue; the reversal costs a release. The point of reversibility is the feature flag, but only if the reviewer knows it exists.

Instead of hiding the discarded option in chat history, move it into the approval card. The card should make the rejected alternative visible, state why it was discarded, separate evidence from design hypotheses, and give the reviewer a way to send the work back without silently fixing it.

A small decision-card schema can be that gate. The fields below are the minimum useful record; translate them to whatever payload your UI already accepts.

const decisionCard = {
  decisionId: 'settings-nav-2026-08-14',
  chosenProposal: 'Two-level settings menu',
  chosenReasoning: 'Reduces route depth from 4 to 2',
  rejectedAlternatives: [
    {
      option: 'Flattened settings list',
      whyRejected: 'Longer visual scan in a 15-second thumbnail test',
      evidenceFor: 'Preserves existing keyboard shortcut order',
      evidenceAgainst: 'Adds two spoken headings for screen reader users',
      accessibilityImpact: 'keeps quick-nav landmarks; minor heading verbosity',
      missingEvidence: 'No keyboard-user task result',
      reversible: 'Yes, behind a feature flag'
    }
  ],
  requiredEvidence: [
    'keyboard reordering remains possible',
    'screen reader heading order is sequenced'
  ],
  reviewerAction: 'approve | send_back | request_evidence'
};
Enter fullscreen mode Exit fullscreen mode

This is not a prompt template. It is the record a reviewer must be able to inspect before clicking approve. The evidenceFor and evidenceAgainst fields force a separation: one records the observation, the other records the cost. The missingEvidence field is the stop condition. If a required piece of evidence is absent, the UI blocks approval and offers a hand-back action instead of a quiet fix.

MonkeyCode's free model access and free server option (30 million free tokens) make this practical to run as a small review service. Disclosure: This article was prepared as part of MonkeyCode's product outreach. You can ask the model to generate more than one candidate and then explain its own rejects, and host the decision log instead of keeping it in chat transcripts. A small server can accept a card and refuse any card that lacks rejected alternatives or required evidence. The following is an unexecuted sketch; replace the env vars with your provider's endpoint and model name.

const http = require('node:http');

const requiredFields = [
  'chosenProposal',
  'chosenReasoning',
  'rejectedAlternatives',
  'requiredEvidence'
];

function hasRunnableStopCondition(card) {
  return card.requiredEvidence.some(
    (item) => typeof item === 'string' && item.trim().length > 0
  );
}

const cards = new Map();

const server = http.createServer((req, res) => {
  if (req.method !== 'POST' || req.url !== '/cards') {
    res.statusCode = 405;
    return res.end(JSON.stringify({ error: 'POST /cards only' }));
  }

  let body = '';
  req.on('data', (chunk) => (body += chunk));
  req.on('end', () => {
    const card = JSON.parse(body);

    const missing = requiredFields.filter((field) => !card[field]);
    if (missing.length > 0 || !hasRunnableStopCondition(card)) {
      res.statusCode = 422;
      return res.end(
        JSON.stringify({
          error: 'approval card is missing decision evidence',
          missing_fields: missing
        })
      );
    }

    cards.set(card.decisionId, card);
    res.statusCode = 201;
    res.end(
      JSON.stringify({ status: 'recorded', decisionId: card.decisionId })
    );
  });
});

server.listen(process.env.PORT || 3000);
Enter fullscreen mode Exit fullscreen mode

This server does not call the model. It validates the decision record after the model has generated candidates. That separation is deliberate: the model can create options, but the review gate owns the evidence requirements.

The user flow should make rejected options visible before approval can proceed:

Designer requests options
      |
Agent drafts N design candidates
      |
Generation step records chosen + rejected alternatives
      |
Reviewer opens approval card
      |
Card shows chosen, rejected options, evidence gaps
      |
Reviewer chooses: approve / send back / request missing evidence
      |
Action and reasoning append to decision log
Enter fullscreen mode Exit fullscreen mode

The stop condition is not 'the model sounds confident.' It is 'the card contains the required evidence fields and the reviewer can identify what was discarded.'

A research protocol can test whether this gate changes real decisions. Run three scenarios:

Scenario Missing evidence stop condition Success measure
Keyboard user path Approve is disabled until accessibilityImpact is non-empty Reviewer can explain the discarded keyboard option before approving
Screen reader heading order Approve is disabled until heading sequence is recorded No heading regressions escape without a recorded alternative
Empty or error state Approve is disabled until error text is included Hand-back rate falls; reviewer no longer types corrections silently

Each scenario uses the same card schema. The evidence is not a benchmark score; it is a field the reviewer can inspect.

Accessibility checks for the card itself:

  • The approval card must not hide rejectedAlternatives behind a hover or collapsed section.
  • It should announce the presence of missing evidence before the approve button in the focus order.
  • Contrast must meet WCAG 1.4.3 for the evidence gap badge or text.
  • The hand-back action should preserve the reviewer's rationale as a review comment instead of discarding it.

Who should not use this approach: teams that cannot send design content through a third-party model, teams that need fine-grained access control before human review, production systems where the review card becomes another prompt template, and teams that expect free servers to hold secrets or provide a permanent production SLA. Free allocations can change; verify current limits before building a dependency on them.

The useful part is not the model. It is the decision record. Put rejected options in the reviewer's card, block approval on missing evidence, and make the hand-back visible. You can try this with MonkeyCode's free model and free server option using the card schema above; start with one design decision rather than an entire review pipeline.