Build and Run Artifacts
Package v2 jobs and persistent agents into self-contained deployable artifacts.
fh build compiles the embedded workspace, bundles authored definitions, and emits a target-specific
runtime. Node-derived targets use the same v2 HTTP server as fh dev, so local and deployed routes
have the same semantics.
Start with both definition types
Finite work lives in .fabricharness/jobs/:
import { job, schema } from '@fabric-harness/sdk';
export default job({
name: 'summarize',
input: schema.object({ text: schema.string() }),
output: schema.string(),
triggers: { webhook: true },
async run({ init, input }) {
const session = await (await init()).session();
return session.prompt(`Summarize:\n\n${input.text}`);
},
});Long-lived addressable agents live in .fabricharness/agents/:
import { defineAgent } from '@fabric-harness/sdk';
export default defineAgent(({ id }) => ({
name: 'support',
instructions: `You are the support agent for account ${id}.`,
model: 'openai/gpt-5.5',
triggers: { webhook: true },
}));Build Node
fh build --target nodeThe build summary distinguishes the two surfaces:
Build complete
Output .fabricharness/build/node
Manifest .fabricharness/build/node/manifest.json
Jobs summarize
Agents supportThe artifact contains the shared server and self-contained definition modules:
.fabricharness/build/node/
.fabricharness/
agents/support.mjs
jobs/summarize.mjs
roles/
skills/
dist/
agents/support.mjs
jobs/summarize.mjs
server.mjs
manifest.json
package.jsonRun it:
PORT=8080 OPENAI_API_KEY="$OPENAI_API_KEY" \
node .fabricharness/build/node/dist/server.mjsInvoke the built artifact
Finite jobs return their result and a generated run ID:
curl -sS http://localhost:8080/jobs/summarize \
-H 'content-type: application/json' \
-d '{"text":"Fabric builds durable agents."}'{
"result": "Fabric is a framework for durable agents.",
"runId": "8f2d...",
"agentPath": "/app/.fabricharness/jobs/summarize.mjs"
}Persistent input is admitted durably and returns 202:
curl -i http://localhost:8080/agents/support/acct-42 \
-H 'content-type: application/json' \
-d '{"message":"Where is my invoice?"}'{
"submissionId": "5ec1...",
"streamUrl": "/agents/support/acct-42/conversation?session=default&offset=0",
"offset": "0"
}Use @fabric-harness/client to wait for settlement:
import { createFabricClient } from '@fabric-harness/client';
const client = createFabricClient({ baseUrl: 'http://localhost:8080' });
const admitted = await client.agents.send({
agent: 'support',
id: 'acct-42',
message: 'Where is my invoice?',
});
const settled = await client.agents.wait({
agent: 'support',
id: 'acct-42',
submissionId: admitted.submissionId,
});Manifest schema v2
Every current artifact emits schemaVersion: 2 with separate collections:
jq '{schemaVersion, jobs, agents}' .fabricharness/build/node/manifest.jsonBuild readers in @fabric-harness/node normalize legacy schema-v1 manifests, but external tooling
should migrate to jobs and agents. See Build manifest.
Production exposure
In production, a public job or persistent agent must declare triggers.webhook: true. Protect the
server and scope tenants with environment variables:
NODE_ENV=production \
FABRIC_HARNESS_API_TOKEN="$API_TOKEN" \
FABRIC_HARNESS_TENANT_REQUIRED=1 \
FABRIC_HARNESS_RATE_LIMIT_MAX=100 \
FABRIC_HARNESS_RATE_LIMIT_WINDOW_MS=60000 \
node dist/server.mjsClients then send both headers:
curl http://localhost:8080/jobs/summarize \
-H "authorization: Bearer $API_TOKEN" \
-H 'x-fabric-tenant: acme' \
-H 'content-type: application/json' \
-d '{"text":"..."}'Other targets
fh build --target docker --docker-build --docker-tag acme/support:1.0.0
fh build --target databricks-app
fh build --target aks
fh build --target acaNode-derived targets inherit the shared v2 server. Cloudflare supports finite jobs and serialized Durable Object-backed persistent sessions. The Cloudflare runtime intentionally omits the Node submission queue, abort, attachment materialization, and offset conversation-stream routes.
Verify supply-chain metadata
fh build --target docker --provenance --attestation --sbom
fh verify-provenance .fabricharness/build/docker
fh verify-attestation .fabricharness/build/dockerSee Docker, Databricks App, and Security hardening.