<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
]>
<?rfc toc="yes"?>
<?rfc symrefs="yes"?>
<?rfc sortrefs="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="no"?>

<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="info"
     docName="draft-gaikwad-agent-friendly-http-api-profile-01"
     ipr="trust200902"
     submissionType="independent"
     version="3">

  <front>
    <title abbrev="Agent-Friendly HTTP API Profile">Design Considerations and Profile for HTTP APIs Consumed by AI Agents</title>

    <seriesInfo name="Internet-Draft" value="draft-gaikwad-agent-friendly-http-api-profile-01"/>

    <author fullname="Madhava Gaikwad" initials="M." surname="Gaikwad">
      <organization>Independent</organization>
      <address>
        <postal>
          <city>Bengaluru</city>
          <country>India</country>
        </postal>
        <email>gaikwad.madhav@gmail.com</email>
      </address>
    </author>

    <date day="30" month="June" year="2026"/>

    <area>General</area>

    <abstract>
      <t>AI agents are a fast-growing kind of HTTP API client.  A human
      developer reads an API's documentation once and then writes code that
      calls it.  An AI agent works from the machine-readable description
      each time it plans a step.  It works within a limited amount of text
      it can hold at once.  It retries often.  It picks operations by
      matching their descriptions to a goal.  An API built mainly for human
      developers can lead an agent into failures that are easy to avoid,
      such as repeating a write, running out of room for the task, or
      getting stuck on an error it cannot recover from.</t>

      <t>This document lists the properties that make an HTTP API easy for AI
      agents to use, including APIs reached through tool-calling layers
      such as the Model Context Protocol.  It gathers these properties into
      a profile of existing HTTP and API-description mechanisms, with a
      checklist at the end.  It covers the API and its description.  It
      does not define new ways to identify, authenticate, or authorize an
      agent.  That work is happening elsewhere and is referenced here for
      context.</t>
    </abstract>
  </front>

  <middle>

    <!-- ============================================================ -->
    <section anchor="introduction">
      <name>Introduction</name>

      <t>Autonomous software agents built on large language models are
      starting to call HTTP APIs.  Sometimes the agent forms the HTTP
      request itself.  More often it goes through a tool-calling layer that
      presents each API operation as a callable "tool".  The Model Context
      Protocol <xref target="MCP"/> is one common example of such a layer.
      Many of its servers are generated automatically from an existing API
      description such as an OpenAPI document <xref target="OPENAPI"/>.</t>

      <t>One property matters most.  The description of the API, and the data
      the API returns, both become input to the agent's own reasoning.
      Several single points in this document are also ordinary good API
      practice: stable operation names, bounded pages, structured errors,
      idempotency.  This document explains why each one matters more when
      the client is an agent.  It adds the guidance that is specific to
      agents.  It collects the result as a profile that a provider can
      apply and check against.  This document does not assume that an agent
      is reliable or well-behaved.  It treats the agent as a client whose
      behavior is shaped by the shape of the API.</t>

      <!-- ======== -->
      <section anchor="two-layers">
        <name>Two Layers</name>

        <t>There are two layers to keep separate.  The API layer is the HTTP API
        and its machine-readable description.  The tool layer is the surface
        that a tool-calling protocol or generator builds from that
        description.  This document is about the API layer.  A good API layer
        is the most reusable way to get a good tool layer.  The tool layer is
        increasingly handled by its own protocols.</t>
      </section>

      <!-- ======== -->
      <section anchor="api-styles">
        <name>API Styles</name>

        <t>The advice here is written for resource-oriented HTTP APIs, where
        each operation acts on an identified resource.  Most of it also
        applies to query-based APIs such as GraphQL and to remote-procedure-
        call styles such as gRPC.  A few points change.  A query-based API
        lets the client ask for exactly the fields it needs, which handles
        the over-fetching concern in <xref target="keep-responses-small"/> on its own.  In return it adds
        query-cost and query-depth concerns that an agent-facing deployment
        <bcp14>SHOULD</bcp14> limit.  A reader using this document with another style should
        map each point to the matching idea in that style.</t>
      </section>

      <!-- ======== -->
      <section anchor="scope">
        <name>Scope and Non-Goals</name>

        <t>This document is informational.  It lists considerations, gives non-
        normative recommendations, and assembles a profile and a checklist.
        It does not define a protocol or a wire format.  These topics are out
        of scope:</t>

        <ul>
          <li>How an agent proves its identity, authenticates, or is granted
          authority by a user.  That work is active in the IETF, including
          OAuth 2.0 Token Exchange <xref target="RFC8693"/>, on-behalf-of authorization for
          agents <xref target="I-D.oauth-ai-agents-obo"/>, and wider frameworks
          <xref target="I-D.klrc-aiagent-auth"/>.  <xref target="identity-and-auth"/> explains the connection.</li>

          <li>The internal design of tool-calling protocols, including how those
          protocols define tools, resources, and prompts.</li>

          <li>Agent-side topics such as planning, reasoning traces, and model
          evaluation.</li>
        </ul>
      </section>

      <!-- ======== -->
      <section anchor="requirements-language">
        <name>Requirements Language</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.
        This document is informational.  These words give guidance to API
        authors.  They are not protocol requirements.</t>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="terminology">
      <name>Terminology</name>

      <dl>
        <dt>Agent:</dt>
        <dd>An autonomous software system, usually built on a large
        language model, that picks and calls API operations to reach a
        goal.</dd>

        <dt>Tool:</dt>
        <dd>An API operation as it is shown to an agent by a tool-calling
        layer.  It has a name, a short description, and an input schema.</dd>

        <dt>API description:</dt>
        <dd>A machine-readable definition of an API, such as an
        OpenAPI document <xref target="OPENAPI"/>, that a tool layer can be built from.</dd>

        <dt>Context window:</dt>
        <dd>The limited amount of text the agent's model can
        hold and read at one time.  Operation descriptions and response
        bodies use up this space.</dd>

        <dt>Affordance:</dt>
        <dd>A machine-readable part of a request or response that
        tells the agent what it can or should do, in a form it can act on
        without reading prose.</dd>
      </dl>
    </section>

    <!-- ============================================================ -->
    <section anchor="how-agent-uses-api">
      <name>How an Agent Uses an API</name>

      <t>The advice below follows from a few facts about how an agent uses an
      API.  Stating them shows where the advice applies.</t>

      <ul>
        <li>The description is input.  The agent is shown operation names,
        descriptions, and schemas while it plans and picks a tool.  Their
        wording decides which operation it picks and how it fills in the
        arguments.</li>

        <li>Selection is by similarity.  The agent picks an operation because
        its description reads close to the goal.  It does not follow fixed
        logic.  Two operations that read alike cause wrong-operation and
        wrong-argument mistakes.</li>

        <li>Space is limited.  Descriptions and responses share one budget of
        text with the task itself.  Large or low-value payloads crowd out
        the task and make later choices worse.</li>

        <li>Retries are common.  An agent retries after a timeout or an
        unclear result.  It may also send a request again as its plan
        changes.</li>

        <li>Writes are easy to trigger.  An agent can call an operation that
        changes state while it is exploring.  So an unintended or repeated
        write costs more than it would for a human-driven client.</li>
      </ul>

      <t>These facts apply most directly when operation descriptions, schemas,
      error messages, and response bodies reach a language model or a
      model-guided planner.  When something in between filters, checks, or
      shortens the data before the model sees it, the space and selection
      effects shrink but do not disappear.  The retry and side-effect
      effects usually remain.</t>
    </section>

    <!-- ============================================================ -->
    <section anchor="prefer-signals">
      <name>Prefer Signals the Agent Can Act On</name>

      <t>This is the main idea of the document.  An agent-facing API <bcp14>SHOULD</bcp14>
      give the agent machine-readable signals it can act on.  It <bcp14>SHOULD</bcp14>
      avoid relying on prose that the agent has to read and interpret.  A
      sentence such as "call this carefully" or "try again later" has to be
      understood by the model, and the model follows such sentences
      unevenly.  The same intent stated as a field or a flag can be acted
      on directly.  This swap shows up throughout the profile:</t>

      <ul>
        <li>an error carries a retryable flag the agent can read (<xref target="make-errors-recoverable"/>);</li>
        <li>a response carries links to the operations that are valid next
        steps (<xref target="keep-responses-small"/>);</li>
        <li>a write accepts a dry-run flag that previews its effect
        (<xref target="make-writes-safe"/>);</li>
        <li>a schema lists allowed values as a fixed set (<xref target="api-description-contract"/>);</li>
        <li>a high-risk operation carries metadata that says it needs
        confirmation (<xref target="make-writes-safe"/>).</li>
      </ul>
    </section>

    <!-- ============================================================ -->
    <section anchor="api-description-contract">
      <name>The API Description Is the Contract</name>

      <t>When an API is reached through a generated tool layer, its machine-
      readable description is the single source the tools are built from.
      Anything missing from the description is missing from the tool.  So
      treat the description as a main deliverable.  Do not treat it as
      documentation written after the code.</t>

      <ul>
        <li>Give every operation a stable, meaningful identifier, for example
        the OpenAPI operationId.  Identifiers generated from the URL path
        produce tool names the agent picks badly.</li>

        <li>When several operations share a common verb prefix (such as get_,
        list_, create_), the verb does not help the agent distinguish
        between them.  The distinguishing information is the entity or
        resource name.  Leading with the entity groups related operations
        and lets the agent narrow the search space earlier in the
        identifier.  For example, tasks_list, task_create, task_update
        group by entity, while list_tasks, create_task, update_task group
        by verb.  When an API has many operations across many resource
        types, entity-leading identifiers reduce collisions at the start
        of the name.  For operations where the resource name is the
        complete intent (such as a health summary or an audit log), the
        verb may be omitted.  This guidance is about the operationId or
        tool name.  It does not change the HTTP method or URL structure.
        This <bcp14>SHOULD</bcp14> be treated as a consideration based on
        the size of the tool surface.  Empirical testing shows the effect
        varies by model.</li>

        <li>Give each operation a short summary that sets it apart from
        similar ones.  Give it a longer description that says when to use
        it and when not to.  Wording such as "Use this when ..." and "Do
        not use this when ..." works well.  It heads off the wrong-
        operation mistake from <xref target="how-agent-uses-api"/>.
        <xref target="appendix-weak-strong-description"/> shows this.</li>

        <li>Put the most important information first in the description.  The
        agent may not read all of it.</li>

        <li>State side effects in the description.  Do not leave them implied
        by the HTTP method.</li>

        <li>Type and describe every parameter and response field.  List
        allowed values as an enumeration, which is a fixed set of
        permitted values.  Set additionalProperties to false on objects,
        or use the equivalent, so the agent cannot add invented
        parameters.  Include a real example.</li>

        <li>Put idempotency support, pagination limits, field-selection or
        verbosity controls, and deprecation status in the description
        itself.  The agent acts on the description.  Guidance kept only in
        human documentation does not reach it.</li>

        <li>Keep the description short and free of repeated prose.  Its text
        uses up the agent's space budget.</li>

        <li>Avoid common description mistakes that lead to wrong-operation or
        wrong-argument choices.  The most frequent problems include:
        restating the operation name without adding information (for
        example, "Creates a task" for an operation named create_task);
        omitting side effects; omitting "do not use this when" guidance;
        using jargon or internal names the agent has no context for; and
        describing what the operation returns rather than when to use it.
        <xref target="appendix-anti-patterns"/> lists these in more detail.</li>

        <li>Test the description by running an agent against the API and
        reading where it picks the wrong operation or fills in a bad
        argument.  These wording problems are hard to predict any other
        way.</li>
      </ul>
    </section>

    <!-- ============================================================ -->
    <section anchor="be-consistent">
      <name>Be Consistent and Predictable</name>

      <t>An agent learns patterns and reuses them.  Anything inconsistent
      across the API makes it guess wrong.  Keep naming, identifier
      formats, pagination, error shape, and authentication the same across
      the whole API.  For example, a status value that is pending on one
      operation, IN_PROGRESS on another, and done on a third will cause
      errors.  When an operation only works in certain states of a
      resource, document the states and the moves between them.  Then the
      agent can work out which operations are valid without guessing.  Keep
      enumerated values stable.  The agent may have seen and remembered
      them in an earlier call.</t>
    </section>

    <!-- ============================================================ -->
    <section anchor="set-of-operations">
      <name>The Set of Operations You Expose</name>

      <t>A complete resource-oriented API does not become a good tool surface
      on its own.  Turning every endpoint into its own tool gives the agent
      a surface that is large, low-level, and hard to work through.</t>

      <ul>
        <li>Offer composite operations that finish a whole unit of work in one
        call, where the steps behind them are common, safe, and well-
        bounded.  This saves the agent from chaining several calls, where
        each call is a separate reasoning step.  Keep resource meaning
        intact where you can.  Keep authorization, audit, and partial-
        failure behavior visible.</li>

        <li>Curate the operations you expose.  A small set of well-described
        operations serves the agent better than a large set it has to sort
        through.  Empirical measurements suggest that tool-selection
        accuracy degrades sharply as the number of operations grows into
        the hundreds.  Keeping the exposed set small is not just a
        recommendation for clarity.  It is a practical limit on agent
        effectiveness.</li>

        <li>Some operations need extra care before an agent should reach them:
        the ones that take opaque binary input, change infrastructure, or
        cause effects that cannot be undone.  Expose these to a general-
        purpose agent only with extra controls, such as a clear schema, a
        preview, narrow authorization, a confirmation step, or human
        approval.  Do not expose deprecated operations at all.</li>

        <li>Offer batch operations that do several related actions in one
        call.  A batch operation <bcp14>SHOULD</bcp14> report one result per item, so the
        agent can see which items succeeded and which failed.</li>

        <li>When a value can be found by a human-meaningful name, accept that
        name or offer a lookup operation.  Do not force the agent to
        supply an opaque identifier it has no way to get.</li>
      </ul>
    </section>

    <!-- ============================================================ -->
    <section anchor="keep-responses-small">
      <name>Keep Responses Small</name>

      <t>A response uses up the agent's space budget on the turn it arrives,
      and on every later turn it stays in view.  Asking for too much costs
      more each turn.  A response that is too large is also a denial-of-
      service and cost problem (see <xref target="security-considerations"/>).</t>

      <ul>
        <li>Return the fields that carry signal.  Drop low-level details the
        agent will not use.  When clients need different amounts of data,
        support field selection or a verbosity setting.  A verbosity
        setting can be as simple as a response_format parameter with
        values such as concise and detailed, where concise returns
        display-friendly fields (name, status, assignee name) and detailed
        adds internal identifiers, timestamps, and linking fields needed
        for chaining into downstream operations.  This is simpler than
        field selection when the agent does not know which fields to ask
        for.  <xref target="appendix-field-selection"/> shows both mechanisms.</li>

        <li>Support conditional requests on reads, for example an entity tag
        (an ETag value) with the matching conditional header.  Then an
        agent that asks for the same data again can be told it has not
        changed.  It does not have to receive and re-read an identical
        payload.</li>

        <li>Set a bounded default page size on collections.  Document how the
        agent can narrow the results before it fetches them.  A large or
        open-ended default makes the agent spend its space budget on low-
        value items, and it can make the agent's next tool choice worse.</li>

        <li>Use cursor-based pagination.  A cursor is an opaque token the
        server returns that marks where the next page starts.  Return a
        ready-to-use continuation, either that cursor or a complete
        next_page link, so the agent does not have to compute offsets or
        build URLs.  It does both of those unreliably.</li>

        <li>Give collections a stable, documented order.  Results that change
        order between calls confuse the agent.</li>

        <li>Make values self-describing when the type alone is unclear.  For
        example, return a money amount together with its currency, not as
        a bare number.  Return a human-readable label next to an
        identifier where you can.</li>

        <li>Include links to the operations that are valid next steps on a
        returned resource.  Then the agent can see the available moves and
        does not have to guess them.</li>
      </ul>
    </section>

    <!-- ============================================================ -->
    <section anchor="make-errors-recoverable">
      <name>Make Errors Recoverable</name>

      <t>An error response is not the end of the story.  It is the input to
      the agent's next decision.  An error that is unstructured or unclear
      leads the agent to retry something that cannot work, or to give up on
      something a retry would have fixed.</t>

      <t>Use a structured, machine-readable error format such as Problem
      Details for HTTP APIs <xref target="RFC9457"/>, which is a standard JSON shape for
      errors.  Include a stable error code that is separate from the HTTP
      status code.</t>

      <t>Problem Details lets you add your own fields.  For an agent-facing
      API, say plainly whether a failed call can be retried, using a field.
      Do not leave the agent to read this off the status code.  Report
      every validation problem at once, with the field name for each one.
      A small, consistent set of fields across the API does the job: a
      boolean retryable, an optional retry-delay hint, and a list of field
      errors.  With these the agent can decide to retry, to change the
      request, or to stop, without guessing.  The field names here are only
      examples.  This document does not register them.  That would be the
      job of a later specification (see <xref target="iana-considerations"/>).
      Here is a retryable rate-limit error:</t>

      <figure anchor="fig-retryable-error">
        <name>Error response with an explicit retry indication</name>
        <artwork type="http-message"><![CDATA[
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/problem+json

{
  "type": "https://api.example.com/problems/rate-limited",
  "title": "Rate limit exceeded",
  "status": 429,
  "detail": "Request rate exceeded for this credential.",
  "code": "RATE_LIMITED",
  "retryable": true,
  "retry_after": 30
}]]></artwork>
      </figure>

      <t>A validation error sets retryable to false and lists the fields that
      were wrong.  That tells the agent to change the request before it
      sends it again:</t>

      <figure anchor="fig-validation-error">
        <name>Validation error that should not be retried unchanged</name>
        <artwork type="http-message"><![CDATA[
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json

{
  "type": "https://api.example.com/problems/validation",
  "title": "Invalid request",
  "status": 422,
  "code": "VALIDATION_FAILED",
  "retryable": false,
  "field_errors": [
    { "field": "assignee_email", "code": "INVALID_FORMAT",
      "detail": "Not a valid email address." },
    { "field": "priority", "code": "NOT_IN_ENUM",
      "detail": "Must be one of: low, medium, high." }
  ]
}]]></artwork>
      </figure>
    </section>

    <!-- ============================================================ -->
    <section anchor="make-writes-safe">
      <name>Make Writes Safe to Repeat, Preview, and Undo</name>

      <t>Agents retry after timeouts, after unclear results, and as their plan
      changes.  So safe writing for agents covers more than one idea.  It
      covers repeating a write safely, previewing it, confirming it,
      cancelling it, and undoing it.  As a rule, prefer writes that can be
      previewed, cancelled, and reversed over writes that take effect at
      once and cannot be undone.</t>

      <ul>
        <li>Support a client-supplied idempotency key on operations that have
        side effects.  Idempotency means that sending the same request
        twice has the same effect as sending it once.  With a key, a retry
        that carries the same key returns the first result and does not
        run the operation again.  The Idempotency-Key HTTP header field
        <xref target="I-D.httpapi-idem"/> is one way to do this.  Document the mechanism,
        the length of time a key is honored, and the scope in which a key
        must be unique.  These decide whether a retry is safe.</li>

        <li>Tell a settled result apart from a temporary failure in what you
        store for a key.  A settled result is safe to return again.  A
        temporary server error is not, and returning it again as if it
        were final is a known trap.  Reject a request that reuses a key
        with a clearly different body.  Use a conflict status.</li>

        <li>For operations with large or irreversible effects, offer a
        preview, or dry-run, mode.  It reports what the operation would do
        without doing it.  In a resource-oriented API a request header
        (for example, X-Dry-Run: true) or a query parameter (for example,
        ?dry_run=true) works well.  The response lists the predicted
        changes.  <xref target="appendix-dry-run"/> shows this.</li>

        <li>Mark high-risk operations with explicit metadata, for example a
        flag that the operation cannot be undone or that it needs
        confirmation.  You can also require a separate confirmation step
        outside the request.  The point is that the signal is machine-
        readable, not buried in warning text.</li>
      </ul>
    </section>

    <!-- ============================================================ -->
    <section anchor="signal-slow-down">
      <name>Signal When to Slow Down</name>

      <t>Agent traffic can come in bursts.  It often lacks the natural pacing
      of a person at a keyboard.  Signal clearly when the client should
      slow down, so a well-behaved agent can hold back on its own.</t>

      <ul>
        <li>When you reject or delay a request for rate limiting or a
        temporary outage, include a retry-delay hint such as the Retry-
        After header field.  A client should follow it ahead of its own
        backoff timer.</li>

        <li>You <bcp14>MAY</bcp14> measure limits in units that fit agent traffic, not a flat
        request count.  One agent task can turn into many calls and large
        responses.  Counting by response size, or by a cost unit you
        define, can match real load better.  Document the unit so the
        agent can track what it has left.</li>
      </ul>
    </section>

    <!-- ============================================================ -->
    <section anchor="long-running-operations">
      <name>Long-Running Operations</name>

      <t>An operation that takes more than a few seconds does not fit a single
      blocking request.  The connection may not stay open.  An agent that
      waits for it cannot do anything else in the meantime.</t>

      <ul>
        <li>Acknowledge a long-running operation at once with the right HTTP
        status <xref target="RFC9110"/> (often 202 Accepted).  Return an identifier for
        the operation and a link to a status resource the client can
        check.</li>

        <li>Have the status resource report a clear state, and on completion
        point to the finished resource.  Include a retry-delay hint and
        say how often to poll.  Allow the client to cancel an operation
        that has not finished.</li>

        <li>When the client can receive callbacks, you <bcp14>MAY</bcp14> send a notification
        when the operation finishes, in place of polling.  Authenticate
        the notification, protect it against replay, and give it an
        identifier the receiver can use to drop duplicate deliveries.</li>

        <li>When an operation produces output piece by piece, you <bcp14>MAY</bcp14> stream
        the partial output, for example over server-sent events.  Then the
        agent can start acting on early results before the operation
        finishes.</li>
      </ul>
    </section>

    <!-- ============================================================ -->
    <section anchor="changing-api">
      <name>Changing the API Over Time</name>

      <t>The agent's behavior comes from the API description.  So a change to
      the description is a change to the agent's tools.  Manage change
      carefully.</t>

      <ul>
        <li>Prefer changes that keep working for existing clients, such as
        adding an optional parameter or a new operation.  Save a new
        version for a change that would break an existing client, such as
        removing a field, changing a type, or making an optional parameter
        required.</li>

        <li>Do not change what an operation means while keeping its identifier
        the same.  An agent that learned the operation once will use it
        again and expect the old behavior.</li>

        <li>Signal deprecation in machine-readable form, for example the
        Deprecation and Sunset header fields and a link to the
        replacement.  Show it in the API description too.  Release notes
        on their own do not reach the agent.</li>

        <li>Detect breaking changes automatically by comparing each new
        version of the API description against the last one.</li>

        <li>Choose one way to express versions and use it across the whole
        API.  Mixing several versioning styles makes the API harder for
        the agent and for people to follow.</li>
      </ul>
    </section>

    <!-- ============================================================ -->
    <section anchor="discovery">
      <name>Making the API Easy to Discover</name>

      <t>An agent does best with one machine-readable, low-noise place to
      learn what the API can do.  A complete API description <xref target="OPENAPI"/> is
      the main artifact for this.  Some providers also publish a short,
      plain-text index of their documentation aimed at models.  The
      llms.txt convention <xref target="LLMSTXT"/> is one community example, and it is not
      a standard.  Generate any such file from the same source as the human
      documentation, so the two do not drift apart.  Keep it focused on
      parameters, the meaning of errors, and authentication.</t>
    </section>

    <!-- ============================================================ -->
    <section anchor="observability">
      <name>Observability</name>

      <t>After an agent runs, an operator often needs to work out what it did.
      To let the agent's steps line up with the API's own logs, accept and
      pass along a standard correlation identifier.  The W3C Trace Context
      traceparent header field <xref target="W3C-TRACE-CONTEXT"/> is one such identifier,
      and a generic correlation header is another.  Record it in the API's
      logs next to the identity that acted.  This helps with debugging,
      with working out cost, and with the audit trail in <xref target="security-considerations"/>.</t>
    </section>

    <!-- ============================================================ -->
    <section anchor="identity-and-auth">
      <name>How This Relates to Identity and Authorization</name>

      <t>This document does not say how an agent authenticates to an API, or
      how a user grants it authority.  A single static credential that
      covers the whole API is a poor fit for an agent.  If it leaks, it
      reaches everything.  The direction the field is taking is to issue
      narrow, short-lived credentials that can be revoked, and to record
      delegation openly.  The user the agent acts for is recorded
      separately from the agent.  That keeps actions traceable.</t>

      <t>Authors building for agents should follow the relevant work,
      including OAuth 2.0 Token Exchange <xref target="RFC8693"/>, protected resource
      metadata <xref target="RFC9728"/>, resource indicators <xref target="RFC8707"/>, dynamic client
      registration <xref target="RFC7591"/>, on-behalf-of authorization for agents
      <xref target="I-D.oauth-ai-agents-obo"/>, and the wider analysis in
      <xref target="I-D.klrc-aiagent-auth"/>.</t>
    </section>

    <!-- ============================================================ -->
    <section anchor="security-considerations">
      <name>Security Considerations</name>

      <t>Building an API for agents changes its security picture.  The changes
      connect to the points above.</t>

      <t>Injected instructions in text.  The agent treats the text it receives
      as input to its reasoning.  So both operation descriptions and
      response bodies can carry instructions that an attacker planted.
      This is called indirect prompt injection.  Keep trusted control
      fields apart from untrusted content.  Mark natural-language content
      that came from users or third parties as data, not as instruction.
      One way is to put it in its own named field and keep a note of where
      it came from.  Do not put externally supplied text into operation
      descriptions or API documentation unless it is clearly marked as
      untrusted.  Enforce access decisions at the API.  Do not rely on
      instructions in the agent's prompt, because injected text can
      override them.</t>

      <t>Running out of room and money.  An API can return a payload far
      larger than expected, and so can a downstream system that has been
      compromised.  A huge payload can fill the agent's space budget and
      make the task fail.  Where use is billed, it can also run up a large,
      unexpected cost.  People often treat the limits on response size and
      the cursor-based pagination in <xref target="keep-responses-small"/> as performance tuning.  For
      an agent they are also a security control.  Enforce them on the
      server.  Do not count on the client to ask for less.</t>

      <t>Unsafe retries.  The idempotency, preview, and undo guidance in
      <xref target="make-writes-safe"/> is also a security matter.  Agents retry more than clients
      driven by a person, and an unsafe retry can repeat an effect that
      changes state.  Apply least privilege to operations that have real
      side effects.  Keep an audit log that records who acted and under
      what delegation.  Consider requiring a confirmation step for high-
      risk actions.</t>

      <t>Tool shadowing across providers.  When multiple tool providers share
      the same agent context, a provider can register operations with names
      or descriptions designed to intercept calls meant for another
      provider.  This is a consequence of selection-by-similarity
      (<xref target="how-agent-uses-api"/>).  An agent that picks an operation because its
      description reads closest to the goal cannot tell a legitimate match
      from a planted one.  Mitigations include scoping tool namespaces by
      provider, pinning known-good tool sets, and verifying tool
      fingerprints.  This concern is documented in emerging threat
      taxonomies for tool-calling protocols.</t>

      <t>Wider reach when access is broad.  The discovery artifacts in
      <xref target="discovery"/> make the API easier for any automated client to read,
      including a hostile one.  They do not replace authorization or rate
      limiting.  Authorization is out of scope here.  Still, broad access
      together with easy discovery widens how much a tricked or compromised
      agent can reach.  Scope access narrowly to the task.  That limits the
      damage an injected instruction can do.</t>
    </section>

    <!-- ============================================================ -->
    <section anchor="profile-summary">
      <name>Agent-Friendly Profile Summary</name>

      <t>An HTTP API meant for agents can be called agent-friendly, in the
      sense of this document, when:</t>

      <ul>
        <li>operation identifiers are stable and reveal intent;</li>
        <li>descriptions say when to use and when not to use each operation,
        and state side effects;</li>
        <li>input objects are strictly typed, use fixed value sets, and reject
        unknown properties;</li>
        <li>responses are small by default, with field selection or verbosity
        controls;</li>
        <li>pagination uses cursors and returns a ready-to-use continuation;</li>
        <li>reads support conditional requests, so unchanged data need not be
        sent again;</li>
        <li>collections have a stable, documented order;</li>
        <li>errors are structured, carry stable codes, and say whether a retry
        is safe;</li>
        <li>state-changing operations support idempotency, with a documented
        window and scope;</li>
        <li>high-risk writes can be previewed, cancelled, or confirmed, and
        are marked as such;</li>
        <li>rate limits, retry delays, and polling advice are machine-
        readable;</li>
        <li>deprecation and replacement operations are machine-readable and
        shown in the description;</li>
        <li>a correlation identifier is accepted, passed along, and logged;</li>
        <li>untrusted returned content is kept apart from trusted control
        fields and marked as data.</li>
      </ul>
    </section>

    <!-- ============================================================ -->
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>

      <t>This document has no IANA actions.  It does not define any protocol
      element, header field, media type, or registry entry.  The field
      names used in the error examples in <xref target="make-errors-recoverable"/> are only examples.  If
      such Problem Details fields are ever standardized, registering them
      would be the job of that later specification.</t>
    </section>

  </middle>

  <back>

    <!-- ============================================================ -->
    <references>
      <name>References</name>

      <references>
        <name>Normative References</name>

        <reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
        </reference>

        <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
        </reference>

        <reference anchor="RFC9110" target="https://www.rfc-editor.org/info/rfc9110">
          <front>
            <title>HTTP Semantics</title>
            <author fullname="R. Fielding" initials="R." role="editor" surname="Fielding"/>
            <author fullname="M. Nottingham" initials="M." role="editor" surname="Nottingham"/>
            <author fullname="J. Reschke" initials="J." role="editor" surname="Reschke"/>
            <date month="June" year="2022"/>
          </front>
          <seriesInfo name="STD" value="97"/>
          <seriesInfo name="RFC" value="9110"/>
        </reference>

        <reference anchor="RFC9457" target="https://www.rfc-editor.org/info/rfc9457">
          <front>
            <title>Problem Details for HTTP APIs</title>
            <author fullname="M. Nottingham" initials="M." surname="Nottingham"/>
            <author fullname="E. Wilde" initials="E." surname="Wilde"/>
            <author fullname="S. Dalal" initials="S." surname="Dalal"/>
            <date month="July" year="2023"/>
          </front>
          <seriesInfo name="RFC" value="9457"/>
        </reference>
      </references>

      <references>
        <name>Informative References</name>

        <reference anchor="I-D.httpapi-idem" target="https://datatracker.ietf.org/doc/draft-ietf-httpapi-idempotency-key-header/">
          <front>
            <title>The Idempotency-Key HTTP Header Field</title>
            <author>
              <organization>IETF HTTP API Working Group</organization>
            </author>
            <date year="2025"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-httpapi-idempotency-key-header"/>
        </reference>

        <reference anchor="I-D.klrc-aiagent-auth" target="https://datatracker.ietf.org/doc/draft-klrc-aiagent-auth/">
          <front>
            <title>AI Agent Authentication and Authorization</title>
            <author fullname="P. Kasselman" initials="P." surname="Kasselman"/>
            <author fullname="J. Lombardo" initials="J." surname="Lombardo"/>
            <author fullname="Y. Rosomakho" initials="Y." surname="Rosomakho"/>
            <author fullname="B. Campbell" initials="B." surname="Campbell"/>
            <date year="2026"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-klrc-aiagent-auth"/>
        </reference>

        <reference anchor="I-D.oauth-ai-agents-obo" target="https://datatracker.ietf.org/doc/draft-oauth-ai-agents-on-behalf-of-user/">
          <front>
            <title>OAuth 2.0 Extension: On-Behalf-Of User Authorization for AI Agents</title>
            <author>
              <organization>IETF</organization>
            </author>
            <date year="2025"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-oauth-ai-agents-on-behalf-of-user"/>
        </reference>

        <reference anchor="LLMSTXT" target="https://llmstxt.org/">
          <front>
            <title>The /llms.txt file</title>
            <author fullname="J. Howard" initials="J." surname="Howard"/>
            <date year="2024"/>
          </front>
        </reference>

        <reference anchor="MCP" target="https://modelcontextprotocol.io/specification">
          <front>
            <title>Model Context Protocol Specification</title>
            <author>
              <organization>Model Context Protocol</organization>
            </author>
            <date year="2025"/>
          </front>
        </reference>

        <reference anchor="OPENAPI" target="https://spec.openapis.org/oas/latest.html">
          <front>
            <title>OpenAPI Specification</title>
            <author>
              <organization>OpenAPI Initiative</organization>
            </author>
            <date year="2024"/>
          </front>
        </reference>

        <reference anchor="RFC7591" target="https://www.rfc-editor.org/info/rfc7591">
          <front>
            <title>OAuth 2.0 Dynamic Client Registration Protocol</title>
            <author fullname="J. Richer" initials="J." role="editor" surname="Richer"/>
            <date month="July" year="2015"/>
          </front>
          <seriesInfo name="RFC" value="7591"/>
        </reference>

        <reference anchor="RFC8693" target="https://www.rfc-editor.org/info/rfc8693">
          <front>
            <title>OAuth 2.0 Token Exchange</title>
            <author fullname="M. Jones" initials="M." surname="Jones"/>
            <author fullname="A. Nadalin" initials="A." surname="Nadalin"/>
            <author fullname="B. Campbell" initials="B." role="editor" surname="Campbell"/>
            <author fullname="J. Bradley" initials="J." surname="Bradley"/>
            <author fullname="C. Mortimore" initials="C." surname="Mortimore"/>
            <date month="January" year="2020"/>
          </front>
          <seriesInfo name="RFC" value="8693"/>
        </reference>

        <reference anchor="RFC8707" target="https://www.rfc-editor.org/info/rfc8707">
          <front>
            <title>Resource Indicators for OAuth 2.0</title>
            <author fullname="B. Campbell" initials="B." surname="Campbell"/>
            <author fullname="J. Bradley" initials="J." surname="Bradley"/>
            <author fullname="H. Tschofenig" initials="H." surname="Tschofenig"/>
            <date month="February" year="2020"/>
          </front>
          <seriesInfo name="RFC" value="8707"/>
        </reference>

        <reference anchor="RFC9728" target="https://www.rfc-editor.org/info/rfc9728">
          <front>
            <title>OAuth 2.0 Protected Resource Metadata</title>
            <author fullname="M. Jones" initials="M." surname="Jones"/>
            <author fullname="P. Hunt" initials="P." surname="Hunt"/>
            <author fullname="A. Parecki" initials="A." surname="Parecki"/>
            <date month="April" year="2025"/>
          </front>
          <seriesInfo name="RFC" value="9728"/>
        </reference>

        <reference anchor="W3C-TRACE-CONTEXT" target="https://www.w3.org/TR/trace-context/">
          <front>
            <title>Trace Context</title>
            <author>
              <organization>W3C</organization>
            </author>
            <date year="2021"/>
          </front>
        </reference>
      </references>
    </references>

    <!-- ============================================================ -->
    <section anchor="appendix-mcp-tools">
      <name>Example: MCP Tools for a Project Management System</name>

      <t>This appendix applies the profile to a Model Context Protocol <xref target="MCP"/>
      server for a project management system.  The system has projects,
      tasks, and assignees.  Each tool uses a strict JSON Schema, so the
      model can find and call it without inventing parameters.  Every input
      schema sets additionalProperties to false, uses a fixed value set for
      closed choices, marks the required fields, and bounds the size of any
      collection.</t>

      <t>The examples below use verb-first names (find_projects, create_task)
      to match common convention.  An alternative is entity-first names
      (projects_find, task_create), which group related operations by
      resource and can reduce selection collisions when the tool surface
      is large.  The table at the end of this appendix shows both forms.</t>

      <t>An agent is often told a project by name, not by identifier.  A
      lookup tool turns the name into an identifier the other tools need.
      This follows the rule in <xref target="set-of-operations"/> not to demand an identifier the
      agent cannot get:</t>

      <artwork type="json"><![CDATA[
{
  "name": "find_projects",
  "description": "Find projects by name.",
  "inputSchema": {
    "type": "object",
    "additionalProperties": false,
    "required": ["name_contains"],
    "properties": {
      "name_contains": { "type": "string" },
      "limit": {
        "type": "integer",
        "minimum": 1, "maximum": 20, "default": 10
      }
    }
  }
}]]></artwork>

      <t>A creation tool keeps a strict input schema.  Its description, kept
      short in the example, should also say that the operation notifies the
      assignee, point the agent to find_projects when it has only a name,
      and explain that reusing the idempotency_key returns the original
      task instead of making a duplicate:</t>

      <artwork type="json"><![CDATA[
{
  "name": "create_task",
  "description": "Create a task in a project.",
  "inputSchema": {
    "type": "object",
    "additionalProperties": false,
    "required": ["project_id", "title"],
    "properties": {
      "project_id": { "type": "string" },
      "title": { "type": "string", "maxLength": 200 },
      "assignee_email": { "type": "string", "format": "email" },
      "priority": {
        "type": "string",
        "enum": ["low", "medium", "high"],
        "default": "medium"
      },
      "idempotency_key": { "type": "string" }
    }
  }
}]]></artwork>

      <t>A search tool bounds its result size and returns an opaque cursor, so
      the agent never computes an offset.  The status filter lets it narrow
      the results before it fetches them:</t>

      <artwork type="json"><![CDATA[
{
  "name": "find_tasks",
  "description": "Search tasks in a project (bounded page).",
  "inputSchema": {
    "type": "object",
    "additionalProperties": false,
    "required": ["project_id"],
    "properties": {
      "project_id": { "type": "string" },
      "status": {
        "type": "string",
        "enum": ["open", "in_progress", "done"]
      },
      "limit": {
        "type": "integer",
        "minimum": 1, "maximum": 50, "default": 20
      },
      "cursor": { "type": "string" }
    }
  }
}]]></artwork>

      <t>A result is bounded.  It carries human-readable labels and a next
      action, and it gives back a cursor for the following page:</t>

      <artwork type="json"><![CDATA[
{
  "tasks": [
    {
      "task_id": "t_8a1",
      "title": "Draft launch checklist",
      "status": "in_progress",
      "assignee": { "id": "u_42", "name": "Priya Rao" },
      "next_actions": { "complete": "update_task_status" }
    }
  ],
  "next_cursor": "eyJvIjoyMH0"
}]]></artwork>

      <t>To read the next page, the agent calls the same tool again and passes
      the cursor straight back.  It does no arithmetic:</t>

      <artwork type="json"><![CDATA[
{
  "name": "find_tasks",
  "arguments": {
    "project_id": "p1",
    "status": "open",
    "cursor": "eyJvIjoyMH0"
  }
}]]></artwork>

      <t>A batch tool creates several tasks in one call.  It bounds the array
      size, and its result reports one outcome per item, so the agent can
      see which tasks were created and which were rejected:</t>

      <artwork type="json"><![CDATA[
{
  "name": "create_tasks_batch",
  "description": "Create several tasks in one project.",
  "inputSchema": {
    "type": "object",
    "additionalProperties": false,
    "required": ["project_id", "tasks"],
    "properties": {
      "project_id": { "type": "string" },
      "idempotency_key": { "type": "string" },
      "tasks": {
        "type": "array",
        "maxItems": 50,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": ["title"],
          "properties": {
            "title": { "type": "string", "maxLength": 200 },
            "priority": {
              "type": "string",
              "enum": ["low", "medium", "high"]
            }
          }
        }
      }
    }
  }
}]]></artwork>

      <t>The batch result shows the per-item outcomes.  One task was created
      and one was rejected, and the agent can tell exactly which is which:</t>

      <artwork type="json"><![CDATA[
{
  "results": [
    { "index": 0, "status": "created", "task_id": "t_901" },
    { "index": 1, "status": "rejected", "code": "TITLE_TOO_LONG" }
  ],
  "created_count": 1,
  "rejected_count": 1
}]]></artwork>

      <t>A state-changing tool uses a fixed value set for the closed list of
      states and accepts an idempotency key.  Its description should note
      the side effect of notifying the assignee:</t>

      <artwork type="json"><![CDATA[
{
  "name": "update_task_status",
  "description": "Move a task to a new workflow state.",
  "inputSchema": {
    "type": "object",
    "additionalProperties": false,
    "required": ["task_id", "status"],
    "properties": {
      "task_id": { "type": "string" },
      "status": {
        "type": "string",
        "enum": ["open", "in_progress", "done", "cancelled"]
      },
      "idempotency_key": { "type": "string" }
    }
  }
}]]></artwork>

      <t>Each choice maps back to the profile.  The intent-revealing names and
      the use-when guidance reduce wrong-operation mistakes (<xref target="api-description-contract"/>).
      The fixed value sets and additionalProperties: false stop the agent
      from inventing values and parameters.  The bounded limit and the
      opaque cursor follow <xref target="keep-responses-small"/>.  The idempotency key and the stated
      side effects follow <xref target="make-writes-safe"/>.  The batch result follows the
      partial-failure rule in <xref target="set-of-operations"/>.</t>

      <t>The following table shows the verb-first and entity-first forms of
      each tool name used in this appendix.  Verb-first groups operations
      by action type.  Entity-first groups them by resource, which can
      reduce wrong-operation mistakes when the total number of tools is
      large.  Either form works.  Choose based on the size and shape of
      the tool surface and test with agent evaluation.</t>

      <table>
        <thead>
          <tr><th>Verb-first</th><th>Entity-first</th></tr>
        </thead>
        <tbody>
          <tr><td>find_projects</td><td>projects_find</td></tr>
          <tr><td>create_task</td><td>task_create</td></tr>
          <tr><td>find_tasks</td><td>tasks_find</td></tr>
          <tr><td>update_task_status</td><td>task_status_update</td></tr>
          <tr><td>create_tasks_batch</td><td>tasks_batch_create</td></tr>
        </tbody>
      </table>
    </section>

    <!-- ============================================================ -->
    <section anchor="appendix-weak-strong-description">
      <name>Example: A Weak and a Strong Operation Description</name>

      <t>An operation described only well enough for someone who already knows
      the system leaves the agent to guess its scope and its side effects:</t>

      <artwork><![CDATA[
# Too little for an agent
operationId: updateUser
summary: Updates a user]]></artwork>

      <t>The same operation, described for an agent, names its exact purpose,
      says when not to use it, and states the side effect:</t>

      <artwork><![CDATA[
# Enough for an agent
operationId: updateUserEmailAddress
summary: Change a user's email address
description: >
  Use this only to change an existing user's email address. Do not
  use it for other profile fields. Use updateUserProfile for those.
  Side effect: sends a verification email. The new address stays
  unverified until the user confirms it.]]></artwork>
    </section>

    <!-- ============================================================ -->
    <section anchor="appendix-field-selection">
      <name>Example: A Small Response with Field Selection</name>

      <t>The request selects three fields and a bounded page, so the response
      stays small.  The response gives back a ready-to-use link for the
      next page, so the agent does no offset arithmetic:</t>

      <artwork type="http-message"><![CDATA[
GET /projects/p1/tasks?status=open&fields=id,title,status&limit=20
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json

{
  "items": [
    {
      "id": "t_8a1",
      "title": "Draft launch checklist",
      "status": "open"
    }
  ],
  "next_page": "/projects/p1/tasks?status=open&cursor=eyJvIjoyMH0",
  "next_cursor": "eyJvIjoyMH0"
}]]></artwork>

      <t>As an alternative to per-field selection, a response_format parameter
      offers preset levels of detail.  This is simpler when the agent does
      not know which fields to ask for:</t>

      <artwork type="http-message"><![CDATA[
GET /tasks/42?response_format=concise
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json

{
  "task_id": "t_42",
  "title": "Draft launch checklist",
  "status": "in_progress",
  "assignee_name": "Priya Rao"
}]]></artwork>

      <artwork type="http-message"><![CDATA[
GET /tasks/42?response_format=detailed
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json

{
  "task_id": "t_42",
  "title": "Draft launch checklist",
  "status": "in_progress",
  "assignee": { "id": "u_42", "name": "Priya Rao",
                "email": "priya@example.com" },
  "project_id": "p1",
  "created_at": "2026-06-01T10:00:00Z",
  "updated_at": "2026-06-08T14:30:00Z",
  "priority": "high",
  "tags": ["launch", "checklist"]
}]]></artwork>

      <t>The concise form returns display-friendly fields.  The detailed form
      adds internal identifiers, timestamps, and linking fields needed for
      chaining into downstream operations.  Implementers <bcp14>MAY</bcp14> define
      additional levels beyond these two if the data warrants it.</t>
    </section>

    <!-- ============================================================ -->
    <section anchor="appendix-dry-run">
      <name>Example: Previewing a Destructive Write</name>

      <t>A dry-run request reports what an operation would do, without doing
      it.  The agent can check the predicted effects and decide whether to
      go ahead:</t>

      <artwork type="http-message"><![CDATA[
POST /projects/p1/archive
X-Dry-Run: true
Content-Type: application/json

{ "reason": "Project completed" }

HTTP/1.1 200 OK
Content-Type: application/json

{
  "dry_run": true,
  "would_change": {
    "project_status": { "from": "active", "to": "archived" },
    "tasks_closed": 14,
    "members_notified": 6
  },
  "reversible": true
}]]></artwork>

      <t>Sending the same request without the X-Dry-Run header performs the
      operation.  The predicted-effects shape is the same, so the agent can
      use it to decide whether to go ahead or to ask for confirmation
      first.</t>
    </section>

    <!-- ============================================================ -->
    <section anchor="appendix-anti-patterns">
      <name>Example: Common Description Anti-Patterns</name>

      <t>Studies of tool descriptions across MCP servers find that most have
      at least one description problem.  The following anti-patterns lead
      to wrong-operation and wrong-argument mistakes.  Each one is
      followed by the fix.</t>

      <dl>
        <dt>Restating the name without adding information.</dt>
        <dd>Bad: "Creates a task" for an operation named create_task.
        Fix: Say what kind of task, in which system, with what effect.
        "Create a task in the project tracker.  Notifies the assignee by
        email."</dd>

        <dt>Omitting side effects.</dt>
        <dd>Bad: a description of a delete operation that does not mention it
        also cancels pending notifications.
        Fix: State every side effect.  "Deletes the task and cancels any
        pending reminder notifications for it."</dd>

        <dt>Omitting "do not use this when" guidance.</dt>
        <dd>Bad: an updateUser operation that handles only email changes but
        does not say so.
        Fix: "Use this only to change the email address.  Do not use it
        for other profile fields.  Use updateUserProfile for those."</dd>

        <dt>Using jargon or internal names the agent has no context for.</dt>
        <dd>Bad: "Triggers a ZK reconciliation on the specified ledger
        partition."
        Fix: Use plain terms or define the jargon in the description.
        "Rebalances the account ledger for the given partition."</dd>

        <dt>Describing what the operation returns rather than when to use it.</dt>
        <dd>Bad: "Returns a list of task objects with id, title, and status."
        Fix: Lead with the purpose.  "Find tasks in a project, filtered
        by status.  Returns id, title, and status for each match."</dd>

        <dt>Failing to state the purpose of the operation.</dt>
        <dd>Bad: a tool with a name like proc_handler_v2 and a description
        that says "Handles processing."
        Fix: State what it does, for what entity, and why an agent would
        call it.</dd>
      </dl>
    </section>

    <!-- ============================================================ -->
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>

      <t>This document gathers considerations discussed across the API design
      and AI agent engineering communities.  The author thanks the authors
      of the referenced specifications and drafts, whose work covers the
      identity and authorization topics this document leaves to them, and
      the reviewers whose feedback shaped the profile structure, the worked
      examples, and the treatment of context exhaustion and observability.</t>
    </section>

  </back>
</rfc>
