Network Working Group A. Ouchi Internet-Draft 4 November 2026 Intended status: Standards Track Expires: 8 May 2027 Problem Details for AI Agent Harness Errors draft-ouchi-agent-harness-errors-latest Abstract AI agents run language models inside a control program, the "harness", that parses model output, invokes tools, manages context, and enforces limits. Failures in this layer, such as malformed structured output, exceeded turn limits, or context window overflow, are currently reported in incompatible, implementation-specific ways. This document defines a problem type and extension members for Problem Details (RFC 9457) that describe agent harness errors in a machine-readable way, including whether an error is transient and whether it can be repaired by the model itself. It also establishes an IANA registry of harness error codes. Discussion Venues This note is to be removed before publishing as an RFC. Source for this draft and an issue tracker can be found at https://github.com/philtzjp/agent-errors. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on 8 May 2027. Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License. Table of Contents 1. Introduction 1.1. Scope 2. Conventions and Definitions 3. Problem Type 4. Extension Members 4.1. code 4.2. origin 4.3. retryable 4.4. model_recoverable 4.5. model_feedback 4.6. retry_after 4.7. attempts 4.8. max_attempts 4.9. limit 4.10. location 4.11. upstream 4.12. causes 5. Error Codes 5.1. Categories 5.2. Initial Codes 5.3. Code Semantics 5.4. Choosing Between Codes 6. Carrying Harness Errors 6.1. HTTP 6.2. Outside HTTP 6.3. JSON-RPC 6.4. Telemetry 7. Model Context Protocol Binding 7.1. Metadata Key 7.2. Server to Client 7.3. Client Side: Translating MCP Errors 7.4. Sampling 8. Agent2Agent Protocol Binding 8.1. Extension Declaration 8.2. Task Failures 8.3. Protocol Errors 8.4. Client Side: Translating A2A Errors 8.5. Nested Agents 9. Example 10. Security Considerations 11. Privacy Considerations 12. IANA Considerations 12.1. HTTP Problem Type 12.2. Agent Harness Error Codes Registry 13. References 13.1. Normative References 13.2. Informative References Mapping from Existing Implementations Open Issues MCP and A2A Examples Acknowledgments Author's Address 1. Introduction An AI agent is commonly built as a loop: a harness sends a prompt to a language model, interprets the model's output, executes any requested tool calls, appends the results to the context, and repeats until a stopping condition is reached. Errors can arise at several points in this loop. Some originate in upstream model APIs (rate limiting, overload), some in tools (timeouts, permission denial), and some in the harness itself (output that cannot be parsed, schema violations, exhausted turn or token budgets). Existing specifications cover parts of this space: * Protocol-level errors in agent protocols such as [MCP] and [A2A] use [JSON-RPC] error codes, which describe failures of the protocol exchange, not of the agent's reasoning loop. * Model APIs report termination reasons (for example, output truncated at a token limit, or a refusal), but these are not error codes and differ between providers. * Agent frameworks define their own exception types with incompatible names and granularity. * Observability conventions such as [OTEL-GENAI] provide an error.type attribute but do not define its values. As a result, a client that orchestrates agents from several vendors, or a supervising agent that delegates to sub-agents, cannot reliably decide how to react to a failure: retry unchanged, feed the error back to the model so it can correct itself, adjust a limit, escalate to a human, or give up. This document defines: 1. A Problem Details [RFC9457] problem type for agent harness errors (Section 3). 2. Extension members that carry a stable error code, the error's origin, and recovery hints (Section 4). 3. An initial set of error codes (Section 5) and an IANA registry for them (Section 12). 4. Guidance for carrying these objects outside HTTP, including in JSON-RPC error data and telemetry (Section 6). 1.1. Scope This document covers errors detected by the harness during an agent run. It does not define model behavior, tool semantics, agent-to- agent protocols, or how a harness should implement retries. It does not replace protocol-level error codes; it complements them. 2. Conventions and Definitions The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. Agent: A system that uses one or more language models to decide on and perform actions, usually over multiple steps. Harness: The non-model software that drives an agent: it constructs model inputs, interprets model outputs, executes tools, manages context, and enforces limits. Turn: One model invocation together with the processing of its output. Run: A sequence of turns performed to accomplish one task. Structured output: Model output that is required to conform to a machine-readable format, such as JSON conforming to a schema, or a tool call with typed arguments. Model feedback: Text that the harness supplies to the model in a subsequent turn to describe an error, so that the model can correct its behavior. 3. Problem Type This document registers the following problem type: Type URI: https://iana.org/assignments/http-problem-types#agent- harness-error Title: Agent Harness Error Recommended HTTP status code: Varies; see Section 6.1. A problem details object of this type MUST include the code member defined in Section 4. The title member SHOULD be the title registered for that code. The detail member SHOULD describe the specific occurrence in a form suitable for human operators. Consumers MUST use the code member, not title or detail, to determine the kind of error. Until the IANA registration in Section 12 is complete, implementations MAY use the type URI https://agenterrors.org/problems/harness-error. Consumers MUST treat the two type URIs as equivalent. RFC Editor: please remove the preceding paragraph before publication. 4. Extension Members The following extension members are defined for the agent-harness- error problem type. Consumers MUST ignore members they do not recognize, as required by [RFC9457]. 4.1. code A string containing a registered harness error code (Section 5). REQUIRED. Codes have the form ., where both parts consist of lowercase ASCII letters, digits, and underscores. The category groups related codes (Section 5.1). Implementations MAY define private codes using a category of the form x-; such codes MUST NOT be registered. A consumer that receives an unknown code within a known category SHOULD treat it as a generic error of that category. 4.2. origin A string identifying the component in which the error originated. OPTIONAL. Values are: model: The language model produced output that the harness could not accept. harness: The harness itself, including enforcement of its own limits. tool: A tool invoked by the harness. upstream: A remote service used by the harness, typically the model API. user: A human participant, for example by denying an approval. 4.3. retryable A boolean. OPTIONAL. If true, repeating the same operation without modification has a reasonable chance of success (for example, after a transient upstream failure). If false, repeating the operation unchanged is not expected to succeed. If absent, consumers SHOULD use the default recorded in the registry for the code. 4.4. model_recoverable A boolean. OPTIONAL. If true, the harness or a consumer can reasonably expect the model to correct the error if it is informed of it in a subsequent turn, for example by re-generating structured output that conforms to the schema. retryable and model_recoverable are independent. An error can be neither (for example, a turn limit), either, or both. If absent, consumers SHOULD use the default recorded in the registry for the code. 4.5. model_feedback A string. OPTIONAL. Text intended to be supplied to the model so that it can correct the error, such as a description of the schema violation. This member is distinct from detail, which is intended for humans. See Section 10 for considerations on its content. 4.6. retry_after A non-negative number of seconds after which a retry is advised. OPTIONAL. When the problem details object is carried in an HTTP response that also includes a Retry-After header field [RFC9110], the two SHOULD agree. 4.7. attempts A non-negative integer giving the number of attempts that the harness already made for the failed operation, including the one that produced this error. OPTIONAL. This lets a consumer distinguish a first failure from a failure that persisted through internal retries. 4.8. max_attempts A non-negative integer giving the number of attempts the harness was configured to make. OPTIONAL. 4.9. limit A JSON object describing a limit that was exceeded. OPTIONAL. It contains: name: A string naming the limit, for example turns, input_tokens, output_tokens, context_tokens, cost, or wall_clock_seconds. value: A number giving the configured limit. observed: A number giving the observed value, if known. unit: A string giving the unit, if not implied by name. For cost, an ISO 4217 currency code. 4.10. location A JSON object locating the error within the run. OPTIONAL. It MAY contain run_id (string), turn (integer, starting at 1), tool_name (string), tool_call_id (string), and pointer (a JSON Pointer string identifying the offending location within structured output). 4.11. upstream A JSON object containing raw information reported by an upstream component. OPTIONAL. It MAY contain provider (string), status (integer, an HTTP status code), code (string), and stop_reason (string). This member preserves vendor-specific detail; consumers SHOULD NOT depend on its contents for control flow. 4.12. causes An array of problem details objects that caused this error, ordered from most to least recent. OPTIONAL. For example, an output.retries_exhausted error can list the individual output.schema_violation errors that preceded it. 5. Error Codes 5.1. Categories +==========+====================================================+ | Category | Description | +==========+====================================================+ | output | Model output could not be accepted by the harness. | +----------+----------------------------------------------------+ | loop | A limit on the agent loop was reached, or the loop | | | is not progressing. | +----------+----------------------------------------------------+ | context | Context assembly or management failed. | +----------+----------------------------------------------------+ | tool | Tool resolution or execution failed. | +----------+----------------------------------------------------+ | policy | A policy, guardrail, refusal, or human decision | | | stopped the operation. | +----------+----------------------------------------------------+ | upstream | A remote dependency, typically the model API, | | | failed. | +----------+----------------------------------------------------+ | harness | The harness failed for another reason. | +----------+----------------------------------------------------+ Table 1: Error categories 5.2. Initial Codes The columns R and M give the registry defaults for retryable and model_recoverable respectively. +==============================+==============+========+=====+=====+ |Code |Title |Origin |R |M | +==============================+==============+========+=====+=====+ |output.malformed |Malformed |model |false|true | | |Output | | | | +------------------------------+--------------+--------+-----+-----+ |output.schema_violation |Output Schema |model |false|true | | |Violation | | | | +------------------------------+--------------+--------+-----+-----+ |output.truncated |Output |model |false|false| | |Truncated | | | | +------------------------------+--------------+--------+-----+-----+ |output.empty |Empty Output |model |true |true | +------------------------------+--------------+--------+-----+-----+ |output.unknown_tool |Unknown Tool |model |false|true | | |Requested | | | | +------------------------------+--------------+--------+-----+-----+ |output.invalid_tool_arguments |Invalid Tool |model |false|true | | |Arguments | | | | +------------------------------+--------------+--------+-----+-----+ |output.retries_exhausted |Output Retries|harness |false|false| | |Exhausted | | | | +------------------------------+--------------+--------+-----+-----+ |loop.max_turns_exceeded |Maximum Turns |harness |false|false| | |Exceeded | | | | +------------------------------+--------------+--------+-----+-----+ |loop.budget_exceeded |Budget |harness |false|false| | |Exceeded | | | | +------------------------------+--------------+--------+-----+-----+ |loop.timeout |Run Timeout |harness |false|false| +------------------------------+--------------+--------+-----+-----+ |loop.repetition_detected |Repetition |harness |false|true | | |Detected | | | | +------------------------------+--------------+--------+-----+-----+ |context.window_exceeded |Context Window|harness |false|false| | |Exceeded | | | | +------------------------------+--------------+--------+-----+-----+ |context.compaction_failed |Context |harness |true |false| | |Compaction | | | | | |Failed | | | | +------------------------------+--------------+--------+-----+-----+ |tool.not_available |Tool Not |tool |false|true | | |Available | | | | +------------------------------+--------------+--------+-----+-----+ |tool.execution_failed |Tool Execution|tool |false|true | | |Failed | | | | +------------------------------+--------------+--------+-----+-----+ |tool.timeout |Tool Timeout |tool |true |true | +------------------------------+--------------+--------+-----+-----+ |tool.permission_denied |Tool |harness |false|true | | |Permission | | | | | |Denied | | | | +------------------------------+--------------+--------+-----+-----+ |tool.sandbox_violation |Sandbox |harness |false|false| | |Violation | | | | +------------------------------+--------------+--------+-----+-----+ |policy.guardrail_triggered |Guardrail |harness |false|false| | |Triggered | | | | +------------------------------+--------------+--------+-----+-----+ |policy.model_refusal |Model Refusal |model |false|false| +------------------------------+--------------+--------+-----+-----+ |policy.content_filtered |Content |upstream|false|false| | |Filtered | | | | +------------------------------+--------------+--------+-----+-----+ |policy.approval_denied |Approval |user |false|true | | |Denied | | | | +------------------------------+--------------+--------+-----+-----+ |upstream.rate_limited |Upstream Rate |upstream|true |false| | |Limited | | | | +------------------------------+--------------+--------+-----+-----+ |upstream.overloaded |Upstream |upstream|true |false| | |Overloaded | | | | +------------------------------+--------------+--------+-----+-----+ |upstream.unavailable |Upstream |upstream|true |false| | |Unavailable | | | | +------------------------------+--------------+--------+-----+-----+ |upstream.authentication_failed|Upstream |upstream|false|false| | |Authentication| | | | | |Failed | | | | +------------------------------+--------------+--------+-----+-----+ |upstream.invalid_request |Upstream |upstream|false|false| | |Invalid | | | | | |Request | | | | +------------------------------+--------------+--------+-----+-----+ |upstream.invalid_response |Upstream |upstream|true |false| | |Invalid | | | | | |Response | | | | +------------------------------+--------------+--------+-----+-----+ |upstream.agent_failed |Remote Agent |upstream|false|true | | |Failed | | | | +------------------------------+--------------+--------+-----+-----+ |harness.cancelled |Run Cancelled |harness |false|false| +------------------------------+--------------+--------+-----+-----+ |harness.internal_error |Harness |harness |false|false| | |Internal Error| | | | +------------------------------+--------------+--------+-----+-----+ Table 2: Initial harness error codes 5.3. Code Semantics output.malformed: The model output could not be parsed in the required syntax, for example invalid JSON. output.schema_violation: The output was syntactically valid but did not conform to the required schema. location.pointer SHOULD identify the offending location. output.truncated: The output ended before completion because an output token limit was reached. Retrying unchanged is not expected to succeed; raising the limit or reducing the requested output may. output.empty: The model produced no usable content. output.unknown_tool: The model requested a tool that is not offered to it. output.invalid_tool_arguments: The model requested an offered tool with arguments that are missing, malformed, or do not conform to the tool's input schema. output.retries_exhausted: The harness re-prompted the model after one or more output.* errors and the configured number of attempts was exhausted. causes SHOULD list the underlying errors. loop.max_turns_exceeded: The run reached its configured maximum number of turns. loop.budget_exceeded: A token, cost, or other resource budget for the run was exhausted. limit SHOULD be present. loop.timeout: The run exceeded its wall-clock time limit. loop.repetition_detected: The harness determined that the run is not progressing, for example because the same tool call with the same arguments was repeated. context.window_exceeded: The assembled input exceeds the model's context window and could not be reduced. context.compaction_failed: An attempt to reduce the context, for example by summarization, failed. tool.not_available: A requested tool exists but cannot currently be used, for example because its server is disconnected. tool.execution_failed: A tool was invoked and reported failure. tool.timeout: A tool did not complete within its time limit. tool.permission_denied: The harness's permission configuration did not allow the tool call. tool.sandbox_violation: A tool attempted an operation prohibited by its sandbox. policy.guardrail_triggered: An input or output guardrail configured in the harness stopped the operation. policy.model_refusal: The model declined to perform the request. policy.content_filtered: A content filter applied by an upstream provider blocked the input or output. policy.approval_denied: A human denied an approval that the harness requested. upstream.rate_limited: The upstream service rejected the request due to rate limiting. retry_after SHOULD be present if known. upstream.overloaded: The upstream service reported that it is temporarily overloaded. upstream.unavailable: The upstream service could not be reached or returned a server error. upstream.authentication_failed: The upstream service rejected the harness's credentials. upstream.invalid_request: The upstream service rejected the request as invalid, for reasons not covered by a more specific code. upstream.invalid_response: The upstream service returned a response that does not conform to its protocol. upstream.agent_failed: A remote agent to which the harness delegated work reported that the delegated task failed. causes SHOULD contain the remote agent's harness error object, if available. See Section 8. harness.cancelled: The run was cancelled by its caller. harness.internal_error: The harness failed for a reason not covered by any other code. 5.4. Choosing Between Codes When more than one code applies, the harness SHOULD report the most specific code and MAY list others in causes. When an error from a lower layer is the direct cause, the harness SHOULD report the code that best describes what the consumer needs to do. For example, output that is invalid JSON because it was truncated SHOULD be reported as output.truncated, not output.malformed. 6. Carrying Harness Errors 6.1. HTTP When a harness error is returned in an HTTP response, the response SHOULD use the application/problem+json media type [RFC9457]. The following status codes are RECOMMENDED: +===========================================+========+ | Category or code | Status | +===========================================+========+ | upstream.rate_limited | 429 | +-------------------------------------------+--------+ | upstream.overloaded, upstream.unavailable | 503 | +-------------------------------------------+--------+ | upstream.* (other), upstream.agent_failed | 502 | +-------------------------------------------+--------+ | loop.timeout, tool.timeout | 504 | +-------------------------------------------+--------+ | policy.*, tool.permission_denied | 403 | +-------------------------------------------+--------+ | harness.internal_error | 500 | +-------------------------------------------+--------+ | others | 422 | +-------------------------------------------+--------+ Table 3: Recommended HTTP status codes 6.2. Outside HTTP A harness error object is a JSON object [RFC8259] and MAY be used outside HTTP, for example as the result of a library call, in a log record, or in a streamed event. In such cases the status member SHOULD be omitted. 6.3. JSON-RPC When a harness error is reported in a [JSON-RPC] error response, the harness error object SHOULD be placed in the data member of the JSON- RPC error object. The JSON-RPC code and message members continue to be governed by the protocol in use; this document does not allocate JSON-RPC error codes. A receiver that understands this document SHOULD prefer the code in data over the JSON-RPC code for deciding how to react. A receiver can recognize a harness error object in data by the value of its type member. Section 7 and Section 8 give specific rules for the Model Context Protocol and the Agent2Agent protocol. 6.4. Telemetry When harness errors are recorded using [OTEL-GENAI] or similar conventions, the code value SHOULD be used as the value of the error.type attribute. 7. Model Context Protocol Binding This section defines how harness errors are carried in [MCP], in both directions: an MCP server reporting an error to an MCP client (the harness), and a harness translating MCP errors it receives into harness error codes. MCP distinguishes protocol errors, which are JSON-RPC error responses, from tool execution errors, which are successful tools/call results with isError set to true. This binding preserves that distinction. 7.1. Metadata Key Harness error objects are carried in MCP _meta objects under the key org.agenterrors/harness-error. The value is a harness error object. The key uses a reverse-DNS prefix under a domain controlled by the editors of this document, as recommended by MCP for _meta keys. 7.2. Server to Client An MCP server that reports a tool failure SHOULD do so as a tool execution error, so that the model can see it and correct itself: * isError is true; * content contains at least one text item. If the harness error object has a model_feedback member, the first text item SHOULD contain that text; otherwise it SHOULD contain the detail text; * _meta contains the harness error object under the key in Section 7.1. The following codes SHOULD be reported as tool execution errors: tool.execution_failed, tool.timeout, tool.permission_denied, tool.not_available, tool.sandbox_violation, output.invalid_tool_arguments, and any upstream.* error encountered by the tool. Errors that prevent the request from being processed as a tool call at all SHOULD be reported as JSON-RPC errors with the harness error object in data, using the JSON-RPC codes required by MCP: +===========================+=========================+ | Harness error code | JSON-RPC code | +===========================+=========================+ | output.unknown_tool | -32602 (Invalid params) | +---------------------------+-------------------------+ | harness.internal_error | -32603 (Internal error) | +---------------------------+-------------------------+ | other errors not reported | -32603 | | as tool execution errors | | +---------------------------+-------------------------+ Table 4: MCP JSON-RPC codes for harness errors Because the content text is placed in the model's context, a server MUST NOT put information in it that it would not also put in model_feedback. 7.3. Client Side: Translating MCP Errors A harness acting as an MCP client SHOULD convert MCP errors into harness error objects as follows. If a harness error object is present (in _meta or in JSON-RPC data), its code SHOULD be used as is, and the harness SHOULD set origin to tool if absent. Otherwise: +============================+================================+ | MCP signal | Harness error code | +============================+================================+ | tools/call result with | tool.execution_failed | | isError: true | | +----------------------------+--------------------------------+ | JSON-RPC -32602 for a tool | output.unknown_tool | | name the model chose that | | | the server does not offer | | +----------------------------+--------------------------------+ | JSON-RPC -32602 for other | output.invalid_tool_arguments | | reasons | | +----------------------------+--------------------------------+ | JSON-RPC -32601 (Method | tool.not_available | | not found) | | +----------------------------+--------------------------------+ | JSON-RPC -32700, -32600 | harness.internal_error | +----------------------------+--------------------------------+ | JSON-RPC -32603 or other | tool.execution_failed | | server error | | +----------------------------+--------------------------------+ | Request timeout or | tool.timeout | | cancellation by the client | | | due to timeout | | +----------------------------+--------------------------------+ | Transport closed or server | tool.not_available | | not connected | | +----------------------------+--------------------------------+ | HTTP 401 or 403 from an | upstream.authentication_failed | | HTTP-based transport | | +----------------------------+--------------------------------+ Table 5: Translating MCP errors In each case the harness SHOULD preserve the original JSON-RPC code and message in the upstream member, with provider set to mcp. 7.4. Sampling When an MCP server requests sampling from a client and the client's harness fails, the client SHOULD return a JSON-RPC error with the harness error object in data. For example, if the user declines the sampling request, the code is policy.approval_denied. 8. Agent2Agent Protocol Binding This section defines how harness errors are carried in [A2A]. In A2A, failures of a task are reported through the task's status, while failures of the protocol exchange are reported as protocol errors. This binding preserves that distinction. 8.1. Extension Declaration An A2A agent that emits harness error objects SHOULD declare this in its Agent Card as an extension, with the extension URI https://agenterrors.org/ext/a2a/v1 and required set to false. That URI resolves to a description of this binding. Clients can activate the extension using the A2A extension activation mechanism. Agents MUST still report errors in the base A2A form, so that clients that do not support this extension continue to work. 8.2. Task Failures When a task ends because of a harness error, the remote agent SHOULD: * set the task state as given in Table 6; * include in the status message a text part containing the detail text; and * include in the status message a data part whose data is the harness error object. +===================================================+==========+ | Harness error code | A2A task | | | state | +===================================================+==========+ | harness.cancelled | canceled | +---------------------------------------------------+----------+ | policy.model_refusal, policy.guardrail_triggered, | rejected | | policy.content_filtered | | +---------------------------------------------------+----------+ | all other codes | failed | +---------------------------------------------------+----------+ Table 6: A2A task states for harness errors Some conditions are not errors in A2A and SHOULD NOT be reported as harness errors while the task can continue. For example, when a harness needs approval from a human, it uses the input-required state; only if the approval is denied and the task ends does policy.approval_denied apply. Likewise, needing credentials uses auth-required. 8.3. Protocol Errors A2A protocol errors SHOULD carry a harness error object in the JSON- RPC data member (or the corresponding error details in other A2A bindings) when the error was caused by a harness condition, such as upstream.rate_limited or harness.internal_error. The A2A error code is chosen according to A2A. 8.4. Client Side: Translating A2A Errors A harness that delegates to a remote agent over A2A treats the remote agent as an upstream component. If a harness error object is present, the harness SHOULD report upstream.agent_failed and place the received object in causes. The retryable member of the outer object SHOULD be copied from the received object. The model_recoverable member SHOULD be true only if the harness's own model could reasonably react, for example by rephrasing the delegated request. Otherwise: +===================================+==============================+ | A2A signal |Harness error code | +===================================+==============================+ | Task state failed |upstream.agent_failed | +-----------------------------------+------------------------------+ | Task state rejected |policy.model_refusal | +-----------------------------------+------------------------------+ | Task state canceled not requested |upstream.agent_failed | | by this harness | | +-----------------------------------+------------------------------+ | TaskNotFoundError (-32001) |upstream.invalid_request | +-----------------------------------+------------------------------+ | TaskNotCancelableError (-32002) |upstream.invalid_request | +-----------------------------------+------------------------------+ | PushNotificationNotSupportedError |upstream.invalid_request | | (-32003), | | | UnsupportedOperationError | | | (-32004), | | | ContentTypeNotSupportedError | | | (-32005) | | +-----------------------------------+------------------------------+ | InvalidAgentResponseError |upstream.invalid_response | | (-32006) | | +-----------------------------------+------------------------------+ | JSON-RPC -32700 to -32603 |upstream.invalid_request or | | |upstream.unavailable | +-----------------------------------+------------------------------+ | HTTP 429 |upstream.rate_limited | +-----------------------------------+------------------------------+ | HTTP 401 or 403 |upstream.authentication_failed| +-----------------------------------+------------------------------+ | Network failure or HTTP 5xx |upstream.unavailable | +-----------------------------------+------------------------------+ Table 7: Translating A2A errors The harness SHOULD preserve the original A2A error code, message, and task state in the upstream member, with provider set to a2a. 8.5. Nested Agents When an error passes through several agents, each harness wraps the received object in causes instead of rewriting it, so that the outermost consumer can see the original code and origin. A harness MAY truncate causes to limit size, and SHOULD keep the innermost entry. Section 10 applies to model_feedback received from remote agents. 9. Example A harness asked a model for JSON conforming to a schema. The model returned a field of the wrong type three times, and the harness gave up. HTTP/1.1 422 Unprocessable Content Content-Type: application/problem+json { "type": "https://iana.org/assignments/http-problem-types#agent-harness-error", "title": "Output Retries Exhausted", "detail": "Structured output failed validation after 3 attempts.", "code": "output.retries_exhausted", "origin": "harness", "retryable": false, "model_recoverable": false, "attempts": 3, "max_attempts": 3, "location": { "run_id": "run_8f2c", "turn": 5 }, "causes": [ { "type": "https://iana.org/assignments/http-problem-types#agent-harness-error", "title": "Output Schema Violation", "code": "output.schema_violation", "origin": "model", "model_recoverable": true, "model_feedback": "Field 'price' must be a number, got string.", "location": { "turn": 5, "pointer": "/items/0/price" } } ] } 10. Security Considerations Harness error objects may contain fragments of prompts, model output, tool arguments, or tool results. These can include sensitive data or secrets. Harnesses SHOULD NOT include such content in detail, model_feedback, upstream, or causes when the object is sent to a party that is not authorized to see it, and SHOULD redact credentials in all cases. The model_feedback member is designed to be inserted into a model's context. If it contains text derived from untrusted sources, such as tool results or remote agents, it can carry prompt-injection attacks. A harness that receives a harness error object from another party (for example, a sub-agent) MUST NOT insert that party's model_feedback into its own model's context with greater trust than the party's other output. The retryable and model_recoverable members are hints. A consumer that retries automatically MUST enforce its own limits on attempts, time, and cost, since a faulty or malicious producer could otherwise induce unbounded retries and resource consumption. Distinguishing policy.* errors in detail can help an attacker probe guardrails. Harnesses MAY report a less specific code, such as policy.guardrail_triggered, to untrusted consumers. 11. Privacy Considerations Run identifiers, tool names, and error details can reveal information about a user's activity. The considerations in Section 10 regarding disclosure apply. Logs containing harness error objects should be subject to the same retention and access policies as the conversation content they describe. 12. IANA Considerations 12.1. HTTP Problem Type IANA is requested to register the following entry in the "HTTP Problem Types" registry established by [RFC9457]: Type URI: https://iana.org/assignments/http-problem-types#agent- harness-error Title: Agent Harness Error Recommended HTTP status code: 422 Reference: This document 12.2. Agent Harness Error Codes Registry IANA is requested to create a new registry titled "Agent Harness Error Codes". Registrations are made under the Specification Required policy [RFC8126]. Each entry contains: Code: The error code, in the syntax defined in Section 4. Title: A short human-readable title. Default retryable: true or false. Default model_recoverable: true or false. Description: A brief description of the error. Reference: The defining specification. Designated experts should verify that a proposed code is not already covered by an existing code, that its category is appropriate, and that its defaults are justified. New categories require Standards Action. Codes in categories beginning with x- are reserved for private use and are not registered. The initial contents of the registry are the codes listed in Section 5, each with a Reference of this document. 13. References 13.1. Normative References [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, December 2017, . [RFC9457] Nottingham, M., Wilde, E., and S. Dalal, "Problem Details for HTTP APIs", RFC 9457, DOI 10.17487/RFC9457, July 2023, . 13.2. Informative References [A2A] A2A Project, "Agent2Agent (A2A) Protocol Specification", n.d., . [JSON-RPC] JSON-RPC Working Group, "JSON-RPC 2.0 Specification", 2013, . [MCP] Model Context Protocol, "Model Context Protocol Specification", n.d., . [OTEL-GENAI] OpenTelemetry, "Semantic Conventions for Generative AI Systems", n.d., . [RFC9110] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Semantics", STD 97, RFC 9110, DOI 10.17487/RFC9110, June 2022, . Mapping from Existing Implementations This appendix is informative. The following shows how common provider-specific signals could map to harness error codes. Names are given as examples and may change in the cited implementations. +=================================+============================+ | Signal | Harness error code | +=================================+============================+ | Model API stop reason | output.truncated | | indicating an output token | | | limit (e.g. max_tokens, length) | | +---------------------------------+----------------------------+ | Model API stop reason | policy.model_refusal | | indicating refusal | | +---------------------------------+----------------------------+ | Model API stop reason | policy.content_filtered | | indicating a content filter | | +---------------------------------+----------------------------+ | Model API stop reason | context.window_exceeded | | indicating context window | | | overflow | | +---------------------------------+----------------------------+ | HTTP 429 from a model API | upstream.rate_limited | +---------------------------------+----------------------------+ | HTTP 529 or 503 indicating | upstream.overloaded | | overload | | +---------------------------------+----------------------------+ | Framework "max turns exceeded" | loop.max_turns_exceeded | | exception | | +---------------------------------+----------------------------+ | Framework output-parser | output.malformed or | | exception | output.schema_violation | +---------------------------------+----------------------------+ | Framework "retries exhausted" | output.retries_exhausted | | exception for structured output | | +---------------------------------+----------------------------+ | Framework guardrail tripwire | policy.guardrail_triggered | +---------------------------------+----------------------------+ Table 8: Example mappings Open Issues This section is to be removed before publication. * Should the problem type be split into one type URI per category, instead of one type with a code member? * Is a separate IANA registry justified, or should codes be registered as individual problem types? * Should streaming partial results that accompany an error be in scope? * Should there be a code for model output that is well-formed but semantically invalid as judged by a validator (e.g. output.rejected)? * Relationship to work on agent protocols elsewhere in the IETF. * MCP _meta key: org.agenterrors/harness-error is controlled by the editors. If MCP adopts this mechanism (e.g. via an MCP SEP), the key could move to an MCP-reserved prefix. * Should the pre-registration problem type URI (https://agenterrors.org/problems/harness-error) remain valid permanently, or be retired after IANA registration? * The MCP and A2A error codes and mechanisms referenced here should be re-verified against the latest versions of those specifications before each draft revision. MCP and A2A Examples An MCP tool execution error. The text content is what the model sees; the _meta entry is for the harness. { "jsonrpc": "2.0", "id": 7, "result": { "isError": true, "content": [ { "type": "text", "text": "Argument 'date' must be YYYY-MM-DD, got '11/04'." } ], "_meta": { "org.agenterrors/harness-error": { "type": "https://iana.org/assignments/http-problem-types#agent-harness-error", "title": "Invalid Tool Arguments", "code": "output.invalid_tool_arguments", "origin": "model", "model_recoverable": true, "model_feedback": "Argument 'date' must be YYYY-MM-DD, got '11/04'.", "location": { "tool_name": "book_meeting", "pointer": "/date" } } } } } An A2A task that failed because the remote agent hit its turn limit: { "id": "task-123", "status": { "state": "failed", "message": { "role": "agent", "parts": [ { "kind": "text", "text": "Stopped after reaching the 50-turn limit." }, { "kind": "data", "data": { "type": "https://iana.org/assignments/http-problem-types#agent-harness-error", "title": "Maximum Turns Exceeded", "code": "loop.max_turns_exceeded", "origin": "harness", "retryable": false, "model_recoverable": false, "limit": { "name": "turns", "value": 50, "observed": 50 } } } ] } } } The delegating harness reports this to its own caller as upstream.agent_failed with the object above in causes. Acknowledgments TODO. Author's Address Arata Ouchi Email: ouchiarata@philtz.com