SDK entrypoints, runtimes, and targets
Understand Lite vs Full SDK imports, stateless vs inline vs Temporal execution, and deployment targets.
Fabric Harness has three independent choices. They are intentionally separate:
- SDK entrypoint — what you import in agent code.
- Runtime — how sessions execute and whether state is kept.
- Target — where the built or driven agent runs.
Keeping these separate lets a 10-line webhook grow into a durable background agent without changing the core init() / agent.session() / session.prompt() / session.skill() / session.task() / session.shell() primitives.
1. SDK entrypoints
| Entrypoint | Import | Use it when | Includes |
|---|---|---|---|
| Lite SDK | @fabric-harness/sdk/lite | You want the smallest authoring surface and import graph for headless, edge, serverless, or prototype agents. | defineAgent, agent, init, schema, defineCommand, defineTool, session.skill(), tasks, local/empty/remote sandbox helpers, filesystem sources, and basic MCP connection. |
| Full SDK | @fabric-harness/sdk | You are building production agents with typed I/O, policies, providers, durable stores, artifacts, telemetry, Docker/remote sandboxes, result validation, or model runtime control. | Everything in Lite, plus provider implementations, policy evaluators, built-in file/shell tools, stores, telemetry, result extraction, context budgeting, Docker, remote sandbox helpers, and stdio MCP. |
The Full SDK is a runtime-value superset of the Lite SDK. If an import works from @fabric-harness/sdk/lite, the same runtime export should also work from @fabric-harness/sdk.
import { defineAgent } from '@fabric-harness/sdk/lite';
export default defineAgent(async ({ init, payload }) => {
const session = await (await init({ runtime: 'stateless' })).session();
return { reply: await session.prompt<string>(String((payload as any)?.message ?? '')) };
}, { name: 'echo' });import { agent, schema } from '@fabric-harness/sdk';
export default agent({
name: 'echo',
input: schema.object({ message: schema.string() }),
output: schema.object({ reply: schema.string() }),
async run({ init, input }) {
const session = await (await init({ runtime: 'stateless' })).session();
return { reply: await session.prompt<string>(input.message) };
},
});2. Runtimes
| Runtime | State model | Best for | Tradeoff |
|---|---|---|---|
stateless | No persisted session history. Each invocation is independent. | High-volume webhooks, edge/serverless agents, simple headless automations, prototypes. | No durable artifacts, no stored approvals, no resumable history. |
inline | Runs in the current process. Uses in-memory state by default or a configured SessionStore. | Local development, Node servers, CI jobs, production web services with SQLite/Postgres/file storage. | Process-local unless you configure a durable store. |
temporal | Model calls, shell commands, checkpoints, approvals, and child tasks run through Temporal workflows/activities. | Long-running background agents, restartable jobs, approval-gated workflows, multi-day runs. | Requires a Temporal server and worker process. |
Runtime is not the same as SDK entrypoint. These are all valid:
await init({ runtime: 'stateless' }); // works with Lite or Full SDK
await init({ runtime: 'inline' }); // works with Lite or Full SDK
await init({ runtime: 'temporal' }); // driven through the Temporal integration3. Targets
| Target | CLI | What it means |
|---|---|---|
node | fh run ask --target node / fh build --target node | Run or build a Node HTTP/server process. Uses inline runtime unless configured otherwise. |
temporal-worker | fh temporal-worker and fh run ask --target temporal-worker | Start a worker and drive agents through Temporal workflows. |
docker | fh build --target docker | Package a Node build in a Docker-ready output. |
cloudflare | fh build --target cloudflare | Emit a Cloudflare Worker-oriented build. Experimental until live Worker/R2 validation is complete. |
foundry-hosted-agent | fh build --target foundry-hosted-agent | Generate a hosted-agent deployment artifact. |
Target is where the code runs. Runtime is how sessions execute. SDK entrypoint is what the agent imports.
Common combinations
| Scenario | SDK entrypoint | Runtime | Target |
|---|---|---|---|
| 10-line webhook | Lite | stateless | node or cloudflare |
| Support agent with a mounted knowledge base | Lite or Full | stateless or inline | node or cloudflare |
| CI issue triage | Full | inline | node |
| Durable issue triage | Full | temporal | temporal-worker |
| Production Node service | Full | inline + SQLite/Postgres/file store | node or docker |
| Approval-gated background job | Full | temporal | temporal-worker |
Remote coding agents can start from either entrypoint
Remote coding agents usually need a real Linux sandbox, a cloned repository, shell access, and a prompt from the caller. The Lite SDK now exposes the remote sandbox adapter helper, so a connector can provide the same SandboxEnv shape without forcing the Full SDK import:
import { createRemoteSandboxEnv, defineAgent } from '@fabric-harness/sdk/lite';
export default defineAgent(async ({ init, payload, env }) => {
const remote = await createProviderSandbox({ apiKey: env?.SANDBOX_API_KEY });
const sandbox = createRemoteSandboxEnv(remote.api, { cleanup: true });
const setup = await (await init({ sandbox, runtime: 'stateless' })).session();
await setup.shell(`git clone ${(payload as any)?.repo} /workspace/project`);
await setup.shell('npm install', { cwd: '/workspace/project' });
return await setup.prompt(`Work in /workspace/project. ${(payload as any)?.prompt ?? ''}`);
}, { name: 'code' });Use the Full SDK when the coding agent also needs typed input/output, capability policy, durable artifacts, approvals, provider routing, telemetry, or runtime: 'temporal'.
Skills work in both entrypoints
Skills are not a Lite-only feature. They are part of the shared session surface:
await session.skill('triager', { args: { message: 'How do I reset my password?' } });Full metadata agents can also declare default inline skills directly on the agent definition:
import { agent, schema } from '@fabric-harness/sdk';
export default agent({
name: 'support',
skills: [{ name: 'triager', content: 'Search the knowledge base and reply concisely.' }],
input: schema.object({ message: schema.string() }),
async run({ init, input }) {
const session = await (await init()).session();
return { reply: await session.skill('triager', { args: input }) };
},
});Workspace skills under .fabricharness/skills/ are loaded by the Node/build runtimes and are available to both Lite and Full agents.
How to choose
- Choose Lite SDK when you want fewer imports and less ceremony.
- Choose Full SDK when you need typed I/O, policies, providers, artifacts, telemetry, durable stores, or deployment/runtime controls.
- Choose
statelesswhen persistence would be wasted or harmful. - Choose
inlinewhen you want ordinary process-local execution, optionally backed by a store. - Choose
temporalwhen the run must survive restarts, wait for approvals, or continue for a long time.
Do not create separate Lite and Full copies of the same agent. Start with the Lite entrypoint if useful; move to the Full entrypoint when you need the extra imports or metadata. The session primitives stay the same.