Adapter Protocol Reference
This page documents the complete FORG adapter signal contract — the wire format adapters use to POST structured behavioral signals to the FORG Rule Engine. All first-party adapters (Claude Code, Cursor, VS Code, Windsurf, JetBrains, OpenCode, Neovim) implement this protocol. Community adapters must pass the conformance suite before receiving the Verified badge.
Transport
All signals are delivered as HTTP POST requests to the FORG engine endpoint. The engine is never reached directly by internal sub-domain — all public-facing traffic routes through forg.pro/engine/v1/*.
- Method:
POST - Endpoint:
https://forg.pro/engine/v1/signals - Content-Type:
application/json - Protocol version header:
X-Forg-Adapter-Protocol: v1 - Signature header:
X-Forg-Signature: sha256=<hex-digest> - Timeout: Adapters must set a request timeout of ≤ 3 000 ms and fail open — FORG unavailability must never block the user's AI tool.
Example request
POST https://forg.pro/engine/v1/signals
Content-Type: application/json
Authorization: Bearer <token-from-forg-activate>
X-Forg-Adapter-Protocol: v1
X-Forg-Signature: sha256=<hmac-sha256-hex-digest>
{
"type": "session-start",
"ts": "2025-05-29T10:00:00.000Z",
"session_id": "sess_4f9a2e1b8c3d",
"adapter_id": "claude-code-forg",
"goal_declared": "Refactor authentication module to use PKCE"
}Signal types
Every signal payload must include a type field (one of the 10 values below) and a ts field (ISO 8601 UTC timestamp). Additional fields depend on the signal type.
session-start
Emitted when a new AI coding session begins.
session-end
Emitted when the session terminates cleanly.
session-pause
Emitted when a session is interrupted but not ended.
goal-drift
Emitted when the engine detects the session trajectory diverging from the declared goal.
context-switch
Emitted when the user's active context moves from one tool category to another.
tool-switch
Emitted when the user switches between specific AI tools within the same session.
token-milestone
Emitted when cumulative token usage crosses a configured threshold.
refocus-ack
Emitted when the user acknowledges a FORG refocus intervention.
completion-verified
Emitted when the adapter or user confirms a goal has been achieved.
adapter-heartbeat
Periodic liveness signal. Adapters should emit this every 30 s while a session is active.
Engine response shape
The engine returns a JSON object on every 200 OK. Non-200 responses indicate a transport or authentication error — adapters should log and fail open.
Fields
Noop response (normal)
HTTP/1.1 200 OK
Content-Type: application/json
{
"action": "noop",
"session_id": "sess_4f9a2e1b8c3d",
"logged": true
}Intervention response
{
"action": "intervention",
"session_id": "sess_4f9a2e1b8c3d",
"intervention_id": "int_7b3c1a9f",
"message": "Token budget 80% consumed — consider wrapping up this session.",
"severity": "warning",
"logged": true
}Authentication
Adapters authenticate using a bearer token issued during forg activate. The token is stored in the OS-native keychain (macOS Security.framework, Linux libsecret, Windows DPAPI) and never written to disk in plain text. Retrieve it at runtime with:
forg token --printEvery request must carry two authentication artifacts:
- Bearer token in the
Authorizationheader:Authorization: Bearer <token> - HMAC-SHA256 signature in the
X-Forg-Signatureheader. The signature is computed over the raw request body using the first 32 bytes of the bearer token as the HMAC key.
import crypto from "crypto";
// The bearer token from `forg activate` (stored in OS keychain).
// Retrieve with: forg token --print
const BEARER_TOKEN = process.env.FORG_TOKEN!;
// HMAC key = first 32 bytes of the bearer token, UTF-8 encoded
const HMAC_KEY = Buffer.from(BEARER_TOKEN.slice(0, 32), "utf8");
function signPayload(body: string): string {
return crypto.createHmac("sha256", HMAC_KEY).update(body, "utf8").digest("hex");
}
const body = JSON.stringify({ type: "adapter-heartbeat", adapter_id: "my-tool", latency_ms: 4 });
const response = await fetch("https://forg.pro/engine/v1/signals", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${BEARER_TOKEN}`,
"X-Forg-Adapter-Protocol": "v1",
"X-Forg-Signature": `sha256=${signPayload(body)}`,
},
body,
});Requests that fail signature verification receive a 401 Unauthorized response. The engine logs the attempt for anomaly detection.
Versioning
The protocol version is declared in the X-Forg-Adapter-Protocol header. The current stable version is v1.
X-Forg-Adapter-Protocol: v1Breaking changes (new required fields, removed signal types, changed response shape) will increment the version to v2. Minor, additive changes (new optional fields, new signal types) are made within the current version. Adapters that omit the header are assumed to be v1 during the current cycle; future versions may require the header.
- The engine will accept
v1signals for a minimum of 12 months after anyv2announcement. - Version deprecation notices are posted to the FORG changelog and emailed to registered adapter authors.
Conformance test suite
The conformance suite verifies that an adapter correctly implements the v1 protocol: signal shape validation, HMAC signing, fail-open behavior, and session lifecycle ordering. Community adapters must pass all conformance checks to receive the Verified badge in the FORG adapter registry.
# Install the conformance runner
npm install -g @forg-pro/adapter-conformance
# Run against your adapter's emit endpoint
forg-conformance --adapter-id my-tool-forg --endpoint http://localhost:6247Full test suite source: github.com/forgpro/adapter-protocol/conformance