# Capabilities

Capabilities give an Agent a named ability through `defineAgent({ capabilities })`.
They can add tools, triggers, input processing, output metadata, and checks that run before an invocation.

A Capability is not a server primitive.
Server primitives give trusted app code authority.
Capabilities decide which operations an Agent Invocation can use.

## Choose the API by its caller

Installing a Server Primitive does not give an Agent access to it. Attach a Capability when the Agent needs that operation.

| | Server Primitive | Capability |
| --- | --- | --- |
| Caller | Application server code | An Agent during an Invocation |
| Access | A documented server import | Selected tools, policy, requirements, or context |
| Selection | Application code calls it | The Agent Definition or invocation selects it |
| Model access | None | Only the operations the Capability contributes |

A Capability does not expose the full Runtime Context or unrestricted host access. Its tools, requirements, policy, and metadata define what the Agent can inspect and use. Application code can still call the same Server Primitives through their server APIs.

## Capability lifecycle

ViteHub applies Capabilities in the order listed or returned by the Agent Definition.
It validates duplicate ids, checks runtime requirements, applies Capability Trigger Contributions, and then runs configure, prepare, bind, input, resolve, and output phases for each invocation.

`access()` is the only official Capability with a fixed position rule.
Place it first so later Capabilities receive the restricted Workspace and tool access.

## Attach a Capability

Import official factories from `@vite-hub/agent/capabilities`.
Import the factory from the Capabilities entry point:

```ts [server/agents/support.ts]
import { defineAgent } from 'vite-hub/agent'
import { workspaceShell } from 'vite-hub/agent/capabilities'

export default defineAgent({
  driver: { model },
  workspace,
  capabilities: [
    workspaceShell({ mode: 'read' }),
  ],
})
```

Attaching a Capability opts the Agent into that ability. Model-facing tool policy defaults to `allow`. Set `policy: 'require-approval'` or `policy: 'deny'` when a tool needs another runtime check. Modes, scopes, allowlists, requirements, and input validation still restrict the operation before policy runs.

Use a callback when invocation context decides the Agent Definition's Capability list. ViteHub calls it once after resolving the Agent Invoker and before Capability setup; Capabilities contributed by the active Channel still compose normally.

```ts [server/agents/support.ts]
export default defineAgent({
  driver: { model },
  capabilities: ({ actor }) => [
    workspaceShell({ mode: 'read' }),
    ...(actor.meta?.support === true ? [internalDiagnostics] : []),
  ],
})
```

Return only invocation-scoped behavior from the callback. Capabilities that contribute Agent Triggers, chat admission, or static Workspace Sources must stay in a static list because ViteHub registers those contributions before an invocation exists.

## Use an Eve extension

ViteHub detects compatible Eve extension packages in a static Capability list and compiles their tools into a Capability. Install the extension, then use its existing factory and options:

```bash
pnpm add @github-tools/eve-extension
```

```ts [server/agents/reviewer.ts]
import github from '@github-tools/eve-extension'
import { defineAgent } from 'vite-hub/agent'

export default defineAgent({
  driver: { model },
  capabilities: [
    github({ preset: 'code-review' }),
  ],
})
```

`repositoryHost()` and `repositoryHostContext()` are no longer built in. Replace their GitHub tools with the extension above. GitHub Channel invocations still expose trusted pull request context through `pullRequest.read(invocation)` from `vite-hub/agent/channels`; ViteHub no longer creates a provider-neutral repository client or materialized repository context.

The Vite plugin reads the package's Eve manifest and fails the build when a declared contract version is unsupported. The bridge supports one mount per extension package, direct default-import factory calls, static tools, and dynamic tools with one `session.started` or `step.started` handler. It preserves tool schemas, output conversion, and Eve's `always`, `never`, and `once` approval modes. ViteHub maps the supported dynamic handler to Capability tool resolution at the start of each Agent Invocation and uses the invocation's `runId` as the Eve session ID, so every invocation resolves a fresh tool set without relying on process-local state. The built-in HTTP chat route persists pending approvals in its configured Chat state, reconstructs the authoritative tool call server-side, and consumes each response once under a session lock. Client-supplied chat history never creates approval authority. Eve `once` approvals come only from that Chat state for the current invoker and chat session. The route passes them to the Invocation as a request-scoped grant, so Invocation context values, including values set by `admission.context` or `mapInput`, cannot approve a tool. Unsupported dynamic events fail when ViteHub resolves the extension's tools for an Agent Invocation.

This bridge is not yet a complete Eve runtime. Tool and approval contexts do not support `getSandbox()`, `getSkill()`, `getToken()`, or `requireAuth()`; using one throws at runtime. Session authentication and turn sequence metadata are unavailable. A `step.started` handler resolves once per ViteHub Agent Invocation, not before every model step. ViteHub Agent Invocations are not Eve durable sessions, so extensions that depend on one `session.started` resolution spanning several invocations are not supported yet.

## What Capabilities can contribute

| Contribution | What it changes |
| --- | --- |
| Requirements | Primitive, Workspace mode, Workspace path, or policy checks that must pass before the Capability applies. |
| Tools | Model-facing operations exposed only to compatible Agent Drivers. |
| Provider tools | Provider-native tool requests, such as model web search mode. |
| Agent Triggers | Product events that start Agent Invocations through the Agent Package trigger API. |
| Input behavior | Pre-invocation input transforms, transcription, decisions, gates, and rate limits. |
| Output behavior | Stream renderers, finish extensions, usage records, titles, and summaries. |
| Metadata | Inspectable configuration for runtime diagnostics and CLI inspection. |

Capability metadata appears under the Capability id in Agent inspection output. ViteHub keeps JSON values, sorts object keys and Capability ids, drops unsupported or cyclic values, and redacts keys shaped like auth, API keys, credentials, passwords, secrets, or tokens. Metadata must describe configuration or an explicit check result; it must not include Env values, authentication material, or credentials.

Use `defineCapability({ finish })` for metadata read by evals, finish hooks, or channel delivery code after an invocation.
Agent Evals expose those values through `observation.extensions.get(capabilityId)` and the `hasCapabilityExtension(capabilityId)` scorer.

## Finish without the Driver

A Capability `input` phase can finish an Invocation only with a `Response`. When app code decides the result for some inputs, such as mail rules that label an email before a model runs, use `defineAgent({ data, intercept })` instead. `intercept` returns a typed value that becomes the Invocation output, and `runAgent()` types its output as the union of that value and the Driver output.

```ts [server/agents/labeller.ts]
export default defineAgent({
  data: email,
  intercept: ({ data }) => data.from.endsWith('@github.com') ? { source: 'rule' as const, label: 'GitHub' } : undefined,
  driver: { model, output: { schema: modelLabel } },
})
```

Read [Finish before the Driver](https://vitehub.dev/docs/agents/agent-definitions#finish-before-the-driver) for hooks, traces, and layer rules.

## Driver support

A model-backed Agent Driver can consume model-facing tools and Provider Tool contributions.
A provider-backed Agent Driver receives Agent tools through the private MCP bridge and scoped Workspace behavior. Provider-backed Drivers do not support model-specific Capability Provider Tool contributions such as `webSearch({ mode: 'model' })`.
A custom-run-backed Agent Driver receives prepared input and invocation context; the `driver.run` implementation decides which Capability outputs to read.

Free-form guidance about when and why to use a Capability belongs in Agent Driver Instructions or deterministic imported instruction Markdown. Tool descriptions and schemas remain part of the model-facing tool contract.

## Next steps

- [Official capabilities](https://vitehub.dev/docs/agents/capabilities/official)
- [Custom capabilities](https://vitehub.dev/docs/agents/capabilities/custom)
- [Agent definitions](https://vitehub.dev/docs/agents/agent-definitions)
