Bassam Ismail
Make Agent Integration Failures Explicit Before Asking Humans
Agent operating noteJuly 11, 2026
Field note / operating model / team artifact

Make Agent Integration Failures Explicit Before Asking Humans

A practical field note from real Claude, Codex, and coding-agent work: the incident, engineering decision, reusable artifact, and limits.

Format
Field note + team artifact
Reading time
4 min
Primary use
Agent operating practice

Some of the worst agent experiences begin with a polite clarification question. The assistant asks for an issue ID, a document, or "a little more context." The human supplies it, only to discover later that the agent could not access the tracker, connector, or account in the first place.

That is not conversational friction. It is an integration failure being misreported as missing user input.

Agent context
Agent runtimeConnectorsReviewer
Pattern
Capability-aware failure
Output
Integration contract
Use when
An agent depends on private repositories, trackers, documents, cloud accounts, or browser state

A question concealed the real fault

In one of the mined sessions, the task depended on a private tracker and a linked document. The integration could not retrieve them, but the fallback path turned the lookup failure into a vague request for more information. From the user's side, the assistant appeared lazy. From the system side, a missing capability had been swallowed.

The important failure happened before the question was generated. The orchestration layer lost the difference between these states:

  1. The user did not specify the object.
  2. The object reference could not be resolved.
  3. The connector was unavailable.
  4. The identity was authenticated but lacked permission.
  5. The source returned data that was too stale to trust.

Collapsing those into needs_clarification makes the interface simpler for the implementation and much worse for everyone operating it.

Use a failure taxonomy the model cannot blur

The agent should receive structured tool failures and be required to preserve their category in its response.

CodeMeaningAgent behaviorHuman action
INPUT_MISSINGRequired intent or object was not suppliedAsk one precise questionProvide the missing decision or reference
REFERENCE_UNRESOLVEDA name or link maps to multiple or zero objectsShow candidates or the failed lookupDisambiguate only if needed
CAPABILITY_UNAVAILABLEThe runtime has no connector or tool for the sourceStop claiming it can inspect the sourceEnable the capability or change scope
ACCESS_DENIEDThe capability exists but this context lacks permissionName the denied scope without exposing secretsGrant bounded access or choose another operator
SOURCE_UNRELIABLEThe source is stale, partial, or contradictoryReturn available evidence with a confidence limitDecide whether to proceed under uncertainty

The distinction between CAPABILITY_UNAVAILABLE and ACCESS_DENIED is operationally important. Retrying a connector that does not exist is pointless. Re-authenticating a connector that exists may solve the task. A language model should not be expected to infer that distinction from an arbitrary error string.

The contract belongs below the prompt

Prompt instructions such as "do not ask vague questions" improve tone, not system truth. The tool boundary needs a typed result that preserves what failed.

type ToolFailure = {
  code:
    | "INPUT_MISSING"
    | "REFERENCE_UNRESOLVED"
    | "CAPABILITY_UNAVAILABLE"
    | "ACCESS_DENIED"
    | "SOURCE_UNRELIABLE";
  dependency: string;
  operation: string;
  retryable: boolean;
  requiredCapability?: string;
  safeFallback?: string;
  operatorMessage: string;
};

The model can turn operatorMessage into clear prose, but it should not be allowed to relabel the failure. I would also log the code separately from the generated response. Otherwise, a well-written apology can erase the only signal that a connector is broken.

For user-facing output, the minimum useful report is:

I could not read the linked tracker item.
 
Failure: ACCESS_DENIED
Attempted: read issue metadata and recent comments
Missing capability: tracker.issue:read for this project
What I can still do: inspect the local repository and prepare a provisional plan
What would unblock the full task: grant read access or paste an approved export

That is longer than "Can you send the details?" It is also actionable, auditable, and honest about scope.

Loud does not mean leaking internals

There is a real tradeoff. Raw provider errors can expose account names, internal object IDs, policy details, or security-sensitive topology. A fail-loud design should surface the category, dependency class, attempted operation, and unblocking action without dumping the connector's exception into the conversation.

It can also create alert fatigue. A transient timeout should not produce the same escalation as a missing connector. The taxonomy therefore needs retry semantics and a bounded retry policy. Retry only failures marked retryable, and stop when the dependency fingerprint has not changed.

What I would require in review

For every connected agent feature, test at least these paths:

  • The object is genuinely missing from the request.
  • The reference is ambiguous.
  • The connector is disabled.
  • The identity lacks the required read scope.
  • The source times out repeatedly.
  • A safe fallback exists, and the fallback is clearly labelled as partial.

The acceptance criterion is not merely that the UI shows an error. It is that each state leads to a different, correct next action.

An agent should ask a human for information only when the human owns that information. When the system owns the missing capability, the system should say so.

More to read