It bridges the gap between raw API design and autonomous AI agency, providing a clear path for other developers to implement the same "Link-Schema Bridge" logic.
The HDTC Protocol is a standardized method for enabling AI agents to interact with RESTful APIs dynamically. Unlike traditional "static" tool calling, HDTC uses HATEOAS (Hypermedia as the Engine of Application State) to inform the agent which actions are available in the current resource state.
By combining HAL (Hypertext Application Language) and OpenAPI, HDTC constrains the agent to actions explicitly exposed by the server for the current resource state.
To maintain backward compatibility with legacy clients, agents must signal their capability to process namespaced transitions using the Prefer header.
- Header:
Prefer: namespaced-rels - Purpose: Toggles the API to return specific, namespaced link relations (e.g.,
order:payinstead ofpay).
The protocol uses an OpenAPI extension, x-hal-rel, which stores an array of valid relations. This acts as the glue between the JSON data and the functional schema.
# OpenAPI Snippet
paths:
/orders/{id}/cancel:
delete:
operationId: cancelOrder
x-hal-rel: ["order:cancel", "cancel"]To prevent "Cross-Resource Collisions" (e.g., calling cancel on an Order when the intent was a Subscription), the agent must perform Coordinate-Based Matching:
- Relation Match: The key in
_linksmust exist in thex-hal-relarray. - Path Template Match: The
hrefprovided in the link must structurally match the OpenAPI path template.
- Detect the
Prefer: namespaced-relsheader. - In the HAL response, return links with namespaces (e.g.,
namespace:action). - Decorate OpenAPI operations with the x-hal-rel array.
The agent follows this logic for every interaction:
- Extract: Normalize the href (strip domain/base-path).
- Verify: Check if the relation key is present in the x-hal-rel list of a tool.
- Validate: Ensure the normalized href matches the path pattern.
- Extract & Call: Pull path parameters from the URL and execute the tool.
- State Safety: The agent can only invoke actions explicitly exposed as links in the current resource state, preventing LLM-driven attempts to execute unavailable operations and reducing
400 Bad Requestand409 Conflicterrors. - Collision Proof: Identical actions (like
editorcancel) are namespaced by domain. - Standard Compliant: Follows RFC 7240 and RFC 8288.
- Developer Friendly: Uses existing OpenAPI and HAL formats with minimal custom extensions.
Context: User says "Pay for my order." The server returns the order:pay link.
Agent Internal Monologue:
- Handshake: Request sent with
Prefer: namespaced-rels. - Observation: Received HAL response for Order
ord_01KXRFSQEY5TKWEN0WN86XNXJZ. Found_links["order:pay"]. - Discovery: Searching tool manifest for
x-hal-relcontaining"order:pay". - Match Found: Tool
processOrderPaymentcontains"order:pay"in itsx-hal-relarray. - Validation: Normalizing href:
"/v1/orders/ord_01KXRFSQEY5TKWEN0WN86XNXJZ/payment". This matches OpenAPI path template/v1/orders/{orderId}/payment. - Action: Extraction successful (
orderId=ord_01KXRFSQEY5TKWEN0WN86XNXJZ). Executing tool.
Agent Output: "Certainly! I'm processing the payment for Order #ord_01KXRFSQEY5TKWEN0WN86XNXJZ now."
Context: User says "Cancel my order," but the order is already shipped. The order:cancel link is missing from the JSON.
Agent Internal Monologue:
- Observation: Received HAL response.
statusis"shipped". - Discovery: Scanned
_links. The keyorder:cancelis not present. - Protocol Check: HDTC Protocol rule #2: Actions are strictly governed by link presence.
- Constraint: Even though the
cancelOrdertool exists in my manifest, it is currently "Locked" by the server state.
Agent Output: "I cannot cancel Order #ord_01KXRFSQEY5TKWEN0WN86XNXJZ because it has already been shipped. According to the current order status, that option is no longer available."
Context: User says "Cancel it," while looking at a page that has both a Subscription and an Order.
Agent Internal Monologue:
- Ambiguity Found: User said "cancel," but I see
subscription:cancelandorder:cancel. - Context Resolution: The user's last query was about their subscription.
- Verification: Checked
_linksfor Subscription sub_01KXRG8E124VM51BAY38E1GYKE. Foundsubscription:cancel. - Protocol Match: Selected tool with
x-hal-rel: ["subscription:cancel"].
Agent Output: "I've initiated the cancellation for your subscription. Would you like me to do the same for your pending order?"