0Pricing
Claude Architect · 강의

isError 플래그

MCP 응답에서 실패를 명확하게 알립니다

isError 플래그은(는) CoddyKit의 무료 Claude Architect 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Claude Architect 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Claude Architect 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

Why Signalling Failure Matters

When an MCP tool runs, two things can happen: it succeeds, or it fails. The model needs to know which — clearly and unambiguously — to decide what to do next.

If a failure looks like a normal result, the agent may treat garbage as truth, hallucinate a recovery, or silently move on. The fix is a dedicated failure signal: the isError flag.

In this lesson you'll learn how to signal failure cleanly so the agentic loop can route intelligently instead of guessing.

What isError Actually Does

A tool result carries an isError boolean. When isError is true, you're telling Claude: this tool did not produce a valid result — treat the content as a failure report, not data.

This is structurally separate from your tool's normal output. The model can branch on it without parsing prose: success path vs. failure path. That separation is the whole point.

tool_result = {
    "type": "tool_result",
    "tool_use_id": tool_use.id,
    "is_error": True,
    "content": "..."  # structured failure report
}

Generic Errors Block Recovery

The classic anti-pattern is a generic error string like "Operation failed". It tells the model that something went wrong but nothing it can act on.

Can it retry? Was the input malformed? Did the user lack permission? Is there partial data to salvage? A generic message answers none of these — so the agent stalls or improvises badly.

Generic errors block recovery. Structured errors enable intelligent routing.

The Anatomy of a Structured Error

A well-formed MCP error pairs isError: true with a structured body. The exam-standard fields are:

  • errorCategory — one of transient, validation, business, permission
  • isRetryable — can the same call succeed if tried again?
  • message — human-readable explanation
  • attempted_query — exactly what the tool tried to do
  • partial_results — anything usable it managed to gather

Together these let the model decide: retry, reformulate, escalate, or proceed with partial data.

{
    "isError": true,
    "errorCategory": "transient",
    "isRetryable": true,
    "message": "Upstream inventory service timed out after 5s",
    "attempted_query": "GET /inventory?sku=ABX-19",
    "partial_results": null
}

errorCategory Drives the Decision

The four categories aren't decoration — each implies a different next action:

  • transient — temporary fault (timeout, rate limit). Usually retryable; recover locally.
  • validation — bad input. Don't blind-retry; fix the arguments first.
  • business — a rule was violated (e.g. refund exceeds policy). Often needs escalation, not retry.
  • permission — caller lacks access. Retrying won't help; escalate or request credentials.

The category turns a vague failure into a routing instruction the model can follow.

isRetryable: Don't Make the Model Guess

Whether a failure is worth retrying is often invisible from the message text alone. Make it explicit with isRetryable.

A timeout (transient) is retryable. A malformed argument (validation) is not — retrying the same bad input just fails again. A permission denial is not retryable without new credentials.

By stating isRetryable directly, you keep retry decisions deterministic instead of leaving them to probabilistic text-reading.

{
    "isError": true,
    "errorCategory": "validation",
    "isRetryable": false,
    "message": "sku must match pattern ^[A-Z]{3}-[0-9]{2}$; got 'abx19'",
    "attempted_query": "lookup_inventory(sku='abx19')"
}

attempted_query Preserves Context

When the model decides how to recover, it needs to know what was actually tried. Including attempted_query means the agent can reformulate intelligently instead of repeating the same failing call.

This is part of good error propagation: structured context = failure type, attempted query, partial results, and alternatives. The richer the context, the better the recovery routing.

partial_results: Don't Throw Away Good Data

A tool can fail and still have gathered something useful. A multi-source lookup might return 3 of 5 records before the 4th source times out.

Returning partial_results alongside the error lets the agent proceed with what it has, annotate the gap, and avoid restarting from zero. Discarding partial data on any failure wastes work and degrades answers.

{
    "isError": true,
    "errorCategory": "transient",
    "isRetryable": true,
    "message": "3 of 5 sources responded; 2 timed out",
    "attempted_query": "search_catalog(term='thermostat')",
    "partial_results": [{"id": 11}, {"id": 12}, {"id": 19}]
}

Failure vs. a Valid Empty Result

A critical distinction: an access failure is not the same as a valid empty result.

  • isError: true — the tool couldn't complete (timeout, denied, bad input). Maybe retry or escalate.
  • isError: false with empty content — the tool ran fine and the honest answer is "no matches."

Conflating these is a common bug: an empty search marked as an error triggers pointless retries, while a real failure marked as empty hides the problem. Keep them distinct.

{
    "isError": false,
    "errorCategory": null,
    "message": "Query succeeded; 0 orders match customer C-7781",
    "results": []
}

Recover Locally, Escalate When You Must

The structured signal drives where recovery happens. In a multi-agent system, a subagent should recover transient faults locally — retry the timeout, re-issue the call — and only bubble up failures it truly can't resolve.

When it does escalate, it passes the structured error with partial results so the coordinator can decide: route elsewhere, ask for more identifiers, or surface the gap. Never silently suppress a failure, and never abort the whole workflow over one recoverable fault.

Putting It Together in a Tool

Inside an MCP tool handler, wrap the work and return a structured error on failure instead of letting an exception leak as a generic string.

Notice how each branch sets isError, a category, and a retry hint — giving the agentic loop everything it needs to route the next step deterministically.

def lookup_order(order_id: str):
    try:
        order = db.fetch(order_id)
        if order is None:
            return {"isError": False, "results": []}  # valid empty
        return {"isError": False, "results": [order]}
    except TimeoutError as e:
        return {
            "isError": True,
            "errorCategory": "transient",
            "isRetryable": True,
            "message": str(e),
            "attempted_query": f"fetch(order_id={order_id})",
            "partial_results": None,
        }

Quick Check: Choosing the Right Error Shape

A subagent's MCP tool queries a customer's order history. One of three backend shards is unreachable; the other two return 8 orders. What should the tool return?

Recap: Signalling Failure Cleanly

Key takeaways for the isError flag:

  • isError: true is the structural signal that a tool did not produce valid data — separate from normal output.
  • Pair it with errorCategory (transient / validation / business / permission), isRetryable, message, attempted_query, and partial_results.
  • Generic errors like "Operation failed" block recovery; structured errors enable intelligent routing.
  • Distinguish an access failure from a valid empty result — never mark "no matches" as an error.
  • Recover transient faults locally; escalate non-recoverable ones with partial results. Avoid silent suppression and avoid aborting the whole workflow on one fault.

자주 묻는 질문

“isError 플래그” 강의는 무료인가요?

네 — “isError 플래그” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Claude Architect 강의 전체를 잠금 해제할 수 있습니다. Claude Architect 강의에는 총 4개의 강의가 포함되어 있습니다.

“isError 플래그”에서 뭘 배우나요?

MCP 응답에서 실패를 명확하게 알립니다 브라우저에서 직접 실행하는 실습 코드로 Claude Architect을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Claude Architect을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Claude Architect은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.

“isError 플래그” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Claude Architect 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Claude Architect 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. isError 플래그
  2. 오류 범주
  3. 재시도 가능 메타데이터 및 부분 결과
  4. 안티 패턴: 일반적인 오류 메시지
← Claude Architect(으)로 돌아가기