<!--
title: Enforce API Contracts
domain: ai-agents
topic: API
language: TSX
source: nousresearch/hermes-agent
updated: 2026-07-19
url: https://awesomereviewers.com/reviewers/hermes-agent-enforce-api-contracts/
-->

Client and UI code must explicitly follow the real API/component contract—both for *what state transitions are allowed* and *which side effects/transport paths are actually executed*.

Apply this by:
- **Model allowed transitions from the backend**: only present or enable UI actions (e.g., drag/drop targets) that the backend will accept, or introduce an explicit “transition contract” endpoint/schema used by the client.
- **Force the intended integration path**: when a feature requires a specific transport (e.g., gateway API vs local filesystem/IPC), ensure the client has an explicit forced path and tests cover edge cases.
- **Don’t rely on “notification” callbacks for cancellation**: if you need to prevent a side effect/state change, intercept it *before* the underlying system commits state (use controlled state / pre-commit logic), rather than assuming an `onXChange`/callback can suppress the underlying action.

Example pattern for transition gating:
```ts
// pseudo: fetch/derive allowed destinations for the client
const allowed = await api.getAllowedKanbanTransitions(taskId)

function onDrop(toStatus: KanbanStatus) {
  if (!allowed.includes(toStatus)) return // backend will reject; avoid optimistic move

  // then call backend and update UI
  await api.updateKanbanTask(taskId, { status: toStatus })
  await refreshBoard()
}
```

Outcome: fewer “optimistic” failures, fewer integration drift bugs (wrong transport), and predictable behavior when APIs/components have non-cancelable lifecycle hooks.
