05 — Interface Contracts

Four contracts hold the system together. They are frozen: anything behind them can be rewritten without cross-team coordination, and any change to them is a versioned, announced event. This is what lets one stream own a plane end to end.


Contract 1 — Inference API (OpenAI-compatible)

Owner: hunter-gateway · Consumers: terminal, agent, CLI, SDK, external agents.

We deliberately implement an existing standard rather than invent one: every OpenAI SDK works by changing base_url, which removes all client-library work and makes migration to Hunter a one-line change for customers.

POST /v1/chat/completions   # streaming and non-streaming
POST /v1/embeddings
GET  /v1/models             # + credits_per_1k_tokens, min_tier, available

Auth: Authorization: Bearer hk_live_… or an x402 X-PAYMENT header.

Hunter-specific extensions (additive, never breaking): - /v1/models entries carry credits_per_1k_tokens, min_tier, available. - X-PAYMENT-RESPONSE response header on settled x402 calls. - 402 bodies carry {x402Version, error, accepts[]}.

Stability rules: public model ids (hunter-small, …) are permanent aliases — the upstream model behind an id may change, the id may not. Upstream ids are never exposed.


Contract 2 — Platform API

Owner: hunter-platform · Consumers: gateway, terminal, workers, public.

GET  /entitlements/{wallet}                 → {tier, source, expires_at}   [PLANNED]
POST /api/v1/signals                        (service token)
POST /api/v1/signals/{external_id}/outcome  (service token)
GET  /api/v1/scoreboard                     PUBLIC
GET  /api/v1/signals                        PUBLIC

/entitlements/{wallet} is the single point where "what may this wallet do" is answered off-chain. Its shape is fixed because the gateway's resolver depends on it; the derivation (which contracts, what thresholds) may change freely behind it.

The public endpoints are public on purpose — an accuracy record only has value if anyone can audit it without asking us.


Contract 3 — MCP tool plane

Owner: hunter-mcps · Consumers: agent, workers, [PLANNED] premium tier customers.

Every capability is an MCP server: one domain per server, streamable-HTTP or stdio transport, declared in MCP_CONFIG:

{ "mcpServers": { "twitter": { "url": "http://mcp-twitter:8000/mcp" } } }

hunter-agent translates this into langchain-mcp-adapters connections at startup and exposes every discovered tool to the graph. Adding a tool requires no agent code change — that is the whole point of the boundary.

Normalised tweet shape (stable regardless of provider):

{id, text, author, author_name, created_at,
 likes, retweets, replies, quotes, views, url, is_reply, lang}

Because consumers code against this shape and not against twitterapi.io's, the provider swap in ADR-003 touched one file.


Contract 4 — On-chain events and ABIs

Owner: hunter-contracts · Consumers: indexer, dashboards, supply server, explorers, anyone.

// Access
event Locked(address indexed user, uint256 amount, uint64 start, uint64 end);
event Unlocked(address indexed user, uint256 amount);
event EarlyExit(address indexed user, uint256 returned, uint256 penalty);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event Subscribed(address indexed user, uint256 indexed planId,
                 address payToken, uint256 paid, uint64 paidUntil);

// Value accrual
event Distributed(address indexed token, uint256 buybackAmount,
                  uint256 stakingAmount, uint256 treasuryAmount);
event BuybackExecuted(address indexed tokenIn, uint256 amountIn, uint256 burned);
event RewardPaid(address indexed user, uint256 reward);

Read functions consumed off-chain: tierOf(address), totalLocked(), balanceOf(0x…dEaD), totalSupply(), isActive(address), earned(address).

Contracts are not upgradeable (ADR-006), so these signatures are immutable for the life of a deployment. A change means a new deployment and a migration — which is the correct amount of friction for money.


Contract change policy

Change Allowed? Process
Add an optional response field Yes Ship it
Add an endpoint / tool / event Yes Ship it, document it
Add a required request field No New version
Change a field's type or meaning No New version
Remove anything No Deprecate ≥1 release, then new version
Rename a public model id Never Ids are permanent aliases

Versioning: gateway paths are /v1/…; the platform API is /api/v1/…. A breaking change means /v2 served alongside /v1 until consumers migrate.

HUNTER · $DRPXBT · drpxbt.xyz edit this page