@fabric-harness/sdk
v6.1.0
Published
Headless TypeScript framework for building durable, deployable autonomous agents — core SDK.
Readme
@fabric-harness/sdk
Core SDK for Fabric Harness — a headless TypeScript framework for building durable, deployable autonomous agents.
Install
npm install @fabric-harness/sdk
# or
pnpm add @fabric-harness/sdkQuick start
Minimal — bare import, headless defaults (8 lines)
import { defineAgent } from '@fabric-harness/sdk';
export default defineAgent<{ message: string }>({
name: 'echo',
triggers: { webhook: true },
run: async ({ init, input }) => {
const session = await (await init({ model: 'openai/gpt-5.5' })).session();
return { reply: await session.prompt<string>(input.message) };
},
});Complete — same import, more fields
With typed I/O + capability policy + skills (same import)
import { defineAgent, schema } from '@fabric-harness/sdk';
export default defineAgent({
name: 'triage',
input: schema.object({ issueNumber: schema.number(), title: schema.string() }),
output: schema.object({ severity: schema.enum(['low','medium','high']), summary: schema.string() }),
model: process.env.FABRIC_MODEL,
run: async ({ init, input }) => {
const session = await (await init()).session();
return await session.prompt('Triage and return the typed result.');
},
});Both forms share the same init(), session.prompt() / skill() / task() / shell() APIs. Runtime (stateless, inline, or temporal) is a separate choice configured at init().
Persistent agents that evolve
createAgent() renders per interaction. Hooks let durable state change the current model, tools,
skills, subagents, MCP connections, and sandbox without introducing another builder:
import { createAgent, useModel, usePersistentState, useTool } from '@fabric-harness/sdk';
export default createAgent(() => {
const [level, setLevel] = usePersistentState('level', 0);
useModel(level < 2 ? 'anthropic/claude-haiku-4-5' : 'anthropic/claude-sonnet-4-6');
useTool({ name: 'advance', durable: true, run: async ({ step }) => {
const receipt = await step.do('advance', async () => ({ advanced: true }));
setLevel((value) => value + 1);
return receipt;
}});
if (level >= 1) useTool(advancedAnalysis);
return `Current capability level: ${level}.`;
});One SDK, one import
@fabric-harness/sdk is the single import everyone uses. defineAgent({...}) from the bare import auto-injects headless defaults (runtime: 'stateless', sandbox: 'virtual', loopRuntime: pi-agent-core, compaction: { enabled: true }) on every init() call. Override any of them by passing values to init(). Add typed input/output schemas, policy, artifacts, custom stores, telemetry — they're all options on the same defineAgent({...})/init() shape.
For Temporal-backed durable agents or compliance workloads where no implicit behaviour is wanted, use @fabric-harness/sdk/strict — same call shape, no defaults injected.
Runtime (stateless, inline, or temporal) controls persistence and durability and is configured at init(). The deploy target (node, temporal-worker, docker, cloudflare, …) is chosen via fh build --target.
What's in the box
init({ model, sandbox, policy, runtime, sessionRuntime, ... })— initialize an agent runtime.session.prompt / skill / task / shell— the four agent operations.session.mount(mountAt, source, { mode })— mount aFilesystemSourceinto the sandbox at runtime. Read-only by default; writes under the mount are blocked at the policy layer.session.approval.request({ reason, risk?, timeoutMs? })— custom approval gate. Returnstrueon approval; throwsAPPROVAL_DENIED/APPROVAL_REQUIREDon denial / timeout.ApprovalResponse.grant— durable approved responses carry the call/input/principal-bound grant; denied responses never do.defineAgent({...})— single builder. Same call shape from the bare@fabric-harness/sdkimport and from@fabric-harness/sdk/strict; the import you choose controls whether headless defaults are injected at runtime.createAgent()hooks — compose persistent state, delivery and initial data, dynamic resources, lifecycle guards, response metadata/data parts, durable tool steps, MCP, and subagents.defineCommand— bind a privileged CLI (gh,npm, …) with secrets at the command level, never in model context.withFilesystemSources/session.mount()— two ways to mount read-only content into a sandbox; agent's built-ingrep/glob/readtools see it as ordinary files.runtime: 'inline' | 'stateless' | 'temporal'+sessionRuntime— pick by persistence needs. Pairruntime: 'temporal'withtemporalSessionRuntime({...})from@fabric-harness/temporalto route every session call through durable workflows.CapabilityPolicy— filesystem read/write globs, command/tool allow-deny-approve, andnetwork: { mode, hosts }allowlist/denylist.policiedFetch(fetch, policy)wraps any fetch-like with policy enforcement.- Schemas (
schema.object,schema.enum, etc.) — validate inputs/outputs without external deps. - MCP —
connectMcpServerfor remote tool servers. - Telemetry —
openTelemetryExporter,langfuseExporter,consoleTelemetryExporteradapt theTelemetrySpanshape to OTel / Langfuse / stdout.
Named OpenAI-compatible presets are available as deepseek/<model> (DEEPSEEK_API_KEY),
moonshot/<model> or kimi/<model> (MOONSHOT_API_KEY), and xai/<model> (XAI_API_KEY). They
use direct provider endpoints and never silently fall back to a gateway or mock model.
Documentation
- Headless agents with the minimal entrypoint
- SDK entrypoints, runtimes, and targets
- Runtime modes — including the direct
temporalSessionRuntimeAPI. - Dynamic agents and hooks
- Filesystem sources —
session.mount()and source connectors. - Policies and approvals — capability policy, network policy, mount permissions, custom approvals.
- Telemetry — events, transports, metrics.
- Roadmap
- Full reference
License
Apache-2.0
