Node
Build and run the shared v2 HTTP server as a self-contained Node artifact.
The Node target is the simplest production artifact. It packages finite jobs, persistent agents,
roles, skills, configuration, and the same HTTP server used by fh dev.
Build
fh build --target nodeOutput:
.fabricharness/build/node/
.fabricharness/
jobs/*.mjs
agents/*.mjs
roles/
skills/
dist/
jobs/*.mjs
agents/*.mjs
server.mjs
manifest.json
package.jsonDefinitions are bundled into .mjs modules so the runtime can discover them dynamically without
depending on the source workspace.
Run
PORT=8080 OPENAI_API_KEY="$OPENAI_API_KEY" \
node .fabricharness/build/node/dist/server.mjsThe server binds 0.0.0.0:3000 by default for container compatibility.
Invoke a finite job
curl http://localhost:8080/jobs/ask \
-H 'content-type: application/json' \
-d '{"question":"What is durable execution?"}'The response includes { result, runId, agentPath }.
Invoke a persistent agent
curl -i http://localhost:8080/agents/support/customer-42 \
-H 'content-type: application/json' \
-d '{"message":"Help me understand my bill."}'The default response is 202 { submissionId, streamUrl, offset }. Add ?wait=true only when a
synchronous bridge is required. Prefer @fabric-harness/client for waiting and offset streaming.
Core routes
| Method | Route | Purpose |
|---|---|---|
GET | /health | Liveness probe. |
GET | /ready | Readiness and workspace root. |
GET | /admin/agents | List finite jobs and persistent agents with kind. |
POST | /jobs/:name | Invoke a finite job. |
POST | /agents/:name/:id | Admit persistent input; 202 by default. |
POST | /agents/:name/:id/dispatch | Enqueue asynchronous persistent input. |
GET | /agents/:name/:id/conversation | Read conversation batches by offset. |
GET | /agents/:name/:id/stream?offset=... | Catch up and tail with SSE. |
GET | /agents/:name/:id/submissions/:submissionId | Read settlement status. |
POST | /agents/:name/:id/abort | Request durable abort. |
GET | /sessions | List persisted sessions. |
GET | /builds/:target/manifest | Read a build manifest under the workspace build directory. |
Environment
| Variable | Purpose |
|---|---|
PORT | Listen port; default 3000. |
DATABRICKS_APP_PORT | Takes precedence over PORT in a generated App artifact. |
FABRIC_HARNESS_HOST | Listen address; default 0.0.0.0. |
FABRIC_HARNESS_API_TOKEN | Bearer token for HTTP and WebSocket access; required for protected routes in production unless a custom authorizer is installed. |
FABRIC_HARNESS_MAX_BODY_BYTES | JSON/body limit; default 1 MiB. |
FABRIC_HARNESS_RATE_LIMIT_MAX | Per-process request limit; 0 disables it. |
FABRIC_HARNESS_RATE_LIMIT_WINDOW_MS | Rate-limit window; default 60 seconds. |
FABRIC_HARNESS_TENANT_REQUIRED=1 | Require X-Fabric-Tenant. |
Production exposure
When NODE_ENV=production or FABRIC_ENV=production, public job and agent routes require
triggers.webhook: true. Authentication and triggers serve different purposes: the bearer token
identifies an allowed caller, while the trigger opts a definition into public HTTP exposure.
NODE_ENV=production \
FABRIC_HARNESS_API_TOKEN="$API_TOKEN" \
node dist/server.mjsContainer wrapper
Copy the complete build directory, not only dist/; the embedded workspace contains discoverable
definitions, roles, skills, and runtime configuration.
FROM node:22-slim
WORKDIR /app
COPY . .
ENV NODE_ENV=production PORT=8080
EXPOSE 8080
CMD ["node", "dist/server.mjs"]For a generated container and optional image build, use the Docker target. For the full job/agent walkthrough, see Build and run artifacts.