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

# Test and troubleshoot a harness

> Verify a custom driver contract without provider calls and diagnose configuration, lifecycle, and watch failures.

Use the separate `@agentium/harness/testing` entrypoint to verify the runtime contract of a custom driver. Prefer deterministic fixtures before testing a real provider or external effect.

## Run the driver contract fixture

Save as `driver-contract.ts` and run `npx tsx driver-contract.ts` after the [quickstart installation](/harness/quickstart).

```typescript theme={null}
import assert from "node:assert/strict";
import type { ExecutionDriver } from "@agentium/harness";
import { testDriverContract } from "@agentium/harness/testing";

const driver: ExecutionDriver = {
  id: "fixture",
  version: 1,
  capabilities: {
    controls: [],
    durable: false,
    policyCoverage: "local",
    controlledExecution: true,
  },
  async start(request, services) {
    const text = "Fixture passed";
    services.append([
      { role: "user", content: request.input },
      { role: "assistant", content: text },
    ]);
    return { text };
  },
};

const { result, eventCount } = await testDriverContract(driver, {
  grants: { toolIds: [], modelRoles: [] },
  budgets: { maxModelCalls: 0, maxToolCalls: 0 },
});
assert.equal(result.status, "completed");
assert.equal(result.text, "Fixture passed");
assert.equal(eventCount, 2);
console.log("Driver contract passed");
```

The helper returns `{ result, eventCount }` and checks ordered event sequences, run identity, schema version, exactly one terminal event, terminal/result agreement, final cursor, observer completion, and stable results after late cancellation. It rejects a failed result and closes fixture session resources.

Its optional second argument is `Omit<HarnessRuntimeConfig, "driver">`; the default grants no tools and the `main` model role. The helper executes the supplied driver with a conformance input. A real driver may call a provider or perform effects, so choose its test configuration deliberately. Passing the fixture does not prove that custom code never bypasses controlled services.

## Troubleshoot common failures

| Symptom | Cause and next step |
| - | - |
| `A trusted execution driver is required` | Supply `driver`, or a definition with a resolvable driver binding. |
| `HarnessUnsupportedError` / `unsupported` | Driver advertises durable recovery, replace, or insufficient local execution coverage. Use supported capabilities. |
| `session_conflict` | Another writer or active resource lease owns the scoped session. Wait for it to settle before starting/closing. |
| `budget_exhausted` | A shared run cap was reached. Inspect task and policy usage before changing budgets. |
| `revision_limit` | Completion policy requested a revision after the configured allowance. Default allowance is zero. |
| Ungranted model role or missing binding | Add the intended role to grants and supply its provider; aliases must resolve to host names. |
| Rejected model option override | Add that option name to the selected role's `options` allowlist if your host permits it. |
| Missing required tool | Tool is absent, ungranted, or removed by a controller. Check `ToolDef.name` and required IDs. |
| Agent defaults rejected | A borrowed Agent is already configured. Pass Agent configuration to `agentDriver()` to apply harness defaults. |
| Duplicate ID or ordering error | Give abilities and emitted capabilities unique IDs; verify middleware dependency targets and cycles. |
| Manifest export fails | Use explicit stable IDs, portable factories, and approved references for executable runtime bindings. |
| `event_gap` | Observer fell outside retained events. Recover from the terminal result or explicitly show a gap. |
| Cancelled run remains active briefly | Owned work or a noncooperative callback has not settled. Propagate abort signals and bound external calls. |
| Watch construction rejects durability | Supply durable store/outbox/scheduler capabilities; only use `requireDurability: false` for fixtures. |
| Watch delivers no newer digest | Check quiet hours, limits, authorization, and unresolved earlier outbox effects with `inspect()`. |

Handle synchronous configuration errors separately from a run's `result.reason`. Do not import internal validation classes from private package paths; `HarnessValidationError` is not a root package export. Inspect thrown errors and their diagnostics where present.

## Validate your integration

Exercise one successful run, a denied tool, budget exhaustion, cancellation, a session conflict, observer reconnection, and cleanup failure handling using deterministic clients. For watches, verify cursor/digest persistence and uncertain-send reconciliation with your store and connector implementations. Do not infer live provider guarantees from an in-memory fixture.

See [testing helper signature](/harness/api/testing), [runtime options](/harness/api/runtime), and [watch state types](/harness/api/watches).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.