﻿<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="info"
     docName="draft-boone-prompt-uri-scheme-01"
     ipr="trust200902"
     submissionType="independent"
     xml:lang="en"
     version="3">

  <front>
    <title abbrev="prompt URI Scheme">The 'prompt' URI Scheme for AI Agent Sessions and Prompts</title>

    <seriesInfo name="Internet-Draft" value="draft-boone-prompt-uri-scheme-01"/>

    <author fullname="Keith W. Boone" initials="K." surname="Boone">
      <organization>Audacious Inquiry</organization>
      <address>
        <email>kboone@ainq.com</email>
      </address>
    </author>

    <date year="2026" month="July" day="21"/>

    <area>Applications and Real-Time</area>
    <workgroup>agentproto</workgroup>

    <keyword>URI</keyword>
    <keyword>AI</keyword>
    <keyword>agent</keyword>
    <keyword>prompt</keyword>
    <keyword>provenance</keyword>

    <abstract>
      <t>This document defines the <tt>prompt</tt> Uniform Resource Identifier (URI) scheme for
      identifying prompts within AI agent sessions.  A prompt URI encodes the agent
      identity, session identifier, and a timestamp sufficient to locate the originating
      prompt within an agent session log.  The scheme is intended for use in provenance
      records, audit trails, and cross-agent references where a human-readable, stable
      locator for a prompt interaction is required.</t>
      <t>This document also addresses the conditions under which multiple URIs <bcp14>MAY</bcp14> resolve
      to the same prompt and the conditions under which a single URI <bcp14>MAY</bcp14> be ambiguous
      with respect to the prompt it identifies.</t>
    </abstract>
  </front>

  <middle>

    <section anchor="intro" numbered="true" toc="default">
      <name>Introduction</name>
      <t>AI agent systems produce interactions  --  prompts from users, tool calls by agents,
      responses, and observations  --  that generate artifacts (files, analyses, transformed
      documents) whose provenance is difficult to trace after the fact.  Existing identifier
      schemes are insufficient for this use case:</t>
      <ul>
        <li>A session identifier alone does not distinguish which prompt within a session
        produced a given artifact.</li>
        <li>A wall-clock timestamp alone does not identify the agent or session.</li>
        <li>An agent-internal correlation identifier (such as a <tt>promptId</tt> or <tt>interactionId</tt>)
        is not exposed to callers of agent tools at call time.</li>
      </ul>
      <t>The <tt>prompt</tt> URI scheme addresses this gap by providing a stable, human-readable
      identifier that encodes the three pieces of information consistently available to
      any tool executing within an agent session: the agent identity, the session
      identifier, and the approximate call time.</t>
      <t>The resulting URI is suitable for embedding in file provenance metadata, log
      cross-references, and audit records.  It is NOT a globally unique identifier in
      the strict sense; see <xref target="ambiguity-multiple-uris"/> and
      <xref target="ambiguity-one-uri"/> for a full treatment of ambiguity.</t>
      <t>The scheme has been implemented and deployed as an open-source Model Context
      Protocol (MCP) server <xref target="PROMPT-URL-MCP"/> that resolves, generates,
      and searches <tt>prompt</tt> URIs against local agent session logs.  This
      implementation validates the design under real-world agent workloads involving
      both Claude Code and GitHub Copilot sessions.</t>
      <t>Several proposals currently under active consideration in IETF AI-focused
      forums address broader questions of AI agent accountability, transparency,
      auditability, and interoperability.  The <tt>prompt</tt> URI scheme is intended
      as a composable, low-level building block for those frameworks: any mechanism
      that tracks, attests to, or makes claims about AI-generated artifacts needs a
      stable, lightweight way to reference the specific agent interaction that produced
      them.  This document defines that reference.</t>
    </section>

    <section anchor="terminology" numbered="true" toc="default">
      <name>Terminology</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>",
      "<bcp14>SHALL</bcp14>", "<bcp14>SHALL NOT</bcp14>", "<bcp14>SHOULD</bcp14>",
      "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
      "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
      described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when,
      they appear in all capitals, as shown here.</t>
      <t>The following terms are used throughout this document:</t>
      <dl newline="true" spacing="normal">
        <dt>Agent:</dt>
        <dd>A software system that processes user prompts, invokes tools, and
        produces responses.  Examples include Claude Code, GitHub Copilot, and similar
        AI-assisted development tools.</dd>
        <dt>Session:</dt>
        <dd>A bounded interaction context shared between a user and an agent,
        identified by a session identifier assigned at session initiation.</dd>
        <dt>Prompt:</dt>
        <dd>A single user message that initiates one or more agent actions within
        a session.</dd>
        <dt>Session log:</dt>
        <dd>A persistent record maintained by the agent of all interactions
        within a session, including prompts, tool calls, and responses, together with
        timestamps and internal correlation identifiers.</dd>
        <dt>Tool call:</dt>
        <dd>An invocation of an external capability (such as a file write
        operation) by the agent in response to a prompt.  The Model Context Protocol
        <xref target="MCP"/> is one standardized mechanism by which agents invoke such
        capabilities.</dd>
        <dt>Provenance record:</dt>
        <dd>Metadata attached to an artifact describing its origin, including the
        agent, session, and prompt responsible for its creation.</dd>
        <dt>Prompt URI:</dt>
        <dd>A URI conforming to this specification that identifies a prompt
        within a specific agent session.</dd>
        <dt>Session alias:</dt>
        <dd>A human-readable string registered by the user or agent as an
        alternative identifier for a session, usable in place of the session identifier
        in a prompt URI.  An alias is scoped to a single agent and <bcp14>MUST</bcp14> be unique
        within that agent's alias registry.</dd>
        <dt>Alias registry:</dt>
        <dd>A local store, maintained by an implementation, that maps registered
        session aliases to their corresponding session identifiers.</dd>
      </dl>
    </section>

    <section anchor="syntax" numbered="true" toc="default">
      <name>URI Syntax</name>

      <section anchor="scheme-name" numbered="true" toc="default">
        <name>Scheme Name</name>
        <t>The scheme name is <tt>prompt</tt>.  It <bcp14>SHALL</bcp14> be written in lowercase in all generated
        URIs.  Implementations processing incoming URIs <bcp14>SHOULD</bcp14> treat the scheme name as
        case-insensitive per <xref target="RFC3986"/> Section 6.2.2.1.</t>
      </section>

      <section anchor="abnf" numbered="true" toc="default">
        <name>Complete ABNF</name>
        <t>The following grammar, expressed in Augmented Backus-Naur Form
        <xref target="RFC5234"/>, defines the syntax of a prompt URI.  Terms not defined
        here are imported from <xref target="RFC3986"/> (<tt>unreserved</tt>,
        <tt>pct-encoded</tt>, <tt>host</tt>, <tt>sub-delims</tt>) and
        <xref target="RFC3339"/> (<tt>date-time</tt>).</t>
        <sourcecode type="abnf"><![CDATA[
prompt-URI    =  "prompt:" hier-part
                 agent-name "/" session-ref "/" prompt-ref

hier-part     =  "//" authority "/"   ; remote: authority-based
               / "/"                  ; local-only resolution

authority     =  [ userinfo "@" ] host [ ":" port ]
                 ; host: hostname or IP-literal (RFC 3986 s3.2.3)
                 ; userinfo: optional username
                 ; port: optional; default port is 7560

userinfo      =  1*( unreserved / pct-encoded / sub-delims )
                 ; Username identifying the user at the remote host;
                 ; the "user:password" form of RFC 3986 s3.2.1 is
                 ; NOT RECOMMENDED -- use username only

host          =  <host as defined in RFC 3986 Section 3.2.3>
                 ; DNS hostname, IPv4 address, or IP-literal

port          =  *DIGIT
                 ; decimal; absent port defaults to 7560

agent-name    =  1*agent-char
agent-char    =  unreserved / pct-encoded / "+" / "."

session-ref   =  session-id / session-alias
                 ; parsers cannot distinguish the two forms;
                 ; the distinction is semantic (Sections 4.4, 4.6)

session-id    =  1*( unreserved / pct-encoded )
                 ; Typically a UUID per RFC 9562

session-alias =  1*( unreserved / pct-encoded )
                 ; Special characters including SP (U+0020) MUST be
                 ; percent-encoded per [RFC3986] -- see Section 4.6

prompt-ref    =  date-time / prompt-id
                 ; RFC 3339 timestamp or a prompt identifier;
                 ; date-time always begins with a 4-digit year, so
                 ; the "~" prefix of prompt-id is unambiguous
                 ; See Sections 4.5 and 4.7

date-time     =  <date-time as defined in RFC 3339, Section 5.6>
                 ; Colons within date-time are valid in URI path
                 ; segments per RFC 3986 Section 3.3
                 ; Example: 2026-07-07T16:45:23.856Z

prompt-id     =  "~" 1*( unreserved / pct-encoded )
                 ; Agent-internal prompt correlation identifier;
                 ; "~" (U+007E, unreserved, RFC 3986) distinguishes
                 ; prompt-id from date-time in all syntactic contexts
                 ; Example: ~abc123, ~promptId%3Axyz
]]></sourcecode>
        <t>The following prompt URIs illustrate the syntactic forms.  The first two use
        local-only resolution (single slash, no authority); the remaining three use
        remote resolution via a named host:</t>
        <sourcecode><![CDATA[
; NOTE: Lines ending with '\' are folded per [RFC8792].
;       No whitespace is implied at the fold point.

; Local-only forms (prompt:/ -- single slash, no authority)
prompt:/claude-code/\
  5674b542-0b94-4d12-bc05-d271a4131354/2026-07-07T16:45:23.856Z
prompt:/claude-code/5674b542-0b94-4d12-bc05-d271a4131354/~abc123

; Remote forms (prompt:// -- authority present)
prompt://mcp.example.com/claude-code/\
  5674b542-0b94-4d12-bc05-d271a4131354/~abc123
prompt://kboone@mcp.example.com/claude-code/\
  5674b542-0b94-4d12-bc05-d271a4131354/~abc123
prompt://mcp.example.com/claude-code/\
  md-csv-mcp%20design/2026-07-07T16:45:23.856Z
]]></sourcecode>
        <t>Breaking the local prompt-id form into components:</t>
        <sourcecode><![CDATA[
prompt-URI  = "prompt:"
              "/"  ; hier-part: local-only (single slash)
              "claude-code"  ; agent-name
              "/"
              "5674b542-0b94-4d12-bc05-d271a4131354"  ; session-id
              "/"
              "~abc123"  ; prompt-ref: prompt-id form
]]></sourcecode>
        <t>Breaking the remote form with username into components:</t>
        <sourcecode><![CDATA[
prompt-URI  = "prompt:"
              "//"  ; hier-part: remote resolution
              "kboone"  ; userinfo (username)
              "@"
              "mcp.example.com"  ; host (agent client machine)
              "/"
              "claude-code"  ; agent-name
              "/"
              "5674b542-0b94-4d12-bc05-d271a4131354"  ; session-id
              "/"
              "~abc123"  ; prompt-ref: prompt-id form
]]></sourcecode>
        <t>Breaking the remote alias form into components:</t>
        <sourcecode><![CDATA[
prompt-URI  = "prompt:"
              "//"  ; hier-part: remote resolution
              "mcp.example.com"  ; host (no username)
              "/"
              "claude-code"  ; agent-name
              "/"
              "md-csv-mcp%20design"  ; session-alias (%20 = space)
              "/"
              "2026-07-07T16:45:23.856Z"  ; prompt-ref: timestamp
]]></sourcecode>
      </section>

      <section anchor="authority-comp" numbered="true" toc="default">
        <name>Authority Component (Optional)</name>
        <t>The authority component is <bcp14>OPTIONAL</bcp14>.  Its presence is signaled by the
        double-slash <tt>//</tt> prefix following the scheme (<tt>prompt://</tt>), in
        accordance with <xref target="RFC3986"/> Section 3.  When the authority is absent,
        the URI uses a single slash (<tt>prompt:/</tt>) and is resolvable only through a
        local MCP server instance.</t>
        <t>When present, the authority takes the form:</t>
        <sourcecode><![CDATA[
[ username "@" ] host [ ":" port ]
]]></sourcecode>
        <t>The <tt>host</tt> subcomponent identifies the network host where the agent client
        application resides and operates on behalf of the user.  The agent may reside in
        the cloud (such as Claude Code or GitHub Copilot), but this is the user machine
        where the agent's client application stores logs and session data that enable
        prompt resolution.  The host <bcp14>MAY</bcp14> also provide an HTTP endpoint where an MCP
        server is accessible, enabling remote resolution of the URI over the network.
        It follows the <tt>host</tt> syntax of <xref target="RFC3986"/> Section 3.2.3
        (DNS name, IPv4 address, or IP-literal).</t>
        <t>The <tt>port</tt> subcomponent is <bcp14>OPTIONAL</bcp14>.  When present, it is separated from
        the <tt>host</tt> by a colon (<tt>:</tt>), as defined in <xref target="RFC3986"/>
        Section 3.2.3.  When absent, the port defaults to <tt>7560</tt>, which is the
        registered default port for the <tt>prompt</tt>-scheme MCP server reference
        implementation.</t>
        <t>The <tt>username</tt> subcomponent is <bcp14>OPTIONAL</bcp14>.  When present, it is separated
        from the <tt>host</tt> by an <tt>@</tt> (U+0040) character, following the same
        convention as HTTP and other URI schemes (<xref target="RFC3986"/> Section 3.2.1).
        It identifies the user account or identity principal under which the agent
        session log is stored at the remote host, and <bcp14>MAY</bcp14> be used by the remote MCP
        server to scope its session log search.</t>
        <t>The <tt>agent-name</tt> is NOT part of the authority; it is always the first
        segment of the path (<xref target="path-comp"/>).</t>
      </section>

      <section anchor="path-comp" numbered="true" toc="default">
        <name>Path Component</name>
        <t>The path component <bcp14>SHALL</bcp14> consist of exactly three segments separated by
        slashes:</t>
        <ol>
          <li>The agent name (<xref target="agent-name-comp"/>)  --  identifies the software
          agent that generated the URI.</li>
          <li>A session reference  --  either a session identifier
          (<xref target="session-id-comp"/>) or a registered session alias
          (<xref target="session-aliases"/>).</li>
          <li>A prompt reference  --  either an RFC 3339 timestamp
          (<xref target="timestamp-comp"/>) or a prompt identifier
          (<xref target="canonical-uri"/>).</li>
        </ol>
        <t>The path <bcp14>MUST</bcp14> begin with a slash.  All three segments <bcp14>MUST NOT</bcp14> be empty.</t>
      </section>

      <section anchor="query-fragment" numbered="true" toc="default">
        <name>Query and Fragment Components</name>
        <t>This specification does not define semantics for query (<tt>?</tt>) or fragment
        (<tt>#</tt>) components.  Implementations <bcp14>MAY</bcp14> append a fragment to a prompt URI as
        an implementation-specific disambiguation hint (see <xref target="ambiguity-one-uri"/>),
        but <bcp14>SHALL NOT</bcp14> rely on fragment processing in interoperable contexts.  The query
        component <bcp14>SHOULD NOT</bcp14> be used; its presence does not affect identity or
        comparison.</t>
      </section>

    </section>

    <section anchor="semantics" numbered="true" toc="default">
      <name>URI Components and Semantics</name>

      <section anchor="resolution-mode" numbered="true" toc="default">
        <name>Remote vs. Local Resolution</name>
        <t>A prompt URI selects its resolution mode by the presence or absence of the
        authority (<tt>//host</tt>) prefix:</t>
        <ul>
          <li><strong>Remote (<tt>prompt://[user@]host/...</tt>)</strong>  --  The double-slash signals
          that an authority is present.  The URI is intended to be resolved by contacting
          the <tt>prompt</tt>-scheme MCP server running at <tt>host</tt> over the network.  This
          form is appropriate for sharing prompt references across machines, teams, or
          systems where the originating session log is accessible through a web-facing
          MCP endpoint.</li>
          <li><strong>Local-only (<tt>prompt:/...</tt>)</strong>  --  The single slash signals that no
          authority is present.  The URI is resolvable only by a local MCP server instance
          that has access to the originating agent's session logs on the same machine.
          This form is appropriate for provenance records that will only ever be resolved
          on the machine that generated them.</li>
        </ul>
        <t>Implementations that generate prompt URIs <bcp14>SHOULD</bcp14> choose the local form by
        default and <bcp14>SHOULD</bcp14> allow the user or configuration to specify a remote host when
        a web-accessible MCP server is available.  Implementations <bcp14>SHOULD NOT</bcp14> silently
        upgrade a local URI to a remote one; the resolution mode is part of the URI's
        identity.</t>
      </section>

      <section anchor="host-comp" numbered="true" toc="default">
        <name>Host</name>
        <t>The host subcomponent identifies the network host where the agent client
        application resides and operates on behalf of the user.  The agent may reside in
        the cloud (such as Claude Code or GitHub Copilot), but this is the user machine
        where the agent's client application stores logs and session data that enable
        prompt resolution.  It follows the <tt>host</tt> production of
        <xref target="RFC3986"/> Section 3.2.3.  The host <bcp14>MAY</bcp14> also provide an HTTP
        endpoint where a <tt>prompt</tt>-scheme MCP server is accessible, enabling remote
        resolution of the URI over the network.  A single MCP server <bcp14>MAY</bcp14> host
        resolution for multiple AI agents.</t>
        <t>Host names <bcp14>SHOULD</bcp14> be stable DNS names.  IP addresses <bcp14>SHOULD</bcp14> be avoided in
        long-lived provenance records because they are subject to renumbering.</t>
        <t>The optional port number, when present, identifies the TCP port on which the
        <tt>prompt</tt>-scheme MCP server listens at that host.  When absent, the port
        defaults to <tt>7560</tt>, the default port of the reference implementation.
        When an explicit port number equal to <tt>7560</tt> is present, it is equivalent
        to the form with no port for comparison purposes
        (<xref target="normalization"/>).</t>
      </section>

      <section anchor="username-comp" numbered="true" toc="default">
        <name>Username</name>
        <t>The username is the <bcp14>OPTIONAL</bcp14> <tt>userinfo</tt> subcomponent of the authority.
        When present, it identifies the user account or identity principal whose agent
        session logs are stored at the remote host.  The remote MCP server <bcp14>MAY</bcp14> use it
        to scope its session log search to that user's log partition.</t>
        <t>The username is meaningful only when the authority is present (remote form).
        It <bcp14>SHOULD</bcp14> be omitted in local-only URIs, and <bcp14>SHOULD</bcp14> be omitted in remote URIs
        when the MCP server does not partition logs by user.</t>
        <t>Two prompt URIs that differ only in the presence or absence of a username, or
        in the value of the username, are NOT equivalent (<xref target="normalization"/>)
        unless the resolver determines that both usernames map to the same identity
        principal.</t>
      </section>

      <section anchor="agent-name-comp" numbered="true" toc="default">
        <name>Agent Name</name>
        <t>The agent name is the first segment of the path.  It identifies the software
        agent that generated the URI.  It is NOT a globally registered identifier;
        implementations <bcp14>SHOULD</bcp14> use a stable, recognizable short name (e.g.,
        <tt>claude-code</tt>, <tt>github-copilot</tt>, <tt>cursor</tt>).  Agents operated by
        different organizations <bcp14>SHOULD</bcp14> use distinct names to avoid collision.</t>
        <t>The agent name <bcp14>MAY</bcp14> include a dot-separated hierarchy for namespacing
        (e.g., <tt>anthropic.claude-code</tt>), but this structure carries no defined
        semantics in this specification.</t>
        <t>The agent name <bcp14>SHALL</bcp14> remain constant across all sessions and versions of a
        given agent implementation.  Including a version number in the agent name is
        <bcp14>NOT RECOMMENDED</bcp14>, as it would render URIs from different versions incomparable
        even when they refer to the same logical agent.</t>
      </section>

      <section anchor="session-id-comp" numbered="true" toc="default">
        <name>Session Identifier</name>
        <t>The session identifier <bcp14>SHALL</bcp14> be an opaque string assigned by the agent at
        session initiation.  Implementations <bcp14>SHOULD</bcp14> use a UUID <xref target="RFC9562"/> for
        the session identifier to minimize collision probability across agents and
        deployments.  UUID version 7 <xref target="RFC9562"/> is <bcp14>RECOMMENDED</bcp14> over version 4
        because its monotonically increasing structure supports chronological ordering
        of sessions.</t>
        <t>The session identifier <bcp14>SHALL</bcp14> be consistent throughout a session and
        <bcp14>SHALL NOT</bcp14> change during a session's lifetime.</t>
      </section>

      <section anchor="timestamp-comp" numbered="true" toc="default">
        <name>Timestamp</name>
        <t>The timestamp <bcp14>SHALL</bcp14> be formatted as an RFC 3339 <xref target="RFC3339"/>
        <tt>date-time</tt> value and <bcp14>SHALL</bcp14> use UTC (the <tt>Z</tt> suffix).  The timestamp
        records the wall-clock time at which the tool call generating the URI was
        executed.</t>
        <t>Implementations <bcp14>SHOULD</bcp14> include sub-second precision (milliseconds) in the
        timestamp to reduce the probability of within-session collisions
        (see <xref target="ambiguity-one-uri"/>).  A timestamp with second-level precision is
        <bcp14>REQUIRED</bcp14>; millisecond precision is <bcp14>RECOMMENDED</bcp14>; microsecond precision
        <bcp14>MAY</bcp14> be used.</t>
        <t>The timestamp is NOT the time at which the originating prompt was submitted.
        It is the time at which the tool call was executed.  For a given prompt, multiple
        tool calls <bcp14>MAY</bcp14> be executed, potentially spanning multiple seconds.  Each tool
        call produces a URI with its own timestamp; all such URIs are considered to
        refer to the same prompt for resolution purposes (see <xref target="resolution"/>).</t>
        <t>When the agent maintains an internal prompt correlation identifier, the
        canonical form of the URI <bcp14>SHOULD</bcp14> use that identifier in place of the timestamp
        (see <xref target="canonical-uri"/>).</t>
      </section>

      <section anchor="session-aliases" numbered="true" toc="default">
        <name>Session Aliases</name>
        <t>A session alias is a human-readable string that a user or implementation
        <bcp14>MAY</bcp14> register as an alternative to the session identifier in a prompt URI.
        Aliases improve legibility: <tt>prompt:/claude-code/md-csv-mcp-design/...</tt> is
        more immediately meaningful than
        <tt>prompt:/claude-code/5674b542-.../...</tt>.</t>
        <t><strong>Registration:</strong> Aliases <bcp14>SHALL</bcp14> be registered in a local alias registry
        that maps each alias to the session identifier it represents.  An alias is
        scoped to a single agent name and <bcp14>MUST</bcp14> map to exactly one session within
        that agent's registry.  A session <bcp14>MAY</bcp14> have more than one alias registered
        to it.</t>
        <t>Attempting to register an alias that is already registered to a different
        session <bcp14>SHALL</bcp14> be rejected with a conflict error.  Attempting to register an
        alias that is already registered to the same session is idempotent and
        <bcp14>SHALL</bcp14> succeed without modifying the registry.</t>
        <t><strong>Case insensitivity:</strong> Alias lookup <bcp14>SHALL</bcp14> be case-insensitive.  The alias
        <tt>MD-CSV-MCP-Design</tt>, <tt>md-csv-mcp-design</tt>, and <tt>Md-Csv-Mcp-Design</tt>
        <bcp14>MUST</bcp14> all resolve to the same session.  Implementations <bcp14>SHOULD</bcp14> store aliases
        in normalized lowercase and normalize incoming aliases to lowercase before
        lookup.</t>
        <t><strong>Canonical URI form:</strong> In a prompt URI, an alias <bcp14>SHALL</bcp14> appear in its
        canonical URI form, which is the percent-encoded representation of the alias
        string with all characters encoded per <xref target="RFC3986"/> as required.</t>
        <t><strong>Handling of spaces and special characters:</strong> Spaces (U+0020) and any other
        characters not permitted in a URI path segment by <xref target="RFC3986"/> <bcp14>MUST</bcp14> be
        percent-encoded in the canonical URI form of an alias.  The alias
        <tt>md-csv-mcp design</tt> is canonically encoded as <tt>md-csv-mcp%20design</tt> in a
        prompt URI.  Hyphens and spaces remain distinct: the alias
        <tt>md-csv-mcp design</tt> and the alias <tt>md-csv-mcp-design</tt> are different aliases
        and resolve to different sessions (if both are registered).</t>
        <t>Implementations that accept prompt URIs as input <bcp14>MAY</bcp14> repair aliases
        containing unencoded special characters by applying percent-encoding before
        lookup, in the same manner that web browsers correct malformed URIs.</t>
        <t>Implementations <bcp14>MUST</bcp14> preserve the original human-readable alias string
        (as supplied at registration time, before percent-encoding) in the alias
        registry.  This allows the original label to be displayed in user interfaces
        without loss of information.</t>
        <t><strong>Alias persistence:</strong> Alias registries are implementation-defined and may
        not persist indefinitely.  Agents are not required to maintain alias registries
        across restarts, updates, or deployments.  Users and systems requiring
        long-term, portable provenance references <bcp14>SHOULD</bcp14> use the session-identifier
        form of the prompt URI rather than the alias form, since session identifiers
        are generated by the agent and stored in its session log independently of any
        alias registry.  Prompt URIs using an alias remain valid provenance references
        as long as the alias registry is intact, but are subject to becoming
        unresolvable (<xref target="unresolvable"/>) if the registry is lost or
        unavailable.</t>
        <t><strong>Alias-to-session-id URIs:</strong> When a session has both a registered alias and
        a session identifier, both forms of prompt URI are valid and refer to the same
        session.  Implementations <bcp14>MAY</bcp14> use the alias form in newly generated provenance
        records when an alias is registered, as it improves human readability.</t>
      </section>

      <section anchor="canonical-uri" numbered="true" toc="default">
        <name>Canonical Prompt URI</name>
        <t>A prompt URI is <em>canonical</em> if its <tt>prompt-ref</tt> component is the most
        specific and stable identifier available for the prompt it represents.  The
        canonical form determines which URI <bcp14>SHOULD</bcp14> be stored in provenance records.</t>
        <t><strong>Prompt identifier form (preferred):</strong> When the agent maintains an internal
        correlation identifier for each prompt (for example, <tt>promptId</tt> in Claude Code
        session logs <xref target="CLAUDE-SESSIONS"/> or <tt>interactionId</tt> in Copilot session
        logs <xref target="COPILOT-SESSIONS"/>), the canonical URI <bcp14>SHOULD</bcp14> use the
        <tt>prompt-id</tt> form (<xref target="abnf"/>) with a leading <tt>~</tt> character:</t>
        <sourcecode><![CDATA[
prompt:/claude-code/5674b542-0b94-4d12-bc05-d271a4131354/~abc123
]]></sourcecode>
        <t>A canonical prompt-id URI uniquely identifies the prompt regardless of when
        tool calls execute within the prompt's processing.  Because all tool calls from
        the same prompt share the same prompt identifier, two prompt-id URIs with the
        same <tt>session-ref</tt> and <tt>prompt-id</tt> components can be detected as equivalent
        by string comparison, without consulting the session log.</t>
        <t><strong>Timestamp form (fallback):</strong> When no prompt identifier is available, the
        canonical URI <bcp14>SHOULD</bcp14> use the timestamp at which the originating prompt was
        submitted by the user  --  not the timestamp of any particular tool call within
        the prompt's processing.  An implementation that records prompt-submission
        timestamps <bcp14>MAY</bcp14> use that timestamp in the canonical URI even if individual
        tool calls use their own tool-call timestamps (<xref target="timestamp-comp"/>).</t>
        <t>Tool-call timestamp URIs (those generated at the time a tool call executes)
        are valid provenance references but are not canonical: multiple such URIs from
        the same prompt are not equivalent by comparison (<xref target="normalization"/>), even
        though they resolve to the same prompt (<xref target="resolution"/>).</t>
        <t><strong>Normalizing to canonical form:</strong> Implementations <bcp14>SHOULD</bcp14> normalize all
        prompt URI references for a given prompt to the canonical URI before writing
        provenance records.  Normalizing to the prompt-id form, when available, enables
        deduplication of provenance entries across the tool calls of a single prompt
        without requiring session log access.</t>
      </section>
    </section>

    <section anchor="normalization" numbered="true" toc="default">
      <name>Normalization and Comparison</name>
      <t>Two prompt URIs <bcp14>SHOULD</bcp14> be considered equivalent if and only if all of the
      following hold after applying the normalization rules in <xref target="RFC3986"/>
      Section 6:</t>
      <ol>
        <li>Their scheme components are identical (case-insensitively).</li>
        <li>Their resolution mode is identical: either both have an authority (remote)
        or both lack one (local-only).</li>
        <li><t>When both have an authority: their host subcomponents are identical
        (case-insensitively per <xref target="RFC3986"/> Section 6.2.2.1); their port
        subcomponents are equivalent (treating an absent port as equal to port
        <tt>7560</tt>); and their username (userinfo) subcomponents are equivalent  -- 
        both absent, both present and identical after percent-decoding
        (case-sensitive), or both present and determined by the resolver to map to
        the same identity principal.</t></li>
        <li>Their agent-name components are identical (case-insensitively).</li>
        <li>
          <t>Their session-ref components identify the same session, determined as
          follows:</t>
          <ul>
            <li>If both are session identifiers: they are identical after
            percent-decoding (case-sensitive).</li>
            <li>If both are session aliases: they are identical after percent-decoding
            and case-folding to lowercase.</li>
            <li>If one is a session identifier and the other a session alias: they are
            equivalent if and only if the alias resolves to the same session identifier
            per the alias registry (<xref target="alias-resolution"/>).</li>
          </ul>
        </li>
        <li>
          <t>Their <tt>prompt-ref</tt> components identify the same prompt reference, as
          determined by the following rules:</t>
          <ul>
            <li>If both are timestamps (<tt>date-time</tt>): they represent the same instant
            in time, after normalizing to UTC and applying the date-time comparison rules
            of <xref target="RFC3339"/>.</li>
            <li>If both are prompt identifiers (<tt>prompt-id</tt>): they are identical after
            percent-decoding (case-sensitive, following percent-decoding).</li>
            <li>If one is a timestamp and the other is a prompt identifier: they are NOT
            equivalent; resolution (<xref target="resolution"/>) is required to determine
            whether they refer to the same prompt.</li>
          </ul>
        </li>
      </ol>
      <t>Timestamps that differ by any amount of time, however small, are NOT equivalent
      and <bcp14>SHALL NOT</bcp14> be treated as identifying the same prompt URI.  Equivalence and
      resolution are distinct concepts: two non-equivalent URIs <bcp14>MAY</bcp14> nonetheless resolve
      to the same prompt (<xref target="ambiguity-multiple-uris"/>), and a single URI <bcp14>MAY</bcp14> be
      ambiguous (<xref target="ambiguity-one-uri"/>).  Two URIs that differ only in their
      <tt>prompt-ref</tt> form (one using a timestamp, one using a prompt identifier) are
      likewise non-equivalent by this definition, even if they identify the same
      underlying prompt.</t>
    </section>

    <section anchor="resolution" numbered="true" toc="default">
      <name>Resolution</name>

      <section anchor="resolution-algorithm" numbered="true" toc="default">
        <name>Resolution Algorithm</name>
        <t>Resolution is the process of mapping a prompt URI to one or more candidate
        prompts in an agent's session log.  Resolution is <bcp14>OPTIONAL</bcp14>; a prompt URI
        is valid and useful as a provenance reference even when the referenced session
        log is unavailable.</t>
        <t>A conformant resolver <bcp14>SHALL</bcp14> apply the following steps:</t>
        <ol>
          <li><t>Parse the prompt URI and determine the resolution mode
          (<xref target="resolution-mode"/>):</t>
          <ul>
            <li><strong>Remote</strong> (<tt>prompt://...</tt>): extract <tt>host</tt>,
            <tt>username</tt> (if present), <tt>agent-name</tt>, <tt>session-ref</tt>, and
            <tt>prompt-ref</tt>.  Contact the MCP server at <tt>host</tt> to perform steps
            2-7 on the remote server.  If <tt>username</tt> is present, pass it to the
            remote server so that it <bcp14>MAY</bcp14> scope its session log search.</li>
            <li><strong>Local-only</strong> (<tt>prompt:/...</tt>): extract <tt>agent-name</tt>,
            <tt>session-ref</tt>, and <tt>prompt-ref</tt>.  Perform steps 2-7 using the
            local session log store.</li>
          </ul>
          <t>If <tt>session-ref</tt> is an alias, resolve it per
          <xref target="alias-resolution"/> to obtain the session identifier before
          proceeding.</t></li>
          <li>Locate the session log associated with the session identifier for the
          agent identified by <tt>agent-name</tt>.  If resolving remotely and a
          <tt>username</tt> is present, the resolver <bcp14>MAY</bcp14> restrict its search to session
          logs owned by or accessible under that identity principal.  If no matching
          log is accessible, the URI is unresolvable
          (<xref target="unresolvable"/>).</li>
          <li><t>If <tt>prompt-ref</tt> is a <tt>prompt-id</tt> (begins with <tt>~</tt>): strip the
          <tt>~</tt> prefix, percent-decode the remainder, and locate all session log entries
          whose prompt correlation identifier matches.  If exactly one entry is found,
          the URI resolves to that prompt.  Proceed to step 5.</t>
          <t>If <tt>prompt-ref</tt> is a <tt>date-time</tt>: identify the most recent
          human-authored prompt entry in the session log whose recorded timestamp is on
          or before the URI timestamp.  Because a single prompt may drive multiple agent
          actions -- file writes, commits, and pushes -- before the URI timestamp is
          captured, the elapsed time between the prompt and the URI timestamp may be
          substantial.</t></li>
          <li>From the candidate entries, identify those that are prompt-type entries
          (user messages that initiated a turn), as opposed to tool call or response
          entries.</li>
          <li>If exactly one prompt-type candidate is found, the URI resolves to that
          prompt.</li>
          <li>If multiple prompt-type candidates are found, the URI is ambiguous
          (<xref target="ambiguity-one-uri"/>).  The resolver <bcp14>SHOULD</bcp14> report all candidates
          and <bcp14>SHOULD NOT</bcp14> silently select one.</li>
          <li>If the session log records an agent-internal correlation identifier
          (e.g., <tt>promptId</tt> in Claude Code session logs <xref target="CLAUDE-SESSIONS"/>,
          <tt>interactionId</tt> in Copilot session logs <xref target="COPILOT-SESSIONS"/>),
          implementations <bcp14>MAY</bcp14> use that identifier to narrow candidate selection
          to a single result.</li>
        </ol>
      </section>

      <section anchor="alias-resolution" numbered="true" toc="default">
        <name>Alias Resolution</name>
        <t>When the session-ref component of a prompt URI does not parse as a UUID and
        is not otherwise recognizable as a session identifier, the resolver <bcp14>SHALL</bcp14>
        treat it as a session alias and apply the following steps before proceeding
        with <xref target="resolution-algorithm"/>:</t>
        <ol>
          <li>Normalize the alias: percent-decode, then fold to lowercase.</li>
          <li>Look up the normalized alias in the alias registry for the agent
          identified by <tt>agent-name</tt>.</li>
          <li>If a matching entry is found, substitute the corresponding session
          identifier into the resolution process and continue with
          <xref target="resolution-algorithm"/> step 2.</li>
          <li>If no matching entry is found, the URI is unresolvable
          (<xref target="unresolvable"/>).  Implementations <bcp14>SHOULD</bcp14> report "alias not
          registered" as a distinct unresolvable condition, separate from "session log
          not found."</li>
        </ol>
      </section>

      <section anchor="unresolvable" numbered="true" toc="default">
        <name>Unresolvable URIs</name>
        <t>A prompt URI is unresolvable if any of the following conditions hold:</t>
        <ul>
          <li>The URI is in remote form (<tt>prompt://</tt>) and the <tt>host</tt>
          subcomponent does not match the hostname of the machine on which the
          resolver is running (case-insensitive comparison).  A resolver
          <bcp14>MUST NOT</bcp14> attempt to forward the request to another machine; it
          <bcp14>SHALL</bcp14> return an error indicating the host mismatch.</li>
          <li>The URI is in remote form and contains a <tt>username</tt>
          subcomponent that does not match the OS-level username of the user
          under whose account the resolver is operating (case-insensitive
          comparison).  The resolver <bcp14>SHALL</bcp14> return an error indicating the
          user mismatch.</li>
          <li>The <tt>session-ref</tt> is a session alias that is not registered in the
          alias registry.</li>
          <li>The session log for the resolved session identifier is not accessible
          to the resolver.</li>
          <li>The session log has been deleted, expired, or is otherwise
          unavailable.</li>
          <li>The <tt>agent-name</tt> is not recognized by the resolver.</li>
          <li>No session log entries fall within the resolution window.</li>
        </ul>
        <t>An unresolvable URI is NOT invalid.  The URI remains a valid provenance
        identifier and <bcp14>SHALL</bcp14> be preserved in provenance records even when the
        referenced session is no longer accessible.  Resolvers <bcp14>SHOULD</bcp14> distinguish
        between "unresolvable" and "invalid" when reporting resolution status, and
        <bcp14>SHOULD</bcp14> report host-mismatch and user-mismatch conditions as distinct
        errors to aid debugging.</t>
        <t>When resolution succeeds, the resolver <bcp14>SHALL</bcp14> return the canonical URI
        in the same form as the URI that was presented for resolution: if the input
        was a local-only URI (<tt>prompt:/...</tt>), the returned
        <tt>canonical_uri</tt> <bcp14>SHALL</bcp14> be in local form; if the input was a remote
        URI (<tt>prompt://...</tt>), the returned <tt>canonical_uri</tt> <bcp14>SHALL</bcp14>
        be in remote form, preserving the <tt>host</tt>, <tt>username</tt> (if
        present), and <tt>port</tt> (if non-default) from the input URI.</t>
      </section>
    </section>

    <section anchor="ambiguity-multiple-uris" numbered="true" toc="default">
      <name>Ambiguity: Multiple URIs for One Prompt</name>
      <t>A single prompt <bcp14>MAY</bcp14> be the source of multiple tool calls, each of which
      produces a prompt URI with a distinct timestamp.  This is the common case in
      agent workflows, where a single user message triggers a sequence of file reads,
      web fetches, and file writes, each implemented as a separate tool call.</t>
      <t>All prompt URIs generated within the same session from the same originating
      prompt refer to that same prompt, even though their <tt>prompt-ref</tt> components
      differ.  Implementations <bcp14>SHOULD</bcp14> treat these URIs as semantically equivalent
      for provenance purposes, even though they are not syntactically equivalent
      (<xref target="normalization"/>) and will not compare as equal.</t>
      <t>When the agent provides a prompt correlation identifier, implementations
      <bcp14>SHOULD</bcp14> normalize all such URIs to the canonical prompt-id form
      (<xref target="canonical-uri"/>) before writing provenance records.  This eliminates the
      proliferation of distinct URIs for the same prompt and enables deduplication by
      string comparison, without session log access.</t>
      <t>Additionally, the same prompt may be identifiable by URIs with different
      timestamp precision:</t>
      <sourcecode><![CDATA[
prompt:/claude-code/5674b542.../2026-07-07T16:45:23Z
prompt:/claude-code/5674b542.../2026-07-07T16:45:23.856Z
]]></sourcecode>
      <t>Both of the above URIs identify the same instant in time at different precision
      levels.  Per <xref target="normalization"/>, these URIs are NOT equivalent.  Per
      <xref target="resolution"/>, they <bcp14>SHOULD</bcp14> resolve to the same candidate when the
      resolution window is applied.  Implementations that store provenance records
      <bcp14>SHOULD</bcp14> use a consistent timestamp precision to minimize the proliferation of
      distinct URIs for the same prompt.</t>
    </section>

    <section anchor="ambiguity-one-uri" numbered="true" toc="default">
      <name>Ambiguity: One URI for Multiple Prompts</name>
      <t>A single prompt URI <bcp14>MAY</bcp14> be ambiguous when multiple distinct prompts occur
      within the resolution window of its timestamp.  This arises in the following
      conditions:</t>
      <t><strong>Within-session collision:</strong> Two or more distinct user prompts within the
      same session are submitted and processed within the same second (or within the
      resolution window of a sub-second timestamp).  This is uncommon in interactive
      agent sessions, where user prompts are typically separated by seconds to minutes,
      but <bcp14>MAY</bcp14> occur in automated pipelines where prompts are submitted
      programmatically without human pacing.</t>
      <t><strong>Cross-session collision:</strong> Two sessions with different session identifiers
      are not a source of ambiguity for a given URI, since the session identifier is
      a URI component.  However, if a resolver has access to session logs from multiple
      agents with the same <tt>agent-name</tt>, and two such logs share a <tt>session-id</tt> value
      (which <bcp14>SHOULD NOT</bcp14> occur when UUIDs are used), a cross-log collision is
      possible.</t>

      <section anchor="mitigation" numbered="true" toc="default">
        <name>Mitigation</name>
        <t>Implementations <bcp14>SHOULD</bcp14> use millisecond-precision timestamps (rather than
        second-precision) to reduce the probability of within-session collisions.
        With millisecond precision, a collision requires two distinct prompts to arrive
        within the same millisecond, which is negligible in interactive use.</t>
        <t>Implementations <bcp14>MAY</bcp14> append a fragment identifier to a prompt URI to encode
        an agent-internal correlation identifier when that identifier is known at call
        time:</t>
        <sourcecode><![CDATA[
prompt:/claude-code/5674b542.../2026-07-07T16:45:23.856Z#id=abc123
]]></sourcecode>
        <t>Fragment identifiers used for this purpose are implementation-specific and
        are <bcp14>OPTIONAL</bcp14> and not required for interoperability.  Resolvers that do not
        recognize a fragment identifier <bcp14>SHOULD</bcp14> ignore it and apply the standard
        resolution algorithm.</t>
      </section>

      <section anchor="disclosure" numbered="true" toc="default">
        <name>Disclosure Requirement</name>
        <t>Implementations that generate prompt URIs <bcp14>SHOULD</bcp14> document the timestamp
        precision they use and the conditions under which within-session collisions
        are possible, so that consumers of provenance records can assess the
        reliability of URI-based prompt identification in their deployment context.</t>
      </section>
    </section>

    <section anchor="mcp-api" numbered="true" toc="default">
      <name>MCP Resolution API</name>
      <t>This document does not yet formally define the Model Context Protocol
      <xref target="MCP"/> API that a conformant <tt>prompt</tt>-scheme resolver
      <bcp14>SHALL</bcp14> implement.  That definition is deferred to a future revision or
      companion document.</t>
      <t>However, the reference implementation <xref target="PROMPT-URL-MCP"/>
      demonstrates a working API, and it is <bcp14>RECOMMENDED</bcp14> that
      implementations follow it for interoperability.  The reference implementation
      exposes the following MCP tools over an HTTP/1.1 StreamableHTTP transport
      (JSON-RPC 2.0, <tt>POST /mcp</tt>, default port <tt>7560</tt>):</t>
      <dl newline="true" spacing="normal">
        <dt><tt>resolve_prompt</tt></dt>
        <dd>Resolves a prompt URI to the originating user message.  Accepts a
        single parameter <tt>uri</tt> (string).  Returns the resolved user message
        text, agent identifier, session identifier, timestamp, and canonical URI.
        Validates host and username in remote URIs against the local machine's
        hostname and current OS user, respectively.</dd>
        <dt><tt>generate_prompt_url</tt></dt>
        <dd>Generates a prompt URI for a given agent, session identifier, and
        optional prompt reference.  Accepts <tt>agent</tt>, <tt>session_id</tt>,
        <tt>prompt_ref</tt> (optional), <tt>host</tt> (optional), <tt>username</tt>
        (optional), and <tt>port</tt> (optional).  When <tt>host</tt> is absent,
        generates a local-only URI (<tt>prompt:/...</tt>); when present, generates a
        remote URI (<tt>prompt://[user@]host[:port]/...</tt>).</dd>
        <dt><tt>find_prompt</tt></dt>
        <dd>Searches session logs for prompts within a time range.  Accepts
        <tt>since</tt>, <tt>until</tt>, <tt>agent</tt>, and <tt>limit</tt> parameters.
        Returns a list of matching prompts sorted oldest first, each including its
        <tt>prompt_url</tt>, <tt>user_message</tt>, and <tt>timestamp</tt>.  A
        <tt>commit</tt> parameter <bcp14>MAY</bcp14> be supplied in lieu of explicit time
        bounds; when present, the time range is derived from the commit timestamp
        and its predecessor using <tt>git log</tt>.</dd>
        <dt><tt>list_sessions</tt></dt>
        <dd>Lists known agent sessions for the current user, optionally filtered
        by agent identifier.</dd>
        <dt><tt>register_alias</tt></dt>
        <dd>Registers a human-readable alias for a session identifier, enabling
        the alias form of the prompt URI (<xref target="session-aliases"/>).</dd>
      </dl>
      <t>Implementations that provide remote resolution (<tt>prompt://</tt> form) over
      the network <bcp14>SHOULD</bcp14> require authentication before serving session log
      content.  The reference implementation currently binds to
      <tt>127.0.0.1</tt> only (loopback) and does not expose session content to
      other machines without explicit network reconfiguration.  Deployers that
      choose to expose the service on a non-loopback interface
      <bcp14>MUST</bcp14> implement appropriate access controls.</t>
    </section>

    <section anchor="security" numbered="true" toc="default">
      <name>Security Considerations</name>
      <t><strong>Confidentiality:</strong> A prompt URI encodes the agent identity, session
      identifier, and approximate timestamp of a tool call.  In its remote form,
      it additionally encodes the hostname of the user's machine and optionally
      the username of the account under which the agent operates.  Any or all of
      this information <bcp14>MAY</bcp14> be sensitive: session identifiers may be treated as
      access credentials; hostnames and usernames identify specific individuals
      and machines; and the existence of a particular agent interaction may itself
      be confidential in some deployments.  Implementors <bcp14>SHOULD</bcp14> treat prompt
      URIs  --  particularly remote-form URIs containing hostname or username  --  with
      the same access controls applied to session logs, and <bcp14>SHOULD NOT</bcp14> embed
      remote-form URIs in artifacts that will be shared beyond the trust boundary
      of the originating user and machine.</t>
      <t><strong>Spoofability:</strong> Prompt URIs are not cryptographically signed.  Any party
      with knowledge of a valid agent name, session identifier, and approximate
      timestamp can construct a syntactically valid URI.  Resolvers <bcp14>SHALL NOT</bcp14> treat a
      prompt URI as proof of authenticity; they <bcp14>SHOULD</bcp14> verify that the referenced
      session log actually contains a prompt at the indicated time.</t>
      <t><strong>Log availability:</strong> Resolution depends on the availability of session logs,
      which are typically stored on the client machine.  Logs may be deleted,
      corrupted, or unavailable to the resolver.  Provenance systems <bcp14>SHALL NOT</bcp14> treat
      an unresolvable URI as evidence of tampering; unresolvability is an expected
      operational condition.</t>
      <t><strong>Session identifier reuse:</strong> If an agent implementation reuses session
      identifiers across sessions (which <bcp14>SHOULD NOT</bcp14> occur when UUIDs are used), URIs
      from different sessions would become ambiguous.  Implementations <bcp14>SHALL</bcp14> use
      session identifiers with negligible collision probability.</t>
    </section>

    <section anchor="iana" numbered="true" toc="default">
      <name>IANA Considerations</name>
      <t>This document requests registration of the <tt>prompt</tt> URI scheme in the IANA
      Uniform Resource Identifier (URI) Schemes registry, established by
      <xref target="RFC7595"/>.</t>
      <dl newline="false" spacing="normal">
        <dt>Scheme name:</dt>
        <dd><tt>prompt</tt></dd>
        <dt>Status:</dt>
        <dd>Provisional</dd>
        <dt>Applications/protocols that use this scheme:</dt>
        <dd>AI agent provenance metadata, session log indexers, agent tool
        frameworks.</dd>
        <dt>Contact:</dt>
        <dd>Keith W. Boone</dd>
        <dt>Change controller:</dt>
        <dd>Keith W. Boone</dd>
        <dt>References:</dt>
        <dd>This document.</dd>
      </dl>
      <t>Pending IANA registration, implementations <bcp14>SHALL</bcp14> treat the <tt>prompt</tt> scheme
      as an unregistered provisional scheme per <xref target="RFC7595"/> Section 3.3.</t>
    </section>

  </middle>

  <back>
    <references>
      <name>References</name>

      <references anchor="normative-refs">
        <name>Normative References</name>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3339.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5234.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7595.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9562.xml"/>
      </references>

      <references anchor="informative-refs">
        <name>Informative References</name>
        <reference anchor="MCP">
          <front>
            <title>Model Context Protocol Specification</title>
            <author>
              <organization>Anthropic</organization>
            </author>
            <date year="2024"/>
          </front>
          <refcontent>Available at: https://modelcontextprotocol.io/</refcontent>
        </reference>
        <reference anchor="CLAUDE-SESSIONS">
          <front>
            <title>Claude Code Session Log Format</title>
            <author>
              <organization>Anthropic</organization>
            </author>
            <date year="2026"/>
          </front>
          <refcontent>Internal format; session logs stored at
          ~/.claude/projects/{project}/{session-id}.jsonl.
          Prompt correlation field: promptId.</refcontent>
        </reference>
        <reference anchor="COPILOT-SESSIONS">
          <front>
            <title>Copilot Session State Format</title>
            <author>
              <organization>GitHub</organization>
            </author>
            <date year="2026"/>
          </front>
          <refcontent>Internal format; session events stored at
          ~/.copilot/session-state/{session-id}/events.jsonl.
          Timestamp format: ISO 8601 UTC with milliseconds.
          Prompt correlation field: interactionId.</refcontent>
        </reference>
        <reference anchor="PROMPT-URL-MCP">
          <front>
            <title>prompt-url-mcp: MCP Server for prompt: URI Resolution and Generation</title>
            <author fullname="Keith W. Boone" initials="K." surname="Boone">
              <organization>Audacious Inquiry</organization>
            </author>
            <date year="2026"/>
          </front>
          <refcontent>Available at: https://github.com/AudaciousInquiry/prompt-url
          and https://www.npmjs.com/package/@audaciousinquiry/prompt-url-mcp</refcontent>
        </reference>
      </references>
    </references>

    <section anchor="git-hook" numbered="false" toc="default">
      <name>Appendix A: Automatic Prompt-URL Trailer via Git Hook</name>
      <t>This appendix describes a <tt>prepare-commit-msg</tt> git hook, provided
      alongside the reference implementation <xref target="PROMPT-URL-MCP"/>, that
      automatically appends a <tt>Prompt-URL:</tt> trailer to any git commit that was
      AI-assisted by GitHub Copilot.</t>

      <section anchor="git-hook-operation" numbered="false" toc="default">
        <name>Operation</name>
        <t>Git invokes <tt>prepare-commit-msg</tt> after the initial commit message
        is prepared but before the editor is opened.  The hook:</t>
        <ol>
          <li>Examines the draft commit message for a
          <tt>Co-authored-by: Copilot</tt> trailer injected automatically by
          VS Code / GitHub Copilot.</li>
          <li>If the trailer is present and no <tt>Prompt-URL:</tt> trailer already
          exists, queries the local <tt>prompt-url-mcp</tt> daemon (via its
          <tt>find_prompt</tt> tool, <xref target="mcp-api"/>) for the most recent
          Copilot prompt submitted within the past 30 minutes.</li>
          <li>If a result is returned, appends a <tt>Prompt-URL:</tt> trailer
          containing the local-form prompt URI
          (<tt>prompt:/github-copilot/...</tt>) to the commit message.</li>
          <li>If the daemon is not running or returns no results, exits silently
          without modifying the commit message.  The hook
          <bcp14>MUST NOT</bcp14> block a commit under any error condition.</li>
        </ol>
      </section>

      <section anchor="git-hook-installation" numbered="false" toc="default">
        <name>Installation</name>
        <t>The hook is a Node.js script that requires Node.js in <tt>PATH</tt>
        and the <tt>prompt-url-mcp</tt> daemon to be running.  It is located at
        <tt>hooks/prepare-commit-msg</tt> in the reference implementation
        repository.</t>
        <t><strong>Per-repository installation:</strong></t>
        <sourcecode type="bash"><![CDATA[
cp hooks/prepare-commit-msg .git/hooks/prepare-commit-msg
chmod +x .git/hooks/prepare-commit-msg
]]></sourcecode>
        <t><strong>Global installation</strong> (applies to all repositories for the
        current user).  The recommended global hooks directory is
        <tt>~/.git-hooks/</tt>:</t>
        <sourcecode type="bash"><![CDATA[
git config --global core.hooksPath ~/.git-hooks
mkdir -p ~/.git-hooks
cp hooks/prepare-commit-msg ~/.git-hooks/prepare-commit-msg
chmod +x ~/.git-hooks/prepare-commit-msg
]]></sourcecode>
        <t>On Windows the <tt>chmod</tt> command may be run in Git Bash or WSL.
        Git for Windows treats copied scripts as executable by default.</t>
      </section>

      <section anchor="git-hook-example" numbered="false" toc="default">
        <name>Resulting Commit Message</name>
        <t>A commit message with Copilot co-authorship, after the hook appends
        the trailer, takes the following form:</t>
        <sourcecode><![CDATA[
feat: add user registration validation

Implement unique-email check at registration time. Returns 409
if the email address is already in use.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Prompt-URL: prompt:/github-copilot/95602ecf-.../~8e16a698-...
]]></sourcecode>
      </section>
    </section>

  </back>

</rfc>
