Skip to main content

V2 Runtime API

The V2 Runtime API provides governed agent orchestration — task lifecycle, model routing, artifact validation, lineage tracking, and human-in-the-loop gates. All V2 data lives in the hd_runtime PostgreSQL schema.

Feature Flag

V2 endpoints require HATIDATA_V2_RUNTIME_ENABLED=true. When disabled, all V2 endpoints return 404.


Base URL

https://api.hatidata.com/v2

All V2 endpoints are prefixed with /v2. Authentication is the same as V1 (JWT or API key).


Rate Limits

V2 endpoints share the same rate limits as V1:

ScopeDefaultEnv Var
Per organization600/minHATIDATA_RATE_LIMIT_ORG
Per API key200/minHATIDATA_RATE_LIMIT_KEY

Every response includes RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset headers.


Tasks

Tasks are the top-level unit of work. Each task has a lifecycle (pending → active → completed/failed/cancelled) and can have multiple attempts.

Create Task

POST /v2/runtime/tasks

{
"kind": "code_review",
"project_id": "proj-abc-123",
"work_item_key": "run-1:code_review:default:main",
"max_retries": 3,
"metadata": {
"phase": "build",
"agent_type": "code_reviewer"
}
}

Idempotent dispatch: If work_item_key is set, only one non-terminal task can exist per key per org. Creating a task with a key that already has a pending/active task returns the existing task instead of creating a duplicate. Enforced by a partial unique index in the database.

Response: 200 OK

{
"id": "70e8d8bb-b924-4be1-8015-cce149657d01",
"org_id": "604d4d37-025c-4426-83b7-454cf4d78dba",
"kind": "code_review",
"status": "pending",
"project_id": "proj-abc-123",
"work_item_key": "run-1:code_review:default:main",
"max_retries": 3,
"metadata": { "phase": "build", "agent_type": "code_reviewer" },
"latest_attempt": null,
"created_at": "2026-04-05T03:55:38.587119Z",
"updated_at": "2026-04-05T03:55:38.587119Z"
}

List Tasks

GET /v2/runtime/tasks

ParameterTypeDefaultDescription
statusstringFilter by status: pending, active, completed, failed, cancelled
project_idstringFilter by project ID (uses indexed column)
limitinteger50Max results (capped at 200)
offsetinteger0Pagination offset
curl "https://api.hatidata.com/v2/runtime/tasks?project_id=proj-abc&status=active&limit=20" \
-H "Authorization: ApiKey hd_live_..."
Performance

Always use project_id when polling for a specific project's tasks. Without it, the query scans all tasks for the org.

Get Task

GET /v2/runtime/tasks/:task_id

Returns the task with its latest attempt.

Get Task Detail (Aggregate)

GET /v2/runtime/tasks/:task_id/detail

Returns the full task with all attempts, decisions, invocations, artifacts, events, and reviews in a single response. Use this instead of making separate API calls per entity type.

{
"id": "70e8d8bb-...",
"kind": "code_review",
"status": "completed",
"attempts": [
{ "id": "...", "agent_id": "fleet-001", "status": "succeeded", ... }
],
"decisions": [
{ "id": "...", "model_id": "claude-sonnet-4-6", "confidence": 0.92, ... }
],
"invocations": [
{ "id": "...", "input_tokens": 2048, "output_tokens": 1024, "cost_usd": 0.012, "latency_ms": 450, ... }
],
"artifacts": [
{ "id": "...", "kind": "code", "confidence": 0.94, "validation_status": "pass", ... }
],
"events": [
{ "id": "...", "kind": "attempt_lifecycle", "sequence_num": 1, "payload": {"action": "started"}, ... }
],
"reviews": []
}

Cancel Task

POST /v2/runtime/tasks/:task_id/cancel

Cancels the task and all its active attempts. Used for L4 recovery escalation when retry budget is exhausted.

{
"reason": "Retry budget exhausted, no repair possible"
}

Returns 409 Conflict if the task is already terminal.


Attempts

Attempts represent individual execution runs of a task. Each attempt has a lease (heartbeat-based) and transitions through: pendingrunningsucceeded/failed/timed_out/cancelled.

Create Attempt

POST /v2/runtime/tasks/:task_id/attempts

{
"agent_id": "fleet-compliance-scanner-03"
}

A lease token is automatically issued. The agent_id triggers best-effort agent self-registration (trust_level: provisional).

Task status transition: When an attempt fails with retries remaining (retry_count < max_retries), the task transitions back to pending — making it available for the next agent to claim.

Claim Attempt

PUT /v2/runtime/attempts/:attempt_id/claim

{
"lease_token": "uuid-of-lease",
"agent_id": "fleet-compliance-scanner-03"
}

Heartbeat

PUT /v2/runtime/attempts/:attempt_id/heartbeat

Extends the lease. Call every 60–120 seconds to prevent lease expiry timeout.

{
"lease_token": "uuid-of-lease"
}

Complete Attempt

PUT /v2/runtime/attempts/:attempt_id/complete

{
"lease_token": "uuid-of-lease",
"outcome": "succeeded"
}

Or for failure:

{
"lease_token": "uuid-of-lease",
"outcome": "failed",
"failure_reason": "Budget exceeded: 16000 tokens > 8192 limit"
}

Decisions & Invocations

Record Decision

POST /v2/runtime/decisions

{
"attempt_id": "uuid",
"model_id": "claude-sonnet-4-6",
"routing_reason": "cost_optimized",
"confidence": 0.91,
"fallback_used": false,
"cost_estimate": 0.008
}

Record Invocation

POST /v2/runtime/invocations

{
"decision_id": "uuid",
"model_id": "claude-sonnet-4-6",
"input_tokens": 2048,
"output_tokens": 1024,
"cost_usd": 0.012,
"latency_ms": 450
}

Artifacts

Publish Artifact

POST /v2/runtime/artifacts

{
"attempt_id": "uuid",
"kind": "code",
"content_hash": "sha256:a8f2c901...",
"confidence": 0.94,
"artifact_key": "proj:abc:architecture"
}

List Artifacts

GET /v2/runtime/artifacts

ParameterTypeDescription
task_idUUIDFilter by task (across all attempts)
project_idstringFilter by project (across all tasks) — uses indexed column
kindstringFilter by artifact kind
limitintegerMax results (default 100, max 1000)

Either task_id or project_id is required.

Promote Artifact

POST /v2/runtime/artifacts/:artifact_id/promote

Promotes a branched artifact to mainline by setting branch_id = null. Used at phase boundaries to merge branched work so downstream phases can find artifacts without branch-awareness.

  • In-place update: artifact ID does not change (preserves lineage)
  • Idempotent: promoting an already-mainline artifact is a no-op
  • Preserves: validation_status, confidence, content_hash, artifact_key

Record Validation

POST /v2/runtime/artifacts/:artifact_id/validations


Events

Append-only workflow events. Sequence numbers are assigned atomically per attempt.

Ingest Event

POST /v2/runtime/events

{
"attempt_id": "uuid",
"kind": "attempt_lifecycle",
"payload": { "action": "started", "agent": "fleet-001" }
}

List Events

GET /v2/runtime/events

ParameterTypeDescription
task_idUUIDRequired. Filter by task (across all attempts)
kindstringFilter by event kind
limitintegerMax results (default 100, max 1000)

Reviews & Releases

Request Review

POST /v2/reviews

List Reviews

GET /v2/reviews

ParameterTypeDescription
task_idUUIDFilter reviews for a specific task's artifacts
statusstringFilter by status: pending, in_review, approved, rejected
limitintegerMax results (default 50, max 200)

Resolve Review

PUT /v2/reviews/:review_id/resolve

Record Release

POST /v2/releases

Record Recovery

POST /v2/recovery


Routing Signals

GET /v2/routing/signals

Returns per-model routing performance over a configurable time window. Use this to optimize model selection at dispatch time.

ParameterTypeDefaultDescription
window_daysinteger7Lookback window (1–90 days)
{
"window_days": 7,
"models": [
{
"model_id": "claude-sonnet-4-6",
"sample_size": 5231,
"success_rate": 0.94,
"avg_confidence": 0.91,
"avg_cost_usd": 0.008,
"avg_latency_ms": 340.0,
"total_cost_usd": 41.85,
"override_rate": 0.05,
"p50_latency_ms": 310.0,
"p99_latency_ms": 0.0
}
],
"freshness": {
"computed_at": "2026-04-05T04:50:56Z",
"staleness_ms": 15,
"within_slo": true
}
}

Operator Views

Real-time metrics from SQL-queryable hd_runtime views. Each response includes a freshness object indicating data age and SLO compliance.

Active Attempts

GET /v2/runtime/views/active-attempts

Returns running/pending/blocked attempt counts, oldest attempt age, and lease expiry warnings.

Invocation Costs

GET /v2/runtime/views/invocation-costs

Returns total cost, invocation count, token count, broken down by model.

Confidence Distribution

GET /v2/runtime/views/confidence-distribution

Returns artifact confidence buckets (low/medium/high) and percentiles (P50/P90/P99).

Recovery Actions

GET /v2/runtime/views/recovery-actions

Returns total recovery actions, broken down by kind, with recent action details.


Agent Self-Registration

When POST /v2/runtime/tasks/:task_id/attempts is called with an agent_id, the agent is automatically registered in the agent fleet with:

  • trust_level: provisional (never auto-upgraded from this path)
  • registration_source: v2_create_attempt
  • status: active

This makes V2-only agents visible in the Agent Fleet dashboard without requiring a wire protocol connection. The registration is best-effort — if it fails, the attempt still succeeds.


Database Configuration

The control plane's PostgreSQL connection pool is configurable to prevent resource exhaustion under burst load:

Env VarDefaultDescription
DATABASE_MAX_CONNECTIONS20Maximum pool connections
DATABASE_MIN_CONNECTIONS2Minimum idle connections
DATABASE_ACQUIRE_TIMEOUT_SECS5Max wait for a connection (returns 503 if exceeded)
DATABASE_IDLE_TIMEOUT_SECS300Close idle connections after this duration
Burst Load Protection

The DATABASE_ACQUIRE_TIMEOUT_SECS setting is critical for preventing OOM under burst load. Without it, requests queue indefinitely in memory when all connections are busy. The default 5-second timeout returns 503 Service Unavailable instead, bounding memory growth.

Stay in the loop

Product updates, engineering deep-dives, and agent-native insights. No spam.