> ## Documentation Index
> Fetch the complete documentation index at: https://nativeharness.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrating

> Putting nativeharness into your own application: what Harness assembles for you, how to build it yourself, and the four contracts nothing else tells you.

nativeharness is parts that compose, not a framework that composes them. There is no
`Harness.create()`; you construct each layer and hand it the ones below. This is what the
assembly looks like, and then what each line is for.

```ts theme={null}
import { BashTool, Events } from "@nativeharness/core";
import { SqliteWorkspaceStore } from "@nativeharness/store-sqlite";
import { NativeSandboxProvider } from "@nativeharness/sandbox-nativesandbox";
import { Agent } from "@nativeharness/agent";
import { AnthropicAdapter } from "@nativeharness/adapter-anthropic";

const store   = new SqliteWorkspaceStore({ root: "/var/lib/myapp/workspaces" });
const sandbox = new NativeSandboxProvider({ root: "/var/lib/myapp/sandboxes" });
const events  = new Events(store);
const bash    = new BashTool({ store, sandbox, events });
const agent   = new Agent({ store, bash, events, model: new AnthropicAdapter() });
```

| Layer     | What it is                                                    | Needs                            |
| --------- | ------------------------------------------------------------- | -------------------------------- |
| `store`   | the `WorkspaceStore` — every workspace, in one root directory | a root                           |
| `sandbox` | the `SandboxProvider` — where commands run                    | an engine socket (auto-detected) |
| `events`  | persist-then-emit; the bus the protocol replays from          | **the store**                    |
| `bash`    | the one tool: authorise, hydrate, run, collect, guard, commit | store, sandbox, events           |
| `agent`   | the turn loop                                                 | all of the above, plus a model   |

Construct one of each per process. The store holds open database handles; the provider holds an
engine connection and a reap timer; two of either is two of everything.

## Four contracts nothing else tells you

These were found by writing the CLI — the first consumer to assemble the layers from outside a
test. Every one is a compile error in TypeScript and a confusing runtime failure without it.

**`Events` takes the store.** It has no useful default. Miss it and the failure is
`Cannot read properties of undefined (reading 'appendEvents')` from inside an emit, several
layers below your code.

**`Actor` is a string.** Not an object. Pass `{ kind: "user", id }` to a store method and
better-sqlite3 reads it as a named-parameter binding, and fails with an arity error that
names nothing.

**A commit is credited to a `FileCommitAuthor`.**
`{ by: { kind: "actor", id: "user-42" } }` — or `execution`, or `import`. Not a name.

**A workspace whose `permissions` do not name the actor cannot run commands in it.** That is
correct — it is how one user's agent is kept out of another user's workspace — but it means
*creating* a workspace is not enough. Grant the actor at creation:

```ts theme={null}
await store.createWorkspace({
  name: "acme / billing service",
  permissions: [{ actor: "user-42", scope: "/", mode: "commit" }],
});
```

## Mapping to your users

The harness has no users table and wants none. An **actor** is whatever string identifies a
principal in your system — a user id, a service account, a tenant. You decide the mapping:

* one workspace per user, per project, or per conversation
* which actors may work in each, with what scope and what mode
* which connector credentials each actor holds

[Your users](/guides/your-users) covers this in detail.

## Lifecycle

```ts theme={null}
await sandbox.close();   // stops the reap timer, releases the engine
await store.close();     // closes every open database
```

Call both at shutdown. A short-lived process — a CLI, a job — should pass
`reapIntervalMs: 0` to the provider so a timer never fires mid-command, and call
`sandbox.reap()` by hand if it wants to.

## Without a model

`core` has no LLM in it. If your application drives its own loop, or just wants sandboxed,
versioned, auditable command execution, stop at `BashTool`:

```ts theme={null}
const outcome = await bash.execute({ workspaceId, sessionId, command: "npm test" });
```

Every guard, the sync report, the execution record and the events all still apply.

## What you still own

The harness draws a line at product features: **no** billing, scheduling, notifications,
retrieval, user management or domain validators. Those are yours, above the harness, and the
approval policy and connector permissions are the hooks they attach to.
