Open Harness
Guides

Production Deployment

Checklist for deploying Open Harness workflows

Production Deployment

A practical checklist for running Open Harness in production.

Deployment Targets

  • Node.js/Bun server: Run workflows behind an HTTP API
  • Serverless: Supported for short-lived workflows (avoid long-running streams)
  • Edge: For lightweight workflows with minimal dependencies

Example: Workflow API Service

import express from "express";
import { createWorkflow, ClaudeHarness } from "@open-harness/core";

const app = express();
app.use(express.json());

type State = { input: string; result: string | null };
const { agent, runReactive } = createWorkflow<State>();

const analyzer = agent({
  prompt: "Analyze: {{ state.input }}",
  activateOn: ["workflow:start"],
  emits: ["analysis:complete"],
  updates: "result",
});

const harness = new ClaudeHarness({
  model: "claude-sonnet-4-20250514",
});

app.post("/analyze", async (req, res) => {
  try {
    const result = await runReactive({
      agents: { analyzer },
      state: { input: req.body.input, result: null },
      harness,
      endWhen: (s) => s.result !== null,
    });

    res.json({
      result: result.state.result,
      metrics: result.metrics,
    });
  } catch (error) {
    res.status(500).json({ error: "Workflow failed" });
  }
});

app.listen(3000, () => {
  console.log("Workflow service on :3000");
});

Error Handling

Handle workflow failures gracefully:

try {
  const result = await runReactive({
    agents: { analyzer },
    state: initialState,
    harness,
  });
} catch (error) {
  if (error instanceof HarnessError) {
    // Harness API failure
    logger.error("Harness failed", { error: error.message });
  } else if (error instanceof TimeoutError) {
    // Workflow timeout
    logger.error("Workflow timeout", { durationMs: error.elapsed });
  }
}

Observability

Signal Logging

Log signals for debugging:

const result = await runReactive({
  agents: { analyzer },
  state: initialState,
  harness,
});

// Log signal trace
for (const signal of result.signals) {
  logger.info(`[${signal.name}]`, {
    timestamp: signal.timestamp,
    payload: signal.payload,
  });
}

Metrics

Extract metrics from results:

// Duration and activation count
console.log(`Duration: ${result.metrics.durationMs}ms`);
console.log(`Activations: ${result.metrics.activations}`);

// Count signals by type
const signalCounts = result.signals.reduce((acc, s) => {
  acc[s.name] = (acc[s.name] || 0) + 1;
  return acc;
}, {} as Record<string, number>);

Security Best Practices

  • Authentication: Protect endpoints that start workflows
  • Rate limiting: Throttle runs per user or API key
  • Input validation: Validate user input before runReactive
  • Secrets management: Store harness credentials in environment variables

Environment Variables

VariableDescriptionRequired
LOG_LEVELLogging verbosity (trace, debug, info, warn, error)Optional

Authentication

Open Harness uses Claude Code subscription authentication. No API key is required - authentication is handled automatically when running from within Claude Code.

Pre-Production Checklist

  • Validate workflows with test inputs
  • Set appropriate timeouts
  • Add structured logging
  • Configure error handling
  • Lock down network access and secrets
  • Test recording/replay for CI

Next Steps

On this page