跪拜 Guibai
← Back to the summary

AI Assistants Fail Silently: Four Safeguards That Catch 'Successful' Errors

The Most Dangerous Thing About AI Assistants Isn't Errors — It's 'Looking Successful': I Added Four Safeguards to My Workflow

AI assistants' truly headache-inducing moments are often not when a red error pops up on the page, but when they quietly tell you: it's done.

The file was indeed generated, but half the content is missing; the message was indeed sent, but to the wrong recipient; the spreadsheet was indeed updated, but the same record appears twice; the article was indeed submitted, but the body saved on the platform is empty.

None of these are 'failures' in the traditional sense. The request might have returned a 200, the tool might have returned success: true, and the model might have given a summary that looks very complete. But from the user's outcome perspective, the task wasn't truly completed.

I later added a simple principle to my AI workflows:

No action can be judged as complete based solely on 'successful invocation'; it must undergo result verification.

Going a step further, if verification fails, there must be a clear fallback path: retry, switch tools, check status, preserve the scene, or stop and ask for human confirmation.

This methodology doesn't depend on any specific model, nor is it limited to any particular Agent framework. As long as a workflow reads files, writes data, calls web pages, or sends messages, it's worth adding these safeguards.

1. Why 'Success' Can Deceive

A complete automated action contains at least three layers of results:

Was the request sent?
    ↓
Was it accepted by the service?
    ↓
Was the user's desired result actually produced?

Many tools only tell you about the first two layers.

For example, calling a 'create document' API and getting back a document ID only proves the server accepted the creation request. It doesn't prove the body was written completely, much less that the title, code blocks, and links are all correct.

Similarly, getting a piece of text after calling a model only proves the model generated output. It doesn't prove the output meets the task requirements, much less that the model executed file writing, web page operations, or message sending on your behalf.

I now break down 'action success' into four questions:

  1. Was the request sent?
  2. Was it accepted by the server?
  3. Is the result complete?
  4. Does the result meet the user's goal?

The first three can be checked programmatically; the fourth sometimes requires human confirmation.

2. First Safeguard: Define 'Completion Criteria' for Results

Without completion criteria, there is no real verification.

The requirement 'generate an article' is too vague; a program cannot judge what counts as complete. Replacing it with checkable criteria makes things much clearer:

A file task can be defined like this:

from pathlib import Path


def verify_article(path: str) -> tuple[bool, list[str]]:
    file = Path(path)
    issues = []

    if not file.exists():
        issues.append("File does not exist")
        return False, issues

    content = file.read_text(encoding="utf-8").strip()
    if len(content) < 2000:
        issues.append("Body length insufficient")
    if not content.startswith("# "):
        issues.append("Missing top-level heading")
    if content.count("`" * 3) % 2 != 0:
        issues.append("Code fences are not paired")

    return not issues, issues

This code isn't intelligent, but it's far more reliable than a sentence like 'please confirm the article has been generated.'

Verification rules don't need to be written complexly all at once. First cover the most error-prone areas, then gradually supplement based on real problems. The key is to turn 'I think it should be done' into 'these conditions have all been met.'

3. Second Safeguard: Treat Read Results as Untrusted Input

AI workflows frequently need to read web pages, documents, or API return values. There's an easy pitfall here: reading successfully doesn't mean you've read the target content.

The web page might return a CAPTCHA page, the API might return an error object, the document might only have loaded the first half, and an expired login might also result in a redirect page with a normal status code.

So I check both status and content simultaneously:


def verify_page(status_code: int, text: str) -> tuple[bool, str]:
    if status_code != 200:
        return False, f"HTTP status abnormal: {status_code}"

    body = text.strip()
    if len(body) < 200:
        return False, "Body too short"

    blocked = ("CAPTCHA", "Login to continue", "Too many requests")
    for marker in blocked:
        if marker in body:
            return False, f"Suspected block page: {marker}"

    return True, "ok"

When checking content, you can't just look at length. An error page tens of thousands of words long is still an error page. A more practical approach combines several signals:

For JSON responses, you also need to distinguish between 'parseable' and 'business success.'


def verify_response(data: dict) -> tuple[bool, str]:
    if not isinstance(data, dict):
        return False, "Return value is not an object"
    if data.get("err_no") not in (None, 0):
        return False, data.get("err_msg", "Business error")
    if not data.get("data"):
        return False, "Missing business data"
    return True, "ok"

The more an AI assistant can operate on the external world, the less you should treat 'having a return value' as 'the return value is trustworthy.'

4. Third Safeguard: Write Operations Must Prevent Duplicates

A failed read operation at most means you didn't get the result; a failed write operation can leave behind duplicate results.

This is the type of problem I pay the most attention to in automated processes.

Suppose a request to create a record has already executed successfully on the server, but the client didn't receive the response due to a network timeout. Retrying directly at this point could result in two completely identical records:

Client initiates creation
    ↓
Server creates successfully
    ↓
Response times out during return
    ↓
Client mistakenly thinks it failed
    ↓
Creates again
    ↓
Duplicate record

Therefore, write operations cannot just have 'retry on failure'; they also need three-step protection:

1. Check for duplicates before execution

Based on title, subject, content summary, or business ID, first check if an identical object exists.

2. Use idempotency keys

Generate a fixed request identifier for the same action. Even if the client submits repeatedly, the server can recognize it as the same operation.

3. Post-execution check-back

If the response is lost, first query the final state, then decide whether to compensate. Don't directly recreate.

This process can be abstracted as:


def safe_create(find_existing, create, key):
    existing = find_existing(key)
    if existing:
        return existing, "already_exists"

    result = create(key)
    if result is not None:
        return result, "created"

    # When creation result is uncertain, check back first, don't retry directly
    existing = find_existing(key)
    if existing:
        return existing, "confirmed_after_timeout"

    return None, "needs_review"

This logic looks more troublesome than 'try again after failure,' but the thing external systems fear most is duplicate creation. The cost of one extra query is usually more worthwhile than cleaning up duplicate data later.

5. Fourth Safeguard: Give Every Fallback a Boundary

Fallback is not unlimited retries.

If a task keeps auto-retrying after failure, the system can fall into three loops:

I set three boundaries for fallback actions.

Count Boundary

Retry the same path at most once or twice. If exceeded, switch paths or stop.

Cost Boundary

Prioritize low-cost fallbacks: re-read, reduce task scope, check login status, then consider switching browsers or heavier models.

Risk Boundary

Read operations can auto-retry; write operations need status checks first; external actions like publishing, sending, or deleting are best stopped at a human confirmation point.

A simple fallback decision could be:

Read failure → Brief retry
Still fails → Switch read method
Content suspected incomplete → Preserve scene and re-validate
Write result uncertain → Query status
Before external publishing → Human confirmation

A truly stable system isn't the one with the most backup plans, but the one that knows when to stop automation.

6. Human Confirmation Is Not a Process Failure

Many people building Agents view human confirmation as insufficient automation. My view is the opposite: retaining confirmation points before high-risk actions is a sign of mature process design.

Tasks can be divided into three categories:

Low Risk: Can be completed automatically

Reversible: Complete automatically, but keep versions

External Impact: Default requires confirmation

During human confirmation, there's no need for the user to re-read the entire process; just show the content that truly impacts the result: title, target, change summary, final version, and risk warning.

Automation is responsible for lowering the cost of choice; the user is responsible for making the final judgment at key nodes.

7. Logs Should Record 'Why,' Not Just 'What Happened'

Many automation logs only write:

Task completed
Task failed
Retry succeeded

Such logs are not very helpful for troubleshooting. More valuable is recording the basis for decisions:

Task: Create article draft
Default path: Request timed out
Fallback action: Query whether title already exists
Query result: Found draft with same title
Final judgment: Initial creation already succeeded, will not resubmit
Status: Awaiting human confirmation

I usually only keep four types of information:

If a fallback is triggered, record one more thing: why the fallback occurred.

This way, the next time a similar problem occurs, you don't need to re-guess what the system actually did.

8. Start with a Minimal Verifier

If you're preparing to add a fallback mechanism to your AI workflow, I don't recommend starting by designing a complex Agent orchestration system.

First, pick the action most prone to problems and add a verifier to it:

  1. Define success criteria;
  2. Check if the result is complete;
  3. Distinguish between reads and writes;
  4. Set a retry limit for failures;
  5. When the result is uncertain, check status first;
  6. Retain confirmation points before high-risk actions;
  7. Write the fallback reason into the log.

Once these seven steps run smoothly, then consider model switching, tool degradation, and multi-path orchestration.

The value of an AI assistant is not making everything happen automatically, but making things still controllable after automation.

The default path can be responsible for speed, the fallback path for stability; the verifier judges the result, and human confirmation guards the boundary.

When these layers are put together, an AI assistant won't turn a small problem into a public incident just because of one timeout, one empty response, or one misunderstanding.

It might still make mistakes, but at least every time it errs, you'll know where it went wrong, what to do next, and when to stop and ask a person.

#ArtificialIntelligence #AIWorkflow #Automation #Agent #Programmer

Comments

Top 1 from juejin.cn, machine-translated. The original thread is authoritative.

用户292254077519 1 likes

The point 'when the result of a write operation is uncertain, first check back, don't retry directly' is especially important. We've encountered similar situations in long-text parsing and translation workflows: individual chunks appear successful, but after merging, we find missing code blocks, figure captions, or formulas. Later, we had to make structural gates, protection-item hashes, and per-chunk QA into hard conditions. The more specific the completion criteria, the less likely the Agent is to mistake a pretty output for a delivered result.