Configuration
How config.ts and environment variables combine, and which one wins when the same setting is declared in both places.
Most agents work with zero configuration. When you need defaults across agents — a model, a Temporal address, a session-store backend, a capability policy, a sandbox profile — put them in .fabricharness/config.ts.
.fabricharness/config.ts
import type { FabricHarnessConfig } from '@fabric-harness/node';
const config: FabricHarnessConfig = {
agent: {
model: 'openai/gpt-5.5',
// Optional capability policy applied to every agent unless overridden by init():
policy: {
commandPolicy: {
allow: ['git status*', 'git log*', 'gh issue view*'],
requireApproval: ['gh issue comment*', 'psql*'],
deny: ['git push*', 'rm -rf*'],
},
maxCommandTimeoutMs: 30_000,
approvals: { requiredApprovals: 1, defaultTimeoutMs: 60_000, risk: 'medium' },
},
},
run: {
target: 'node', // 'node' | 'temporal-worker'
model: 'openai/gpt-5.5',
idPrefix: 'fab',
cwd: 'project', // default sandbox/session cwd for fh run
},
temporal: {
address: 'localhost:7233',
taskQueue: 'fabric-harness',
namespace: 'default',
workflowIdPrefix: 'fabric-cli',
promptWorkflowMode: 'hybrid',
},
sandbox: {
backend: 'local', // 'empty' | 'virtual' | 'local' | 'docker' | 'cloudflare' |
// 'e2b' | 'daytona' | 'modal' | 'kubernetes' | 'firecracker' |
// 'azure-container-apps' | 'azure-container-instances' | 'aks' | 'databricks'
metadata: {
inheritSafeEnv: true,
envAllowlist: ['GH_TOKEN', 'DATABASE_URL'],
defaultTimeoutMs: 30_000,
outputLimitBytes: 256_000,
},
},
store: {
backend: 'file', // 'file' | 'sqlite' | 'postgres'
},
metadata: {
// Default Cloudflare Worker name (overridable per environment); bindings and
// routes are edited in the wrangler configuration the cloudflare build emits.
name: 'my-agent',
},
};
export default config;The config is loaded dynamically — you can use TypeScript freely (imports, type checks, conditional logic, etc.).
Precedence
For each setting, the highest source wins:
CLI flag > environment variable > config.ts > agent defaultCommon environment variables:
| Variable | Purpose |
|---|---|
FABRIC_MODEL | Default provider/model-id for fh run. |
FABRIC_TARGET / FABRIC_HARNESS_TARGET | Default --target for fh run. |
FABRIC_TEMPORAL_TASK_QUEUE | Default Temporal task queue. |
FABRIC_TEMPORAL_ADDRESS | Default Temporal address. |
FABRIC_TEMPORAL_NAMESPACE | Default Temporal namespace. |
FABRIC_DOCKER_TEST | Gates live Docker tests (=1 to enable). |
OPENAI_API_KEY, AZURE_OPENAI_*, etc. | Provider credentials. |
Loading .env files
TechFabric Harness auto-loads common env files from the repo root and workspace root:
.env
.env.local
.fabricharness/.env
.fabricharness/.env.localFor local development, put provider keys once in the repo-level .env.local:
cp .env.example .env.local
# edit .env.local and set OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.Shell environment values always win. Use explicit --env <file> only for overrides; repeatable explicit env files override auto-loaded files but not shell env.
fh run ask --env .env.test --question "hi"
fh dev --env .env.test
fh temporal-worker --env .env.test--env is supported on run, dev, and temporal-worker.
Agent-level overrides
A metadata agent can declare its own defaults:
export default defineAgent({
name: 'ask',
model: 'openai/gpt-5.5', // wins over config.run.model
target: 'node', // wins over config.run.target
// ...
});CLI flags still override agent defaults.
Where config files live in the build
fh build reads .fabricharness/config.ts at build time and bakes the relevant subset into the manifest. Runtime-sensitive values (Temporal address, secrets, etc.) stay env-driven so they can change per environment.