Skip to content

Instantly share code, notes, and snippets.

@bymyslf
Created August 19, 2026 08:24
Show Gist options
  • Select an option

  • Save bymyslf/44fabf490a3c218da1702a747df21e27 to your computer and use it in GitHub Desktop.

Select an option

Save bymyslf/44fabf490a3c218da1702a747df21e27 to your computer and use it in GitHub Desktop.
The Hypermedia-Driven Tool Calling (HDTC) Protocol

The Hypermedia-Driven Tool Calling (HDTC) Protocol

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.

1. Introduction

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.

2. Key Concepts

A. Capability Negotiation

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:pay instead of pay).

B. The Link-Schema Bridge (x-hal-rel)

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

C. Contextual Validation

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:

  1. Relation Match: The key in _links must exist in the x-hal-rel array.
  2. Path Template Match: The href provided in the link must structurally match the OpenAPI path template.

3. Implementation Guide

Server-Side

  1. Detect the Prefer: namespaced-rels header.
  2. In the HAL response, return links with namespaces (e.g., namespace:action).
  3. Decorate OpenAPI operations with the x-hal-rel array.

Client (Agent) Side

The agent follows this logic for every interaction:

  1. Extract: Normalize the href (strip domain/base-path).
  2. Verify: Check if the relation key is present in the x-hal-rel list of a tool.
  3. Validate: Ensure the normalized href matches the path pattern.
  4. Extract & Call: Pull path parameters from the URL and execute the tool.

4. Advantages

  • 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 Request and 409 Conflict errors.
  • Collision Proof: Identical actions (like edit or cancel) are namespaced by domain.
  • Standard Compliant: Follows RFC 7240 and RFC 8288.
  • Developer Friendly: Uses existing OpenAPI and HAL formats with minimal custom extensions.

5. Agent Reasoning Logs (Success & Failure)

Scenario A: Successful Execution (The Protocol Works)

Context: User says "Pay for my order." The server returns the order:pay link.

Agent Internal Monologue:

  1. Handshake: Request sent with Prefer: namespaced-rels.
  2. Observation: Received HAL response for Order ord_01KXRFSQEY5TKWEN0WN86XNXJZ. Found _links["order:pay"].
  3. Discovery: Searching tool manifest for x-hal-rel containing "order:pay".
  4. Match Found: Tool processOrderPayment contains "order:pay" in its x-hal-rel array.
  5. Validation: Normalizing href: "/v1/orders/ord_01KXRFSQEY5TKWEN0WN86XNXJZ/payment". This matches OpenAPI path template /v1/orders/{orderId}/payment.
  6. Action: Extraction successful (orderId=ord_01KXRFSQEY5TKWEN0WN86XNXJZ). Executing tool.

Agent Output: "Certainly! I'm processing the payment for Order #ord_01KXRFSQEY5TKWEN0WN86XNXJZ now."

Scenario B: Forbidden Action (State Safety)

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. status is "shipped".
  • Discovery: Scanned _links. The key order:cancel is not present.
  • Protocol Check: HDTC Protocol rule #2: Actions are strictly governed by link presence.
  • Constraint: Even though the cancelOrder tool 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."

Scenario C: Collision Prevention (Namespace Safety)

Context: User says "Cancel it," while looking at a page that has both a Subscription and an Order.

Agent Internal Monologue:

  1. Ambiguity Found: User said "cancel," but I see subscription:cancel and order:cancel.
  2. Context Resolution: The user's last query was about their subscription.
  3. Verification: Checked _links for Subscription sub_01KXRG8E124VM51BAY38E1GYKE. Found subscription:cancel.
  4. 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?"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment