Skip to main content

Router Contracts

Hokusai exposes several related data shapes. They are not interchangeable.

ContractWho constructs itNamingPurpose
@hokusai/router input and resultTypeScript applicationcamelCaseSimple public SDK façade
Model 30 REST request and responseDirect API callersnake_caseLanguage-neutral HTTP API
Task descriptorSDK and router internalssnake_caseNormalized comparison features
harness_outcome_row/v1SDK or advanced harnesssnake_caseOptional contribution record

1. TypeScript SDK contract​

The public SDK accepts a task, categorical context, and routing constraints:

const decision = await route({
task: 'Refactor billing webhook retry handling.',
context: {
language: 'typescript',
task_type: 'refactor',
},
availableModels: ['claude-sonnet-4-6', 'gpt-5'],
objective: 'reliability',
maxCostUsd: 1,
maxLatencySeconds: 60,
});

The result contains:

type RouteResult = {
model: string;
reasoning?: string;
confidence?: number;
alternatives: Array<{
model: string;
reason?: string;
confidence?: number;
}>;
routeId: string;
correlationId: string;
};

context accepts categorical string values. Candidate models, cost limits, latency limits, and the routing objective belong at the top level, not inside context.

2. Direct Model 30 REST contract​

Direct callers send the nested public Model 30 payload:

{
"inputs": {
"task": {
"description": "Refactor billing webhook retry handling",
"task_type": "refactor",
"language": "typescript",
"repo_type": "monorepo"
},
"routing": {
"available_models": ["claude-sonnet-4-6", "gpt-5"],
"max_cost_usd": 1,
"objective": "highest_reliability"
}
}
}

Send it to:

POST https://api.hokus.ai/api/v1/models/30/predict

The response exposes the model strategy under predictions.recommended_strategy and returns inference_log_id for attribution. The TypeScript façade converts the relevant recommendation into decision.model and exposes the same persisted route identifier as decision.routeId.

3. Internal task descriptor​

The SDK and router derive a normalized descriptor so outcomes can be compared across integrations. Public SDK users normally do not construct this object themselves.

{
"task_type": "refactor",
"language": "typescript",
"domain": "backend",
"complexity": 6,
"repo_size_bucket": "medium",
"files_touched_bucket": "2_5",
"description_length_bucket": "medium",
"is_greenfield": false,
"is_migration": false,
"requires_tests": true,
"cross_service": false,
"ui_heavy": false,
"risk_level": "medium"
}

See Task Packets for the conceptual role of normalization.

4. Contribution row​

Advanced harnesses may construct the canonical optional contribution row directly:

{
"schema_version": "harness_outcome_row/v1",
"task_descriptor": {
"task_type": "refactor",
"language": "typescript",
"complexity": 6,
"repo_size_bucket": "medium"
},
"allowed_models": ["claude-sonnet-4-6", "gpt-5"],
"selected_models": {
"coder": "claude-sonnet-4-6",
"reviewer": "claude-sonnet-4-6"
},
"completion_result": "success",
"budget_usd": 1,
"actual_cost_usd": 0.42,
"wall_clock_seconds": 31,
"inference_log_id": "<route inference_log_id>"
}

task_descriptor, allowed_models, selected_models, and completion_result are required by the row schema. The server decides whether an accepted row is training_eligible or partial based on its contents and attribution.

Identifier mapping​

SurfaceIdentifierMeaning
TypeScript SDK resultrouteIdPersisted router decision; maps to inference_log_id
TypeScript SDK resultcorrelationIdClient-side correlation and outcome guard
Direct REST responseinference_log_idPersisted router decision used for contribution attribution
Contribution rowinference_log_idMust be threaded back unchanged from the route

Sources of truth​