Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .github/workflows/site.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: "Deploy Site"

# Serves agenterrors.org from the Worker philtzjp-agenterrors-shared.
# The editor's copy built by "Update Editor's Copy" on gh-pages is copied under /draft/.
on:
push:
branches: [main]
paths:
- site/**
- .github/workflows/site.yml
workflow_run:
workflows: ["Update Editor's Copy"]
branches: [main]
types: [completed]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: site
cancel-in-progress: false

jobs:
deploy:
name: "Deploy Site"
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
environment: cloudflare
steps:
- name: "Checkout"
uses: actions/checkout@v6
with:
ref: main

- name: "Checkout Editor's Copy"
uses: actions/checkout@v6
with:
ref: gh-pages
path: gh-pages

- name: "Copy Editor's Copy"
run: cp gh-pages/draft-*.html gh-pages/draft-*.txt site/public/draft/

- name: "Deploy"
working-directory: site
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
run: npx --yes wrangler@4 deploy
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ draft-ouchi-agent-harness-errors.xml
package-lock.json
report.xml
!requirements.txt
!/site/public/**/*.html
/site/public/draft/draft-*
/site/.wrangler/
16 changes: 16 additions & 0 deletions site/public/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Not found — Agent Errors</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<main>
<header><a class="home" href="/">Agent Errors</a></header>
<h1>Not found</h1>
<p>This page does not exist. Start from the <a href="/">home page</a>.</p>
</main>
</body>
</html>
20 changes: 20 additions & 0 deletions site/public/draft/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Editor's copy — Agent Errors</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<main>
<header><a class="home" href="/">Agent Errors</a></header>
<h1>Editor's copy</h1>
<p>The editor's copy is rebuilt from the main branch of <a href="https://github.com/philtzjp/agent-errors">philtzjp/agent-errors</a> on every change.</p>
<ul>
<li><a href="/draft/draft-ouchi-agent-harness-errors.html">draft-ouchi-agent-harness-errors (HTML)</a></li>
<li><a href="/draft/draft-ouchi-agent-harness-errors.txt">draft-ouchi-agent-harness-errors (text)</a></li>
</ul>
</main>
</body>
</html>
66 changes: 66 additions & 0 deletions site/public/ext/a2a/v1/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>A2A extension v1 — Agent Errors</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<main>
<header><a class="home" href="/">Agent Errors</a></header>

<h1>A2A extension <code>v1</code></h1>

<p>This URI identifies an Agent2Agent (A2A) protocol extension. An agent that declares it reports harness errors as <a href="/problems/harness-error">harness error objects</a>:</p>
<pre><code>https://agenterrors.org/ext/a2a/v1</code></pre>

<p class="note">This page summarizes the A2A binding in the <a href="/draft/draft-ouchi-agent-harness-errors.html">editor's copy of the draft</a>. If they differ, the draft is authoritative.</p>

<h2>Declaring the extension</h2>
<p>Declare the extension in the Agent Card with <code>required</code> set to <code>false</code>. Agents still report errors in the base A2A form, so clients that do not support the extension keep working.</p>
<pre><code>"capabilities": {
"extensions": [
{ "uri": "https://agenterrors.org/ext/a2a/v1", "required": false }
]
}</code></pre>

<h2>Task failures</h2>
<p>When a task ends because of a harness error, the status message carries a text part with the <code>detail</code> text and a data part with the harness error object. The task state depends on the code:</p>
<table>
<tr><th>Harness error code</th><th>Task state</th></tr>
<tr><td><code>harness.cancelled</code></td><td><code>canceled</code></td></tr>
<tr><td><code>policy.model_refusal</code>, <code>policy.guardrail_triggered</code>, <code>policy.content_filtered</code></td><td><code>rejected</code></td></tr>
<tr><td>all other codes</td><td><code>failed</code></td></tr>
</table>
<p>Conditions that let the task continue, such as waiting for human approval or credentials, use <code>input-required</code> or <code>auth-required</code> and are not reported as harness errors.</p>

<h2>Example</h2>
<pre><code>{
"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://agenterrors.org/problems/harness-error",
"title": "Maximum Turns Exceeded",
"code": "loop.max_turns_exceeded",
"origin": "harness",
"retryable": false,
"limit": { "name": "turns", "value": 50, "observed": 50 }
} }
]
}
}
}</code></pre>

<h2>Delegating agents</h2>
<p>An agent that delegates to a remote agent reports the remote failure as <code>upstream.agent_failed</code> and places the received object in <code>causes</code>. Each agent wraps the received object instead of rewriting it, so the original code and origin stay visible at the outermost level.</p>

<footer><a href="https://github.com/philtzjp/agent-errors">github.com/philtzjp/agent-errors</a></footer>
</main>
</body>
</html>
47 changes: 47 additions & 0 deletions site/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Agent Errors</title>
<meta name="description" content="Machine-readable errors for AI agent harnesses, built on Problem Details (RFC 9457).">
<link rel="stylesheet" href="/style.css">
</head>
<body>
<main>
<header><a class="home" href="/">Agent Errors</a></header>

<h1>Machine-readable errors for AI agent harnesses</h1>

<p>An AI agent runs a language model inside a harness. The harness parses model output, calls tools, manages context, and enforces limits. When something fails in this layer, such as malformed structured output, an exceeded turn limit, or context overflow, each implementation reports it differently. Many of them classify upstream failures by matching message text.</p>

<p>Agent Errors defines a single error object for these failures. It is built on <a href="https://www.rfc-editor.org/rfc/rfc9457">Problem Details (RFC 9457)</a>, carries a stable error code, and says whether the error is transient and whether the model can repair it. It also defines bindings to the Model Context Protocol and the Agent2Agent protocol.</p>

<h2>Specification</h2>
<ul>
<li><a href="/draft/draft-ouchi-agent-harness-errors.html">Editor's copy of draft-ouchi-agent-harness-errors</a> (<a href="/draft/draft-ouchi-agent-harness-errors.txt">text</a>)</li>
<li><a href="/problems/harness-error">Problem type <code>harness-error</code></a></li>
<li><a href="/ext/a2a/v1">A2A extension <code>v1</code></a></li>
</ul>

<h2>Example</h2>
<pre><code>{
"type": "https://agenterrors.org/problems/harness-error",
"title": "Output Schema Violation",
"code": "output.schema_violation",
"origin": "model",
"retryable": false,
"model_recoverable": true,
"model_feedback": "Field 'price' must be a number, got string.",
"location": { "turn": 5, "pointer": "/items/0/price" }
}</code></pre>

<h2>Participate</h2>
<p>Work happens in the open on GitHub. Use <a href="https://github.com/philtzjp/agent-errors/issues">issues</a> for specific problems with the text, and <a href="https://github.com/philtzjp/agent-errors/discussions">discussions</a> for broader questions. Contributions are subject to the IETF Note Well; see <a href="https://github.com/philtzjp/agent-errors/blob/main/CONTRIBUTING.md">CONTRIBUTING</a>.</p>

<p class="note">This is an individual Internet-Draft. It has no formal standing in the IETF and may change at any time.</p>

<footer>agenterrors.org</footer>
</main>
</body>
</html>
86 changes: 86 additions & 0 deletions site/public/problems/harness-error/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Problem type: harness-error — Agent Errors</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<main>
<header><a class="home" href="/">Agent Errors</a></header>

<h1>Problem type <code>harness-error</code></h1>

<p>This URI identifies a Problem Details (<a href="https://www.rfc-editor.org/rfc/rfc9457">RFC 9457</a>) object that describes an error detected by an AI agent harness:</p>
<pre><code>https://agenterrors.org/problems/harness-error</code></pre>

<p>Implementations may use this URI until the problem type is registered with IANA as <code>https://iana.org/assignments/http-problem-types#agent-harness-error</code>. Consumers must treat the two URIs as equivalent.</p>

<p class="note">This page summarizes the <a href="/draft/draft-ouchi-agent-harness-errors.html">editor's copy of the draft</a>. If they differ, the draft is authoritative.</p>

<h2>Required member</h2>
<p><code>code</code> is a registered error code of the form <code>&lt;category&gt;.&lt;name&gt;</code>, for example <code>output.schema_violation</code>. Consumers decide what kind of error occurred from <code>code</code>, never from <code>title</code> or <code>detail</code>.</p>

<h2>Extension members</h2>
<table>
<tr><th>Member</th><th>Meaning</th></tr>
<tr><td><code>origin</code></td><td>Where the error originated: <code>model</code>, <code>harness</code>, <code>tool</code>, <code>upstream</code>, or <code>user</code>.</td></tr>
<tr><td><code>retryable</code></td><td>Whether repeating the same operation unchanged may succeed.</td></tr>
<tr><td><code>model_recoverable</code></td><td>Whether the model is likely to correct the error if it is told about it.</td></tr>
<tr><td><code>model_feedback</code></td><td>Text intended for the model, distinct from <code>detail</code>, which is for humans.</td></tr>
<tr><td><code>retry_after</code></td><td>Seconds after which a retry is advised.</td></tr>
<tr><td><code>attempts</code>, <code>max_attempts</code></td><td>Attempts already made, and the configured maximum.</td></tr>
<tr><td><code>limit</code></td><td>The exceeded limit: <code>name</code>, <code>value</code>, <code>observed</code>, <code>unit</code>.</td></tr>
<tr><td><code>location</code></td><td>Where in the run: <code>run_id</code>, <code>turn</code>, <code>tool_name</code>, <code>tool_call_id</code>, <code>pointer</code>.</td></tr>
<tr><td><code>upstream</code></td><td>Raw information from an upstream component, kept for diagnosis.</td></tr>
<tr><td><code>causes</code></td><td>Problem details objects that caused this one, most recent first.</td></tr>
</table>

<h2>Code categories</h2>
<table>
<tr><th>Category</th><th>Description</th></tr>
<tr><td><code>output</code></td><td>Model output could not be accepted by the harness.</td></tr>
<tr><td><code>loop</code></td><td>A limit on the agent loop was reached, or the loop is not progressing.</td></tr>
<tr><td><code>context</code></td><td>Context assembly or management failed.</td></tr>
<tr><td><code>tool</code></td><td>Tool resolution or execution failed.</td></tr>
<tr><td><code>policy</code></td><td>A policy, guardrail, refusal, or human decision stopped the operation.</td></tr>
<tr><td><code>upstream</code></td><td>A remote dependency, typically the model API, failed.</td></tr>
<tr><td><code>harness</code></td><td>The harness failed for another reason.</td></tr>
</table>
<p>The full list of codes, with default values for <code>retryable</code> and <code>model_recoverable</code>, is in the draft.</p>

<h2>Example</h2>
<pre><code>HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json

{
"type": "https://agenterrors.org/problems/harness-error",
"title": "Output Retries Exhausted",
"code": "output.retries_exhausted",
"origin": "harness",
"retryable": false,
"attempts": 3,
"max_attempts": 3,
"causes": [
{
"type": "https://agenterrors.org/problems/harness-error",
"title": "Output Schema Violation",
"code": "output.schema_violation",
"origin": "model",
"model_feedback": "Field 'price' must be a number, got string.",
"location": { "turn": 5, "pointer": "/items/0/price" }
}
]
}</code></pre>

<h2>Other bindings</h2>
<ul>
<li>MCP: the object goes in <code>_meta</code> under the key <code>org.agenterrors/harness-error</code>, or in JSON-RPC <code>error.data</code>.</li>
<li>A2A: see the <a href="/ext/a2a/v1">A2A extension</a>.</li>
</ul>

<footer><a href="https://github.com/philtzjp/agent-errors">github.com/philtzjp/agent-errors</a></footer>
</main>
</body>
</html>
18 changes: 18 additions & 0 deletions site/public/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
:root { color-scheme: light dark; --fg: #1d1d1f; --bg: #fff; --muted: #6e6e73; --rule: #d2d2d7; --code: #f5f5f7; --link: #0b62c4; }
@media (prefers-color-scheme: dark) { :root { --fg: #f5f5f7; --bg: #111; --muted: #a1a1a6; --rule: #333; --code: #1c1c1e; --link: #6cb0ff; } }
* { box-sizing: border-box; }
body { margin: 0; background: var(--bg); color: var(--fg); font: 16px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
main { max-width: 46rem; margin: 0 auto; padding: 3rem 1.25rem 4rem; }
header { margin-bottom: 2rem; }
header a.home { color: var(--muted); text-decoration: none; font-weight: 600; letter-spacing: .02em; }
h1 { font-size: 2rem; line-height: 1.25; margin: .5rem 0 1rem; }
h2 { font-size: 1.25rem; margin-top: 2.5rem; border-top: 1px solid var(--rule); padding-top: 1.5rem; }
a { color: var(--link); }
code, pre { font: 14px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; background: var(--code); border-radius: 4px; }
code { padding: .1em .3em; }
pre { padding: 1rem; overflow-x: auto; }
pre code { padding: 0; background: none; }
table { border-collapse: collapse; width: 100%; margin: 1rem 0; font-size: 15px; }
th, td { text-align: left; padding: .4rem .6rem; border-bottom: 1px solid var(--rule); vertical-align: top; }
.note { color: var(--muted); font-size: 15px; }
footer { margin-top: 3rem; color: var(--muted); font-size: 14px; }
17 changes: 17 additions & 0 deletions site/wrangler.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Static-assets-only Worker that serves agenterrors.org.
// The Worker, the zone, and the deploy token live in the same Cloudflare account,
// so wrangler attaches the custom domain on deploy.
{
"$schema": "https://unpkg.com/wrangler/config-schema.json",
"name": "philtzjp-agenterrors-shared",
"compatibility_date": "2026-11-01",
"workers_dev": false,
"routes": [
{ "pattern": "agenterrors.org", "custom_domain": true },
],
"assets": {
"directory": "./public",
"html_handling": "auto-trailing-slash",
"not_found_handling": "404-page",
},
}
Loading