Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/joseluis-dev/harness-ai/llms.txt

Use this file to discover all available pages before exploring further.

harness-core is the only public-facing service; all endpoints listed here are accessible on port 4321. It acts as a BFF (Backend for Frontend) — validating inputs with Zod, resolving actor identity from bearer tokens, enforcing fail-closed identity gates, and forwarding validated requests to runtime-python over the private Docker network. The BFF never writes to Postgres directly and never imports the rq Python library or speaks the Redis wire protocol.

Zod Schema: ExecutionCreateBodySchema

The POST create body is validated against this Zod schema before any call to the runtime. A Zod failure short-circuits immediately and returns 400 invalid_payload without creating a Postgres row.
const RiskLevel = z.enum(["low", "medium", "high", "critical"]);

const ConstraintsSchema = z
  .object({
    allow_cloud: z.boolean().optional(),
    require_audit: z.boolean().optional(),
    risk_level: RiskLevel.optional(),
  })
  .strict();

const ExecutionCreateBodySchema = z
  .object({
    source_type: z.string().min(1).max(128),
    intent: z.string().min(1).max(128),
    payload: z.record(z.string(), z.unknown()).default({}),
    constraints: ConstraintsSchema.optional(),
  })
  .strict();

Identity Forwarding

When a valid bearer token is present, the middleware resolves the actor via mcp-identity-connector and stores it in Astro.locals.actor. The BFF then builds two forwarding headers for the runtime:
HeaderValueWhen included
X-Harness-Actor-IdResolved user_id, trimmed, ≤128 charsOnly when actor_type is user
X-Harness-Actor-DepartmentResolved department, trimmed, ≤128 charsOnly when actor_type is user
Both headers are omitted when actor_type is "system" or "service" — only resolved user identities produce forwarded headers. The runtime accepts requests without these headers for non-sensitive reads.

GET /api/healthz

Aggregate health check. Probes the runtime’s /healthz and returns a combined status. No authentication required.

Response — 200 OK

{
  "status": "ok",
  "runtime": "ok",
  "service": "harness-core",
  "version": "0.1.0"
}

Response — 503 Service Unavailable

Returned when the runtime’s /healthz does not respond with 200 within 3 seconds.
{
  "status": "degraded",
  "runtime": "error",
  "service": "harness-core",
  "version": "0.1.0",
  "error": "runtime unreachable (AbortError: The operation was aborted)"
}
status
string
"ok" when runtime is reachable; "degraded" otherwise.
runtime
string
"ok" when runtime returned HTTP 200; "error" otherwise.
service
string
Always "harness-core".
version
string
BFF version string.
error
string
Present only on 503. Describes the probe failure (e.g. timeout, connection refused).
The BFF does not perform a Postgres ping. Container-level health for Postgres and Redis is observed via docker compose ps. A BFF-side Postgres connection is forbidden by the architecture (design AD-3) and would silently drift from the connection string the runtime actually uses.

POST /api/executions

Creates a new execution. Validates the body with Zod, resolves actor identity, enforces the fail-closed identity gate for sensitive writes, and forwards the validated payload to POST /internal/executions on the runtime.

Auth

Bearer token is optional for low-risk requests. It is required for any request where constraints.risk_level is high or critical — degraded identity (actor_type=system) is blocked for those levels.

Request Body

source_type
string
required
Origin of the execution request. 1–128 characters. Maps to the source.type field of the execution event.
intent
string
required
Semantic intent of the execution. 1–128 characters.
payload
object
default:"{}"
Intent-specific data. Free-form key-value object. Defaults to an empty object when omitted.
constraints
object
Execution constraint envelope.

Example Request

POST /api/executions HTTP/1.1
Host: harness-core:4321
Content-Type: application/json
Authorization: Bearer <access_token>

{
  "source_type": "astro",
  "intent": "query_sql_view",
  "payload": { "view": "v_traffic_monthly", "month": "2024-01" },
  "constraints": {
    "allow_cloud": false,
    "require_audit": true,
    "risk_level": "low"
  }
}

Response — 201 Created

Proxied verbatim from the runtime.
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "queued"
}

Error Responses

// 400 — malformed JSON body
{
  "error": "invalid_json",
  "message": "Request body must be valid JSON."
}

// 400 — Zod schema validation failure
{
  "error": "invalid_payload",
  "message": "Request body failed schema validation.",
  "issues": [
    {
      "path": "source_type",
      "message": "String must contain at least 1 character(s)",
      "code": "too_small"
    }
  ]
}

// 400 — actor user_id or department exceeds 128 chars
{
  "error": "actor_id_too_long",
  "message": "Actor field user_id exceeds the 128-char limit.",
  "field": "user_id"
}

// 401 — sensitive write with degraded identity
{
  "error": "identity_unavailable",
  "message": "Sensitive execution requests require a resolved identity. Provide a valid bearer token so the BFF can verify the principal against mcp-identity-connector before forwarding."
}

// 502 — runtime container unreachable
{
  "error": "runtime_unreachable",
  "message": "Failed to reach runtime at http://runtime-python:8000/internal/executions: AbortError: The operation was aborted"
}

Fail-Closed Identity Gate

If the request’s constraints.risk_level is "high" or "critical" and the resolved actor type is "system" (degraded identity — no valid bearer token), the BFF returns 401 identity_unavailable without calling the runtime. This is the Phase 1 fail-closed contract: sensitive actions are blocked if the external identity service is unavailable or no token was provided.
The upstream fetch to the runtime has a 5-second timeout. If the runtime does not respond within that window, the request is aborted and the BFF returns 502 runtime_unreachable. The execution row may or may not have been committed by the runtime at that point — callers should treat 502 as an indeterminate state and check GET /api/executions to confirm.

GET /api/executions

Lists recent executions. Proxies GET /internal/executions on the runtime. Read operations are non-sensitive; actor headers are not forwarded on this path.

Query Parameters

limit
integer
default:"50"
Number of results to return. Minimum 1, maximum 200.
offset
integer
default:"0"
Number of results to skip for pagination. Minimum 0.

Response — 200 OK

Array of execution objects proxied from the runtime. See Runtime API — GET /internal/executions for the full field descriptions.
[
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "completed",
    "source_type": "astro",
    "intent": "query_sql_view",
    "payload": {},
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:05Z",
    "completed_at": "2024-01-15T10:30:05Z"
  }
]

GET /api/executions/{id}

Fetches a single execution by UUID. Proxies GET /internal/executions/{id} on the runtime and passes through the runtime’s 404 verbatim when the execution does not exist.

Path Parameters

id
UUID
required
The execution UUID. Must be a valid UUID string — a non-UUID value returns 400 invalid_id without calling the runtime.

Response — 200 OK

Full ExecutionResponse object proxied from the runtime. See Runtime API — GET /internal/executions/{execution_id} for field descriptions.

Error Responses

// 400 — id is not a valid UUID
{
  "error": "invalid_id",
  "message": "Execution id must be a UUID."
}

// 404 — execution not found (proxied from runtime)
{
  "detail": "Execution not found."
}

// 502 — runtime unreachable
{
  "error": "runtime_unreachable",
  "message": "..."
}

GET /api/executions/{id}/events

Fetches the audit event trail for an execution. Proxies GET /internal/executions/{id}/events on the runtime.

Path Parameters

id
UUID
required
The execution UUID.

Response — 200 OK

Array of AuditEventItem objects proxied from the runtime.
[
  {
    "id": "f1e2d3c4-b5a6-7890-fedc-ba9876543210",
    "execution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "event_type": "execution.queued",
    "from_status": null,
    "to_status": "queued",
    "actor_type": "system",
    "actor_id": null,
    "payload": null,
    "created_at": "2024-01-15T10:30:00Z"
  }
]
The runtime returns 200 [] for unknown execution IDs (not 404), and the BFF passes this through unchanged — the UI can render “no events yet” without branching. See Runtime API — GET /internal/executions/{execution_id}/events for full field descriptions.
The BFF never writes to Postgres directly. All writes — execution rows, audit events, status transitions — flow through the runtime’s internal API. This constraint is validated on every PR gate and is enforced by the fact that apps/harness-core does not have a Postgres client dependency.

Build docs developers (and LLMs) love