| Internet-Draft | GPT | August 2026 |
| Ferguson | Expires 5 February 2027 | [Page] |
This document specifies GPT (Generic Protocol Type), a convention by which an HTTP address publishes the JSON Schema of the action it accepts, and accepts that action as a request body validated against the same schema. A client retrieves the schema at the moment of contact, produces a conforming value, and submits it unchanged. No client library, prior registration, or separate description of the capability is required. The schema serves as both the published description and the server-side check, so the two cannot diverge.¶
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 5 February 2027.¶
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.¶
An HTTP address that expects structured input generally describes that input somewhere other than in the response itself: in documentation, in a client library, in a tool definition supplied to a language model in advance, or in a registry retrieved separately. Each of those descriptions is maintained apart from the code that validates incoming requests, and can therefore disagree with it.¶
GPT removes the separate description. An address returns the JSON Schema [JSON-SCHEMA] of what it accepts as part of its ordinary representation. A client — commonly a language model with constrained-decoding support, but the protocol does not require one — produces a value conforming to that schema and submits it as the request body. The server validates against the same schema value it published.¶
This document specifies the wire behavior only. It does not specify what any particular address does with an accepted body.¶
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.¶
An HTTP or HTTPS URI implementing this document.¶
The JSON Schema an address publishes, carried in the member s. It is both
the description of what may be submitted and the check applied to what is
submitted.¶
A single POST whose body validates against the form.¶
Whatever produced the body. This protocol does not distinguish a language model, a program, or a person composing JSON by hand.¶
A client retrieves the form with an ordinary GET:¶
GET / HTTP/1.1 Host: example.com¶
No request header is required. An address MUST NOT require a header, query parameter, cookie, or prior request in order to return its form.¶
The response status is 200 with a Content-Type of application/json. The
body MUST be a JSON object [RFC8259] containing these members:¶
| Member | Type | Meaning |
|---|---|---|
p
|
string | System context: what this address is, and what to do |
m
|
array | Prior messages, each an object with role and content
|
s
|
object | The form: a JSON Schema (see Section 4) |
The members p and m are context for the actor and carry no normative
weight. The member s is normative: it is the sole statement of what the
address accepts.¶
An address MAY include additional members. A client MUST ignore members it does not recognize.¶
An address MAY include a GPT-Type response header field naming the kind of
address it is. This is advisory; a client MUST NOT depend on it, as s already
states everything the address accepts.¶
The response MUST NOT vary based on whether the client has contacted the address before.¶
An address MAY return a different representation when the request carries an
Accept header field including text/html. That representation is not part of
this protocol and MUST NOT be the only means of obtaining the form. A request
with no Accept header field, or one not including text/html, MUST receive
the response described in Section 3.2.¶
The value of s MUST be a valid JSON Schema describing a single JSON value:
the body of an act.¶
An address SHOULD restrict its schema to keywords that constrain the shape of a value, and SHOULD NOT depend on keywords whose omission by a validator would widen what is accepted.¶
The reference implementation uses:¶
type properties required additionalProperties const enum minLength maxLength minItems maxItems items description $defs $ref anyOf¶
An address SHOULD use anyOf in preference to oneOf. Both express a union of
alternatives; some constrained-decoding implementations reject oneOf outright,
and where the alternatives are disjoint the distinction does not affect which
values validate.¶
A form MAY describe a recursive structure. Where it does, the recursion SHOULD be bounded by the schema itself rather than by a check performed at runtime.¶
A self-referencing definition such as:¶
node = { content: [ node ] }
¶
is unbounded. The effective depth then becomes a property of the actor's sampling behavior rather than of the published grammar, and differs between actors.¶
Unrolling the definitions bounds depth within the document:¶
node1 = anyOf [ leaf, { content: [ node2 ] } ]
node2 = anyOf [ leaf, { content: [ node3 ] } ]
...
nodeN = anyOf [ leaf ]
¶
The final level omits the recursive alternative, so no conforming value exceeds depth N. The published form is the limit.¶
The description keyword, wherever it appears, is context for the actor and
carries no normative weight. A server MUST NOT rely on an actor having read it.¶
POST / HTTP/1.1 Host: example.com Content-Type: application/json <a JSON value conforming to s>¶
The body MUST be exactly the value the actor produced. Intermediaries MUST NOT reshape, re-serialize, or wrap it.¶
Before acting on a body, a server MUST:¶
Reject bodies exceeding an implementation-defined maximum size.¶
Parse strictly. The parser MUST reject bytes following the JSON value, and MUST reject duplicate object member names at any depth. Both are ambiguous at a trust boundary, and permissive parsers disagree about which duplicate value prevails.¶
Validate the body against the same value of s returned in
Section 3.2 — not a copy of it, and not a subset of it.¶
Fail closed on any schema keyword the validator does not implement. A form containing an unrecognized constraint MUST NOT be treated as though that constraint were absent.¶
Requirement 3 is the substance of this protocol. A description that can diverge from its enforcement is the condition being eliminated.¶
On success, the server returns 200 with Content-Type: application/json and a
body describing the consequence of the act. The shape of that body is not
specified here.¶
On failure, the server SHOULD return 204 with no body, and SHOULD NOT indicate which constraint rejected the body. An address that reports why a body was rejected assists an unauthorized actor in constructing one that is accepted.¶
Acts are not idempotent unless a particular address specifies otherwise. This document defines no retry semantics.¶
An address MAY read a GPT-Actor request header field in order to record how a
body was produced. It carries no authority: it is unauthenticated and
self-asserted, and MUST NOT be used to gate access.¶
A server MUST NOT infer actor identity from the body. Fields naming a speaker, where a form defines them, are content.¶
That an actor's output conforms to a schema is a property of how the output was generated, not a property of the request. Some implementations supply a schema to a language model as a tool definition the model is instructed but not compelled to use.¶
A server MUST treat every body as untrusted regardless of how it was produced. Generation-time constraint is a strong prior on well-formedness and nothing more.¶
Everything an actor can cause at an address is the set of values its form
admits. That set SHOULD be as small as the address can tolerate: bounded string
lengths, bounded array sizes, closed enumerations, and
additionalProperties: false on every object.¶
An address publishing a permissive form has published a permissive capability, whatever it does with the body afterward.¶
This protocol provides no channel by which a server describes what it will do that is separate from the form. This is deliberate. A prose description of a capability is unverifiable by the actor and unenforced by the server, and its presence invites reliance on a statement nothing checks.¶
A form is retrieved before every act, so an address serves its schema to unauthenticated clients at whatever rate they request it. Implementations SHOULD serve a precomputed representation and SHOULD apply rate limiting independent of this protocol.¶
Tool calling and tool registries supply a language model with definitions in advance, from the client side. GPT supplies them from the address at the moment of contact, and the same definition serves as the server's check. The tradeoff is that a registry can present many capabilities at once, where a GPT address presents one.¶
Proactive content negotiation [RFC9110] is used as specified, rather than maintaining separate paths for human and machine representations that can disagree about what an address offers.¶
GPT resembles hypermedia controls in that a response states what is possible next. It differs in that the statement is directly executable by the actor: a grammar to generate within, rather than links an actor must be programmed to interpret.¶
This document has no IANA actions.¶
The header fields GPT-Type and GPT-Actor are used by the reference
implementation but are not registered by this document. A future version may
request registration in the "Hypertext Transfer Protocol (HTTP) Field Name
Registry".¶
A running implementation is available at https://appgp.tv. Its form describes
a tree of text and styled spans.¶
Retrieving the form and submitting an act, using a language model runtime with native JSON Schema support:¶
x=$(curl -L appgp.tv)
claude -p --system-prompt "$(jq -r .p<<<$x)" \
--json-schema "$(jq -c .s<<<$x)" \
"$(jq -c .m<<<$x)" | curl -L appgp.tv -d@-
¶
The same address with a different runtime:¶
x=$(curl -L appgp.tv) jq -c .m<<<$x | codex e --skip-git-repo-check \ --output-schema <(jq -c .s<<<$x) "$(jq -r .p<<<$x)" \ | curl -L appgp.tv -d@-¶
And with a locally hosted model:¶
curl -L appgp.tv | jq '{model:"qwen3.5:9b",
messages:([{role:"system",content:.p}]+.m),
stream:false, format:.s}' \
| curl localhost:11434/api/chat -d@- \
| jq -r .message.content | curl -L appgp.tv -d@-
¶
No client library is installed in any of the three cases, and the address is unaware which runtime contacted it.¶
The following are unresolved in this version.¶
Whether an address should be able to name other addresses, and if so whether as data within the form or as a protocol-level member. Naming them within the form keeps the protocol to a single primitive but gives an actor no means of reasoning about the graph before entering it.¶
A form may change between arrival and act. Nothing in this document detects that. An entity-tag on the form, echoed by the act, would — at the cost of a required header field.¶
Returning 204 with no explanation is appropriate for a public address and unhelpful for one under development. This document provides no means of distinguishing the two.¶
Acts are a single request and response. Progressive results and acts that outlive a request are unaddressed.¶
TODO.¶