nativeharness
v0.3.0
Published
The agent harness native to your app — one import that assembles the workspace store, the sandbox, the tool and the turn loop, plus the `nhar` command line.
Downloads
681
Maintainers
Readme
nativeharness
The agent harness native to your app. One import that assembles a durable workspace, a disposable sandbox, the bash tool and the turn loop — and exposes every one of them.
For developers building products whose users need an agent that takes action. The harness, the workspaces and the sandboxes stay on your infrastructure; the only thing that leaves is what you send to the model you chose.
npm install nativeharnessimport { Harness } from "nativeharness";
const harness = new Harness({ root: "./data" });
const workspace = await harness.workspace({ name: "demo", actor: "user-42" });
await workspace.write("/main.js", "console.log(41 + 1)");
const { result } = await workspace.exec("node main.js && echo built > out.txt");
result.stdout; // "42\n"
result.files.changed; // ["/out.txt"]
await workspace.readText("/out.txt"); // "built\n"The file you wrote was hydrated into a fresh sandbox, the command ran there, and the file the command created was synced back. The sandbox is disposable; the workspace is what survives. No model is involved in any of the above.
With a model
import { AnthropicAdapter } from "@nativeharness/adapter-anthropic";
const harness = new Harness({ root: "./data", model: new AnthropicAdapter() });
for await (const event of workspace.chat("make main.js print the date too")) {
if (event.type === "token") process.stdout.write(event.payload.text);
if (event.type === "output") process.stdout.write(event.payload.chunk);
}Adapters are optional peer dependencies — five vendor SDKs, about 69 MB together, and nobody needs more than one. Install the one you use.
Connectors
Let the agent reach GitHub, Slack or your own API without the credential entering the sandbox:
import { pick } from "@nativeharness/catalog";
const harness = new Harness({
connectors: {
registry: pick("github", "slack"),
credentials: async (_workspace, _connector, reference) => vault.get(reference),
apiUrl: "https://app.example.com/nh/connector-call", // reachable from INSIDE the sandbox
secret: process.env.APP_KEY!,
},
});
await workspace.attach({ connector: "github", credential: "vault:gh/user-42", tools: "*" });For services that sign people in, add oauth: { redirectUrl, clients } and send people to
await workspace.connect("notion") — the harness runs the OAuth flow and keeps tokens fresh.
Mount harness.connectors.endpoint on your own server; the agent's commands then call
nh call github create_issue '{…}' with a token minted for that one command. See the
connectors guide.
The command line
The same package installs nhar:
npm install -g nativeharness
nhar create demo # a workspace, with you granted access
nhar exec <id> "npm test" # a command in its sandbox, streamed
nhar chat <id> -m "fix the failing test"Reaching past the facade
Nothing here is privileged. Harness builds the same objects you would build by hand and
hands each of them back:
harness.store // WorkspaceStore — swap for your own
harness.sandbox // SandboxProvider
harness.events // the bus the protocol replays from
harness.bash // the tool, without the loop
harness.agent // the loopRequires Node 22+ and a container engine — podman or docker — for the default sandbox.
Part of nativeharness — the agent harness native to your app. Apache-2.0 · docs · source
