> ## 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.

# Compose definitions and abilities

> Build reusable harness definitions with tools, context, middleware, and explicit ownership.

A definition describes what a harness needs. An ability supplies capabilities when the runtime binds it to a run. Defining, extending, or describing a harness does not open files, connect clients, or call a model.

## Define a harness

```typescript theme={null}
import { defineHarness, describeHarness, textContext } from "@agentium/harness";

const definition = defineHarness({
  id: "project-assistant",
  abilities: [
    textContext(
      { id: "project", entries: [{ id: "name", text: "Project name: Atlas." }] },
      { instanceId: "project-source" },
    ),
  ],
  defaults: {
    workspace: { path: ".", mode: "read" },
    skillDirs: [".agents/skills"],
    contextFiles: true,
  },
  limits: { toolRoundtrips: 8, maxChildDepth: 1 },
});

console.log(describeHarness(definition));
```

Pass `definition` to `new HarnessRuntime({ definition, driver, grants })`. A definition can also carry runtime bindings; see [registries](/harness/manifests).

| Input | Meaning |
| - | - |
| `id` | Stable definition identifier. Omission creates a local ID that cannot be exported as a portable manifest. |
| `abilities` | Ordered ability uses. Each `instanceId` must be unique. Defaults to an empty list. |
| `defaults` | Declarative settings applied by `agentDriver(config)`. Explicit Agent options override defaults. |
| `limits` | `toolRoundtrips` caps Agent tool rounds; `maxChildDepth` caps enabled subagents. These do not grant tools or replace run budgets. |
| `runtime` | Direct driver, controller, context-policy, completion-policy, and model-role bindings. |
| `runtimeReferences`, `runtimeRegistry` | Versioned references and host-approved implementations for portable runtime selection. |

`HarnessDefaults` supports `workspace`, `skillDirs`, `contextFiles`, `filesystem`, `subagents`, `fileMemory`, and `searchPastSessions`. Use `workspace: false` or `skillDirs: false` to disable those settings. Other defaults are optional booleans. Relative workspace, skill, and context-file paths resolve against `HarnessRuntime.projectRoot`.

Defaults do not silently approve generated tools. Grant each intended tool name in the runtime. For a filesystem and skills Agent, names include `fs_read_file`, `fs_list_directory`, `fs_file_info`, `list_skills`, `get_skill_instructions`, and `get_skill_reference`.

## Write an ability

An ability has pure validation and description functions, followed by a binding function that may acquire resources. This example adds a host-authored prompt fragment:

```typescript theme={null}
import { defineAbility, defineHarness } from "@agentium/harness";

const answerStyle = defineAbility<{ text: string }>({
  type: "example/answer-style",
  version: 1,
  validate(options) {
    if (!options.text.trim()) throw new Error("Answer style must be nonempty");
    return { text: options.text };
  },
  describe: () => ({ toolNames: [], requirements: [] }),
  bind: (options) => ({
    tools: [],
    promptFragments: [{ id: "answer-style", text: options.text }],
  }),
});

export const definition = defineHarness({
  id: "concise-assistant",
  abilities: [answerStyle({ text: "Use short paragraphs." }, { instanceId: "style" })],
});
```

`type` identifies an ability implementation; `instanceId` identifies one configured use. `version` defaults to `1` and must be a positive safe integer. Omitted instance IDs are generated; explicit IDs make composition and manifest export predictable.

`AbilityBinding.tools` is required, even when empty. A binding may also supply:

| Field | Contract |
| - | - |
| `promptFragments` | Host-authored instructions with unique IDs. Do not put retrieved documents here. |
| `contextSources` | Bounded retrieval through `fetch(query, ctx, budget)`; returned content is source data. |
| `middleware` | Ordered `beforeModel`, `afterModel`, and `afterTool` hooks. |
| `dispose` | Async cleanup called once for an acquired binding. |

The runtime binds abilities sequentially for each run. It disposes acquired bindings in reverse order, including after partial initialization failure. Plain option objects and arrays are snapshotted; service instances and callbacks remain host-owned references.

## Declare requirements and middleware ordering

Use `describe().requirements` for host capabilities such as `filesystem:read`. Supply approved capabilities through `HarnessRuntime.requirements`. A declaration documents and gates binding; it does not create an OS permission or authenticate a service.

Middleware IDs are unique. `before` and `after` refer to other middleware IDs. Missing ordering targets and cycles fail validation. `beforeModel` returns the projected messages; `afterModel` receives the response; `afterTool` receives the tool result. All hooks receive `RunContext`.

Duplicate tool names, prompt IDs, context-source IDs, or middleware IDs are errors. Coordinate IDs across abilities; defining a second ability does not implicitly replace the first one's output.

## Extend a definition

```typescript theme={null}
import { defineHarness, extendHarness, textContext } from "@agentium/harness";

const original = defineHarness({
  id: "base-reader",
  abilities: [textContext(
    { id: "notes", entries: [{ id: "v1", text: "Original notes." }] },
    { instanceId: "notes" },
  )],
});
export const updated = extendHarness(original, {
  id: "updated-reader",
  replaceAbilities: [textContext(
    { id: "notes", entries: [{ id: "v2", text: "Updated notes." }] },
    { instanceId: "notes" },
  )],
  defaults: { filesystem: false },
});
```

`abilities` appends uses. `disable` removes existing instance IDs. `replaceAbilities` replaces enabled instances with matching IDs; unknown IDs and replacing a disabled instance fail. Defaults and limits merge by field. Two `skillDirs` arrays merge with deduplication; `false` disables them. Extension is explicit configuration, not a runtime grant escalation.

`describeHarness()` returns declared tools, requirements, defaults, limits, runtime dependence, and diagnostics without binding. See [exact types](/harness/api/definitions) and [portable manifests](/harness/manifests) for serialization.


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