# Quickstart: build an adapter

<!-- [doc->REQ-DOCS-2] the dev-agent killer quickstart: minimal adapter satisfying the manifest + api contract, walked via the shipped mock adapter -->
The "build a harness for spt-core" hello-world: take the reference
**mock adapter** apart, register it, drive the contract with real commands,
then swap in your own harness. No spt-core source required — the public
contract is the manifest plus the `spt api` surface.

> Integrating an agent harness and a building a driven surface (notifier,
> robot, sensor) are the same contract with a different manifest body. For
> the latter, read this page first, then
> [Shells: getting started](../shells/getting-started.md).

## 0. What an adapter is

A TOML **manifest** that declares what varies for your harness — how to spawn
a session, which of your hook events fire which `spt api` command, how spt-core
can read session history — plus whatever your harness already has (hooks,
plugin config). Command templates are **opaque strings**: spt-core fills
`{key}` placeholders and runs them. It never parses out a model, a tool list,
or a flag. Your harness's business stays yours.

## 1. Get the reference adapter

Every release ships the mock adapter's source. With spt-core
[installed](messaging.md#1-install-one-line):

```sh
curl -fsSL -o mock-adapter.zip \
  https://github.com/SaberMage/spt-releases/releases/latest/download/mock-adapter.zip
unzip mock-adapter.zip -d mock-adapter
```

(Windows: `irm -OutFile mock-adapter.zip https://github.com/SaberMage/spt-releases/releases/latest/download/mock-adapter.zip`
then `Expand-Archive mock-adapter.zip mock-adapter`.)

The interesting file is `mock-adapter/manifest.toml`. It is deliberately
harness-agnostic — generic event names, a trivial `mock-session` helper
standing in for a real harness binary.

## 2. Read the manifest

The header is the only mandatory section:

```toml
[adapter]
name = "mock"
kind = "harness"                  # or "shell" (a driven surface)
version = "1.0.0"
min_spt_core_version = "1.0.0"    # compat gate, readable before any install/update
hostable_types = ["LiveAgent", "ReadyAgent", "Worker"]
```

Inbound: your harness's hook events, each firing one `spt api` command:

```toml
[hooks.SessionStart]
fires = "api seed --pid {parent_pid} --session-id {session_id} --adapter {adapter_name}"
reads = ["session_id", "parent_pid"]
can_inject = true     # this hook can surface text back into the agent's context

[hooks.Idle]
fires = "api state idle"
can_inject = false    # no inject channel -> spt-core uses its sentinel/relay fallback
```

`can_inject` is the load-bearing harness-varying fact: when a hook can't put
text in front of the agent, spt-core routes around it automatically.

Outbound: opaque session templates spt-core spawns with `{key}` placeholders
filled:

```toml
[session.self]
command = "mock-session --id {id} --session-id {session_id}"
detach = true
keys = ["id", "session_id"]
```

A real adapter's template is your harness's full command line — model, flags,
tools, everything — exactly as you'd type it.

The rest declares history access (`[history]`), env bridging (`[env.*]`),
input injection (`[inject]`), and session identity (`[identity]`). Every
section beyond `[adapter]` is optional; the
[manifest reference](../harness-contract/manifest.md) covers them all.

## 3. Validate and register

Two layers of validation, both mechanical:

- **Schema** — your manifest must validate against
  [`manifest.schema.json`](https://sabermage.github.io/spt-releases/manifest.schema.json).
  The schema is generated from the same code that parses manifests, so it is
  always current; closed vocabularies (adapter kinds, history strategies,
  update avenues, …) are enums in it.
- **Registration** — `spt adapter add` parses, validates (including
  cross-field rules the schema can't express), and registers in one step:

```console
$ spt adapter add ./mock-adapter
ADAPTER_ADD:mock:Harness:Copy (registered)
ADAPTER_INSTALL_SKIP: no [update] avenue (manifest-only adapter)
$ spt adapter list
mock: Harness Copy active (from ./mock-adapter)
```

A bad manifest is rejected here with a message naming the offending field —
nothing half-registers.

## 4. Drive the contract

Every machinery call your adapter makes carries `--adapter <name>` — that's
the rule that makes multi-harness nodes unambiguous. Ask spt-core what your
adapter declared:

```console
$ spt api --adapter mock --manifest ./mock-adapter/manifest.toml capability
LiveAgent
ReadyAgent
Worker
```

Now the harness-hosted startup flow, exactly what your `SessionStart` hook
will fire (here with a stand-in pid):

```console
$ spt api --adapter mock seed --pid 4242 --session-id demo-session-1
SEEDED:4242
```

`seed` records an ephemeral hand-off keyed by the parent process id; the
session's listener then consumes it with `spt api … listen` and holds the
perch. That seed→listen pair *is* harness-hosted startup. (The other
direction — spt-core spawning the session itself from your `[session.self]`
template, then `api bind` — is spt-hosted startup. Both are in the
[`spt api` reference](../harness-contract/api.md).)

## 5. Make it yours

1. Copy `manifest.toml`, set `name`, `version`, and your real
   `hostable_types`.
2. Point `[hooks.*]` at the events your harness actually fires, with honest
   `can_inject` values.
3. Replace each `[session.*].command` with your harness's real command line.
4. Pick the `[history]` strategy your harness permits (binary that emits
   history → `fetcher`; transcript file on disk → `locate_normalize`; you
   push via `api history-log` → `native`).
5. Validate against the schema, `spt adapter add` it, and fire the
   `capability`/`seed` calls above against your own manifest.

Building adapters against this contract is **unrestricted and royalty-free**
— see the [license split](https://github.com/SaberMage/spt-releases#license).

## Next

- **Checklist:** the [harness integration checklist](../harness-contract/integration-checklist.md)
  — every contract surface grouped by necessity, mapped to the interaction
  lifecycle, plus the beyond-the-API integrations that make an adapter feel
  native. Work it top to bottom when building a real harness.
- **Reference:** the complete [manifest reference](../harness-contract/manifest.md)
  and [`spt api` reference](../harness-contract/api.md).
- **How-to:** ship spt-core *with* your adapter — the
  [install-on-demand bootstrap pattern](../harness-contract/install-on-demand.md).
- **Concept:** where adapters sit in the [mental model](../concepts/overview.md).
