diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml new file mode 100644 index 0000000..058f2cb --- /dev/null +++ b/.github/workflows/site.yml @@ -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 diff --git a/.gitignore b/.gitignore index 48c2eb5..69d3fff 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/site/public/404.html b/site/public/404.html new file mode 100644 index 0000000..1821e5b --- /dev/null +++ b/site/public/404.html @@ -0,0 +1,16 @@ + + + + + +Not found — Agent Errors + + + +
+
Agent Errors
+

Not found

+

This page does not exist. Start from the home page.

+
+ + diff --git a/site/public/draft/index.html b/site/public/draft/index.html new file mode 100644 index 0000000..b8ac672 --- /dev/null +++ b/site/public/draft/index.html @@ -0,0 +1,20 @@ + + + + + +Editor's copy — Agent Errors + + + +
+
Agent Errors
+

Editor's copy

+

The editor's copy is rebuilt from the main branch of philtzjp/agent-errors on every change.

+ +
+ + diff --git a/site/public/ext/a2a/v1/index.html b/site/public/ext/a2a/v1/index.html new file mode 100644 index 0000000..002c089 --- /dev/null +++ b/site/public/ext/a2a/v1/index.html @@ -0,0 +1,66 @@ + + + + + +A2A extension v1 — Agent Errors + + + +
+
Agent Errors
+ +

A2A extension v1

+ +

This URI identifies an Agent2Agent (A2A) protocol extension. An agent that declares it reports harness errors as harness error objects:

+
https://agenterrors.org/ext/a2a/v1
+ +

This page summarizes the A2A binding in the editor's copy of the draft. If they differ, the draft is authoritative.

+ +

Declaring the extension

+

Declare the extension in the Agent Card with required set to false. Agents still report errors in the base A2A form, so clients that do not support the extension keep working.

+
"capabilities": {
+  "extensions": [
+    { "uri": "https://agenterrors.org/ext/a2a/v1", "required": false }
+  ]
+}
+ +

Task failures

+

When a task ends because of a harness error, the status message carries a text part with the detail text and a data part with the harness error object. The task state depends on the code:

+ + + + + +
Harness error codeTask state
harness.cancelledcanceled
policy.model_refusal, policy.guardrail_triggered, policy.content_filteredrejected
all other codesfailed
+

Conditions that let the task continue, such as waiting for human approval or credentials, use input-required or auth-required and are not reported as harness errors.

+ +

Example

+
{
+  "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 }
+        } }
+      ]
+    }
+  }
+}
+ +

Delegating agents

+

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

+ + +
+ + diff --git a/site/public/index.html b/site/public/index.html new file mode 100644 index 0000000..75a0ae9 --- /dev/null +++ b/site/public/index.html @@ -0,0 +1,47 @@ + + + + + +Agent Errors + + + + +
+
Agent Errors
+ +

Machine-readable errors for AI agent harnesses

+ +

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.

+ +

Agent Errors defines a single error object for these failures. It is built on Problem Details (RFC 9457), 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.

+ +

Specification

+ + +

Example

+
{
+  "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" }
+}
+ +

Participate

+

Work happens in the open on GitHub. Use issues for specific problems with the text, and discussions for broader questions. Contributions are subject to the IETF Note Well; see CONTRIBUTING.

+ +

This is an individual Internet-Draft. It has no formal standing in the IETF and may change at any time.

+ + +
+ + diff --git a/site/public/problems/harness-error/index.html b/site/public/problems/harness-error/index.html new file mode 100644 index 0000000..7c9c51b --- /dev/null +++ b/site/public/problems/harness-error/index.html @@ -0,0 +1,86 @@ + + + + + +Problem type: harness-error — Agent Errors + + + +
+
Agent Errors
+ +

Problem type harness-error

+ +

This URI identifies a Problem Details (RFC 9457) object that describes an error detected by an AI agent harness:

+
https://agenterrors.org/problems/harness-error
+ +

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

+ +

This page summarizes the editor's copy of the draft. If they differ, the draft is authoritative.

+ +

Required member

+

code is a registered error code of the form <category>.<name>, for example output.schema_violation. Consumers decide what kind of error occurred from code, never from title or detail.

+ +

Extension members

+ + + + + + + + + + + + +
MemberMeaning
originWhere the error originated: model, harness, tool, upstream, or user.
retryableWhether repeating the same operation unchanged may succeed.
model_recoverableWhether the model is likely to correct the error if it is told about it.
model_feedbackText intended for the model, distinct from detail, which is for humans.
retry_afterSeconds after which a retry is advised.
attempts, max_attemptsAttempts already made, and the configured maximum.
limitThe exceeded limit: name, value, observed, unit.
locationWhere in the run: run_id, turn, tool_name, tool_call_id, pointer.
upstreamRaw information from an upstream component, kept for diagnosis.
causesProblem details objects that caused this one, most recent first.
+ +

Code categories

+ + + + + + + + + +
CategoryDescription
outputModel output could not be accepted by the harness.
loopA limit on the agent loop was reached, or the loop is not progressing.
contextContext assembly or management failed.
toolTool resolution or execution failed.
policyA policy, guardrail, refusal, or human decision stopped the operation.
upstreamA remote dependency, typically the model API, failed.
harnessThe harness failed for another reason.
+

The full list of codes, with default values for retryable and model_recoverable, is in the draft.

+ +

Example

+
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" }
+    }
+  ]
+}
+ +

Other bindings

+ + + +
+ + diff --git a/site/public/style.css b/site/public/style.css new file mode 100644 index 0000000..1b9efcb --- /dev/null +++ b/site/public/style.css @@ -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; } diff --git a/site/wrangler.jsonc b/site/wrangler.jsonc new file mode 100644 index 0000000..6c3573b --- /dev/null +++ b/site/wrangler.jsonc @@ -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", + }, +}